none
VB.NET mit WPF: Kollisionsberechnung zweier Panels

    Frage

  • Hallo,

    ich möchte checken, ob sich zwei Panels (in WPF!) berühren. Dabei ist es auch wichtig, dass das auch bei einem (oder zwei) gedrehten Panel funktioniert.

    Vielen Dank im Voraus.


    Gruß, Bolzen PS: Ich programmiere mit VS12(Desktop) und VS10

    Mittwoch, 17. Juli 2013 11:50

Alle Antworten

  • Hi,
    mit dem VisualTreeHelper und der HitTest-Methode kannst Du so etwas lösen. Du benötigst eine Geometrie für ein Objekt und eine Funktion zur Berechnung der Überschneidung. Bei der Geometrie kannst Du eine Transformation berücksichtigen und damit auch Drehungen berücksichtigen.

    --
    Peter

    Mittwoch, 17. Juli 2013 15:11
  • Hallo Peter,

    danke für deine Antwort. Ist eine solche Geometrie dann zum Beispiel RectangleGeometry ? Kannst du mir vielleicht ein anschauliches Besipiel zeigen?


    Gruß, Bolzen PS: Ich programmiere mit VS12(Desktop) und VS10


    • Bearbeitet Bolzen Samstag, 20. Juli 2013 10:28 ....
    Samstag, 20. Juli 2013 10:28
  • Hallo,

    noch ein kleiner Zusatz. Sobald sich die Panels berühren, müssen sie in die entsprechende Richtung geblockt werden. Es ist also auch wichtig, wo die Kollision stattfindet.


    Gruß, Bolzen PS: Ich programmiere mit VS12(Desktop) in VB.NET


    • Bearbeitet Bolzen Samstag, 20. Juli 2013 14:43 ....
    Samstag, 20. Juli 2013 14:42
  • Hallo, ich kenne mich leider recht wenig mit dem VisualTreeHelper aus, weswegen ich noch einen anderen Ansatz vorschlage, welcher aber nur bedingt einfach ist.

    Bei meiner Idee musst du die Punkte von Polygon1 überprüfen, ob diese in Polygon2 liegen. Weil du dann weißt, welche Punkte im Polygon1 liegen, weißt du automatisch auch die Seite, an der die Objekte kolidierten. Alternativ könnte man auch alle Rahmenlinien miteinander abgleichen und überprüfen, wo sich die 2 Polygone schneiden.

    Die Treffer kann man ermitteln, in dem man zählt, wie oft die Rahmenlinie getroffen wird, bis man den Punkt erreicht. Ich habe damals auf dieser Seite einen Code in C# dafür gefunden. Bei mir Funktioniert dieser tadellos. Einen Konverter zwischen C# und VB.NET steht in meiner Signatur.

    Ich rede hier die ganze Zeit von Polygonen, weil ich nicht davon ausgehe, das es immer bei rechteckigen Figuren bleiben wird. Die Treffer-Funktion könnte man bei einem Viereck auch stark vereinfachen, was sich aber für die Zukunft eventuell nicht lohnt, wewegen ich hierfür auch keinen Weg zeige.


    <Code-13/>- Koopakiller [kuːpakɪllɐ] (Tom Lambert)
    Webseite | Code Beispiele | Facebook | Twitter | Snippets   C# ↔ VB.NET Konverter
    Markiert bitte beantwortende Posts als Antwort und bewertet Beiträge. Danke.

    Samstag, 20. Juli 2013 15:46
  • Hi,
    nachfolgend eine kleine Demo. Mit gedrückter Maustaste ist das grüne Rechteck zu verschieben und bei Kollision mit dem roten Rechteckt wird oben "Hit" angezeigt.

    XAML:

    <Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="500" Width="525">
      <Grid>
        <Grid.RowDefinitions>
          <RowDefinition Height="30"/>
          <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Label Name="result"/>
        <Canvas Name="cvs" Grid.Row="1">
          <Grid Name="grd1" Background="Red" Width="100" Height="100" Canvas.Left="100" Canvas.Top="100"></Grid>
          <Grid Name="grd2" Background="Green" Width="100" Height="100" Canvas.Left="-50" Canvas.Top="-50"/>
        </Canvas>
      </Grid>
    </Window>

    Und der Codebehind:

    Class MainWindow
      Private sw As Boolean = False
      Private x As Double
      Private y As Double
      Private Sub grd2_MouseDown(sender As Object, e As MouseButtonEventArgs) Handles grd2.MouseDown
        x = Canvas.GetLeft(Me.grd2) - e.GetPosition(Me.cvs).X
        y = Canvas.GetTop(Me.grd2) - e.GetPosition(Me.cvs).Y
        sw = True
      End Sub
      Private hitResultsList As New List(Of DependencyObject)
      Private Sub grd2_MouseMove(sender As Object, e As MouseEventArgs) Handles grd2.MouseMove
        If sw Then
          Canvas.SetLeft(Me.grd2, e.GetPosition(Me.cvs).X + x)
          Canvas.SetTop(Me.grd2, e.GetPosition(Me.cvs).Y + y)
          Dim rec2 As New RectangleGeometry(New Rect With {.X = Canvas.GetLeft(Me.grd2), _
                                                           .Y = Canvas.GetTop(Me.grd2), _
                                                           .Width = Me.grd2.Width, _
                                                           .Height = Me.grd2.Height})
          Me.result.Content = ""
          hitResultsList.Clear()
          VisualTreeHelper.HitTest(cvs, Nothing, New HitTestResultCallback(AddressOf HitTestres), New GeometryHitTestParameters(rec2))
          If hitResultsList.Count > 0 Then Me.result.Content = "Hit"
        End If
      End Sub
      Private Sub grd2_MouseUp(sender As Object, e As MouseButtonEventArgs) Handles grd2.MouseUp
        sw = False
      End Sub
      Private Function HitTestres(result As HitTestResult) As HitTestResultBehavior
        If result.VisualHit Is Me.grd1 Then
          hitResultsList.Add(result.VisualHit)
          Return HitTestResultBehavior.Stop
        End If
        Return HitTestResultBehavior.Continue
      End Function
    End Class

    --
    Peter
    Sonntag, 21. Juli 2013 20:40
  • Hallo Peter,

    tut mir Leid das ich verspätet antworte. Klappt alles optimal, aber wie blockier ich jetzt die Bewegung?


    Gru&#223;, Bolzen PS: Ich programmiere mit VS12(Desktop) in VB.NET

    Freitag, 26. Juli 2013 14:14
  • Hi,
    unter welchen Bedingungen soll welche Bewegung blockiert werden?

    Falls Du das MouseMove-Ereignis in meinem Programm meinst, setze einfach sw=false in dem Moment, wo blockiert wird.

    --
    Peter

    Mittwoch, 31. Juli 2013 18:47