diff python/moving.py @ 372:349eb1e09f45

Cleaned the methods/functions indicating if a point is in a polygon In general, shapely should be used, especially for lots of points: from shapely.geometry import Polygon, Point poly = Polygon(array([[0,0],[0,1],[1,1],[1,0]])) p = Point(0.5,0.5) poly.contains(p) -> returns True poly.contains(Point(-1,-1)) -> returns False You can convert a moving.Point to a shapely point: p = moving.Point(1,2) p.asShapely() returns the equivalent shapely point If you have several points to test, use moving.pointsInPolygon(points, polygon) where points are moving.Point and polygon is a shapely polygon.
author Nicolas Saunier <nicolas.saunier@polymtl.ca>
date Tue, 16 Jul 2013 17:00:17 -0400
parents 027e254f0b53
children 2aed569f39e7
line wrap: on
line diff
--- a/python/moving.py	Tue Jul 16 01:36:50 2013 -0400
+++ b/python/moving.py	Tue Jul 16 17:00:17 2013 -0400
@@ -7,7 +7,13 @@
 from math import sqrt
 from numpy import median
 
-#from shapely.geometry import Polygon
+try:
+    from shapely.geometry import Polygon, Point as shapelyPoint
+    from shapely.prepared import prep
+    shapelyAvailable = True
+except ImportError:
+    print('Shapely library could not be loaded')
+    shapelyAvailable = False
 
 __metaclass__ = type
 
@@ -197,31 +203,35 @@
     def asint(self):
         return Point(int(self.x), int(self.y))
 
+    if shapelyAvailable:
+        def asShapely(self):
+            return shapelyPoint(self.x, self.y)
+
     def project(self, homography):
         from numpy.core.multiarray import array
         projected = cvutils.projectArray(homography, array([[self.x], [self.y]]))
         return Point(projected[0], projected[1])
 
-    def inPolygon(self, poly):
-        '''Returns if the point x, y is inside the polygon.
-        The polygon is defined by the ordered list of points in poly
-        
+    def inPolygonNoShapely(self, polygon):
+        '''Indicates if the point x, y is inside the polygon
+        (array of Nx2 coordinates of the polygon vertices)
+
         taken from http://www.ariel.com.au/a/python-point-int-poly.html
 
-        Use points_inside_poly from matplotlib.nxutils'''
+        Use Polygon.contains if Shapely is installed'''
 
-        n = len(poly);
+        n = polygon.shape[0];
         counter = 0;
 
-        p1 = poly[0];
+        p1 = polygon[0,:];
         for i in range(n+1):
-            p2 = poly[i % n];
-            if self.y > min(p1.y,p2.y):
-                if self.y <= max(p1.y,p2.y):
-                    if self.x <= max(p1.x,p2.x):
-                        if p1.y != p2.y:
-                            xinters = (self.y-p1.y)*(p2.x-p1.x)/(p2.y-p1.y)+p1.x;
-                        if p1.x == p2.x or self.x <= xinters:
+            p2 = polygon[i % n,:];
+            if self.y > min(p1[1],p2[1]):
+                if self.y <= max(p1[1],p2[1]):
+                    if self.x <= max(p1[0],p2[0]):
+                        if p1[1] != p2[1]:
+                            xinters = (self.y-p1[1])*(p2[0]-p1[0])/(p2[1]-p1[1])+p1[0];
+                        if p1[0] == p2[0] or self.x <= xinters:
                             counter+=1;
             p1=p2
         return (counter%2 == 1);
@@ -245,6 +255,13 @@
         from matplotlib.pyplot import scatter
         scatter([p.x for p in points],[p.y for p in points], **kwargs)
 
+if shapelyAvailable:
+    def pointsInPolygon(points, polygon):
+        '''Optimized tests of a series of points within (Shapely) polygon '''
+        prepared_polygon = prep(polygon)
+        return filter(prepared_polygon.contains, points)
+
+
 class NormAngle(object):
     '''Alternate encoding of a point, by its norm and orientation'''
 
@@ -525,19 +542,24 @@
         else:
             return None
     
-    def getTrajectoryInPolygon(self, polygon):
-        '''Returns the set of points inside the polygon
+    def getTrajectoryInPolygonNoShapely(self, polygon):
+        '''Returns the trajectory built with the set of points inside the polygon
         (array of Nx2 coordinates of the polygon vertices)'''
-        import matplotlib.nxutils as nx
         traj = Trajectory()
-        result = nx.points_inside_poly(self.asArray().T, polygon)
-        for i in xrange(self.length()):
-            if result[i]:
-                traj.addPositionXY(self.positions[0][i], self.positions[1][i])
+        for p in self:
+            if p.inPolygonNoShapely(polygon):
+                traj.addPosition(p)
         return traj
 
-    # version 2: use shapely polygon contains
-
+    if shapelyAvailable:
+        def getTrajectoryInPolygon(self, polygon):
+            '''Returns the trajectory built with the set of points inside the (shapely) polygon'''
+            traj = Trajectory()
+            points = [p.asShapely() for p in self]
+            for p in pointsInPolygon(points, polygon):
+                    traj.addPositionXY(p.x, p.y)
+            return traj
+    
     @staticmethod
     def lcss(t1, t2, lcss):
         return lcss.compute(t1, t2)