Commit 32a381b9 authored by UVA Multi-touch's avatar UVA Multi-touch

Added linear flick movement to test application.

parent 4ae31ae0
...@@ -123,7 +123,7 @@ class MovingPositionable(Positionable): ...@@ -123,7 +123,7 @@ class MovingPositionable(Positionable):
positionable. positionable.
""" """
px, py = self.prev px, py = self.prev
return self.x - px, self.y - py return Positionable(self.x - px, self.y - py)
def translation_distance(self): def translation_distance(self):
return self.distance_to(self.prev) return self.distance_to(self.prev)
......
...@@ -68,12 +68,31 @@ class DragGesture(Gesture, Positionable): ...@@ -68,12 +68,31 @@ class DragGesture(Gesture, Positionable):
return self.translation return self.translation
class FlickGesture(Gesture, Positionable):
_type = 'flick'
def __init__(self, event, initial_position, translation):
Gesture.__init__(self, event)
Positionable.__init__(self, *initial_position.get_position())
self.translation = translation
def __str__(self):
x, y = self.get_position()
tx, ty = self.translation
return '<FlickGesture at (%s, %s) translation=(%s, %s)>' \
% (x, y, tx, ty)
def get_translation(self):
return self.translation
class TransformationTracker(GestureTracker): class TransformationTracker(GestureTracker):
""" """
Tracker for linear transformations. This implementation detects rotation, Tracker for linear transformations. This implementation detects rotation,
scaling and translation using the centroid of all touch points. scaling and translation using the centroid of all touch points.
""" """
supported_gestures = [RotationGesture, PinchGesture, DragGesture] supported_gestures = [RotationGesture, PinchGesture, DragGesture,
FlickGesture]
def __init__(self, area): def __init__(self, area):
super(TransformationTracker, self).__init__(area) super(TransformationTracker, self).__init__(area)
...@@ -151,9 +170,14 @@ class TransformationTracker(GestureTracker): ...@@ -151,9 +170,14 @@ class TransformationTracker(GestureTracker):
def on_point_up(self, event): def on_point_up(self, event):
if event.point in self.points: if event.point in self.points:
self.points.remove(event.point) self.points.remove(event.point)
if not self.points:
self.trigger(FlickGesture(event, self.centroid,
self.centroid.translation()))
self.update_centroid() self.update_centroid()
event.stop_propagation() event.stop_propagation()
def invalidate_points(self): def invalidate_points(self):
""" """
Check if all points are still in the corresponding area, and remove Check if all points are still in the corresponding area, and remove
......
...@@ -5,7 +5,7 @@ from threading import Thread ...@@ -5,7 +5,7 @@ from threading import Thread
from math import pi, tan from math import pi, tan
import src as mt import src as mt
from utils import BoundingBoxArea from utils import BoundingBoxArea, Flick, FlickThread
RED = 1, 0, 0 RED = 1, 0, 0
...@@ -42,6 +42,20 @@ class Polygon(BoundingBoxArea): ...@@ -42,6 +42,20 @@ class Polygon(BoundingBoxArea):
self.on_drag(self.handle_drag) self.on_drag(self.handle_drag)
self.on_pinch(self.handle_pinch) self.on_pinch(self.handle_pinch)
self.on_rotate(self.handle_rotate) self.on_rotate(self.handle_rotate)
self.on_flick(self.handle_flick)
def flick_drag(self, amt):
tx, ty = self.flick_direction
self.translate(tx * amt, ty * amt)
refresh()
def handle_flick(self, g):
trans = g.get_translation()
print trans.distance_to((0, 0))
if trans.distance_to((0, 0)) > 10:
self.flick_direction = trans
flicks.add(Flick(self.flick_drag, 0.7, 0.4))
def handle_drag(self, g): def handle_drag(self, g):
tx, ty = g.get_translation() tx, ty = g.get_translation()
...@@ -217,7 +231,7 @@ def quit(*args): ...@@ -217,7 +231,7 @@ def quit(*args):
# Global variables # Global variables
window = cr = root = overlay = None window = cr = root = overlay = flicks = None
draw_objects = [] draw_objects = []
touch_hands = [] touch_hands = []
...@@ -247,7 +261,7 @@ def on_show(window): ...@@ -247,7 +261,7 @@ def on_show(window):
draw_objects.append(triangle) draw_objects.append(triangle)
root.add_area(triangle) root.add_area(triangle)
# Overlay catches basic events # Overlay catches finger events to be able to draw touch points
def handle_down(gesture): def handle_down(gesture):
if gesture.is_first(): if gesture.is_first():
touch_hands.append(gesture.get_hand()) touch_hands.append(gesture.get_hand())
...@@ -279,7 +293,6 @@ if __name__ == '__main__': ...@@ -279,7 +293,6 @@ if __name__ == '__main__':
fullscreen = args.fullscreen fullscreen = args.fullscreen
# Create a window with a Cairo context in it and a multi-touch area # Create a window with a Cairo context in it and a multi-touch area
# syncronized with it # syncronized with it
create_context_window(800, 600, on_show) create_context_window(800, 600, on_show)
...@@ -290,6 +303,11 @@ if __name__ == '__main__': ...@@ -290,6 +303,11 @@ if __name__ == '__main__':
mt_thread.daemon = True mt_thread.daemon = True
mt_thread.start() mt_thread.start()
# Flick movement is also handled in a separate thread
flicks = FlickThread()
flicks.daemon = True
flicks.start()
# Initialize threads in GTK so that the thread started above will work # Initialize threads in GTK so that the thread started above will work
gtk.gdk.threads_init() gtk.gdk.threads_init()
......
from __future__ import division
from time import sleep
from threading import Thread
from numpy import array, diag, dot, cos, sin from numpy import array, diag, dot, cos, sin
from src import RectangularArea from src import RectangularArea
...@@ -33,3 +37,40 @@ class BoundingBoxArea(RectangularArea): ...@@ -33,3 +37,40 @@ class BoundingBoxArea(RectangularArea):
if min_x or min_y: if min_x or min_y:
self.translate(min_x, min_y) self.translate(min_x, min_y)
self.translate_points(-min_x, -min_y) self.translate_points(-min_x, -min_y)
FLICK_UPDATE_RATE = 30
class Flick(object):
def __init__(self, callback, seconds, start_amount=1.0):
self.callback = callback
self.amount = start_amount
self.iterations = int(seconds * FLICK_UPDATE_RATE)
self.reduce_rate = start_amount / self.iterations
def iteration(self):
self.callback(self.amount)
self.amount -= self.reduce_rate
self.iterations -= 1
return self.is_not_done()
def is_not_done(self):
return self.iterations > 0
def is_done(self):
return self.iterations <= 0
class FlickThread(Thread):
def __init__(self):
super(FlickThread, self).__init__()
self.flicks = []
def run(self):
while True:
self.flicks = filter(Flick.iteration, self.flicks)
sleep(1 / FLICK_UPDATE_RATE)
def add(self, flick):
self.flicks.append(flick)
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