Skip to content
Snippets Groups Projects
Commit 1a11d1c4 authored by Taddeus Kroes's avatar Taddeus Kroes
Browse files

Brought rotation back to point instead of global state.

parents 6c3dfa9c 879ef48e
No related branches found
No related tags found
No related merge requests found
#!/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):
self.angle = angle
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 if pinch:
self.trigger(Pinch(cx, cy, pinch, l))
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
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment