什么';用C实现椭圆方程的正确方法是什么?

什么';用C实现椭圆方程的正确方法是什么?,c,geometry,render,equation,ellipse,C,Geometry,Render,Equation,Ellipse,我试图在由MCU供电的绘图仪上绘制椭圆,所以内存不足,最好使用整数算法 我得到了这个等式 我尝试通过以下方式在C中实现它: y = sqrt( (b*b) * ( 1 - ( (x*x) / (a*a) ))); 其中y、b、x和a是整数值,但结果不正确 Q1这是椭圆方程的正确实现吗? Q2还有其他方法吗?实现是正确的。我将y、b、x和a设置为双值,这修复了错误的输出 绘制椭圆(用线勾勒轮廓)的参数方程是最好的。 此处轴对齐椭圆: x=x0+a*cos(t); y=y0+b*sin(t);

我试图在由MCU供电的绘图仪上绘制椭圆,所以内存不足,最好使用整数算法

我得到了这个等式

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

y = sqrt( (b*b) * ( 1 - ( (x*x) / (a*a) )));
其中
y
b
x
a
是整数值,但结果不正确

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


Q2还有其他方法吗?实现是正确的。我将y、b、x和a设置为双值,这修复了错误的输出

  • 绘制椭圆(用线勾勒轮廓)的参数方程是最好的。

    此处轴对齐椭圆:

    x=x0+a*cos(t);
    y=y0+b*sin(t);
    
    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
     }
    
    其中:

    • (x0,y0)
      是椭圆中心
    • a、b
      是半轴
    • t
      是角度参数
      t=

    • 因此,形成一个循环,其中
      t
      以足够小的步长完成整个循环
    • 计算t的每一步的
      (x,y)
    • 每一步插值/渲染线(从上一步到新点)
    由于您的
    x,y,x0,y0,a,b
    是整数,请将它们转换为浮点/双精度或为
    cos[],sin[]创建整数表,例如:

    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;
        }
    
    • inttcos[360],tsin[360]
    其中
    tcos[i]=浮点数(1000.0*cos(浮点数(i)*M_PI/180.0))现在只使用整数,如:

    for (i=0;i<360;i++)
     {
     x=x0+(a*tcos(i))/1000;
     y=y0+(b*tsin(i))/1000;
     //...
     }
    
    如果需要整数
    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;
        }
    

  • 注意:整数除法将导致截断。您可能需要转换为浮点。
    sqrt
    将返回一个双精度,为什么y必须是整数?请详细说明程序无法运行的原因,尤其是代码。不要在评论中发布代码,用代码编辑您的帖子。@ThomasMatthews不要大声喊叫。只需投票关闭并继续。注意:椭圆有一个双差分引擎实现(“Bresenham”)。不,它不是。如果你用therm乘以
    (b*b)
    项,以摆脱
    ()
    ,现在除法后你得到了一个不错的数字,那么它也可以用于整数(最初您得到的是小于
    1
    的整数
    0
    1
    )始终首先在整数的末尾进行乘法和除法。(在浮点上也是为了不降低精度)看到我的答案了吗?我为你提供了一些实现方案,其中包括你是对的,你的解决方案可能是有效的,但是我的绘图仪由一个只有几KB内存的微控制器驱动,所以我不能在绘图之前计算所有的值,因为这对更少的内存不起作用。b将始终是一个整数,因为我正在转换cm(从输入)到步骤(用于打印)。因此通常情况下,它大约在5000到1之间(如果它是0,我无论如何也不能打印椭圆)。是的,我应该在我的问题中添加此详细信息。@Mattis
    tIn,tcos
    表可以只包含几个步骤(通常情况下,对于总计768B的32位整数而言,96就足够了。
    1000
    可以是
    1024
    ,因此可以使用位移位。还有整数正弦波和余弦波近似,因此在这种情况下不需要表格。Bresenham也是一个选项,但如果需要保留像素顺序(就像绘图仪那样)如果你需要像素完美椭圆,那么#2是我能想到的唯一选择(因为你引入了额外的限制)@Mattis顺便问一下,你是如何制定运动规划的?你的MCU里有自己的插补器吗?或者每个电机都使用运动处理器?或者使用模拟控制?或者使用伺服来代替所有这些?…很高兴看到有人在这些日子里被真正的硬件弄脏了