We closed this forum 18 June 2010. It has served us well since 2005 as the ALPHA forum did before it from 2002 to 2005. New discussions are ongoing at the new URL http://forum.processing.org. You'll need to sign up and get a new user account. We're sorry about that inconvenience, but we think it's better in the long run. The content on this forum will remain online.
IndexProgramming Questions & HelpPrograms › Ellipse Math Help
Page Index Toggle Pages: 1
Ellipse Math Help (Read 1618 times)
Ellipse Math Help
Feb 8th, 2010, 10:13pm
 
Hi,
I'm working on a game project where I'm trying to constrain a ball to inside an ellipse, but I am having REAL trouble with the math (it's been a decade since math class).  I've spent the last few days looking at equations and code online with no luck, but much frustration, so I'm hoping someone can help me out.

What I need is one of two things:

-how to find a point on ellipse given an angle
or
-how to determine line (ray) & ellipse intersection point

I dont know if they are the same functions mathmatically or not...

Any help greatly appreciated.
thanks, tom

Code:



void setup() {
size(700,500);
frameRate(30);
 smooth();
}


void draw() {
 //ellipse variables
 float ellCX = 350;
 float ellCY = 250;
 float mjDia = 600;
 float mnDia = 400;
 

 float mx = mouseX;
 float my = mouseY;
 //angle of mouse from center
 float mouseAngle = atan2(my - ellCY, mx - ellCX );
 //distance from center
 float mouseDist = dist(ellCX, ellCY, mx, my);
 
 /*
 given the angle from the center of the ellipse,
 how do I find the intersection point on the ellipse!????
 */
 
 //draw white ball constrained to inside ellipse
 //via polar coordinates using angle
 //and  distance from center to intersection
 
 float ballx = 0;
 float bally = 0;
 //if we are too far out bring it inside
 //using ellipse minor radius for example
 //but this will be distance from center to ellispe radius
 if (mouseDist > mnDia / 2) {
   ballx = ellCX + mnDia/2 * cos(mouseAngle);
   bally = ellCY + mnDia/2 * sin(mouseAngle);
 } else {
   ballx = mx;
   bally = my;
 }
 
 /* background section */
 
 background(0,0,0);
 noFill();
 strokeWeight(2);
 stroke(255,0,0);
 ellipse(ellCX, ellCY, mjDia, mnDia);
 
 /* mouse section */
 
 line(mx, my, ellCX, ellCY);
 noStroke();
 fill(255,255,255);
 ellipse( ballx, bally,20, 20);

}//end draw


Re: Ellipse Math Help
Reply #1 - Feb 9th, 2010, 1:56am
 
An ellipse is a squashed/stretched circle.

Unit circle centred at the origin: x^2 + y^2 = 1

Canonical ellipse: (x/a)^2 + (y/b)^2 = 1
where a is the "x-radius" and b is the "y-radius".
Re: Ellipse Math Help
Reply #2 - Feb 9th, 2010, 4:15am
 
If you work in polar coordinates, you might be able to use the dist() function to test for intersection.

compare:
       the distance between the center of the ellipse and some point
and see if it is less than:
       the distance between the center of the ellipse and some point on the ellipse with a given theta

you can translate to the center of the ellipse and convert the given point to polar coordinates this way:
       float theta = acos(x/radius);
       float theta = asin(y/radius);

Once you have theta of the given point you can plug it into the equation of the ellipse and find the distance of that point.  the equation of an ellipse is:

Quote:
Circle
A circle with equation r(θ) = 1

The general equation for a circle with a center at (r0, φ) and radius a is

   r^2 - 2 r r_0 \cos(\theta - \varphi) + r_0^2 = a^2.\,

This can be simplified in various ways, to conform to more specific cases, such as the equation

   r(\theta)=a \,

for a circle with a center at the pole and radius a.[15]


more info at:
http://en.wikipedia.org/wiki/Polar_coordinate_system#Circle
Re: Ellipse Math Help
Reply #3 - Feb 9th, 2010, 8:01pm
 
There is an Ellipse Wikipedia entry that might be more useful.
Re: Ellipse Math Help
Reply #4 - Feb 10th, 2010, 12:40am
 
I appreciate the help so far, but I'm still haven't got it....

bbq9000: I'm afraid I don't understand how to use that circle formula - I can get the angle from 2 points using atan2() if that's what you were suggesting?  We're on the same page as far as methodology though.

I "plugged in" the angle from the mouse to the center of the ellipse into two equations from wikipedia ellipse page, but the line that defines the angle doesn't intersect the x/y ellipse coords derived from that angle ( run code below to see it).

I thought the section below from wiki would be worth a try, but I'm not 100% on it..  What defines X & Y (not x & y)?  Are these the major and minor radii (a & b) ?  
Quote:
Here (x,y) are the point coordinates in the canonical system, whose origin is the center (Xc,Yc) of the ellipse, whose x-axis is the unit vector (Xa,Ya) parallel to the major axis, and whose y-axis is the perpendicular vector ( − Ya,Xa) That is, x = Xa(X − Xc) + Ya(Y − Yc) and y = − Ya(X − Xc) + Xa(Y − Yc).



Code:


void setup() {
size(700,500);
frameRate(30);
 smooth();
}


void draw() {
 //ellipse variables
 float ellCX = 350;
 float ellCY = 250;
 float mjDia = 600;
 float mnDia = 400;
 //mouse variables
 float mx = mouseX;
 float my = mouseY;
 //angle of mouse from center
 float mouseAngle = atan2(my - ellCY, mx - ellCX );
 //distance from center
 float mouseDist = dist(ellCX, ellCY, mx, my);
 
//get x,y of ellipse from mouseAngle ("Canonical form" wikipedia)
//this equation is for ellipse at origin 0,0
 float ellTmpX = ((mjDia / 2) * cos(mouseAngle)) ;
 float ellTmpY = ((mnDia / 2) * sin(mouseAngle));
 //distance  from center (a^2 + b^2 = c^)
 float ellPntDist = sqrt(pow(ellTmpX,2) + pow(ellTmpY,2));
 

 float ballx = 0;
 float bally = 0;

//apply distance from ellipse above to white ball,
//but use angle read from mouse
 if (mouseDist > ellPntDist ) {
   //translating it back with polar coords
   ballx = ellCX + ellPntDist  * cos(mouseAngle);
   bally = ellCY + ellPntDist  * sin(mouseAngle);
 } else {
   ballx = mx;
   bally = my;
 }
 
 /* background section */
 
 background(0,0,0);
 noFill();
 strokeWeight(2);
 stroke(255,0,0);
 ellipse(ellCX, ellCY, mjDia, mnDia);
 
 /* mouse section */
 
 line(mx, my, ellCX, ellCY);
 noStroke();
 fill(255,255,255);
 ellipse( ballx, bally,20, 20);



/*
testing from wikipedia equations

*/

 //Parametric form in canonical position
 float testX = ((mjDia / 2) * cos(mouseAngle)) ;
 float testY = ((mnDia / 2) * sin(mouseAngle));

 //green ball
 fill(0,255,0);
 //translate back
 ellipse( ellCX + testX, ellCY + testY, 40, 40);

 //General parametric form
 //note angle between major axis and x axis = 0
 float xAxisAng = 0;
 //inverse of mouseAngle used to get correct point!?... (ball went opposite direction around ellipse)
 testX=  (mjDia / 2) * cos(-mouseAngle) * cos(xAxisAng) - (mnDia / 2) * sin(-mouseAngle) * sin(xAxisAng);
 testY=  (mjDia / 2) * cos(-mouseAngle) * sin(xAxisAng) - (mnDia / 2) * sin(-mouseAngle) * cos(xAxisAng);

 //blue ball
 fill(0,0,255);
 ellipse(ellCX + testX, ellCY + testY, 20, 20);
 
 //println(degrees(PI));
 
}//end draw


Re: Ellipse Math Help
Reply #5 - Feb 10th, 2010, 1:51am
 
mapache wrote on Feb 10th, 2010, 12:40am:
What defines X & Y (not x & y)  Are these the major and minor radii (a & b)

It seems to me that (X,Y) is "global" coordinates, for example mouse coordinates, and (x,y) is talking about your ellipse as though it were centred at the origin (0,0) with the major axis (of the ellipse) along the x-axis.

Supposing you're not using an ellipse "at an angle", this is something like:

Code:
X = mouseX;
Y = mouseY;

x = X - ellipseCentreX;
y = Y - ellipseCentreY;


since (Xa, Ya) is (1,0) [and (-Ya, Xa) is (0, 1)]
Re: Ellipse Math Help
Reply #6 - Feb 10th, 2010, 2:57am
 
mapache wrote on Feb 8th, 2010, 10:13pm:
-how to find a point on ellipse given an angle
or
-how to determine line (ray) & ellipse intersection point


In the following, assume an ellipse centred at the origin.

The "angle" you are feeding into the parametric equations,

Code:
float ellTmpX = ((mjDia / 2) * cos(mouseAngle));
float ellTmpY = ((mnDia / 2) * sin(mouseAngle));


will produce the a point on the ellipse, but a line from the origin to this point does not subtend an angle of "mouseAngle" with the x-axis. In other words, the mouse cursor will not be on the line joining the origin and this point - except in the cases where the ellipse is a circle, and for the four points of the ellipse on the x-axis and y-axis.

Try going back to the drawing board (or pen/pencil and paper!) and doing the basic maths.

Do you have an angle to start with, or do you only think you need an angle to get your answer? It seems to me the input values are are things like mouse coordinates, ellipse centre, major and minor ellipse diameters... no "angle".

You ask about determining the intersection or a "ray" and the ellipse. How are you defining your ray? You don't seem to have that yet.

I suggest looking at some variant of:

y = mx + c

That is a simple line equation (for a line that isn't vertical).

For any given x, you can calculate y to find a point on the line.

What about the ellipse? One way to draw an ellipse is to go in the direction of the x-axis and work out what the y values are.

If (x/a)^2 + (y/b)^2 = 1

then (y/b)^2 = 1 - (x/a)^2
and y/b = +- sqrt( 1 - (x/a)^2 )
so y = +- b * sqrt( 1 - (x/a)^2 )

The +- (plus or minus) comes about since there is a "top half" of the ellipse and a "bottom half"

So.. when are these equations both satisfied?

mx + c = +- b * sqrt( 1 - (x^a)^2 )

Let's say c is 0 (the line passed through the origin)

x = +- b/m * sqrt( 1 - (x/a)^2 )

x^2 = (b/m)^2 * ( 1 - (x/a)^2 )
x^2 + (b/m)^2 * ((x/a)^2) = (b/m)^2
(x^2) * (1 + (b/am)^2) = (b/m)^2
x^2 = (b/m)^2 / (1 + (b/am)^2)
x = +- (b/m) * sqrt( 1 / (1 + (b/am)^2) )

Unit circle, line y = x :
x = +- (1/1) * sqrt( 1 / (1 + (1/1)^2) )
x = +- sqrt( 1 / 2 )

I tested this quickly in code... and it worked!

Code:
/**
* spxlEllipseBoundary
* 2010-02-10 by subpixel
* http://subpixels.com
*/

// Ellipse centre
float Xc;
float Yc;

// Ellipse radii (a along x-axis, b along y-axis)
float a = 150;
float b = 80;

void setup()
{
 size(600, 400, P2D);
 Xc = width / 2;
 Yc = width / 2;
 
 ellipseMode(RADIUS);
}

void draw()
{
 // Turn mouse coordinates into ellipse-centre coordinates
 float x = mouseX - Xc;
 float y = mouseY - Yc;

 translate(Xc, Yc); // centre of ellipse
 
 background(0);

 stroke(255);
 noFill();
 ellipse(0, 0, a, b);
 
 if (x != 0)
 {
   float m = y / x; // line gradient
   
   // x = +- (b/m) * sqrt( 1 / (1 + (b/am)^2) )
   // y = mx (+c, but c == 0)

   float n1 = b / (a * m);
   float n2 = n1 * n1;
   
   float Px1 = + (b/m) * sqrt( 1 / (1 + n2) );
   float Px2 = - Px1;

   float Py1 = m * Px1;
   float Py2 = m * Px2;
   
   line (Px1, Py1, Px2, Py2);
 }
}
Re: Ellipse Math Help
Reply #7 - Feb 10th, 2010, 1:34pm
 
Hey subpixel,
I don't fully understand it all (yet), but I'll take some time and look through it some more.  I see what you are getting at:  I need to focus on the coordinates rather than the angle. This is great though - I really appreciate the example code - thanks!
tom
Re: Ellipse Math Help
Reply #8 - Feb 10th, 2010, 2:05pm
 
Problems:
  • didn't check for y == 0 (which leads to m == 0 and problems dividing by m)
  • didn't specify which end of the diameter drawn was in the direction of the mouse


Improvement:

Working demo: spxlEllipseBoundary on OpenProcessing.org

Code:
  // Determine intersection of ellipse bondary and
 // ray from ellipse centre toward mouse location
 float Px, Py;

 String desc;
 
 if (x == 0 && y == 0)
 {
   // No direction
   Px = 0;
   Py = 0;
   desc = "Centre (no line)";
 }
 else if (x == 0)
 {
   // Vertical line
   Px = 0;
   Py = (y < 0) ? -b : b;
   desc = "Vertical line";
 }
 else if (y == 0)
 {
   // Horizontal line
   Px = (x < 0) ? -a : a;
   Py = 0;
   desc = "Horizontal line";
 }
 else
 {
   // Line at some gradient
   float m = y / x;
   
   desc = "Gradient: " + y + " / " + x + " = " + m;

   // Line: y = mx + c (and c==0 since line through origin)
   // Ellipse: (x/a)^2 + (y/b)^2 = 1
   // Solve for x:
   // x = +- (b/m) * sqrt( 1 / (1 + (b/am)^2) )
   // ..then substitute back into line equation for y
   // y = mx + c (again, c == 0)

   float n1 = b / (a * m);
   float n2 = n1 * n1;
   
   // Two possible solutions; find the +ve solution
   Px = (b/m) * sqrt( 1 / (1 + n2) );

   // Make that the -ve solution if we have a -ve y value
   if (y < 0) Px = -Px;

   // Get the y value from the line equation
   Py = m * Px;
 }

Page Index Toggle Pages: 1