2014-04-11 3 views
5

Ich habe ein Liniensegment (x1, y1, x2, y2), die einen Kreis mit dem Radius r schneiden. Wie kann ich feststellen, welcher Schnittpunkt am nächsten ist (x1, y1)?Liniensegment und Kreisschnittpunkt

circle-line

+1

Können Sie erklären, was Sie mit dem "nächsten Schnittpunkt" meinen. Ist das ein Punkt auf dem Kreis? Ein Punkt auf dem Segment? Irgendwas nicht? – andand

+4

Dies ist eine grundlegende mathematische Frage und die Übersetzung der Lösung in C# ist wirklich geradlinig und macht die Frage nicht relevanter. –

+0

@andand Schnittpunkt gehört zu den beiden Linien. – Dmitry

Antwort

7

Um das zu tun zuerst die Schnittpunkte mit dem Kreis finden und dann die nächste zu der Linie Startpunkt nehmen

diesem Code

// cx So prüfen, ist cy Zentrum des Kreises

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

Überschneidung-Code Form hier LINK

+1

Die Reihenfolge der Abstände ändert sich nicht um sqrt, daher ist es besser, sie für eine bessere Geschwindigkeit im Quadrat zu belassen. – Preza8

Verwandte Themen