I've been fooling around with this for a while, but can't figure it out. How can I determine if a given pixel is outside the bounds of an ellipse (not a circle) in C++ (and I'm using Allegro, if it has any math functions that'll make it easier).
Well, just use maths
A ellipse is something defined as y^2/b^2 + x^2/a^2 = 1 where a and b are the two radius of the ellipse.
Any point that causes to be y^2/b^2 + x^2/a^2 > 1 will be outside the ellipsoid, and if y^2/b^2 + x^2/a^2 < 1 the point is inside.
Well, if the ellipse is not tilted
I didn't know that formula, but as Nathe already said, using Maths it is easy to solve
. Still often those circular shaped formulas are derived from Pythagoras
na_th_an's equations (and inequalities) work for elipses centered at (0,0). It is an easy fix if it is centered at some other point (Xc,Yc):
(y - Yc)^2 / b^2 + (x - Xc)^2 / a^2 = 1.
If it is tilted you can still solve it if you know the coordinates of the center and the angle of the tilt (or two points on the a axis of the elipse). Subtract the center from the point you want to test. Rotate it by the negative angle of tilt. Then test it using na_th_an's inequalities since it will already have been translated to having the center at the origin.
This program generates a random elipse that fits on the screen, then tests the points of the screen for being inside or outside. The hardest part was making sure the elipse would fit on the screen. The testing is fairly simple. (Sorry that it is in QB. I haven't learned C)
Code:
CONST Pi = 3.14159265358979#
CONST x = 0, y = 1
DIM MxPxl(y), Cntr(y), P(y), V(y), V2(y)
MxPxl(x) = 639
MxPxl(y) = 470
SCREEN 12
'========================== Create a random elipse ======================
RANDOMIZE TIMER
Theta = (RND - .5) * Pi / 2 'Angle of a axis of the elipse to the x axis
CosTh = COS(Theta)
SinTh = SIN(Theta)
m = TAN(Theta) 'Slope of the a axis
a = 96 + RND * 144
b = 96 + RND * 144
a2 = a * a
b2 = b * b
m2 = m * m
'Set coordinates for the center of the elipse so that the elipse
'will fit on the screen
'Find the coordinates of the point on (x/a)^2+(y/b)^2=1 with
'a tangent of slope 1/m
Denom = SQR(a2 + b2 * m2)
V2(x) = a2 / Denom
V2(y) = m * b2 / Denom
'Find the x coordinate of the point rotated -Theta about the origin
V2(x) = V2(x) * CosTh + V2(y) * SinTh
'Use this to find a random x coordinate for the center
Cntr(x) = RND * (MxPxl(x) - 2 * V2(x)) + V2(x)
'Find the coordinates of the point on (x/a)^2+(y/b)^2=1 with
'a tangent of slope -m
Denom = SQR(a2 * m2 + b2)
V2(x) = a2 * m / Denom
V2(y) = b2 / Denom
'Find the absolute value of y for the point rotated Theta about the origin
V2(y) = ABS(V2(y) * CosTh + V2(x) * SinTh)
'Use this to find a random y coordinate for the center
Cntr(y) = RND * (MxPxl(y) - 2 * V2(y)) + V2(y)
'Draw the elipse
Phi = 0
DO
'Find the coordinates of a point on the elipse in normal orientation
'centered at the origin
V2(x) = a * COS(Phi)
V2(y) = b * SIN(Phi)
'Rotate the point about the origin
V(x) = V2(x) * CosTh - V2(y) * SinTh
V(y) = V2(y) * CosTh + V2(x) * SinTh
'Translate the point and plot it
PSET (V(x) + Cntr(x), V(y) + Cntr(y)), 1
'Select a new angle so that the next point is about 1 pixel away
Phi = Phi + 1 / SQR(a2 * SIN(Phi) ^ 2 + b2 * COS(Phi) ^ 2)
LOOP WHILE Phi < 2 * Pi
'========================== End of create an elipse =======================
'==================== Test points for being inside elipse =================
FOR i = 0 TO MxPxl(x)
FOR j = 0 TO MxPxl(y)
IF POINT(i, j) <> 1 THEN 'Only test points that are not on the elipse
'Translate points to centered at origin
V(x) = i - Cntr(x)
V(y) = j - Cntr(y)
'Rotate the point -Theta
V2(x) = V(x) * CosTh + V(y) * SinTh
V2(y) = V(y) * CosTh - V(x) * SinTh
'Test for being inside (x/a)^2+(y/b)^2=1
IF (V2(x) * V2(x) / a2 + V2(y) * V2(y) / b2) < 1 THEN
PSET (i, j), 4
ELSE
PSET (i, j), 2
END IF
END IF
NEXT
NEXT
SLEEP
And, in case anyone is interested, for circles, to find out if a point lies on the circle (not in, but rather on):
(x^2) +(y^2)=(r^2)
Where r is the radius.
So, if you have the radius, then:
Code:
if (x^2 + y^2 = r^2)
{
//code that runs if x and y fall directly on the circle
}
I'm not sure about the exponentiation operator in C/C++, though.
You use pow(base, exponent) in C
it's in maths.h
Anyhow, you only have squares, so it is far faster doing x*x than x^2. Optimize!
I think there is something better in allegro for fixed point math (the FIXED data type that comes soooo handy).
BTW, SCM, great maths lesson
Zack: If you pay attention, you'll realize that the circle equation is a special (yet very usable) case of the ellipse equation. As a=b, you can subsitute both by "r" and multiply twice to break the fractions, et... voila!
Nath: Heh, I didn't really look at the ellipse equation...I just thought I'd put an application to this grade 10 math I'm doing.