Преглед на файлове

Some bugfixes in MultiTouchListener.

- TUIO server now has a separate verbose level.
- For practical reasons, active touch points are now stored in a list instead of a dictionary.
- Fixed AttributeError for some unitialized attributes.
UVA Multi-touch преди 14 години
родител
ревизия
9e95bdd728
променени са 1 файла, в които са добавени 42 реда и са изтрити 29 реда
  1. 42 29
      src/touch.py

+ 42 - 29
src/touch.py

@@ -3,7 +3,7 @@ import time
 from threading import Thread
 from math import atan2, pi
 
-from tuio_server import TuiListener
+from tuio_server import TuioServer2D
 from logger import Logger
 from events import TapEvent, FlickEvent, RotateEvent, PinchEvent, PanEvent
 
@@ -25,8 +25,8 @@ def add(a, b):
 class TouchPoint(object):
     def __init__(self, sid, x, y):
         self.sid = sid
-        self.x = x
-        self.y = y
+        self.px = self.x = x
+        self.py = self.y = y
 
     def update(self, x, y):
         self.px = self.x
@@ -35,7 +35,10 @@ class TouchPoint(object):
         self.y = y
 
     def distance_to(self, other_x, other_y):
-        return distance(self.x, self.y, other_x, other_y)
+        return distance((self.x, self.y), (other_x, other_y))
+
+    def distance_to_prev(self):
+        return self.distance_to(self.px, self.py)
 
     def init_gesture_data(self, cx, cy):
         self.pinch = self.old_pinch = self.distance_to(cx, cy)
@@ -62,7 +65,6 @@ class TouchPoint(object):
 # Heuristic constants
 # TODO: Encapsulate DPI resolution in distance heuristics
 SUPPORTED_GESTURES = ('tap', 'pan', 'flick', 'rotate', 'pinch')
-TUIO_ADDRESS = ('localhost', 3333)
 DOUBLE_TAP_DISTANCE_THRESHOLD = 30
 FLICK_VELOCITY_TRESHOLD = 20
 TAP_INTERVAL = .200
@@ -71,24 +73,31 @@ MAX_MULTI_DRAG_DISTANCE = 100
 
 
 class MultiTouchListener(Logger):
-    def __init__(self, verbose=0, update_rate=60, **kwargs):
+    def __init__(self, update_rate=60, verbose=0, tuio_verbose=0, **kwargs):
         super(MultiTouchListener, self).__init__(**kwargs)
         self.verbose = verbose
+        self.tuio_verbose = tuio_verbose
         self.last_tap = 0
         self.update_rate = update_rate
         self.points_changed = False
         self.handlers = {}
 
         # Session id's pointing to point coordinates
-        self.points = {}
+        self.points = []
 
         self.taps_down = []
         self.taps = []
+        self.centroid = (0, 0)
 
     def update_centroid(self):
         self.old_centroid = self.centroid
-        cx, cy = zip(*[(p.x, p.y) for p in self.points])
         l = len(self.points)
+
+        if not l:
+            self.centroid = (0, 0)
+            return
+
+        cx, cy = zip(*[(p.x, p.y) for p in self.points])
         self.centroid = (reduce(add, cx, 0) / l, reduce(add, cy, 0) / l)
 
     def analyze(self):
@@ -148,7 +157,7 @@ class MultiTouchListener(Logger):
 
             rotation += da
 
-            p.set_pinch(distance(p.x, p.y, cx, cy))
+            p.set_pinch(p.distance_to(cx, cy))
             pinch += p.pinch_diff()
 
         if rotation:
@@ -166,7 +175,8 @@ class MultiTouchListener(Logger):
         m = MAX_MULTI_DRAG_DISTANCE
         clustered = l == 1 or all([p.distance_to(*self.centroid) <= m \
                                    for p in self.points])
-        directions = [(cmp(p.dx(), 0), cmp(p.dy(), 0)) for p in self.points]
+        directions = [(cmp(p.dx(), 0), cmp(p.dy(), 0)) \
+                      for p in self.points]
 
         if any(map(all, zip(*directions))) and clustered:
             if l == 1:
@@ -180,10 +190,11 @@ class MultiTouchListener(Logger):
             self.trigger(PanEvent(cx, cy, dx, dy, l))
 
     def point_down(self, sid, x, y):
-        if sid in self.points:
-            raise KeyError('Point with session id "%s" already exists.' % sid)
+        if self.find_point(sid):
+            raise ValueError('Point with session id "%s" already exists.' % sid)
 
-        self.points[sid] = p = TouchPoint(sid, x, y)
+        p = TouchPoint(sid, x, y)
+        self.points.append(p)
         self.update_centroid()
 
         # Detect multi-point gestures
@@ -191,24 +202,32 @@ class MultiTouchListener(Logger):
             p.init_gesture_data(*self.centroid)
 
             if len(self.points) == 2:
-                first_p = self.points[0]
-                first_p.init_gesture_data(*self.centroid)
+                self.points[0].init_gesture_data(*self.centroid)
 
         self.taps_down.append(p)
         self.last_tap = time.time()
         self.points_changed = True
 
+    def find_point(self, sid, index=False):
+        for i, p in enumerate(self.points):
+            if p.sid == sid:
+                return (i, p) if index else p
+
+        if index:
+            return -1, None
+
     def point_up(self, sid):
-        if sid not in self.points:
+        i, p = self.find_point(sid, index=True)
+
+        if not p:
             raise KeyError('No point with session id "%s".' % sid)
 
-        p = self.points[sid]
-        del self.points[sid]
+        del self.points[i]
 
         # Tap/flick detection
         if p in self.taps_down:
             # Detect if Flick based on movement
-            if distance(p.x, p.y, p.px, p.py) > FLICK_VELOCITY_TRESHOLD:
+            if p.distance_to_prev() > FLICK_VELOCITY_TRESHOLD:
                 self.trigger(FlickEvent(p.px, p.py, (p.dx(), p.dy())))
             else:
                 if time.time() - self.last_tap < TAP_INTERVAL:
@@ -219,18 +238,12 @@ class MultiTouchListener(Logger):
         self.points_changed = True
 
     def point_move(self, sid, x, y):
-        self.points[sid].update(x, y)
+        self.find_point(sid).update(x, y)
         self.points_changed = True
 
-    def _tuio_handler(self, addr, tags, data, source):
-        # TODO: Call self.point_{down,up,move}
-        pass
-
     def _tuio_server(self):
-        server = OSCServer(TUIO_ADDRESS)
-        server.addDefaultHandlers()
-        server.addMsgHandler('/tuio', self._tuio_handler)
-        server.serve_forever()
+        server = TuioServer2D(self, verbose=self.tuio_verbose)
+        server.start()
 
     def start(self):
         """
@@ -275,6 +288,6 @@ if __name__ == '__main__':
     def tap(event):
         print 'tap:', event
 
-    loop = MultiTouchListener(verbose=2)
+    loop = MultiTouchListener(verbose=2, tuio_verbose=1)
     loop.bind('tap', tap)
     loop.start()