Reputation: 186
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?
Upvotes: 1
Views: 273
Reputation: 51845
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 centera,b
are the semi-axisest
is angular parameter t=<0,2*M_PI>
t
goes the full circle with some small enough step(x,y)
per each step of tas 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;
//...
}
If you need pixel perfect rendering or render filled ellipse
Then you need use different approach (the same as your equation)
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.
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)
Upvotes: 2
Reputation: 186
The implementation is correct. I set y,b,x and a as double values this fixed the wrong output.
Upvotes: -1