Prechádzať zdrojové kódy

Polygon contains() function now does not use bounding box anymore.

Taddeus Kroes 13 rokov pred
rodič
commit
0107775aaf
2 zmenil súbory, kde vykonal 53 pridanie a 6 odobranie
  1. 12 5
      tests/testapp.py
  2. 41 1
      tests/utils.py

+ 12 - 5
tests/testapp.py

@@ -57,6 +57,12 @@ class Polygon(BoundingBoxArea):
             self.flick_direction = trans
             flicks.add(Flick(self.flick_drag, 0.7, 0.4))
 
+    def contains(self, x, y):
+        if draw_bounding_boxes:
+            return mt.RectangularArea.contains(self, x, y)
+
+        return BoundingBoxArea.contains(self, x, y)
+
     def handle_drag(self, g):
         tx, ty = g.get_translation()
         self.translate(tx, ty)
@@ -74,10 +80,10 @@ class Polygon(BoundingBoxArea):
         self.update_bounds()
         refresh()
 
-    def contains(self, x, y):
-        m = self.margin
-        return self.x - m <= x < self.x + self.width + m \
-               and self.y - m <= y < self.y + self.height + m
+    #def contains(self, x, y):
+    #    m = self.margin
+    #    return self.x - m <= x < self.x + self.width + m \
+    #           and self.y - m <= y < self.y + self.height + m
 
     def draw(self, cr):
         # Draw bounding box
@@ -102,7 +108,8 @@ class Polygon(BoundingBoxArea):
 
 
 fullscreen = False
-draw_bounding_boxes = draw_touch_objects = True
+draw_bounding_boxes = False
+draw_touch_objects = True
 W, H = mt.screen.screen_size
 
 

+ 41 - 1
tests/utils.py

@@ -1,7 +1,7 @@
 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, asarray, column_stack, c_
 
 from src import RectangularArea
 
@@ -29,6 +29,10 @@ class BoundingBoxArea(RectangularArea):
         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)
@@ -74,3 +78,39 @@ class FlickThread(Thread):
 
     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