c++ 圆和椭圆光栅化算法

8dtrkrch  于 2023-08-09  发布在  其他
关注(0)|答案(2)|浏览(143)

在我的项目中,我需要实现圆和椭圆光栅化(在C++或汇编+ SIMD,如果可能的话)。我知道中点圆算法和Bresenham圆算法。但是这些算法使用整数值(中心x、中心y和半径)。在我的例子中,半径和中心必须以浮点格式表示(或者至少是定点)。并且半径也可以小于lpx。因此,我需要一个算法,工程与浮点值。有人能帮帮我吗

w8f9ii69

w8f9ii691#

我会给予你一个圆的中点算法的基本介绍,但你可以在大多数计算机图形学教科书中找到完整的中点算法。我假设中心和半径是非整数的。从中心为 (x_c,y_c) 且半径为 R的圆的隐式方程开始:
x1c 0d1x的数据
因此,给定平面上的任何一点 (x,y),我们可以测试这个点是在圆内、圆上还是圆外。我们开始只画圆的第一个八分圆中的部分,其中 x - x_c < y_c - y。 在这种情况下,我们在每次迭代中总是在 x 方向上步进一个像素。我们将基于 (x+1,y)(x +1,y+1)之间的中点 m 的符号在 y 方向上步进0或1:

x = round(xc), y = round(yc - R);  // top of circle, y-axis pts down
m = f(x+1,y + 0.5);      // initial midpoint value
while x - cx < yc - y {  // while in first octant
    plot(x,y)            // draw point at pixel grid point (x,y)
    x = x + 1            // step in x by 1
    if m < 0             // if midpoint inside circle
        y = y + 1        // then increment y too
    m = f(x,y)           // update value at midpoint
}

字符串
剩下的主要招数有

  • 推广到所有8个八分圆以完成圆;
  • 为了提高速度,不要在每次迭代时从头开始计算 f,而是计算每个水平和对角步长的 f 的二阶差,并在每次迭代时递增地更新日期 m
  • 或者,如果你在一个具有向量支持的机器上和/或可以访问硬件 * 点积 *,那么直接计算 f 可能会非常快。
  • 如果输入值是整数,您可以缩放 m = f(x + 1,y + 0.5),使其始终是整数(我们只关心 f 的符号),并且只使用整数算术进行所有操作。
  • 要推广到轴与主轴平行的椭圆,只需将隐式方程更改为椭圆的隐式方程,并修改while-loop条件以检查 f 的梯度,从而知道何时完成了八分圆。
  • 如果你想光栅化一个有方向的椭圆,那么答案就超出了这个回答的范围:)。您可以使用椭圆的参数化形式绘制“快速和脏”椭圆,并连续调整参数步长,使步长始终在0.5和1.5之间。
u5i3ibmn

u5i3ibmn2#

根据Wikipedia的Bresenham's algorithm,它被认为是在屏幕的像素上画一个圆。
这就是为什么你可以用浮点数来计算圆的原因,把圆心放在任何非整数的地方,半径也可以是任何非整数的地方,你的圆就会被精确地画成整数像素的地方。

相关问题