Kollision von einem Rechteck mit einem Kreis

  • VB.NET

Es gibt 17 Antworten in diesem Thema. Der letzte Beitrag () ist von ThuCommix.

    Kollision von einem Rechteck mit einem Kreis

    Hey ich suche nach einer Möglichkeit, eine Kollision zwischen einen Rechteck und einen Kreis zu realisieren.

    Ich habe den Radius des Kreises sowie seine Position, und von den Rechteck habe ich alle vier Ecken.


    Welche Ansatz ich sehe:

    Man könnte die Position des Kreises mit einer Ecke des Rechteckes verrechnen, nun überprüfe ich, ob diese Strecke kleiner als der Radius ist, das mache ich mit allen 4 Ecken, ist nun eine kürzer, sind die beiden Objekte kollidiert, was haltet ihr davon? - Geht das so überhaupt ? - Habt ihr bessere Vorschläge?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „ThuCommix“ ()

    Hi,

    Schau mal hier rein: [VB 2010] GDI+ Kollision
    ;)

    Gruß Trade

    Edit:// Ja, ich weiß, dass es dort darum geht. Eventuell gäbe es dort einen Ansatz für dich.
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    Berechne vom Mittelpunkt des Kreises aus die Entfernungen zu den Ecken des Rechteckes und nimm die kürzeste. Ist diese dann kleiner als der Radius des Kreises, überschneiden sie sich. Kp ob das funktioniert, du kannst es aber ja mal ausprobieren :D.
    Ich habe nun folgendes Code aufgrund dieses Videos entwickelt:

    youtube.com/watch?v=Z5ykb5QtY-Y


    VB.NET-Quellcode

    1. Dim rect = DirectCast(particle1.Shape, Rectangle)
    2. Dim circle = DirectCast(particle2.Shape, Circle)
    3. 'check if the circle is in the rectangle
    4. If particle2.Position.Y < particle1.Position.Y AndAlso particle2.Position.Y > particle1.Position.Y - rect.Height AndAlso particle2.Position.X > particle1.Position.X AndAlso particle2.Position.X < particle1.Position.X + rect.Width Then
    5. Return True
    6. End If
    7. 'check if a rectangle corner is in the cirlce
    8. Dim cornerALength = particle2.Position - New Vector2(particle1.Position.X, particle1.Position.Y - rect.Height)
    9. If cornerALength.Length < circle.Radius Then
    10. Return True
    11. End If
    12. Dim cornerBLength = particle2.Position - New Vector2(particle1.Position.X + rect.Width, particle1.Position.Y - rect.Height)
    13. If cornerBLength.Length < circle.Radius Then
    14. Return True
    15. End If
    16. Dim cornerCLength = particle2.Position - New Vector2(particle1.Position.X + rect.Width, particle1.Position.Y)
    17. If cornerCLength.Length < circle.Radius Then
    18. Return True
    19. End If
    20. Dim cornerDLength = particle2.Position - particle1.Position
    21. If cornerDLength.Length < circle.Radius Then
    22. Return True
    23. End If
    24. 'check if the circle pos + radius hits a border
    25. 'upper border:
    26. If particle2.Position.X > particle1.Position.X AndAlso particle2.Position.X < particle1.Position.X + rect.Width AndAlso particle2.Position.Y > particle1.Position.Y Then
    27. Dim upperCircleLength = particle2.Position - New Vector2(0, circle.Radius)
    28. If (particle2.Position - particle1.Position).Length < upperCircleLength.Length Then
    29. Return True
    30. End If
    31. End If
    32. If particle2.Position.X > particle1.Position.X AndAlso particle2.Position.X < particle1.Position.X + rect.Width AndAlso particle2.Position.Y < particle1.Position.Y - rect.Height Then
    33. Dim bottomCircleLength = particle2.Position + New Vector2(0, circle.Radius)
    34. If (particle1.Position - particle2.Position).Length < bottomCircleLength.Length Then
    35. Return True
    36. End If
    37. End If
    38. If particle2.Position.Y < particle1.Position.Y AndAlso particle2.Position.Y > particle1.Position.Y - rect.Height AndAlso particle2.Position.X > particle1.Position.X Then
    39. Dim leftCircleLength = particle2.Position + New Vector2(circle.Radius, 0)
    40. If (particle1.Position - particle2.Position).Length < leftCircleLength.Length Then
    41. Return True
    42. End If
    43. End If
    44. If particle2.Position.Y < particle1.Position.Y AndAlso particle2.Position.Y > particle1.Position.Y - rect.Height AndAlso particle2.Position.X < particle1.Position.X Then
    45. Dim rightCircleLength = particle2.Position + New Vector2(-circle.Radius, 0)
    46. If (particle2.Position - particle1.Position).Length < rightCircleLength.Length Then
    47. Return True
    48. End If
    49. End If
    50. Return False


    Nun habe ich das Gefühl das sich doch Fehler eingeschlichen haben können.. Was denkt ihr?
    Hey,

    du hast zwar 2600 Beiträge, aber ein bisschen googlen würde dir auch nicht Schaden (Stichwörter: rectangle circle intersection).
    Das hier konnte ich auf Anhieb finden (und habe es selber so auch selber schon umgesetzt).

    MfG
    Mach es so, wie nafets es vorgeschlagen hat, nur überprüfe vorher noch auf eine Boundingbox-Intersection. Dadurch schließt du dann auch den Fall aus, dass der Kreis eine Seite berührt. Wenn dieser Test false ist, kannst du dir auch alle weiteren Überprüfungen sparen.
    Oder ein anderer Ansatz wäre es auch, den Kreis als Polygon zu betrachten, also als gleichmäßiges Vieleck mit ganz vielen Ecken, dann könntest du mit SAT rangehen.
    Fang an, das zunächst graphisch zu lösen.
    Ansatzpunkt: Wenn sich der Kreis und der Umkreis des Rechtecks überlagern, musst Du die Methoden verfeinern.
    Stichpunkte: Inkreis des Rechtecks als dichteste Position beider
    und dann die Schnittpunkte des Kreises mit den Verlängerungen der Rechteck-Seiten.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Das sieht ziemlich nach Spaghetti-Code aus ^^ Im Prinzip musst man das befolgen, was in der zweiten Antwort steht.

    e.James schrieb:


    The first pair of lines calculate the absolute values of the x and y difference between the center of the circle and the center of the rectangle. This collapses the four quadrants down into one, so that the calculations do not have to be done four times. The image shows the area in which the center of the circle must now lie. Note that only the single quadrant is shown. The rectangle is the grey area, and the red border outlines the critical area which is exactly one radius away from the edges of the rectangle. The center of the circle has to be within this red border for the intersection to occur.

    The second pair of lines eliminate the easy cases where the circle is far enough away from the rectangle (in either direction) that no intersection is possible. This corresponds to the green area in the image.

    The third pair of lines handle the easy cases where the circle is close enough to the rectangle (in either direction) that an intersection is guaranteed. This corresponds to the orange and grey sections in the image. Note that this step must be done after step 2 for the logic to make sense.

    The remaining lines calculate the difficult case where the circle may intersect the corner of the rectangle. To solve, compute the distance from the center of the circle and the corner, and then verify that the distance is not more than the radius of the circle. This calculation returns false for all circles whose center is within the red shaded area and returns true for all circles whose center is within the white shaded area


    Quelle

    Ich nehme mal an du programmierst C#.

    C-Quellcode

    1. public bool Intersects(BoundingBox box, BoundingSphere sphere)
    2. {
    3. Vector2 circleDistance = Vector2.Abs(sphere.Position - box.Bounds.Center);
    4. Vector2 boxSize = new Vector2(box.Bounds.Width, box.Bounds.Height) / 2f;
    5. if (circleDistance.X > boxSize.X + sphere.Radius ||
    6. circleDistance.Y > boxSize.Y + sphere.Radius)
    7. return false;
    8. if (circleDistance.X <= boxSize.X ||
    9. circleDistance.Y <= boxSize.Y)
    10. return true;
    11. return (circleDistance - boxSize).LengthSquared <= sphere.Radius * sphere.Radius;
    12. }


    MfG :)
    @ThuCommix: Trudi hat den StackOverflow-Thread verlinkt, den ich auch mal gefunden habe.
    Ich hab's so umgesetzt, wie in der Antwort mit 42 Punkten.
    Da kannst Du sogar herausfinden, wo genau der Ball das Rechteck trifft und davon kannst Du z.B. einen Abprallwinkel errechnen.
    Wenn es einfach nur Ja/Nein sein soll, dann reicht der Code komplett so wie er da ist.
    Die Clamp-Funktion musst Du nur noch selbst implementieren, aber die ist ganz einfach. Wenn der Wert kleiner als das Minimum ist, Minimum zurückgeben; wenn er größer als das Maximum ist, Maximum zurückgeben; ansonsten den Wert zurückgeben.
    "Luckily luh... luckily it wasn't poi-"
    -- Brady in Wonderland, 23. Februar 2015, 1:56
    Desktop Pinner | ApplicationSettings | OnUtils