简体   繁体   中英

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

I am trying to render ellipse on plotter powered by an MCU so there is low memory to work with and integer arithmetics is preffered.

I've got this equation

椭圆方程

and I tried to implement it in C in the following way:

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

where y , b , x and a are integer values but the results where wrong .

Q1 Is this correct implementation of ellipse equation?

Q2 Are there any other ways to do this?

  1. for plotting the ellipse (outline by lines) is the parametric equation the best.

    Here axis aligned ellipse:

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

    where:

    • (x0,y0) is the ellipse center
    • a,b are the semi-axises
    • t is angular parameter t=<0,2*M_PI>

      1. So form a loop where t goes the full circle with some small enough step
      2. compute (x,y) per each step of t
      3. interpolate/render line per each step (from last to new point)

    as your x,y,x0,y0,a,b are integers either convert them to float/double or create integer table for cos[],sin[] for example:

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

    where tcos[i]=float(1000.0*cos(float(i)*M_PI/180.0)); now on use just integers like:

     for (i=0;i<360;i++) { x=x0+(a*tcos(i))/1000; y=y0+(b*tsin(i))/1000; //... } 
  2. If you need pixel perfect rendering or render filled ellipse

    Then you need use different approach (the same as your equation)

    1. loop one axis with pixel step
    2. compute the other axis coordinate
    3. render both pixels/or fill the line

    for example axis aligned (0,0) centered ellipse:

     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 } 

    if you need integer sqrt then implement one (instead of using math.h ) for example:

     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; } 

    where DWORD is unsigned 32 bit int data type.

  3. for filling you do not need the sqrt

    You can instead loop through the area and decide if the pixel is inside or not:

     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) 

The implementation is correct. I set y,b,x and a as double values this fixed the wrong output.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM