I have a Line Segment (x1, y1, x2, y2) intersecting a circle of radius r. How can I determine which intersection point is closest to (x1, y1)?
Asked
Active
Viewed 1.8k times
10
-
1Can you explain what you mean by the "closest intersection point" Is that a point on the circle? A point on the segment? Something not on either? – andand Apr 11 '14 at 15:29
-
4This is a basic math question and translating the solution to C# is really straight forward and does not make the question any more relevant. – Daniel Brückner Apr 11 '14 at 15:30
-
@andand Intersection point belongs to the both lines. – Dmitry Apr 11 '14 at 15:32
-
@Dmitry The OP speaks of a line segment and a circle. What is the nature of this second line to which you refer? – andand Apr 11 '14 at 15:35
-
@andand I added an image – Vali Rosca Apr 11 '14 at 15:37
-
Do you know how to find the intersection points between your line and your circle, and not know how to find which one is closer, or do you not know how to find the two intersecting points? – Servy Apr 11 '14 at 15:42
-
@Vali Thanks. The picture makes it clearer. Try looking through http://mathworld.wolfram.com/Circle-LineIntersection.html. Implement something and if you're having difficulty, post your code and describe how it's not meeting your expectations. As written, though, this question is off topic for this site. – andand Apr 11 '14 at 15:42
-
@andand Sorry, maybe in English a circle isn't a line. Maybe curve / geometric primitive / shape is a better term? Vali, Solve a system of equations and find both intersection points. – Dmitry Apr 11 '14 at 15:42
-
@Dmitry Understood. Yes in English, curve is the more general term. Lines and line segments are straight (defined in the 2D case by ax + by = c) in Euclidean Geometry. – andand Apr 11 '14 at 15:55
1 Answers
16
To do that first find the intersection points with the circle and then take the closest one to the line start point
So Check this code
//cx,cy is center point of the circle
public PointF ClosestIntersection(float cx, float cy, float radius,
PointF lineStart, PointF lineEnd)
{
PointF intersection1;
PointF intersection2;
int intersections = FindLineCircleIntersections(cx, cy, radius, lineStart, lineEnd, out intersection1, out intersection2);
if (intersections == 1)
return intersection1; // one intersection
if (intersections == 2)
{
double dist1 = Distance(intersection1, lineStart);
double dist2 = Distance(intersection2, lineStart);
if (dist1 < dist2)
return intersection1;
else
return intersection2;
}
return PointF.Empty; // no intersections at all
}
private double Distance(PointF p1, PointF p2)
{
return Math.Sqrt(Math.Pow(p2.X - p1.X, 2) + Math.Pow(p2.Y - p1.Y, 2));
}
// Find the points of intersection.
private int FindLineCircleIntersections(float cx, float cy, float radius,
PointF point1, PointF point2, out
PointF intersection1, out PointF intersection2)
{
float dx, dy, A, B, C, det, t;
dx = point2.X - point1.X;
dy = point2.Y - point1.Y;
A = dx * dx + dy * dy;
B = 2 * (dx * (point1.X - cx) + dy * (point1.Y - cy));
C = (point1.X - cx) * (point1.X - cx) + (point1.Y - cy) * (point1.Y - cy) - radius * radius;
det = B * B - 4 * A * C;
if ((A <= 0.0000001) || (det < 0))
{
// No real solutions.
intersection1 = new PointF(float.NaN, float.NaN);
intersection2 = new PointF(float.NaN, float.NaN);
return 0;
}
else if (det == 0)
{
// One solution.
t = -B / (2 * A);
intersection1 = new PointF(point1.X + t * dx, point1.Y + t * dy);
intersection2 = new PointF(float.NaN, float.NaN);
return 1;
}
else
{
// Two solutions.
t = (float)((-B + Math.Sqrt(det)) / (2 * A));
intersection1 = new PointF(point1.X + t * dx, point1.Y + t * dy);
t = (float)((-B - Math.Sqrt(det)) / (2 * A));
intersection2 = new PointF(point1.X + t * dx, point1.Y + t * dy);
return 2;
}
}
Intersection Code form here LINK
-
4The order of distances doesn't change by sqrt, therefore it's better to leave them squared for better speed. – Preza8 Jul 08 '15 at 15:35
-
Also - I'm not sure if Math.Pow is the fastest way... And it might in fact not be fastest to handle the special case of det = 0 specially, since it can cause branch mispredictions. In fact if the special case is rare, as I expect it to be, the branch misprediction will happen in the special case and might overshadow any performance gains... While adding a small amount of CPU cycles to the general case. – Jesper Nov 13 '19 at 14:33