Ich hab das auch mal gebraucht und mir dazu ne Funktion geschrieben. Hat allerdings einige Macken:
- wenn beide Mittelpunkte den gleichen Y-Wert haben, gibt's ne Division durch 0
- wenn es keinen Schnittpunkt gibt, wird ne Wurzel aus ner negativen Zahl gezogen
Für mich hat's aber gereicht, da ich diese Fälle vorher abgefangen hab. Hier der Code mit Herleitung (wenn der Parameter Left = True ist, wird der linke Schnittpunkt zurückgeliefert, sonst der rechte (ich weiß, ist nicht so elegant, aber kannst du ja ansonsten umcoden)):
Delphi-Quellcode:
type
TExtPoint = record
X: Extended;
Y: Extended;
end;
function IntersectCircle(Center1: TExtPoint; Radius1: Extended;
Center2: TExtPoint; Radius2: Extended; Left: Boolean): TExtPoint;
var
m: Extended; // Steigung der Schnittpunktgeraden
n: Extended; // Y-Achsen-Abschnitt der Schnittpunktgeraden
p: Extended;
q: Extended;
begin
// m senkrecht auf dY / dX => m = -1 / (dY / dX) = - dX / dY
m := (Center1.X - Center2.X) / (Center2.Y - Center1.Y);
// (X - Xm)² + (Y - Ym)² - r² = 0
// n = Y, wenn X = 0 =>
// (1) Xm1² + n² - 2 * n * Ym1 + Ym1² - r1² = 0
// (2) Xm2² + n² - 2 * n * Ym2 + Ym2² - r2² = 0
// (1) - (2) Xm1² - Xm2² + Ym1² - Ym2² - r1² + r2² + 2 * n * (Ym2 - Ym1) = 0
// => n = (Xm1² + Ym1² - r1² - Xm2² - Ym2² + r2²) / 2 / (Ym1 - Ym2)
n := (Sqr(Center1.X) + Sqr(Center1.Y) - Sqr(Radius1) - Sqr(Center2.X) -
Sqr(Center2.Y) + Sqr(Radius2)) / 2 / (Center1.Y - Center2.Y);
// Y = m * X + n einsetzen in 0 = (X - Xm)² + (Y - Ym)² - r²:
// 0 = (X - Xm)² + (m * X + n - Ym)² - r²
// 0 = (m²+1) * X² + 2*(m*n-Xm-Ym*m) * X + Xm²+Ym²-r²+n²-2*Ym*n
// 0 = X² + 2*(m*n-Xm-Ym*m)/(m²-1) * X + (Xm²+Ym²-r²+n²-2*Ym*n)/(m²-1)
// p = (m*n-Xm-Ym*m)/(m²-1)
p := (m * n - Center1.X - Center1.Y * m) / (Sqr(m) + 1);
// 0 = X² + 2 * p * X + (Xm²+Ym²-r²+n²-2*Ym*n)/(m²-1)
// 0 = (X + p)² - p² + (Xm²+Ym²-r²+n²-2*Ym*n)/(m²-1)
// q = p² - (Xm²+Ym²-r²+n²-2*Ym*n)/(m²-1)
q := Sqr(p) - ((Sqr(Center1.X) + Sqr(Center1.Y) - Sqr(Radius1) + Sqr(n) -
2 * Center1.Y * n) / (Sqr(m) + 1));
// 0 = (X + p)² - q => X = - p + Sqrt(q)
// oder - p - Sqrt(q)
if Left then
Result.X := - p - Sqrt(q)
else
Result.X := - p + Sqrt(q);
// Y = m * X + n
Result.Y := m * Result.X + n;
end;