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):
positionable.
"""
px, py = self.prev
return self.x - px, self.y - py
return Positionable(self.x - px, self.y - py)
def translation_distance(self):
return self.distance_to(self.prev)
......
......@@ -68,12 +68,31 @@ class DragGesture(Gesture, Positionable):
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):
"""
Tracker for linear transformations. This implementation detects rotation,
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):
super(TransformationTracker, self).__init__(area)
......@@ -151,9 +170,14 @@ class TransformationTracker(GestureTracker):
def on_point_up(self, event):
if event.point in self.points:
self.points.remove(event.point)
if not self.points:
self.trigger(FlickGesture(event, self.centroid,
self.centroid.translation()))
self.update_centroid()
event.stop_propagation()
def invalidate_points(self):
"""
Check if all points are still in the corresponding area, and remove
......
......@@ -5,7 +5,7 @@ from threading import Thread
from math import pi, tan
import src as mt
from utils import BoundingBoxArea
from utils import BoundingBoxArea, Flick, FlickThread
RED = 1, 0, 0
......@@ -42,6 +42,20 @@ class Polygon(BoundingBoxArea):
self.on_drag(self.handle_drag)
self.on_pinch(self.handle_pinch)
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):
tx, ty = g.get_translation()
......@@ -217,7 +231,7 @@ def quit(*args):
# Global variables
window = cr = root = overlay = None
window = cr = root = overlay = flicks = None
draw_objects = []
touch_hands = []
......@@ -247,7 +261,7 @@ def on_show(window):
draw_objects.append(triangle)
root.add_area(triangle)
# Overlay catches basic events
# Overlay catches finger events to be able to draw touch points
def handle_down(gesture):
if gesture.is_first():
touch_hands.append(gesture.get_hand())
......@@ -279,7 +293,6 @@ if __name__ == '__main__':
fullscreen = args.fullscreen
# Create a window with a Cairo context in it and a multi-touch area
# syncronized with it
create_context_window(800, 600, on_show)
......@@ -290,6 +303,11 @@ if __name__ == '__main__':
mt_thread.daemon = True
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
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 src import RectangularArea
......@@ -33,3 +37,40 @@ class BoundingBoxArea(RectangularArea):
if min_x or min_y:
self.translate(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