Kollisionserkennung mit 2 GraphicsPath

  • VB.NET

Es gibt 20 Antworten in diesem Thema. Der letzte Beitrag () ist von RodFromGermany.

    Kollisionserkennung mit 2 GraphicsPath

    Hallo Leute,

    ich möchte 2 Objekte die freie Konturen sind aufeinander zu bewegen lassen und bei der Kollision soll die Bewegung unterbrochen werden und mir der X und Y Wert geliefert werden.
    Habe im iNet was mit Region erstellen gefunden.

    Die Abfrage der Kollision funktioniert leider nicht so:

    VB.NET-Quellcode

    1. Dim rgn As New Region(myPath)
    2. Dim rgn1 As New Region(myPath1)
    3. If rgn.Intersect(rgn1) = True Then
    4. Timer1.Stop()
    5. MessageBox.Show("X: " & x & " Y:" & y & "X1: " & x1 & " Y1:" & y1)
    6. End If


    Bekomme bei rgn.Intersect(rgn1) einen Fehler. ;(
    Auch wenn ich für rgn1 ---> myPath1 einfüge.

    Bitte helft mir. Wie kann ich das machen, das es funktioniert

    Hier mein kompletter Code:

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Drawing.Drawing2D
    2. Public Class Form1
    3. Dim x As Integer = 10
    4. Dim y As Integer = 10
    5. Dim x1 As Integer = 10
    6. Dim y1 As Integer = 10
    7. Private Sub Form1_Load(sender As Object, e As System.EventArgs) Handles Me.Load
    8. End Sub
    9. Private Sub Form1_Paint(sender As Object, e As System.Windows.Forms.PaintEventArgs) Handles Me.Paint
    10. Dim myPath As New GraphicsPath
    11. myPath.StartFigure()
    12. myPath.AddLine(0, 0, 0, 20)
    13. myPath.AddLine(0, 20, 20, 20)
    14. myPath.AddLine(20, 20, 20, 0)
    15. Dim translateMatrix As New Matrix
    16. translateMatrix.Translate(x, y)
    17. myPath.Transform(translateMatrix)
    18. Dim myPath1 As New GraphicsPath
    19. myPath1.StartFigure()
    20. myPath1.AddLine(100, 0, 100, 20)
    21. myPath1.AddLine(100, 20, 120, 20)
    22. myPath1.AddLine(120, 20, 120, 0)
    23. Dim translateMatrix1 As New Matrix
    24. translateMatrix1.Translate(x1, y1)
    25. myPath1.Transform(translateMatrix1)
    26. e.Graphics.DrawPath(New Pen(Color.Red, 2), myPath)
    27. e.Graphics.DrawPath(New Pen(Color.Black, 2), myPath1)
    28. Dim rgn As New Region(myPath)
    29. Dim rgn1 As New Region(myPath1)
    30. If rgn.Intersect(rgn1) = True Then
    31. Timer1.Stop()
    32. MessageBox.Show("X: " & x & " Y:" & y & "X1: " & x1 & " Y1:" & y1)
    33. End If
    34. End Sub
    35. Private Sub Timer1_Tick(sender As System.Object, e As System.EventArgs) Handles Timer1.Tick
    36. x += 1
    37. y += 1
    38. x1 -= 1
    39. y1 += 1
    40. Me.Invalidate()
    41. End Sub
    42. End Class



    Vielen Dank im vorraus

    :thumbsup:
    Vorsicht, Intersect <> IntersectsWidth! Intersect führt keine Abfrage auf Überschneidung durch, sondern bildet die Schnittmenge.
    Ich denke aber, sowohl Region alsauch GraphicsPath sind nicht das, was du suchst. Es gibt zwar IsVisible, das funktioniert aber nur mit Punkten und Rechtecken, nicht mit anderen Regions/Graphicspaths. Du musst die Kollisionserkennung also anderweitig realisieren. Ich hab schon mal ne Mathematiklib geschrieben, die pixelgenaue Kollisionserkennung für beliebige konvexe Polygone unterstützt: [OpenSource] MathUtils 2.4.2 - erweiterte Mathematikbibliothek
    Hallo Artentus,

    ich blick bei C# leider nicht durch.

    Gibt es keine "einfache" Lösung für eine Kollisionsabfrage.

    So nach dem Motto:
    Schiebe freie Konturen aus ListOf von Linien und Bögen in einen Path oder was auch immer,
    bewege sie über einen Timer aufeinander zu und wenn irgendwo eine Schnittmenge vorkommt stoppen und positionen ausgeben ?

    Danke ;)
    Du musst das ja nichtmal verstehen, ist sowieso einiges an komplizierter Mathematik involviert, da würde VB vermutlich auch nicht viel ändern. Du hast einfach zwei Polygone (die können übrigens nur aus Linien bestehen, Bögen musst du annähern), und dann kannst du sie mittelst IntersectsWidth auf Überschneidung prüfen. Dabei bekommst du auch gleich noch den MinimumTranslationVector.

    Falls es dir hilft: codeconverter.sharpdevelop.net/SnippetConverter.aspx
    Danke für Deine Antwort.

    Die Kontur enhält auch Kreisbögen... diese wird aus einem DXF File erzeugt.
    Was meinst du mit annähern?

    Ich muss praktisch ein modelliertes Werkzeug (andere Kontur) in der waagerechten auf die kontur zum abspanen bewegen und bei Kontakt soll die Bewegung stoppen und mir die Koordianten liefern.
    Beim nächst höheren Y-Wert das gleiche.
    Kannst du mir bitte einen Ansatz das ich das Prinzip verstehe geben?!

    Besten Dank im vorraus.
    Naja, ein Polygon besteht halt per Definition nur aus Ecken und geraden Kanten. Außerdem ist es mathematisch gesehen enorm schwer, runde Figuren auf Überschneidung zu prüfen.
    Mit Annähern meine ich, dass du runde Segmente aus vielen kleinen geraden Segmenten zusammensetzt. Du musst nichtmal besonders genau werden, schon ab einem vergleichsweise niedrigen Detailgrad lässt sich die Annäherung mit dem Auge nicht mehr vom ursprünglichen Bogen unterscheiden. Afaik wird das überall so gemacht, weils eben enorm viel leichter ist.

    Ich hab keine Ahnung, was du vorhast, aber wenn du zwei Polygone hast, dann prüfst du sie einfach mit bool Polygon1.IntersectsWith(Polygon2, out mvt) auf Überschneidung.
    Als Anhang ein Beispiel:

    Das rosa gefärbte ist die eine Kontur. Der Blaue Zacken ist das Werkzeug.
    Wenn eine Kollision zwischen beiden vorkommt soll wie gesagt die Simulation beendet werden und mir die X und Y Werte des sich bewegenden Werkzeugs ausgegeben werden.

    Hast du mein Vorhaben verstanden ? 8o
    Bilder
    • Cut.jpg

      5,27 kB, 276×214, 208 mal angesehen
    Ja, passt doch.
    Ich hab dir oben gezeigt, wie du zwei Polygone auf Kollision prüfen kannst. Den Rest wirst du wohl besser wissen, als ich, du kennst deinen Code am besten. Grundsätzlich gehts halt:
    Werkzeug wird bewegt -> Werkzeug auf Kollision prüfen -> Wenn Kollision vorhanden, anhalten und Koordinaten des Werkzeugs in die Ausgabe (oder wo auch immer) schreiben
    Wie gesagt, es muss nicht zu genau sein.Du hast am Computer nur ganze Pixel, wenn das Polygon also 0.1 Pixel daneben liegt, dann siehst du genau null Unterschied.

    Alternativ kannst du auch Pixelkollision ausprobieren, wenn das hier nicht funktioniert:
    [C#] [SourceCode] Pixelgenaue Kollisionserkennung mit Laufzeit O(1) Version 1.1
    Dafür musst du dir aber ne Schwarz-Weiß-Maske erstellen und büßt einiges an Performance ein, deswegen wäre sowas nur meine zweite Wahl.
    Hi,

    da mich das auch ein wenig interessiert, hab ich mal geguggt was sich da machen lässt. Es lassen sich mühelos Regionen auf Kollision prüfen, hab da auch was hinbekommen.

    VB.NET-Quellcode

    1. Imports System.Drawing.Drawing2D
    2. Public Class Form1
    3. Private GP As New GraphicsPath
    4. Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
    5. GP.AddLine(New Point(10, 10), New Point(100, 10))
    6. GP.AddLine(New Point(100, 10), New Point(10, 100))
    7. GP.AddLine(New Point(10, 100), New Point(10, 10))
    8. GP.CloseFigure()
    9. End Sub
    10. Private Sub Form1_MouseMove(sender As Object, e As MouseEventArgs) Handles Me.MouseMove
    11. Dim MRect As New Rectangle(e.X, e.Y, 1, 1)
    12. Using MPath As New GraphicsPath
    13. MPath.AddRectangle(MRect)
    14. Using MRegion As New Region(MPath)
    15. Using GpREgion As New Region(GP)
    16. MRegion.Intersect(GpREgion)
    17. If MRegion.GetRegionScans(New Matrix(1, 0, 0, 1, 0, 0)).Length > 0 Then
    18. Me.Text = MRegion.GetRegionScans(New Matrix(1, 0, 0, 1, 0, 0)).First.ToString
    19. Else
    20. Me.Text = "NO HIT"
    21. End If
    22. End Using
    23. End Using
    24. End Using
    25. End Sub
    26. Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles Me.Paint
    27. e.Graphics.FillPath(Brushes.Black, GP)
    28. End Sub
    29. End Class


    damit müsstest du dein vorhaben umsetzen können,
    mfG

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

    Jo, an sonen Hack hab ich nicht gedacht. :P
    Dir muss aber klar sein, dass ein Graphicspath (und damit auch eine daraus erstellte Region) auch einfach auf Annäherungen basiert, weil das zeug wird ja auch gerastert. Also an Genauigkeit gewinnst du damit nichts gegenüber meinen beiden Methoden, es ist aber einfacher und darauf kommt es ja an. :thumbup:

    majachen99 schrieb:

    Hast du mein Vorhaben verstanden ?
    Ist das das, was ich iwann mal "Abformung" genannt habe?
    Ein Tastschnittgerät fährt über eine rauhe Oberfläche oder so was ähnliches?
    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!
    Hallo Leute,

    erstmal nochmal Danke für die Hilfe :thumbsup:

    Mit der Lösung von @Derfuhr bin ich schon weit gekommen und er macht eigentlich optisch fast was er soll.
    Die Spitze gleitet die Kontur entlang und beim Crasht bleibt sie mit Fehlermeldung stehen.

    Die jetztige optische Lösung (über Grafische Kollision errechnen lassen) ist doch zu ungenau.
    Bei den Schnittstellen von Eement zu Element bleibt das Werkzeug auch oft stehen, obwohl da alles i.O. ist.
    - Ist Displayvergrößerungsabhängig / Maßstab / Pixel
    Wenn ich den Maßstab ändere geht er dann wieder an der gleichen Stelle durch. ?(

    Das muß ich irgendwie anders machen.
    Ich kanns mir nur so vorstellen, das ich die komplette Kontur mit Linien und Radien in 0,001mm in X und Y rastere und irgendwo in einen Speicher reinschiebe.
    Das Gleiche dann mit der Werkzeugkontur und dann irgenwie aufeinander los lasse und in der Simulation nur die berechneten Wege fahre, nur wie ? ?(

    @RodFromGermany: sowas ähnliches


    Oder fällt euch etwas besseres ein ?


    Wie immer Besten Dank für die Mühe :rolleyes: