How do you find a normal to a point on an ellipse?

Started by
5 comments, last by haegarr 12 years, 1 month ago
Hey folks,
I hit a road block. I have been trying to find a way to get the normal to an Ellipse at a given point of intersection.
What I am aware of:
With the 2D ellipse equation being (x/a)^2 + (y/b)^2 = 1 taking the first derivative of this equation will give you the slope of the tangent line.
This must be where I am going wrong. You see I figured out that dy/dx = -((b^2 * x)/(a^2 * y)). (I'[color=#FF0000]m thinking this is wrong)

I know that once I have the slope of the tangent line I simply take the negative reciprocal (perpendicular) of that slope and I have my normal.

When using this dy/dx in my code to determine the slope I get an incorrect result:


public Vector2 GetNormalAt(Point intersection)
{
//First derivative of (X/A)^2 + (Y/B)^2 = 1

//This gives the slope of the Tangent line at the given point.
float dx = (Major * Major) * intersection.Y;
float dy = -(Minor * Minor) * intersection.X;

//Take negative reciprocal to get perpendicular slope for that of the normal
Vector2 normal = new Vector2(-dy, dx);
normal.Normalize();
return normal;
}


Unfortunately I seem to be getting nearly the same normal regardless of it's intersection point.

If I have:
A Line at: P0 = 459, 434 and P1 = 449, 454 therefore a slope of dx = -10 and dy = 20
An Ellipse at: Center = 449, 472 with a Major radius = 32 and a Minor Radius = 16
I get an intersection point = 449, 453

When I try to get the normal at this position I get <0.238, 0,971>

Now if I move the line so that the intersection point = 490, 458

My normal is now <0.249, 0.969> which definitely does nto seem right to me.

My only guess is that I did something wrong taking the first derivative yet I can't seem to find where I went wrong. Obviously math is not my strong point. :(

Does anyone have a suggestion for me that I could use or a sample snippet of code that actually properly calculates the normal to an ellipse at a given intersection point?

Thanks in advance,
Jonathan
Advertisement
I'm not sure at all, but if
f(x,y) := x[sup]2[/sup]/a[sup]2[/sup] + y[sup]2[/sup]/b[sup]2[/sup] - 1 = 0
I would have tried
( df/dx df/dy )[sup]t[/sup] = ( 2x/a[sup]2[/sup] 2y/b[sup]2[/sup] )[sup]t[/sup]
as some kind of orthogonal vector at (x,y).

once I have the slope of the tangent line I simply take the negative reciprocal (perpendicular) of that slope and I have my normal.


Don't you have to integrate it back once you're done? And include a constant offset after that. I'm a bit rusty with this, but here's my worksheet:

> x[sup]2[/sup]/a[sup]2[/sup] + y[sup]2[/sup]/b[sup]2[/sup] - 1 = 0
> 2x/a[sup]2[/sup] + (2y/b[sup]2[/sup]) * (dy/dx) = 0       // first differential
> (dy/dx) = - (x * b[sup]2[/sup]) / (y * a[sup]2[/sup])       // slope
> (dy/dx) = (y * a[sup]2[/sup]) / (x * b[sup]2[/sup])       // normal in differential form
> (dy/dx) = (pt.y * a[sup]2[/sup]) / (pt.x * b[sup]2[/sup])       // Now replace with actual intersection coordinates
> (dy/dx) = k       // The RHS is going to be a constant value now, say, k
> y = k * x + C       // integrate back to get actual line
> C = pt.y - pt.x * k       // since the intersection point also lies on the line

Hope this helps

Cheers
~dd~
Quick intuition-based solution (which may be wrong):

If you had a circle with radius a, then for a point (x, y) on the circle, the normal vector would be just (x, y) right? (divided by the length of (x, y) to get unit vector). If you compress the circle in the y direction by a factor b/a to get your elipse, i guess that the normal vector would become (x, y*(a/b)). Correct? >.<
( Rationale: I am saying this because in order for the normal vector to the circle to stay normal to the ellipse as the circle is compressed, you need to stretch the vector in the y direction as the circle is compressed in the y direction)
Thank you all for the quick replies.
Apparently I was over complicating this whole mess.
Dr_T thanks a ton. you were right. The Normal to a circle is just plainly the slope from the center to the point on the line. I do NOT know why that didn't click sooner. So as you suggested squishing the y based on the major and minor radii solved the problem and unnecessary calculations.

For anyone interested the final code was:
[font="Consolas"][size="2"][color="#0000ff"][font="Consolas"][size="2"][color="#0000ff"][font="Consolas"][size="2"][color="#0000ff"]public [/font][/font][/font][font="Consolas"][size="2"][color="#2b91af"][font="Consolas"][size="2"][color="#2b91af"][font="Consolas"][size="2"][color="#2b91af"]Vector2[/font][/font][/font][font="Consolas"][size="2"][font="Consolas"][size="2"] GetNormalAt([/font][/font][font="Consolas"][size="2"][color="#2b91af"][font="Consolas"][size="2"][color="#2b91af"][font="Consolas"][size="2"][color="#2b91af"]Point[/font][/font][/font][font="Consolas"][size="2"][font="Consolas"][size="2"] intersection)[/font][/font]
[font="Consolas"][size="2"][font="Consolas"][size="2"]{[/font][/font]
[font="Consolas"][size="2"][color="#2b91af"][font="Consolas"][size="2"][color="#2b91af"][font="Consolas"][size="2"][color="#2b91af"] Vector2[/font][/font][/font][font="Consolas"][size="2"][font="Consolas"][size="2"] normal = [/font][/font][font="Consolas"][size="2"][color="#0000ff"][font="Consolas"][size="2"][color="#0000ff"][font="Consolas"][size="2"][color="#0000ff"]new[/font][/font][/font][font="Consolas"][size="2"][font="Consolas"][size="2"] [/font][/font][font="Consolas"][size="2"][color="#2b91af"][font="Consolas"][size="2"][color="#2b91af"][font="Consolas"][size="2"][color="#2b91af"]Vector2[/font][/font][/font][font="Consolas"][size="2"][font="Consolas"][size="2"](intersection.X - Center.X, (intersection.Y - Center.Y) * (Major / Minor));[/font][/font]
[font="Consolas"][size="2"][font="Consolas"][size="2"] normal.Normalize();[/font][/font]


[font="Consolas"][size="2"][color="#0000ff"][font="Consolas"][size="2"][color="#0000ff"][font="Consolas"][size="2"][color="#0000ff"] return[/font][/font][/font][font="Consolas"][size="2"][font="Consolas"][size="2"] normal;[/font][/font]
[font="Consolas"][size="2"][font="Consolas"][size="2"]}[/font][/font]
The ellipse equation is ((x - h)/a)^2 + ((y-k)/b)^2 = 1 where (h,k) is the center of the ellipse.
So dy/dx = -((x-h)*b^2)/((y-k)*a^2)

Your equation thinks that the ellipse is centered at the origin.

haegarr's way is cool too, but it would be: (2(x-h)/a^2, 2(y-k)/b^2)

D_Tr's way: Just remember that his way (x,y) is a point on a circle with radius a, centered at the origin. If (x,y) was a point on an ellipse, centered at (h,k), then first you might convert it to a point on the circle ((x-h)*b/a,y-k), then do what he said and multiply the second coordinate by a/b: ((x-h)*b/a, (y-k)*a/b).

I'd change your code to Major^2/Minor^2
Whenever doing such a computation you have to know the space you're working in. When you explicitly consider a center (h,k) then you work in a space where the center of the ellipse is not located on the origin. On the other hand, choose the space where (h,k) = (0,0) is perfectly valid, too.

D_Tr solution, for example, goes a step further and works in a space that is build by a non-uniform scaling from the space I've chosen.

Your (John Boozer's) space also considers a simplification already (so to say). E.g. it is chosen with the ellipse being axis aligned.

In fact, subtracting (h,k) from (x,y) changes the space, as well as dividing by a or b, resp.

This topic is closed to new replies.

Advertisement