Determine where a line intersects a circle in C#

line intersects a circle

The FindLineCircleIntersections method shown shortly finds the points where line intersects a circle. It takes as parameters a circle’s center point and radius, and two points on the line. It uses out parameters to return the coordinates of the points of intersection. The method returns the number of points of intersection (0, 1, or 2).

To find the points of intersection, the code considers the line as generated by the equations:

X(t) = x1 + (x2 - x1) * t
Y(t) = y1 + (y2 - y1) * t

Where t ranges from 0 to 1 to generate the points on the line segment.

The code plugs those two equations into the following equation for a circle:

(X - Cx)2 + (Y - Cy)2 = radius2

It then solves for t by using the quadratic formula. The result is 0, 1, or 2 real values for t depending on whether the line cuts through the circle, touches it tangentially, or misses it entirely. The method plugs those values back into the equations for the line to get the points of intersection.

Here’s the FindLineCircleIntersections method.

// 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;
    }
}

Click and drag to draw the line segment. The main program uses the FindLineCircleIntersections method to find the points of intersection (if any). It then draws the segment you selected and the points of intersection. If the points don't lie on the segment, it extends the segment through the points with a dashed line.


Download Example   Follow me on Twitter   RSS feed




This entry was posted in algorithms, geometry, graphics, mathematics and tagged , , , , , , , , , , , , , , , , , . Bookmark the permalink.

3 Responses to Determine where a line intersects a circle in C#

  1. Den says:

    Thanks for your solution! It is very helpful for me.

  2. Chuck says:

    When I set breakpoints in Visual Studio on the return statements, “return 1” never executes. Even if there is logically only one intersection with the circle for a given line segment, the code returns 2 points and the display draws 2.

    • RodStephens says:

      The problem is that there is one intersection only if the segments is exactly tangent to the circle and the determinant is exactly 0. If it’s even a tiny bit off, then there are either two or zero intersections.

      It’s hard to select the points exactly to get that to happen interactively, but you can do it with code. Even then, rounding errors might not make the determinant exactly 0.

      If you want to handle a larger number of cases as single intersections, you could change the code to see if Math.Abs(det) < 0.01 or some other small cutoff value. If you do that, then the program should treat two intersections that are close together as one.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.