changeset 43:6d11d9e7ad4e

methods for trajectories and objects to add and subtract trajectories and extract objects from existing objects, for sub-time intervals
author Nicolas Saunier <nicolas.saunier@polymtl.ca>
date Wed, 14 Jul 2010 14:02:11 -0400
parents 1a2ac2d4f53a
children be3ae926e4e8
files python/moving.py python/tests/moving.txt python/ubc_utils.py
diffstat 3 files changed, 86 insertions(+), 43 deletions(-) [+]
line wrap: on
line diff
--- a/python/moving.py	Thu Jul 01 10:44:32 2010 -0400
+++ b/python/moving.py	Wed Jul 14 14:02:11 2010 -0400
@@ -26,24 +26,10 @@
         return '%d %d'%(self.first, self.last)
 
     def empty(self):
-        '''
-        >>> Interval().empty()
-        True
-        >>> Interval(0,1).empty()
-        False
-        '''
         return self.first > self.last
 
     def length(self):
-        '''Returns the length of the interval
-        
-        >>> Interval(0,1).length()
-        1
-        >>> Interval(23.2,24.9).length()
-        1.6999999999999993
-        >>> Interval(10,8).length()
-        0
-        '''
+        '''Returns the length of the interval'''
         return max(0,self.last-self.first)
 
     def getList(self):
@@ -87,13 +73,7 @@
             return self[self.iterInstantNum]
 
     def length(self):
-        '''Returns the length of the interval
-        
-        >>> TimeInterval(0,1).length()
-        2
-        >>> TimeInterval(10,8).length()
-        0
-        '''
+        '''Returns the length of the interval'''
         return max(0,self.last-self.first+1)
 
 # class BoundingPolygon:
@@ -123,6 +103,12 @@
     def getLastInstant(self):
         return self.timeInterval.last
 
+    def getTimeInterval(self):
+        return self.timeInterval
+
+    def commonTimeInterval(self, obj2):
+        return self.getTimeInterval().intersection(obj2.getTimeInterval())
+
 class Point:
     def __init__(self, x, y):
         self.x = x
@@ -135,10 +121,6 @@
         return str(self)
 
     def __sub__(self, other):
-        '''
-        >>> Point(3,4)-Point(1,7)
-        (2.000000,-3.000000)
-        '''
         return Point(self.x-other.x, self.y-other.y)
 
     def draw(self, options = ''):
@@ -146,10 +128,7 @@
         plot([self.x], [self.y], 'x'+options)
 
     def norm2Squared(self):
-        '''2-norm distance (Euclidean distance)
-        >>> Point(3,2).norm2Squared()
-        13
-        '''
+        '''2-norm distance (Euclidean distance)'''
         return self.x*self.x+self.y*self.y
 
     def norm2(self):
@@ -157,10 +136,6 @@
         return sqrt(self.norm2Squared())
 
     def distanceNorm2(p1, p2):
-        '''
-        >>> Point.distanceNorm2(Point(3,4),Point(1,7))
-        3.6055512754639891
-        '''
         return (p1-p2).norm2()
 
     def aslist(self):
