Qbasicnews.com

Full Version: Determine if outside the bounds of an ellipse in C++...
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
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 Smile

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 Tongue
I didn't know that formula, but as Nathe already said, using Maths it is easy to solve Smile. Still often those circular shaped formulas are derived from Pythagoras Wink
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 Smile it's in maths.h
Anyhow, you only have squares, so it is far faster doing x*x than x^2. Optimize! Wink

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 Smile

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! Smile
also x ** y
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.
Thanks na_th_an.