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]