Einzelnen Beitrag anzeigen

Namenloser

Registriert seit: 7. Jun 2006
Ort: Karlsruhe
3.724 Beiträge
 
FreePascal / Lazarus
 
#1

Schnittpunkt Linie vs. Kreis

  Alt 25. Mär 2009, 23:12
Ich war vorhin auf der Suche nach einem Code, mit dem sich die Schnittpunkte eines Kreises und einer Linie ausrechnen lassen. Da ich für Delphi nichst gefunden habe, habe ich folgende Funktion geschrieben:
Delphi-Quellcode:
function LineHitsCircle(LineX1,LineY1,LineX2,LineY2,
  CircleX,CircleY,CircleRadius: double; out OutPos: Double): boolean;
var
  x1, x2, x: double;
  d: double;
  d_helper: double;
  m,n: double;

  tmp: double;
begin
  LineX1 := LineX1 - CircleX;
  LineY1 := LineY1 - CircleY;
  LineX2 := LineX2 - CircleX;
  LineY2 := LineY2 - CircleY;

  if (LineX2-LineX1=0) then
  begin
    if (LineY2-LineY1=0) then
    begin
      OutPos := 0.0;
      result := sqr(LineX1)+sqr(LineY1) <= sqr(CircleRadius);
      exit;
    end
    else
    begin
      tmp := LineY1;
      LineY1 := LineX1;
      LineX1 := tmp;
      
      tmp := LineY2;
      LineY2 := LineX2;
      LineX2 := tmp;
    end;
  end;

  m := (LineY2-LineY1)/(LineX2-LineX1);
  n := LineY1-m*LineX1;
  d_helper := 4*sqr(m)*sqr(n) - 4*(1+sqr(m))*(sqr(n)+2*n-sqr(CircleRadius));

  if d_helper < 0 then
  begin
    OutPos := -1;
    result := False;
  end
  else
  begin
    d := sqrt(d_helper);
    x1 := (-2*m*n - d)/(2+2*sqr(m));
    x2 := (-2*m*n + d)/(2+2*sqr(m));

    if (x1>=LineX1) and ((x1 - LineX1)<=(x2-LineX1)) then
      x := x1
    else
      x := x2;

    OutPos := abs((x-LineX1)/(LineX2-LineX1));

    result := (OutPos >= 0.0) and (OutPos <= 1.0);
  end;
end;
Sicher noch optimierbar, und gut möglich, dass es mit Vektoren irgendwie eleganter geht (das war bisher immer so ). Die Funktion gibt keinen Punkt zurück, sondern die Stelle auf der Strecke (Gleitkommazahl von 0 (Startpunkt) bis 1 (Endpunkt)), weil das für meine Zwecke praktischer ist. Man könnte aber auch sehr einfach den Punkt ausrechnen (über die lineare Funktion, m und n sind ja gegeben). Wenn es zwei Schnittpunkte gibt, wählt die Funktion den, der am nächsten beim Startpunkt liegt.
Wenn man die If-Abfragen am Ende weglässt, hat man eine Funktion, die die Schnittpunkte einer geraden und eines Kreises berechnet.

Ich hoffe, dass eine solche Funktion nicht schon gibt in der CodeLibrary existiert. Über die Suche habe ich wie gesagt nichts gefunden.

[edit]Bugfix bei senkrechter Linie[/edit]
  Mit Zitat antworten Zitat