Flächenumring prüfen auf Überlappungen

  • VB.NET

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von Morrison.

    @jan99 Kannst Du dazu mal eine Skizze posten?
    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!
    @VB1963 Das muss der Fall sein. Denn wenn nicht lässt sich immer eine Reihenfolge finden, die keine Überlappung hat.

    @jan99 Du musst alle nichtbenachbarten Kantenpaare auf Schneidung prüfen.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()

    @jan99 Sieh Dir mal an, was Wiki zu Polygon schreibt:
    de.wikipedia.org/wiki/Polygon#Regelm%C3%A4%C3%9Figes_Polygon
    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!
    Nimm eine Physik Engine und prüf auf Kollision. Glaube das ist der einfachste weg. Da gibt es bestimmt irgend etwas fertiges um zu sehen ob sich etwas überlappt. Alternativ könntest du dein polygon in linien aufteilen also Punkt A zu B ist eine Line und Punkt B zu C und so weiter. Dann kannst du einfach prüfen ob sich diese linen miteinander überlappen.

    Edit habe hier etwas gefunden: gist.github.com/unitycoder/10241239e080720376830f84511ccd3c
    Meine Projekte Genesis Game Engine | GFX | smartli.me - Der smarte URL shortener

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

    ChatGPT sagt:

    Install-Package NetTopologySuite


    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports NetTopologySuite.Geometries
    2. Imports NetTopologySuite.Operation.Overlay
    3. Module Module1
    4. Sub Main()
    5. ' Beispiel: Umring erstellen
    6. Dim factory As New GeometryFactory()
    7. Dim polygonCoords As Coordinate() = {
    8. New Coordinate(0, 0),
    9. New Coordinate(10, 0),
    10. New Coordinate(10, 10),
    11. New Coordinate(0, 10),
    12. New Coordinate(0, 0) ' Schließt den Umring
    13. }
    14. Dim polygon As Polygon = factory.CreatePolygon(polygonCoords)
    15. ' Beispiel: Punkte innerhalb der Fläche
    16. Dim pointCoords As Coordinate() = {
    17. New Coordinate(5, 5),
    18. New Coordinate(15, 15) ' Dieser Punkt liegt außerhalb
    19. }
    20. Dim points As MultiPoint = factory.CreateMultiPoint(pointCoords)
    21. ' Überprüfung, ob Punkte im Umring liegen
    22. For Each point In points.Geometries
    23. If polygon.Contains(point) Then
    24. Console.WriteLine($"Punkt {point} liegt im Umring.")
    25. Else
    26. Console.WriteLine($"Punkt {point} liegt außerhalb des Umrings.")
    27. End If
    28. Next
    29. ' Beispiel: Zwei Flächen prüfen, ob sie sich überschneiden
    30. Dim anotherPolygonCoords As Coordinate() = {
    31. New Coordinate(5, 5),
    32. New Coordinate(15, 5),
    33. New Coordinate(15, 15),
    34. New Coordinate(5, 15),
    35. New Coordinate(5, 5)
    36. }
    37. Dim anotherPolygon As Polygon = factory.CreatePolygon(anotherPolygonCoords)
    38. If polygon.Intersects(anotherPolygon) Then
    39. Console.WriteLine("Die Flächen überschneiden sich.")
    40. Else
    41. Console.WriteLine("Die Flächen überschneiden sich nicht.")
    42. End If
    43. End Sub
    44. End Module



    Oder ohne externe Bibliothek:


    Spoiler anzeigen

    VB.NET-Quellcode

    1. Function IsPointInPolygon(polygon As List(Of PointF), point As PointF) As Boolean
    2. Dim intersects As Integer = 0
    3. Dim n As Integer = polygon.Count
    4. For i As Integer = 0 To n - 1
    5. Dim p1 As PointF = polygon(i)
    6. Dim p2 As PointF = polygon((i + 1) Mod n)
    7. ' Prüfe, ob die Linie [p1, p2] eine horizontale Linie nach rechts schneidet
    8. If (point.Y > Math.Min(p1.Y, p2.Y)) AndAlso (point.Y <= Math.Max(p1.Y, p2.Y)) AndAlso
    9. (point.X <= Math.Max(p1.X, p2.X)) Then
    10. Dim xinters As Double = (point.Y - p1.Y) * (p2.X - p1.X) / (p2.Y - p1.Y) + p1.X
    11. If p1.Y <> p2.Y AndAlso point.X <= xinters Then
    12. intersects += 1
    13. End If
    14. End If
    15. Next
    16. ' Ist die Anzahl der Schnitte ungerade, liegt der Punkt im Polygon
    17. Return (intersects Mod 2) <> 0
    18. End Function
    19. Function DoLinesIntersect(p1 As PointF, p2 As PointF, q1 As PointF, q2 As PointF) As Boolean
    20. ' Berechnung der Orientierung
    21. Dim o1 As Integer = Orientation(p1, p2, q1)
    22. Dim o2 As Integer = Orientation(p1, p2, q2)
    23. Dim o3 As Integer = Orientation(q1, q2, p1)
    24. Dim o4 As Integer = Orientation(q1, q2, p2)
    25. ' Allgemeine Überschneidung
    26. If (o1 <> o2) AndAlso (o3 <> o4) Then Return True
    27. ' Spezialfälle: Endpunkte liegen auf einer Linie
    28. If (o1 = 0 AndAlso IsOnSegment(p1, q1, p2)) Then Return True
    29. If (o2 = 0 AndAlso IsOnSegment(p1, q2, p2)) Then Return True
    30. If (o3 = 0 AndAlso IsOnSegment(q1, p1, q2)) Then Return True
    31. If (o4 = 0 AndAlso IsOnSegment(q1, p2, q2)) Then Return True
    32. Return False
    33. End Function
    34. Function Orientation(p As PointF, q As PointF, r As PointF) As Integer
    35. ' Berechnet die Orientierung von drei Punkten
    36. Dim val As Double = (q.Y - p.Y) * (r.X - q.X) - (q.X - p.X) * (r.Y - q.Y)
    37. If val = 0 Then Return 0 ' Kollinear
    38. Return If(val > 0, 1, 2) ' Uhrzeigersinn oder gegen Uhrzeigersinn
    39. End Function
    40. Function IsOnSegment(p As PointF, q As PointF, r As PointF) As Boolean
    41. Return (q.X <= Math.Max(p.X, r.X) AndAlso q.X >= Math.Min(p.X, r.X) AndAlso
    42. q.Y <= Math.Max(p.Y, r.Y) AndAlso q.Y >= Math.Min(p.Y, r.Y))
    43. End Function
    44. Function DoPolygonsIntersect(polygon1 As List(Of PointF), polygon2 As List(Of PointF)) As Boolean
    45. For i As Integer = 0 To polygon1.Count - 1
    46. Dim p1 As PointF = polygon1(i)
    47. Dim p2 As PointF = polygon1((i + 1) Mod polygon1.Count)
    48. For j As Integer = 0 To polygon2.Count - 1
    49. Dim q1 As PointF = polygon2(j)
    50. Dim q2 As PointF = polygon2((j + 1) Mod polygon2.Count)
    51. If DoLinesIntersect(p1, p2, q1, q2) Then
    52. Return True
    53. End If
    54. Next
    55. Next
    56. Return False
    57. End Function
    58. Sub Main()
    59. Dim polygon1 As New List(Of PointF) From {
    60. New PointF(0, 0),
    61. New PointF(10, 0),
    62. New PointF(10, 10),
    63. New PointF(0, 10)
    64. }
    65. Dim polygon2 As New List(Of PointF) From {
    66. New PointF(5, 5),
    67. New PointF(15, 5),
    68. New PointF(15, 15),
    69. New PointF(5, 15)
    70. }
    71. ' Prüfe Überschneidung
    72. If DoPolygonsIntersect(polygon1, polygon2) Then
    73. Console.WriteLine("Die Polygone überschneiden sich.")
    74. Else
    75. Console.WriteLine("Die Polygone überschneiden sich nicht.")
    76. End If
    77. ' Prüfe Punkt in Polygon
    78. Dim testPoint As New PointF(5, 5)
    79. If IsPointInPolygon(polygon1, testPoint) Then
    80. Console.WriteLine("Der Punkt liegt im Polygon.")
    81. Else
    82. Console.WriteLine("Der Punkt liegt außerhalb des Polygons.")
    83. End If
    84. End Sub
    85. Function HasSelfIntersections(polygon As List(Of PointF)) As Boolean
    86. Dim n As Integer = polygon.Count
    87. For i As Integer = 0 To n - 1
    88. Dim p1 As PointF = polygon(i)
    89. Dim p2 As PointF = polygon((i + 1) Mod n)
    90. For j As Integer = 0 To n - 1
    91. ' Überspringe benachbarte Kanten und dieselbe Kante
    92. If j = i OrElse j = (i + 1) Mod n OrElse (j + 1) Mod n = i Then
    93. Continue For
    94. End If
    95. Dim q1 As PointF = polygon(j)
    96. Dim q2 As PointF = polygon((j + 1) Mod n)
    97. If DoLinesIntersect(p1, p2, q1, q2) Then
    98. Return True ' Überschneidung gefunden
    99. End If
    100. Next
    101. Next
    102. Return False ' Keine Überschneidungen
    103. End Function
    104. Sub Main()
    105. Dim polygonOk As New List(Of PointF) From {
    106. New PointF(0, 0),
    107. New PointF(10, 0),
    108. New PointF(10, 10),
    109. New PointF(0, 10)
    110. }
    111. Dim polygonWrong As New List(Of PointF) From {
    112. New PointF(0, 0),
    113. New PointF(10, 0),
    114. New PointF(5, 5),
    115. New PointF(10, 10),
    116. New PointF(0, 10)
    117. }
    118. If HasSelfIntersections(polygonOk) Then
    119. Console.WriteLine("Polygon OK: Hat Selbstüberschneidungen")
    120. Else
    121. Console.WriteLine("Polygon OK: Keine Selbstüberschneidungen")
    122. End If
    123. If HasSelfIntersections(polygonWrong) Then
    124. Console.WriteLine("Polygon Falsch: Hat Selbstüberschneidungen")
    125. Else
    126. Console.WriteLine("Polygon Falsch: Keine Selbstüberschneidungen")
    127. End If
    128. End Sub





    Die hochgeladene Datei zeigt zwei Beispiele:

    Links (OK): Ein Polygon, dessen Linien sich nicht überschneiden.
    Rechts (Falsch): Ein Polygon, dessen Linien sich gegenseitig überschneiden.
    Das Problem hier ist, Selbstüberschneidungen innerhalb eines Polygons zu erkennen. Das bedeutet, dass überprüft werden muss, ob eine Linie des Polygons eine andere Linie desselben Polygons schneidet.

    Lösung ohne zusätzliche Bibliotheken
    Du kannst die Funktion DoLinesIntersect aus meinem vorherigen Vorschlag verwenden, um die Kanten des Polygons miteinander zu vergleichen.

    Algorithmus:Iteriere über jede Kante des Polygons.
    Vergleiche jede Kante mit allen anderen Kanten des Polygons.
    Überspringe benachbarte Kanten, da diese sich teilen dürfen (gemeinsamer Punkt).
    Überprüfe mit DoLinesIntersect, ob sich zwei Kanten schneiden.



    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Morrison“ ()