Jump to content
  • Advertisement
Sign in to follow this  
Bungalow 12

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

This topic is 2776 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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);
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,

Share this post

Link to post
Share on other sites
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).

Share this post

Link to post
Share on other sites

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


Share this post

Link to post
Share on other sites
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)

Share this post

Link to post
Share on other sites
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"][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]

Share this post

Link to post
Share on other sites
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

Share this post

Link to post
Share on other sites
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.

Share this post

Link to post
Share on other sites
Sign in to follow this  

  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!