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
from __future__ import division
import time
import pygame.display
from math import atan2, pi
......@@ -35,6 +36,15 @@ GESTURE_UPDATE_RATE = 60
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):
"""
Calculate the Pythagorian distance between points a and b (which are (x, y)
......@@ -46,11 +56,11 @@ def distance(a, b):
return ((xb - xa) ** 2 + (yb - ya) ** 2) ** .5
def add(a, b):
"""
Add a an b, used for some functional programming calls.
"""
return a + b
def average(points):
l = len(points)
x, y = zip(*points)
return sum(x) / l, sum(y) / l
# Maximum distance between touch- and release location of a tap event
......@@ -66,6 +76,7 @@ class TouchPoint(object):
self.sid = sid
self.start_x = self.px = self.x = x
self.start_y = self.py = self.y = y
self.prev_angle = None
@property
def xy(self):
......@@ -75,7 +86,7 @@ class TouchPoint(object):
return self.x - self.px
def dy(self):
return self.y- self.py
return self.y - self.py
def update(self, x, y):
self.update_time = time.time()
......@@ -103,6 +114,22 @@ class TouchPoint(object):
def is_stationary(self):
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):
def __init__(self, verbose=0, tuio_verbose=0, **kwargs):
......@@ -123,6 +150,7 @@ class MultiTouchListener(Logger):
self.server = TuioServer2D(self, verbose=tuio_verbose)
self.angle = self.pinch = None
self.prev_pinch = None
def point_down(self, sid, x, y):
"""
......@@ -201,50 +229,26 @@ class MultiTouchListener(Logger):
if l < 2 or ('pinch' not in self.handlers \
and 'rotate' not in self.handlers):
self.set_state(None, None)
self.prev_pinch = None
return
self.calc_state()
rotation, pinch = self.state_diff()
# Get the sum of all angle differences
l = len(self.points)
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:
self.trigger(Rotate(cx, cy, rotation, l))
if pinch:
self.trigger(Pinch(cx, cy, pinch, l))
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()
if self.prev_pinch == None:
self.prev_pinch = pinch
else:
self.set_prev_state()
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
pinch -= self.prev_pinch
return da, self.distance / self.prev_distance
if pinch:
self.trigger(Pinch(cx, cy, pinch, l))
def update_centroid(self):
"""
......@@ -258,14 +262,12 @@ class MultiTouchListener(Logger):
self.centroid = -1., -1.
return
# Only use stationary points, if any
use = filter(TouchPoint.is_stationary, self.points)
self.centroid = average([p.xy for p in self.points])
if not len(use):
use = self.points
# Only use stationary points for rotational centroid, if any
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):
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