Commit 1a11d1c4 authored by Taddeus Kroes's avatar Taddeus Kroes

Brought rotation back to point instead of global state.

parents 6c3dfa9c 879ef48e
#!/usr/bin/env python #!/usr/bin/env python
from __future__ import division
import time import time
import pygame.display import pygame.display
from math import atan2, pi from math import atan2, pi
...@@ -35,6 +36,15 @@ GESTURE_UPDATE_RATE = 60 ...@@ -35,6 +36,15 @@ GESTURE_UPDATE_RATE = 60
DIST_THRESHOLD = 1. / max(screen_size) DIST_THRESHOLD = 1. / max(screen_size)
def angle_mod(angle):
if angle > pi:
angle -= 2 * pi
elif angle < -pi:
angle += 2 * pi
return angle
def distance(a, b): def distance(a, b):
""" """
Calculate the Pythagorian distance between points a and b (which are (x, y) Calculate the Pythagorian distance between points a and b (which are (x, y)
...@@ -46,11 +56,11 @@ def distance(a, b): ...@@ -46,11 +56,11 @@ def distance(a, b):
return ((xb - xa) ** 2 + (yb - ya) ** 2) ** .5 return ((xb - xa) ** 2 + (yb - ya) ** 2) ** .5
def add(a, b): def average(points):
""" l = len(points)
Add a an b, used for some functional programming calls. x, y = zip(*points)
"""
return a + b return sum(x) / l, sum(y) / l
# Maximum distance between touch- and release location of a tap event # Maximum distance between touch- and release location of a tap event
...@@ -66,6 +76,7 @@ class TouchPoint(object): ...@@ -66,6 +76,7 @@ class TouchPoint(object):
self.sid = sid self.sid = sid
self.start_x = self.px = self.x = x self.start_x = self.px = self.x = x
self.start_y = self.py = self.y = y self.start_y = self.py = self.y = y
self.prev_angle = None
@property @property
def xy(self): def xy(self):
...@@ -75,7 +86,7 @@ class TouchPoint(object): ...@@ -75,7 +86,7 @@ class TouchPoint(object):
return self.x - self.px return self.x - self.px
def dy(self): def dy(self):
return self.y- self.py return self.y - self.py
def update(self, x, y): def update(self, x, y):
self.update_time = time.time() self.update_time = time.time()
...@@ -103,6 +114,22 @@ class TouchPoint(object): ...@@ -103,6 +114,22 @@ class TouchPoint(object):
def is_stationary(self): def is_stationary(self):
return self.distance_to_prev() < DIST_THRESHOLD return self.distance_to_prev() < DIST_THRESHOLD
def angle_diff(self, cx, cy):
angle = atan2(cy - self.y, self.x - cx)
if self.prev_angle == None:
delta = 0
elif self.prev_angle > 0 and angle < 0:
delta = -2 * pi - angle + self.prev_angle
elif self.prev_angle < 0 and angle > 0:
delta = 2 * pi - angle + self.prev_angle
else:
delta = angle - self.prev_angle
self.prev_angle = angle
return delta
class MultiTouchListener(Logger): class MultiTouchListener(Logger):
def __init__(self, verbose=0, tuio_verbose=0, **kwargs): def __init__(self, verbose=0, tuio_verbose=0, **kwargs):
...@@ -123,6 +150,7 @@ class MultiTouchListener(Logger): ...@@ -123,6 +150,7 @@ class MultiTouchListener(Logger):
self.server = TuioServer2D(self, verbose=tuio_verbose) self.server = TuioServer2D(self, verbose=tuio_verbose)
self.angle = self.pinch = None self.angle = self.pinch = None
self.prev_pinch = None
def point_down(self, sid, x, y): def point_down(self, sid, x, y):
""" """
...@@ -201,50 +229,26 @@ class MultiTouchListener(Logger): ...@@ -201,50 +229,26 @@ class MultiTouchListener(Logger):
if l < 2 or ('pinch' not in self.handlers \ if l < 2 or ('pinch' not in self.handlers \
and 'rotate' not in self.handlers): and 'rotate' not in self.handlers):
self.set_state(None, None) self.prev_pinch = None
return return
self.calc_state() # Get the sum of all angle differences
rotation, pinch = self.state_diff() l = len(self.points)
cx, cy = self.centroid cx, cy = self.centroid
#rcx, rcy = self.rot_centroid
rotation = sum([p.angle_diff(cx, cy) for p in self.points]) / l
pinch = sum([p.distance(cx, cy) for p in self.points]) / l
if rotation: if rotation:
self.trigger(Rotate(cx, cy, rotation, l)) self.trigger(Rotate(cx, cy, rotation, l))
if pinch: if self.prev_pinch == None:
self.trigger(Pinch(cx, cy, pinch, l)) self.prev_pinch = pinch
def calc_state(self):
l = len(self.points)
cx, cy = self.centroid
angle = reduce(add, [p.angle(cx, cy) for p in self.points]) / l
distance = reduce(add, [p.distance(cx, cy) for p in self.points]) / l
if self.angle == None:
self.set_state(angle, distance)
self.set_prev_state()
else: else:
self.set_prev_state() pinch -= self.prev_pinch
self.set_state(angle, distance)
def set_state(self, angle, distance): if pinch:
self.angle = angle self.trigger(Pinch(cx, cy, pinch, l))
self.distance = distance
def set_prev_state(self):
self.prev_angle = self.angle
self.prev_distance = self.distance
def state_diff(self):
da = self.angle - self.prev_angle
# Assert that angle is in [-pi, pi]
#if da > pi:
# da %= 2 * pi
#elif da < -pi:
# da %= -2 * pi
return da, self.distance / self.prev_distance
def update_centroid(self): def update_centroid(self):
""" """
...@@ -258,14 +262,12 @@ class MultiTouchListener(Logger): ...@@ -258,14 +262,12 @@ class MultiTouchListener(Logger):
self.centroid = -1., -1. self.centroid = -1., -1.
return return
# Only use stationary points, if any self.centroid = average([p.xy for p in self.points])
use = filter(TouchPoint.is_stationary, self.points)
if not len(use): # Only use stationary points for rotational centroid, if any
use = self.points stat = [p.xy for p in filter(TouchPoint.is_stationary, self.points)]
self.rot_centroid = average(stat) if stat else self.centroid
cx, cy = zip(*[(p.x, p.y) for p in use])
self.centroid = reduce(add, cx, 0) / l, reduce(add, cy, 0) / l
def centroid_movement(self): def centroid_movement(self):
cx, cy = self.centroid cx, cy = self.centroid
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment