Umdrehungen mit Hilfe von Atan2 ermitteln

  • VB.NET

Es gibt 10 Antworten in diesem Thema. Der letzte Beitrag () ist von demmy.

    Umdrehungen mit Hilfe von Atan2 ermitteln

    Hallo zusammen

    ich versuche momentan mit Hilfe der Funktion Atan2 die Anzahl an Mausumdrehungen um einen Punkt zu ermitteln. Momentan bin ich soweit, dass ich mit folgender Formeln den Winkel berechne, den die Maus um den Punkt hat.

    VB.NET-Quellcode

    1. Private Sub Knopf_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseDown
    2. ' Startwinkel der Mausposition
    3. Mauswinkel_start = Int(Math.Atan2((e.Y - Mittelpunkt.Y), (e.X - Mittelpunkt.X)) * (180 / Math.PI)) + 180
    4. End Sub
    5. Private Sub MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove
    6. Dim Mauswinkel_aktuell As Integer = Int(Math.Atan2((e.Y - Mittelpunkt.Y), (e.X - Mittelpunkt.X)) * (180 / Math.PI)) + 180
    7. Dim Mauswinkel_differenz As Integer = Mauswinkel_aktuell - Mauswinkel_start
    8. End Sub


    Ich hänge jetzt nur schon seit ein paar Tagen an dem Problem fest, eine zuverlässige Möglichkeit zu ermitteln, wie ich die Umdrehungen erfassen kann. (Den Übergang von 360° zu 0° und umgedreht). Ich habe verschiedene Wege versucht, allerdings nur mit mäßigem Erfolg.

    Einer der Versuche, war folgender: ( Im MouseMove)

    VB.NET-Quellcode

    1. If (Mauswinkel_differenz - Mauswinkel_alt) < -300 And Mauswinkel_alt <> 0 Then
    2. Umdrehungen += 1
    3. End If
    4. If (Mauswinkel_differenz - Mauswinkel_alt) > 300 And Mauswinkel_alt <> 0 Then
    5. Umdrehungen -= 1
    6. End If
    7. Mauswinkel_alt = Mauswinkel_aktuell


    Es funktioniert aber nicht immer richtig! Ich hoffe jemand hat eine Idee oder kennt einen richtigen Weg und kann mir helfen?

    Vielen Dank schon mal!
    also wenn man die Winkel-Entwicklung so verfolgt, dann werden die ja immer größer und größer, und auf einmal - blup! isser wieder 0.
    also wenn vorher eine kl Steigerung war und auf einmal! ein großer rücksprung! - dann wars wohl der Nulldurchgang.
    vlt. ist ein jeder Sprung um sagenwamal über 200° ein nulldurchgang.
    Nehm einen LongInt und die absolute Distanz. Dann lässt du das ganze auch mal negativ oder größer 360 werden. Verwendest du den Winkel für eine Rotation einfach Modulo 360. Damit du auf Dauer LongInt nicht unter- oder überschreitest auch hier mit Modulo arbeiten, aber nicht mit einem der ein Vielfaches von 360 ist.
    Interessante Frage: was ist für Dich eine 'Umdrehung' ?

    Wenn Du nur die Übergänge 0-360 Grad zählst , so kann man ja auch den Mauszeiger dazwischen hin und her bewegen -> keine Umdrehung.

    Wie wärs mit folgendem Definitionsversuch für eine Links-Umkreisung, fangen wir mal bei 0 Grad an:
    - der Mauszeiger muss sich nacheinander in den Quadranten I-IV befinden
    - der Winkel muss grösser 0 sein (damit der Kreis geschlossen wird)

    Vermutlich gibt es auch eine noch einfachere Lösung.

    @EDR: eine Umkreisung bleibt es dann auch wenn der Mauszeiger zwischendurch wieder 'zurückbewegt' wird.

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

    Kangaroo schrieb:

    so kann man ja auch den Mauszeiger dazwischen hin und her bewegen -> keine Umdrehung.
    Die Frage ist, wie überwacht wird.
    @demmy:
    Die positive x-Achse (y~0) liefert den Vorzeichenwechsel (-0 <=> +0)
    Die negative x-Achse (y~0) liefert den Vorzeichenwechsel (-Pi <=> +Pi)==(-180° <=> 180°)
    Von diesen beiden Übergängen suchst Du Dir einen aus und überwachst ihn, ich würde den (-0 <=> +0) nehmen.
    Da nicht anzunehmen ist, dass ein Mausbewegungskünstler die Maus auf der x-Achse bewegt, sollte es kein Problem geben.
    Also
    W1 > 0 AndAlso W1 < TOLERANZ
    AndAlso
    W2 < 0 AndAlso W2 < TOLERANZ
    liefert Dir den Runden-Impuls. TOLERANZ = 1 sollte reichen.
    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!
    @TE: ups - da war ich wohl bischen albern gen Abend.
    jdfs. im Ernst: Meine Einlassung zielt drauf ab, den jeweils vorherigen Winkel zu merken, und wenn der Winkelbetrag einen großen Sprung, > 180° macht, dass das der Nulldurchgang ist.
    Das kann man identifizieren, also jdfs. hab ich das mal mit einem experimentellen "IPod-Control" so gemacht.
    Ich hoffe, ich ühaupt liege richtig mit meim Problem-Verständnis, weil Umdrehungen hab ich iwie so gezählt, aber ich weiß nimmer, ob ich Atan2 verwendet hab, oder welche annere Funktion.
    Jdfs. auch Hin-Her-Bewegungen, auch über den Nulldurchgang sind so identifizierbar.
    Wäre es denn nicht einfacher, den Punkt zu überwachen, wo die Maus über die 0° bzw. 360° geführt wird? Selbst wenn jemand mit der Maus hoch und runter fährt, müsste dann ja immer eins addiert bzw. subtrahiert werden.
    Also was ich genau meine ist, die Richtung überwachen, in der die Winkel überschritten werden?

    @RodFromGermany

    Könntest du mir deine zuletzt genannte Vorgehensweise noch mal etwas genauer erklären?

    @ErfinderDesRades

    Hättest du evtl. ein kleines Beispiel wie du das damals gelöst hast?

    Eine weitere Überlegung von mir ist folgende, diese funktioniert etwas besser.

    VB.NET-Quellcode

    1. ' Umdrehungen ermitteln
    2. If Mauswinkel_alt > 300 And Mauswinkel_aktuell < 60 Then
    3. Umdrehungen += 1
    4. ElseIf Mauswinkel_alt < 60 And Mauswinkel_aktuell > 300 Then
    5. Umdrehungen -= 1
    6. End If
    7. Mauswinkel_alt = Mauswinkel_aktuell

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

    In jedem MouseMove-Ereignis bestimmst Du den aktuellen Winkel (W1) und vergleichst ihn mit dem vorherigen Winkel (W2).
    Nach dem Vergleich machst Du W2 = W1 und feddich.
    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!

    demmy schrieb:

    Hättest du evtl. ein kleines Beispiel wie du das damals gelöst hast?

    VB.NET-Quellcode

    1. Public Sub ChangeByMousePos(ByVal MousePos As Point)
    2. _MouseRel = MousePos
    3. With _LineStart 'berechnet wird vom Mittelpunkt der Textbox aus, also von _LineStart
    4. _MouseRel.Offset(-.X, -.Y)
    5. End With
    6. 'Winkel rechnen geht ja noch...
    7. Dim Angle As Double
    8. With _MouseRel
    9. _M = .X / .Y
    10. Angle = Math.Atan(_M) / (2 * Math.PI)
    11. If .Y >= 0 Then
    12. Angle += 0.5
    13. End If
    14. End With
    15. '... aber wenner überrundet
    16. Dim Delta As Double 'Unterschied zum vorherigen Input
    17. Static RevolutionCount As Integer
    18. Static _OldAngle As Double
    19. If _IsMouseInput Then
    20. Delta = Angle - _OldAngle
    21. Else
    22. Delta = 0
    23. RevolutionCount = 0
    24. _InitAngle = Angle - _Revolutions
    25. _IsMouseInput = True
    26. End If
    27. _OldAngle = Angle
    28. Select Case Delta 'Beträgt der Unterschied mehr als einen halben Vollkreis, betrachte ich das als
    29. '! einen Nulldurchgang (ne, beim Deg-Kreis kommt nach 359° aufeinmal wieder 0°)
    30. Case Is < -0.5
    31. RevolutionCount += 1
    32. Case Is > 0.5
    33. RevolutionCount -= 1
    34. End Select
    35. ChangeRevolutions(RevolutionCount + Angle - _InitAngle, Nothing)
    36. End Sub
    RevolutionCount + Angle - _InitAngle gibt die Umrundungen als Double an - also eine Revolution entspricht 360°.

    Naja - klein ist das Beispiel nicht, weil ist mal wieder meine gesamte Code-Welt drin eingebunden.
    Dateien

    RodFromGermany schrieb:

    Die Frage ist, wie überwacht wird.
    @demmy
    Die positive x-Achse (y~0) liefert den Vorzeichenwechsel (-0 <=> +0)
    Die negative x-Achse (y~0) liefert den Vorzeichenwechsel (-Pi <=> +Pi)==(-180° <=> 180°)
    Von diesen beiden Übergängen suchst Du Dir einen aus und überwachst ihn, ich würde den (-0 <=> +0) nehmen.
    Da nicht anzunehmen ist, dass ein Mausbewegungskünstler die Maus auf der x-Achse bewegt, sollte es kein Problem geben.

    Absolut bessere Lösung, insbesondere da ohne Winkelberechnung :thumbsup:

    Für einen beliebigen Anfangspunkt P überwacht man das Schneiden des Strahls von (0,0) durch P.

    demmy schrieb:

    Also was ich genau meine ist, die Richtung überwachen, in der die Winkel überschritten werden?
    Ja.

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