Search code examples
geometryprocessingdistanceintersectionequation

Processing: Distance of intersection between line and circle


Now, I know similar questions have been asked. But none of the answers has helped me to find the result I need.

Following situation:

We have a line with a point-of-origin (PO), given as lx, ly. We also have an angle for the line in that it exits PO, where 0° means horizontally to the right, positive degrees mean clockwise. The angle is in [0;360[. Additionally we have the length of the line, since it is not infinitely long, as len.

There is also a circle with the given center-point (CP), given as cx, cy. The radius is given as cr.

I now need a function that takes these numbers as parameters and returns the distance of the closest intersection between line and circle to the PO, or -1 if no intersection occures.

My current approach is a follows:

float getDistance(float lx, float ly, float angle, float len, float cx, float cy, float cr) {
  float nlx = lx - cx;
  float nly = ly - cy;
  float m   = tan(angle);
  float b   = (-lx) * m;

  // a = m^2 + 1
  // b = 2 * m * b
  // c = b^2 - cr^2
  float[] x_12 = quadraticFormula(sq(m) + 1, 2*m*b, sq(b) - sq(cr));

  // if no intersections
  if (Float.isNaN(x_12[0]) && Float.isNaN(x_12[1]))
    return -1;

  float distance;
  if (Float.isNaN(x_12[0])) {
    distance = (x_12[1] - nlx) / cos(angle);
  } else {
    distance = (x_12[0] - nlx) / cos(angle);
  }

  if (distance <= len) {
    return distance;
  }

  return -1;
}

// solves for x
float[] quadraticFormula(float a, float b, float c) {
  float[] results = new float[2];
  results[0] = (-b + sqrt(sq(b) - 4 * a * c)) / (2*a);
  results[1] = (-b - sqrt(sq(b) - 4 * a * c)) / (2*a);
  return results;
}

But the result is not as wished. Sometimes I do get a distance returned, but that is rarely correct, there often isn't even an intersection occuring. Most of the time no intersection is returned though, although there should be one.

Any help would be much appreciated.

EDIT:

I managed to find the solution thanks to MBo's answer. Here is the content of my finished getDistance(...)-function - maybe somebody can be helped by it:

float nlx = lx - cx;
float nly = ly - cy;

float dx = cos(angle);
float dy = sin(angle);

float[] results = quadraticFormula(1, 2*(nlx*dx + nly*dy), sq(nlx)+sq(nly)-sq(cr));

float dist = -1;

if (results[0] >= 0 && results[0] <= len)
  dist = results[0];  
if (results[1] >= 0 && results[1] <= len && results[1] < results[0])
  dist = results[1];

return dist;

Solution

  • Using your nlx, nly, we can build parametric equation of line segment

    dx = Cos(angle)
    dy = Sin(Angle)
    x = nlx + t * dx
    y = nly + t * dy
    

    Condition of intersection with circumference:

    (nlx + t * dx)^2 + (nly + t * dy)^2 = cr^2
    t^2 * (dx^2 + dy^2) + t * (2*nlx*dx + 2*nly*dy) +  nlx^2+nly^2-cr^2 = 0
    

    so we have quadratic equation for unknown parameter t with

    a = 1
    b = 2*(nlx*dx + nly*dy)
    c = nlx^2+nly^2-cr^2
    

    solve quadratic equation, find whether t lies in range 0..len.