it-swarm.com.de

Wie erkenne ich Schnittpunkte zwischen einem Kreis und einem anderen Kreis in derselben Ebene?

Ich suche nach einem Algorithmus, um festzustellen, ob sich ein Kreis mit einem anderen Kreis in derselben Ebene schneidet (vorausgesetzt, es können mehr als ein Kreis in einer Ebene sein).

Eine Methode, die ich gefunden habe, ist den Trennachentest durchzuführen. Es sagt:

Zwei Objekte überschneiden sich nicht, wenn Sie eine Linie finden, die die beiden Objekte voneinander trennt, d. H. Eine Linie, bei der sich alle Objekte oder Punkte eines Objekts auf verschiedenen Seiten der Linie befinden.

Ich weiß jedoch nicht, wie ich diese Methode auf meinen Fall anwenden kann.

Kann mir jemand helfen?

33
Jean-Luc Godard

Zwei Kreise schneiden sich nur dann, wenn der Abstand zwischen ihren Mittelpunkten zwischen der Summe und der Differenz ihrer Radien liegt. Bei zwei Kreisen (x0, y0, R0) und (x1, y1, R1) lautet die Formel wie folgt:

ABS(R0 - R1) <= SQRT((x0 - x1)^2 + (y0 - y1)^2) <= (R0 + R1)

Durch das Quadrieren beider Seiten können Sie die langsame SQRT vermeiden und bei ints bleiben, wenn Ihre Eingaben ganze Zahlen sind:

(R0 - R1)^2 <= (x0 - x1)^2 + (y0 - y1)^2 <= (R0 + R1)^2

Da Sie nur einen Ja/Nein-Test benötigen, ist diese Prüfung schneller als die Berechnung der genauen Schnittpunkte.

Die obige Lösung sollte auch für den Fall "Ein Kreis im anderen" funktionieren.

63
dasblinkenlight

Angenommen, der Schnitt eines gefüllten Kreises (dh ein Kreis in einem anderen ist ein Schnittpunkt).

Woher:

  • x0, y0, r0 = Mittelpunkt und Radius des Kreises 0.
  • x1, y1, r1 = Mittelpunkt und Radius von Kreis 1.

Code:

boolean intersects = Math.hypot(x0-x1, y0-y1) <= (r0 + r1);
6
Craigo

XNA/C # -Lösung

    class Circle
    {
        public Vector2 Center;
        public float Radius;

        public bool Intersects(Circle circle)
        {
            float distanceX = Center.X - circle.Center.X;
            float distanceY = Center.Y - circle.Center.Y;
            float radiusSum = circle.Radius + Radius;
            return distanceX * distanceX + distanceY * distanceY <= radiusSum * radiusSum;
        }
        public bool Contains(Circle circle)
        {
            if (circle.Radius > Radius)
                return false;
            float distanceX = Center.X - circle.Center.X;
            float distanceY = Center.Y - circle.Center.Y;
            float radiusD = Radius - circle.Radius;
            return distanceX * distanceX + distanceY * distanceY <= radiusD * radiusD;
        }
    }

Beachten Sie, dass die Methode Circle.Intersects () true zurückgibt, auch wenn sich ein Kreis in einem anderen befindet (behandelt sie als "gefüllte" Kreise).

4
Peter Gruden

Wenn der Abstand zwischen den Mittelpunkten zweier Kreise höchstens die Summe ihrer Radien ist, mindestens jedoch der absolute Wert der Differenz zwischen den Radien, dann schneiden sich die Kreise selbst irgendwann.

Der Teil "zumindest der Unterschied" gilt, wenn Sie sich nur für die Kreise selbst interessieren und nicht für ihre inneren Bereiche. Wenn es Ihnen wichtig ist, ob die Kreise oder die Bereiche, die sie einschließen Punkte teilen - das heißt, wenn ein Kreis innerhalb des anderen als "sich kreuzend" gilt, dann können Sie das "mindestens die Differenz" löschen prüfen.

2
cHao

Ich habe die hier gegebene Formel ausprobiert, die eine vermeintliche Antwort ist, und jeder stimmte auf, obwohl er ernsthaft fehlerhaft war. Ich habe in JavaFX ein Programm geschrieben, mit dem der Benutzer testen kann, ob zwei Kreise sich schneiden, indem er die Kreise centerX, centerY und Radius ändert. Diese Formel funktioniert absolut nicht, außer auf eine Weise ... Ich kann nicht herausfinden, warum, aber wann Kreis 2 in der Nähe von Kreis 1 bewegen funktioniert zwar, aber wenn ich Kreis 1 auf die andere Seite in der Nähe von Kreis 2 schiebe, funktioniert es nicht ..... ????? Das ist ein bisschen seltsam ... Ich dachte, die Formel müsste in die entgegengesetzte Richtung getestet werden, also probiert es aus und es funktioniert nicht

if (Math.abs(circle1Radius - circle2Radius) <=
            Math.sqrt(Math.pow((circle1X - circle2X), 2)
            + Math.pow((circle1Y - circle2Y), 2)) &&
            Math.sqrt(Math.pow((circle1X - circle2X), 2)
            + Math.pow((circle1X - circle2Y), 2)) <=
            (circle1Radius + circle2Radius)} {
    return true;
} else {
    return false;
}

Das funktioniert:

    // dx and dy are the vertical and horizontal distances
    double dx = circle2X - circle1X;
    double dy = circle2Y - circle1Y;

    // Determine the straight-line distance between centers.
    double d = Math.sqrt((dy * dy) + (dx * dx));

    // Check Intersections
    if (d > (circle1Radius + circle2Radius)) {
        // No Solution. Circles do not intersect
        return false;
    } else if (d < Math.abs(circle1Radius - circle2Radius)) {
        // No Solution. one circle is contained in the other
        return false;
    } else {
        return true;
    }

Hier geht es zur Formel Schnittpunkt zweier Kreise

Die verwendete Formel ist nicht meine Formel. Alle Kredit geht an Paul Bourke (April 1997).

 First calculate the distance d between the center of the circles. d = ||P1 - P0||.

    If d > r0 + r1 then there are no solutions, the circles are separate.

    If d < |r0 - r1| then there are no solutions because one circle is contained within the other.

    If d = 0 and r0 = r1 then the circles are coincident and there are an infinite number of solutions.

Considering the two triangles P0P2P3 and P1P2P3 we can write

a2 + h2 = r02 and b2 + h2 = r12

Using d = a + b we can solve for a,

a = (r02 - r12 + d2 ) / (2 d)

It can be readily shown that this reduces to r0 when the two circles touch at one point, ie: d = r0 + r1

Solve for h by substituting a into the first equation, h2 = r02 - a2
So

P2 = P0 + a ( P1 - P0 ) / d

And finally, P3 = (x3,y3) in terms of P0 = (x0,y0), P1 = (x1,y1) and P2 = (x2,y2), is

x3 = x2 +- h ( y1 - y0 ) / d

y3 = y2 -+ h ( x1 - x0 ) / d 
0
John Conner