【问题标题】:Draw a circle with a specific number of pixels绘制具有特定像素数的圆
【发布时间】:2011-04-21 18:26:15
【问题描述】:

我正在开展一个项目,该项目需要我准确控制用于绘制(大致)圆形刺激的像素数量,尽管 Bresenham 的算法很棒,但它们不会绘制任意区域的圆圈(以我的知识)。我已经尝试过在绘制所需区域时中断 Bresenham 算法的脚本,但结果肯定是命中注定的。有谁知道使用给定数量的像素绘制“最佳”圆(我知道有点主观)的方法?非常感谢!

【问题讨论】:

  • 按照你描述的方式打断 Bresenham 算法有什么问题?
  • 你是在画黑白还是允许使用抗锯齿?

标签: algorithm language-agnostic plot geometry


【解决方案1】:

粗略的做法,例如:

面积为 1000 平方像素的圆的半径为 sqrt(1000/pi) = 17.8... 然后该圆应适合 35x35 矩阵。如果为中心像素为 (0,0) 的矩阵创建“索引”,则可以通过代入圆方程 x^2 + y^2 = r 轻松检查像素是否落在圆中^2。或者,您可以将替代方程用于以 (a,b) 为中心的圆。如果计算结果为 TRUE,则为 TRUE,否则为 TRUE。

作为一个伪代码/示例,在 Python 中我会做一个优化版本:

import numpy, math

target_area = 1000.0

r = (target_area / math.pi) ** 0.5
m = numpy.zeros((2*r+2,2*r+2))

a, b = r, r

for row in range(0, m.shape[0]):
    for col in range(0, m.shape[1]):
        if (col-a)**2 + (row-b)**2 <= r**2:
            m[row,col] = 1

numpy.sum(m)
#>>> 999

下面是目标区域为100,000像素时的结果(实际生成的圆是99988.0):

您还可以编写一个例程,以使用该算法找出哪些区域可以比其他区域更紧密地匹配,并选择这些值以确保一致性。

【讨论】:

    【解决方案2】:

    圆的面积是 A=Pi*r2。您从该区域开始并且(显然)想要半径,所以我们将两边除以 Pi 得到:r2=A/pi。取双方的平方根然后给我们:r=sqrt(A/pi)。有了半径后,使用大多数常规算法进行绘制应该很简单。

    【讨论】:

      【解决方案3】:

      一个简单(但有点幼稚的方法)是简单地计算 Bresenham 算法为给定半径绘制的像素数,然后使用二分搜索找到产生所需像素数的半径。

      【讨论】:

        【解决方案4】:

        我的第一个想法是使用具有亚像素精度的算法。考虑一下如果你的中心有无理坐标并且你逐渐增加半径会发生什么。当它们被包含在圆圈中时,这将填充周边周围看似随机的像素。您希望避免导致圆的 4 个象限同时添加像素的对称性,以便更接近添加单个像素。我不知道如何实现这样的事情。

        我必须解决一次 3d 版本的单个实例。我需要球内的一组格点小于或等于 255。IIRC 如果 r*r = 15,球内有 240 个点。不过,我并不关心获得 255。

        【讨论】:

          【解决方案5】:

          假设您总共有 2000 个像素,应该构成您的完整圆圈。完整的意思是像素应该没有破损,并且必须相互连接。由于 2Pi*R = 周长,圆直径的运行长度,这是您拥有的像素总数。现在只需写 R = 2000/2*Pi,这将为您提供半径。现在您应该能够绘制一个由 2000 像素组成的圆。我希望这是你想要的。

          【讨论】:

            【解决方案6】:

            让我们暂时忘记像素,让我们学习基本的数学/几何。

            我们都知道

            圆的面积 = Pi * 半径 ^2

            和说的一样

            圆的面积 = Pi * (直径 / 2) ^2

            我们都知道

            包围圆的正方形面积(即正方形的每一边都与圆相切)= 直径 * 直径

            因此

            圆形面积与方形面积之比 = 圆形面积 / 方形面积 = (Pi * (Diameter / 2) ^2) / (Diameter * Diameter) = Pi / 4

            现在让我们假设我们有一个像素数足够大的圆形和正方形,这样我们就不必担心圆形边界周围的麻烦边缘情况。事实上,让我们假设我们有一个非常大的直径(可能是 10,000 甚至无限大)。有了这个假设,以下成立:

            圆的像素数=(正方形的像素数)*(圆面积与正方形面积的比)

            换句话说,对于足够多的像素,完美绘制的圆的面积与完美绘制的正方形的面积之比将近似于像素化圆中的像素数与封闭的像素数之比像素化正方形。

            现在在一个像素化的正方形中,该正方形中的像素数是像素数乘以高像素数。或者换句话说,它是正方形的直径(以像素为单位)的平方。我们称正方形的像素直径为d。所以用上面的公式代替我们有:

            圆中的像素数 = (d * d) * (Pi /4)

            所以现在让我们解决 d

            d = Sqrt(4 * (圆中的像素数) / Pi)

            我们之前说过 d 是正方形的直径。好吧,它也恰好是圆的直径。所以当你想画一个有一定像素数的圆时,你画一个直径为:

            圆的直径 = Sqrt(4 * (圆区域内所需的像素数) / Pi)

            现在显然您必须对舍入等做出一些选择(没有小数像素之类的东西),但您明白了。此外,随着圆区域所需像素数的增加,该公式更加准确。对于少量像素,舍入误差可能无法为您提供完全正确的像素数。

            【讨论】:

            • 我们不应该忘记像素!像素数等于面积,因为每个像素的面积为 1 平方像素。上述方法是一种非常复杂的查找直径的方法。不需要这一切,只需使用圆面积的基本公式 A =​​ pi*(2d)^2 并求解 d 甚至更简单,使用半径...
            • 你说得对——第二次看了之后——非常复杂。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2014-05-30
            • 1970-01-01
            • 1970-01-01
            • 2020-02-24
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多