@@ -172,9 +147,13 @@
 
     the class is iterable.'''
 
-    def __init__(self, line1, line2):
-        self.positions = [[float(n) for n in line1.split(' ')],
-                          [float(n) for n in line2.split(' ')]]
+    def __init__(self, positions):
+        self.positions = positions
+
+    @staticmethod
+    def load(line1, line2):
+        return Trajectory([[float(n) for n in line1.split(' ')],
+                           [float(n) for n in line2.split(' ')]])
 
     def __str__(self):
         return ' '.join([self.__getitem__(i).__str__() for i in xrange(self.length())])
@@ -221,6 +200,24 @@
         # look for function that does min and max in one pass
         return [min(self.getYCoordinates()), max(self.getYCoordinates())]
     
+    def add(self, traj2):
+        '''Returns a new trajectory of the same length'''
+        if self.length() != traj2.length():
+            print 'Trajectories of different lengths'
+            return None
+        else:
+            return Trajectory([[a+b for a,b in zip(self.getXCoordinates(),traj2.getXCoordinates())],
+                               [a+b for a,b in zip(self.getYCoordinates(),traj2.getYCoordinates())]])
+
+    def subtract(self, traj2):
+        '''Returns a new trajectory of the same length'''
+        if self.length() != traj2.length():
+            print 'Trajectories of different lengths'
+            return None
+        else:
+            return Trajectory([[a-b for a,b in zip(self.getXCoordinates(),traj2.getXCoordinates())],
+                               [a-b for a,b in zip(self.getYCoordinates(),traj2.getYCoordinates())]])
+
     def norm(self):
         '''Returns the list of the norms at each instant'''
 #        def add(x, y): return x+y
@@ -228,6 +225,13 @@
 #        return sqrt(sq)
         return [hypot(x,y) for x,y in zip(self.positions[0], self.positions[1])]
 
+    def getTrajectoryInInterval(self, inter):
+        if inter.first >=0 and inter.last<= self.length():
+            return Trajectory([self.positions[0][inter.first:inter.last],
+                               self.positions[1][inter.first:inter.last]])
+        else:
+            return None
+    
     def getTrajectoryInPolygon(self, polygon):
         'Returns the set of points inside the polygon'
         # use shapely polygon contains
@@ -246,6 +250,18 @@
         self.type = type
         # compute bounding polygon from trajectory
 
+    def getObjectInTimeInterval(self, inter):
+        '''Returns a new object extracted from self, existing at time interval inter'''
+        if inter.inside(self.timeInterval):
+            inter = TimeInterval(inter.first-self.getFirstInstant(), inter.last-self.getFirstInstant())
+            obj = MovingObject(self.num, inter, self.positions.getTrajectoryInInterval(inter), self.geometry, self.type)
+            if self.velocities:
+                obj.velocities = self.velocities.getTrajectoryInInterval(inter)
+            return obj
+        else:
+            print 'The object does not exist at '+str(inter)
+            return None
+
     def length(self):
         return self.timeInterval.length()
 
@@ -303,8 +319,8 @@
 if __name__ == "__main__":
     import doctest
     import unittest
-    #suite = doctest.DocFileSuite('tests/ubc_utils.txt')
-    suite = doctest.DocTestSuite()
+    suite = doctest.DocFileSuite('tests/moving.txt')
+    #suite = doctest.DocTestSuite()
     unittest.TextTestRunner().run(suite)
     #doctest.testmod()
     #doctest.testfile("example.txt")
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/python/tests/moving.txt	Wed Jul 14 14:02:11 2010 -0400
@@ -0,0 +1,27 @@
+>>> from moving import *
+
+>>> Interval().empty()
+True
+>>> Interval(0,1).empty()
+False
+>>> Interval(0,1).length()
+1
+>>> Interval(23.2,24.9).length()
+1.6999999999999993
+>>> Interval(10,8).length()
+0
+
+>>> TimeInterval(0,1).length()
+2
+>>> TimeInterval(10,8).length()
+0
+
+>>> Point(3,4)-Point(1,7)
+(2.000000,-3.000000)
+
+>>> Point(3,2).norm2Squared()
+13
+
+>>> Point.distanceNorm2(Point(3,4),Point(1,7))
+3.6055512754639891
+
--- a/python/ubc_utils.py	Thu Jul 01 10:44:32 2010 -0400
+++ b/python/ubc_utils.py	Wed Jul 14 14:02:11 2010 -0400
@@ -34,9 +34,9 @@
         obj = MovingObject(num = objNum, timeInterval = TimeInterval(parsedLine[1],parsedLine[2]))
         #add = True
         if len(lines) >= 3:
-            obj.positions = Trajectory(lines[1], lines[2])
+            obj.positions = Trajectory.load(lines[1], lines[2])
             if len(lines) >= 5:
-                obj.velocities = Trajectory(lines[3], lines[4])
+                obj.velocities = Trajectory.load(lines[3], lines[4])
                 if (isObjectFile):
                     obj.userType = parsedLine[3]
                     obj.nObjects = float(l[4])
@@ -45,8 +45,8 @@
                     # load contour data if available
                     if len(lines) >= 6:
                         obj.contourType = utils.line2Floats(lines[6])
-                        obj.contourOrigins = Trajectory(lines[7], lines[8])
-                        obj.contourSizes = Trajectory(lines[9], lines[10])
+                        obj.contourOrigins = Trajectory.load(lines[7], lines[8])
+                        obj.contourSizes = Trajectory.load(lines[9], lines[10])
 
         if len(lines) != 2:
             objects.append(obj)