Mausgesten

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
schic
Beiträge: 68
Registriert: 25.12.2004 19:04

Mausgesten

Beitrag von schic »

da die mousegestures aus http://www.purebasic.fr/english/viewtop ... usegesture keine Diagonalen unterstützen, ich diese aber für eine Touchscreensteuerung gerne verwenden möchte, habe ich nach einiger Suche diesen - http://coffeeghost.net/2011/05/09/moose ... res-module - Python-Code gefunden.

Ich konnte das im Kern erfolgreich nach PureBasic übersetzen.
Falls noch jemand Diagonalen für Mausgesten benötigen sollte:

Code: Alles auswählen


;{ Disclaimer
; this code is the translation of the main-parts of the original python-code 
; to PureBasic by schic

; the original is:

; "MooseGesture 0.1" a mouse gestures recognition library.
; Al Sweigart al@coffeeghost.net
; http://coffeeghost.net/2011/05/09/moosegesture-python-mouse-gestures-module


; Where "PointsList" is a List of x, y coordinate tuples, e.g. [(100, 200), (1234, 5678), ...]
; getGesture returns a List of integers For the recognized mouse gesture. the integers
; correspond To the 8 cardinal And diagonal directions:
;
;   up-left    up   up-right
;         7    8    9
; 
;    left 4         6 right
; 
;         1    2    3
; down-left   down  down-right
 
; Copyright (c) 2011, Al Sweigart
; All rights reserved.
;
; BSD-style license:
;
; Redistribution and use in source and binary forms, with or without
; modification, are permitted provided that the following conditions are met:
;     * Redistributions of source code must retain the above copyright
;       notice, this list of conditions and the following disclaimer.
;     * Redistributions in binary form must reproduce the above copyright
;       notice, this list of conditions and the following disclaimer in the
;       documentation and/or other materials provided with the distribution.
;     * Neither the name of the MooseGesture nor the
;       names of its contributors may be used to endorse or promote products
;       derived from this software without specific prior written permission.
;
; THIS SOFTWARE IS PROVIDED BY Al Sweigart "AS IS" AND ANY
; EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
; WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
; DISCLAIMED. IN NO EVENT SHALL Al Sweigart BE LIABLE FOR ANY
; DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
; (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
; ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
; (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
; SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
;}

Structure twoInt
  int0.i
  int1.i
EndStructure

; the integers-to-directions mapping matches the keypad:
;   7 8 9
;   4   6
;   1 2 3
#DOWNLEFT  = 1
#DOWN      = 2
#DOWNRIGHT = 3
#LEFT      = 4
#RIGHT     = 6
#UPLEFT    = 7
#UP        = 8
#UPRIGHT   = 9

#NONE      = 0


; This is the minimum distance the mouse must travel (in pixels) before a
; segment will be considered for stroke interpretation.
Global _MIN_SEG_LEN = 150;60

Global Dim _strokesStrings.s(9)
_strokesStrings(1)="DownLeft":_strokesStrings(2)="Down":_strokesStrings(3)="DownRight":_strokesStrings(4)="Left"
_strokesStrings(6)="Right":_strokesStrings(7)="UpLeft":_strokesStrings(8)="Up":_strokesStrings(9)="UpRight"


Procedure getDirection(*coord1.point, *coord2.point)
  ; Return the integer of one of the 8 directions this line is going in.
  ; coord1 And coord2 are (x, y) integers coordinates.
  x1 = *coord1\x
  y1 = *coord1\y
  x2 = *coord2\x
  y2 = *coord2\y
  
  If x1 = x2 And y1 = y2
    ProcedureReturn #NONE ; two coordinates are the same.
  ElseIf x1 = x2 And y1 > y2
    ProcedureReturn #UP
  ElseIf x1 = x2 And y1 < y2
    ProcedureReturn #DOWN
  ElseIf x1 > x2 And y1 = y2
    ProcedureReturn #LEFT
  ElseIf x1 < x2 And y1 = y2
    ProcedureReturn #RIGHT
  EndIf
  
  slope.f = (y2 - y1) / (x2 - x1)
  
  ; Figure out which quadrant the line is going in, And then
  ; determine the closest direction by calculating the slope
  If x2 > x1 And y2 < y1 ; UP right quadrant
    If slope > -0.4142
      ProcedureReturn #RIGHT ; slope is between 0 And 22.5 degrees
    ElseIf slope < -2.4142
      ProcedureReturn #UP ; slope is between 67.5 And 90 degrees
    Else
      ProcedureReturn #UPRIGHT ; slope is between 22.5 And 67.5 degrees
    EndIf
  ElseIf x2 > x1 And y2 > y1 ; DOWN RIGHT quadrant
    If slope > 2.4142
      ProcedureReturn #DOWN
    ElseIf slope < 0.4142
      ProcedureReturn #RIGHT
    Else
      ProcedureReturn #DOWNRIGHT
    EndIf
  ElseIf x2 < x1 And y2 < y1 ; UP LEFT quadrant
    If slope < 0.4142
      ProcedureReturn #LEFT
    ElseIf slope > 2.4142
      ProcedureReturn #UP
    Else
      ProcedureReturn #UPLEFT
    EndIf
  ElseIf x2 < x1 And y2 > y1 ; DOWN LEFT quadrant
    If slope < -2.4142
      ProcedureReturn #DOWN
    ElseIf slope > -0.4142
      ProcedureReturn #LEFT
    Else
      ProcedureReturn #DOWNLEFT
    EndIf
  EndIf
EndProcedure

Procedure distance(*coord1.point, *coord2.point)
  xdist = *coord1\x-*coord2\x
  ydist = *coord1\y-*coord2\y
  ProcedureReturn Sqr(xdist*xdist + ydist*ydist)
EndProcedure

Procedure.s getGesture(List myPointsList.point())
  ; creates a gesture as a List of directional integers, i.e. [2,6,4] for
  ; the down-left-right gesture.
  ;
  ; the points param is a List of tuples of XY points that make up the user's
  ; mouse gesture.
  
  Protected NewList StrokesList.i()
  Protected NewList strokeSegmentsList.twoInt()
  Protected NewList DistancesList()
  
  ElementsInPointsList = ListSize(myPointsList())
  If Not ElementsInPointsList: ProcedureReturn "": EndIf
  
  FirstElement(myPointsList()) 
  Repeat
    AddElement(DistancesList())
    *thisPoint.point = @myPointsList()
    DistancesList() = distance(*thisPoint, NextElement(myPointsList()))
  Until ListIndex(myPointsList())+1 = ElementsInPointsList
  
  ; keeps getting points until we go past the min. segment length
  ; startSegPoint = 0
  ; while startSegPoint < Len(points)-1:
  ElementsInDistancesList = ListSize(DistancesList())
  FirstElement(DistancesList()) 
  For startSegPoint=0 To ElementsInPointsList-1
    segmentDist = 0
    curDir      = #NONE
    consistent  = #True
    direction   = #NONE
    For curSegPoint=startSegPoint To ElementsInDistancesList-1
      SelectElement(DistancesList(), curSegPoint)
      segmentDist = segmentDist + DistancesList()
      If segmentDist >= _MIN_SEG_LEN
        ; check if all points are going the same direction.
        SelectElement(myPointsList(), startSegPoint)
        Repeat
          *thisPoint = @myPointsList()
          direction = getDirection(*thisPoint, NextElement(myPointsList()))
          If curDir = #NONE
            curDir = direction
          ElseIf Not direction = curDir
            consistent = #False
            Break
          EndIf
        Until ListIndex(myPointsList()) = curSegPoint
        Break
      EndIf
    Next curSegPoint
    If Not consistent
      Continue
    ElseIf (Not direction=#NONE And ( (Not ListSize(StrokesList())) Or (ListSize(StrokesList()) And Not StrokesList()=direction ) ))
      AddElement(StrokesList())
      StrokesList()=direction
      AddElement(strokeSegmentsList())
      strokeSegmentsList()\int0 = startSegPoint
      strokeSegmentsList()\int1 = curSegPoint
    ElseIf ListSize(strokeSegmentsList())
      LastElement(strokeSegmentsList())
      strokeSegmentsList()\int1 = curSegPoint
    EndIf
  Next startSegPoint
  
  ; make the stroke-numbers to a human readable textlist
  If ListSize(StrokesList())
    ;Returns a String of space-delimited text characters that represent the
    ;strokes passed in. For example, "Down+Right+Left".
    thisString$ = ""
    ForEach StrokesList()
      thisString$+_strokesStrings(StrokesList())+"+"
    Next
    ProcedureReturn Trim(thisString$, "+")
  Else
    ProcedureReturn ""
  EndIf
EndProcedure



If OpenWindow(0, 100, 200, 800, 600, "Mousegesturetestwindow", #PB_Window_SystemMenu | #PB_Window_MinimizeGadget | #PB_Window_MaximizeGadget)
  
  myBackgroundGadget = CanvasGadget(#PB_Any, 0, 40, 800, 560)
  myTextGadget = TextGadget(#PB_Any, 10,10,780,20, "gesticulate with your mouse (left mousebutton pressed)")
  SetGadgetText(myTextGadget, "gesticulate with your mouse (left mousebutton pressed)")
  
  NewList PointsList.point()
  
  Repeat
    event = WaitWindowEvent()
    event_type = EventType()
    
    If event_type = #PB_EventType_LeftButtonDown
      mouseDown = #True
      ClearList(PointsList())
      gesture$ = ""
    ElseIf event_type = #PB_EventType_LeftButtonUp
      mouseDown = #False
      gesture$ = getGesture(PointsList())
      SetGadgetText(myTextGadget, "gesture: >"+gesture$+"<")
      
      rancolor = RGB(Random(255), Random(255), Random(255))
    ElseIf event_type = #PB_EventType_MouseMove And mouseDown
      AddElement(PointsList())
      PointsList()\x = WindowMouseX(0)
      PointsList()\y = WindowMouseY(0)
      
      If StartDrawing(CanvasOutput(myBackgroundGadget))
          Circle(PointsList()\x, PointsList()\y-40, 10, rancolor)
        StopDrawing()
      EndIf
    EndIf
    
    If event = #PB_Event_CloseWindow
      quit = 1
    EndIf
    
  Until quit = 1
  
EndIf
End

Update: etwas kopakter gestaltet und aufgehübscht...
Zuletzt geändert von schic am 02.02.2012 21:42, insgesamt 1-mal geändert.
Benutzeravatar
RSBasic
Admin
Beiträge: 8047
Registriert: 05.10.2006 18:55
Wohnort: Gernsbach
Kontaktdaten:

Re: Mausgesten

Beitrag von RSBasic »

@schic
Schick, funktioniert. :allright:
Ich habe vor ein paar Wochen auch sowas gebastelt, um Mausgesten zu erkennen. Da habe ich vor, dass man mit bestimmten Mausgesten bestimmte Vorgänge ausführen kann, wie z.B. Programme starten o.ä. Das Programm muss ich auch mal fertig stellen, so dass ich dieses hier vorstellen kann.
Aus privaten Gründen habe ich leider nicht mehr so viel Zeit wie früher. Bitte habt Verständnis dafür.
Bild
Bild
Antworten