在 C 中实现椭圆方程的正确方法是什么?

What's the correct way to implement the ellipse equation in C?

我正在尝试在由 MCU 驱动的绘图仪上渲染椭圆,因此可使用的内存不足,并且首选整数算法。

我有这个等式

并且我尝试通过以下方式在 C 中实现它:

y = sqrt( (b*b) * ( 1 - ( (x*x) / (a*a) )));

其中 ybxa 是整数值,但结果是错误的。

Q1 这是椭圆方程的正确实现吗?

Q2 还有其他方法吗?

执行正确。我将 y、b、x 和 a 设置为双精度值,这修复了错误的输出。

  1. 画椭圆(用线勾勒)最好是参数方程

    这里轴对齐的椭圆:

    x=x0+a*cos(t);
    y=y0+b*sin(t);
    

    其中:

    • (x0,y0)是椭圆中心
    • a,b是半轴
    • t 是 angular 参数 t=<0,2*M_PI>

      1. 因此形成一个循环,其中 t 以足够小的步长完成整个循环
      2. 在 t
      3. 的每个步骤中计算 (x,y) 每一步
      4. interpolate/render 行(从最后一点到新点)

    因为您的 x,y,x0,y0,a,b 是整数,请将它们转换为 float/double 或为 cos[],sin[] 创建整数 table 例如:

    • int tcos[360],tsin[360];

    其中 tcos[i]=float(1000.0*cos(float(i)*M_PI/180.0)); 现在只使用整数,例如:

    for (i=0;i<360;i++)
     {
     x=x0+(a*tcos(i))/1000;
     y=y0+(b*tsin(i))/1000;
     //...
     }
    
  2. 如果您需要像素完美渲染或渲染填充椭圆

    那么你需要使用不同的方法(与你的等式相同)

    1. 以像素步长循环一个轴
    2. 计算另一个轴坐标
    3. 渲染两者 pixels/or 填充行

    例如轴对齐 (0,0) 中心椭圆:

    for (x=-a;x<=a;x++)
     {
     y = sqrt( (b*b) - ( (x*x*b*b) / (a*a) )));
     // render pixels: (x,+y) and (x,-y) or join them by line
     }
    

    如果你需要整数 sqrt 然后实现一个(而不是使用 math.h)例如:

    int bits(DWORD p)
        {
        DWORD m=0x80000000; int b=32;
        for (;m;m>>=1,b--)
         if (p>=m) break;
        return b;
        }
    
    DWORD sqrt(const DWORD &x)
        {
        DWORD m,a;
        m=(bits(x)>>1); // bits(x) just return position of MSB nonzero bit can use m=16; instead
        if (m) m=1<<m; else m=1;
        for (a=0;m;m>>=1) { a|=m; if (a*a>x) a^=m; }
        return a;
        }
    

    其中 DWORD 是无符号 32 位 int 数据类型。

  3. 填充不需要sqrt

    您可以改为遍历该区域并确定像素是否在内部:

    for (y=-b;y<=b;y++)
     for (x=-a;x<=a;x++)
      if ( (y*y) <= ( (b*b) - ( (x*x*b*b) / (a*a) ) ) )
       // render pixel: (x,y)