| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- from __future__ import division
- from time import sleep
- from threading import Thread
- from numpy import array, diag, dot, cos, sin, asarray, column_stack, c_
- from gtk import Window
- from src import RectangularArea
- class BoundingBoxArea(RectangularArea):
- def __init__(self, x, y, points):
- super(BoundingBoxArea, self).__init__(x, y, 0, 0)
- self.points = array(points).T
- self.update_bounds()
- def translate_points(self, tx, ty):
- self.points += [[tx], [ty]]
- def scale_points(self, scale, cx, cy):
- self.translate_points(-cx, -cy)
- self.points = dot(diag([scale, scale]), self.points)
- self.translate_points(cx, cy)
- def rotate_points(self, angle, cx, cy):
- cosa = cos(angle)
- sina = sin(angle)
- mat = array([[cosa, -sina], [sina, cosa]])
- self.translate_points(-cx, -cy)
- self.points = dot(mat, self.points)
- self.translate_points(cx, cy)
- def contains(self, x, y):
- ox, oy = self.get_position()
- return inside_shape((x - ox, y - oy), self.points)
- def update_bounds(self):
- min_x, min_y = self.points.min(1)
- max_x, max_y = self.points.max(1)
- width = max_x - min_x
- height = max_y - min_y
- if min_x or min_y:
- self.width = width
- self.height = height
- self.translate_points(-min_x, -min_y)
- self.translate(min_x, min_y)
- elif width != self.width or height != self.height:
- self.set_size(width, height)
- 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)
- def inside_shape(p, verts):
- """Test whether the point p is inside the specified shape.
- The shape is specified by 'verts' and 'edges'
- Arguments:
- p - the 2d point
- verts - (N,2) array of points
- Returns:
- - True/False based on result of in/out test.
- Uses the 'ray to infinity' even-odd test.
- Let the ray be the horizontal ray starting at p and going to +inf in x.
- """
- x, y = p
- inside = False
- for i in range(-1, verts.shape[1] - 1):
- x0, y0 = verts[:,i]
- x1, y1 = verts[:,i + 1]
- # Check for horizontal line - another horz line can't intersect it
- # Check if both verts to the left, bottom or top of ray
- if (y0 == y1) or (x0 < x and x1 < x) or (y0 < y and y1 < y) \
- or (y0 > y and y1 > y):
- continue
- # Compute x intersection value
- xisect = x0 + (x1 - x0) * (y - y0) / (y1 - y0)
- print xisect, x
- if xisect >= x:
- inside = not inside
- return inside
- class GtkEventWindow(Window):
- def __init__(self, width=0, height=0):
- Window.__init__(self)
- self.area = RectangularArea(0, 0, width, height)
- self.connect('configure-event', self.sync_area)
- def get_area(self):
- return self.area
- def on_update(self, handler):
- self.area.on_update(handler)
- def sync_area(self, win, event):
- """Synchronize root multi-touch area with GTK window."""
- self.area.width = event.width
- self.area.height = event.height
- self.area.set_position(*event.get_coords())
|