- Home /
Calculating an arc of on ellipse from an internally offset point
Hey everyone,
I've been struggling a bit with an issue dealing with calculating the arcs of an ellipse. In the attached image you'll see a rectangle surrounded by an ellipse. The ellipse and rectangle share the same center, but both are divided into four quadrants. I am trying to come up with a formula that describes the ellipse's four corresponding arcs, drawn from a point that is offset from the center of the two shapes. I don't have any issues dealing with a circular shape instead of an ellipse as long as the arcs originate in the center instead of being offset. Surely there is some formula out there for drawing an ellipse from any point inside the ellipse? All my searches have come up with just drawing a regular ellipse offset from 0,0, NOT from a point offset internally.
The whole reason for this is to be able to draw a section of shielding around a ship that corresponds to the quadrant it is in.
Answer by Bunny83 · Aug 03, 2021 at 05:51 PM
Sorry but I really do not grasp what you're asking here. What do you mean by calculating "the arcs of an ellipse"? Are you looking for the arc lengths? However how do you actually split up the ellipse? Note that there is no neat equation to calculate the circumference of an ellipse.
I'm also not sure what you mean by "four corresponding arcs, drawn from a point that is offset from the center". To me it's totally unclear what you're actually looking for in terms of numbers, coordinates, lengths, .... One one hand you want to some how start at an arbitrary point inside your ellipse, on the other hand you want to start at the center. When you talk about quadrants, do you actually mean sectors that are 90° apart from each other? Or do you have something else in mind?
edit
Ok since it's now more clear what you want, here's an example how to calculate what you want. First of all, here's the result visually:
Note the magenta lines are your original lines which are defined by the angles at the left. The "center" is the origin of your lines / rays. The actual center of the ellipse is (0, 0) indicated by the cyan lines. The yellow crosses are the intersection points on the squished ellipse / circle while the green crosses are the intersection point transformed back to the ellipse.
Here's the script I quickly hacked together ^^
using UnityEngine;
public class EllipseCalc : MonoBehaviour
{
public float a = 6;
public float b = 4;
public float angB = 42.5f;
public float angR = 137.5f;
public float angF = 222.5f;
public float angL = 317.5f;
public Vector2 center = new Vector2(-2,0);
public int count = 360;
void Update()
{
// draw ellipse
var lastPos = new Vector2(a, 0);
for(int i = 1; i <= count; i++)
{
float ang = i*Mathf.PI*2f / count;
float s = Mathf.Sin(ang);
float c = Mathf.Cos(ang);
var p = new Vector2(c * a, s * b);
Debug.DrawLine(lastPos, p);
lastPos = p;
}
CalcLine(center, angB);
CalcLine(center, angR);
CalcLine(center, angF);
CalcLine(center, angL);
// draw circle
lastPos = new Vector2(b, 0);
for (int i = 1; i <= count; i++)
{
float ang = i * Mathf.PI * 2f / count;
float s = Mathf.Sin(ang);
float c = Mathf.Cos(ang);
var p = new Vector2(c * b, s * b);
Debug.DrawLine(lastPos, p);
lastPos = p;
}
// draw origin
Debug.DrawLine(Vector3.up * 10, -Vector3.up * 10, Color.cyan);
Debug.DrawLine(Vector3.right * 10, -Vector3.right * 10, Color.cyan);
}
Vector2 DrawLine(Vector2 aCenter, float aAng, Color aColor)
{
aAng *= Mathf.Deg2Rad;
float s = Mathf.Sin(aAng);
float c = Mathf.Cos(aAng);
var p = new Vector2(c, s);
Debug.DrawLine(aCenter, aCenter + p * 20, aColor);
return p;
}
float CalcLine(Vector2 aCenter, float aAng)
{
var d = DrawLine(aCenter, aAng, Color.magenta);
d.x *= b / a;
aCenter.x *= b / a;
Debug.DrawLine(aCenter, aCenter + d * 20);
if (IntersectLineCircle(aCenter, d, Vector2.zero, b, out float t))
{
var p = aCenter + d * t;
Debug.DrawLine(p - Vector2.right, p + Vector2.right, Color.yellow);
Debug.DrawLine(p - Vector2.up, p + Vector2.up, Color.yellow);
p.x *= a / b;
Debug.DrawLine(p - Vector2.right, p + Vector2.right, Color.green);
Debug.DrawLine(p - Vector2.up, p + Vector2.up, Color.green);
float newAng = Mathf.Atan2(p.y, p.x);
return newAng;
}
return 0f;
}
public static bool IntersectLineCircle(Vector3 aStart, Vector3 aDir, Vector3 aCenter, float aRadius, out float aT)
{
aT = float.NaN;
var dist = aStart - aCenter;
float a = aDir.sqrMagnitude;
float b = 2 * Vector3.Dot(dist, aDir);
float c = dist.sqrMagnitude - aRadius*aRadius;
float d = b * b - 4 * a * c;
if (d < 0)
return false;
d = Mathf.Sqrt(d);
//float t1 = (-b - d) / (2 * a);
float t2 = (-b + d) / (2 * a);
if (t2 < 0)
return false;
aT = t2;
return true;
}
}
Hi @Bunny83,
Yeah my apologies for not making things clear. What I am trying to do is surround my ship with an ellipse representing its shields. The ship is divided into four different zones (Front, Left, Right, Rear). Each zone has a firing arc (in degrees). The point from which each zone is calculated is offset from the center of the ship. I know the degrees of each arc, the length/width of the ship, and the major/$$anonymous$$or axis lengths of the ellipse.
Want I want is to calculate the points that represent the segment of the shield perimeter based on each zone and its arc. This way when the ship takes damage I can adjust just that section of the shield in some visual way to show that it has been weakened.
Ok just to sum up:
You know the major and $$anonymous$$or axis (size of the ellipse)
You know the point from which your lines originate and you also know the angles.
What you want / need are the actual required angles as seen from the center to reach those same intersection points?
If that's the case, yes, that's possible though it requires a bit of transformation. The first step would be to "unsquish" the ellipse back to a circle. That means your origin point would move closer to the actual center. Next you would need to adjust the angles of your "rays" accordingly. It's essentially just an aspect ratio adjustment in order to get the whole thing into a circle. Once you have done this you can simply use a line / sphere intersection in order to calculate the intersection points on the circle boundary. Once you have them you can just undo the squishing and you're essentially done. I'll update my answer with an example.
Hey @Bunny83,
Thanks for the help - your code, particularly the function IntersectLineCircle(), led me on a path to figure out a slightly different approach to this. I actually wound up calculating an entire ellipse around the center of the ship when the script first loads, giving me a universe of ellipse points. From there, I used an equation to calculate the ellipse intersects from the offset center of the arcs for each zone, then deter$$anonymous$$ing which set of points in the ellipse belonged to which hull/shield zone based on the the points x/y values:
Your answer
Follow this Question
Related Questions
Smooth out cylinder? 4 Answers
Unity 'auto import' of 3DSMax file - can you 'tag' mesh to be unrecognized? 0 Answers
A way to turn texture into geometry in unity? 2 Answers
Using a height map to distort a subdivided plane. 1 Answer
How to see geometry 1 Answer