Mercurial > hg > nsaunier > traffic-intelligence
comparison python/moving.py @ 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 | eb78c6edc0c8 |
| children | 1fb5606506ae |
comparison
equal
deleted
inserted
replaced
| 42:1a2ac2d4f53a | 43:6d11d9e7ad4e |
|---|---|
| 24 | 24 |
| 25 def __str__(self): | 25 def __str__(self): |
| 26 return '%d %d'%(self.first, self.last) | 26 return '%d %d'%(self.first, self.last) |
| 27 | 27 |
| 28 def empty(self): | 28 def empty(self): |
| 29 ''' | |
| 30 >>> Interval().empty() | |
| 31 True | |
| 32 >>> Interval(0,1).empty() | |
| 33 False | |
| 34 ''' | |
| 35 return self.first > self.last | 29 return self.first > self.last |
| 36 | 30 |
| 37 def length(self): | 31 def length(self): |
| 38 '''Returns the length of the interval | 32 '''Returns the length of the interval''' |
| 39 | |
| 40 >>> Interval(0,1).length() | |
| 41 1 | |
| 42 >>> Interval(23.2,24.9).length() | |
| 43 1.6999999999999993 | |
| 44 >>> Interval(10,8).length() | |
| 45 0 | |
| 46 ''' | |
| 47 return max(0,self.last-self.first) | 33 return max(0,self.last-self.first) |
| 48 | 34 |
| 49 def getList(self): | 35 def getList(self): |
| 50 return [self.first, self.last] | 36 return [self.first, self.last] |
| 51 | 37 |
| 85 else: | 71 else: |
| 86 self.iterInstantNum += 1 | 72 self.iterInstantNum += 1 |
| 87 return self[self.iterInstantNum] | 73 return self[self.iterInstantNum] |
| 88 | 74 |
| 89 def length(self): | 75 def length(self): |
| 90 '''Returns the length of the interval | 76 '''Returns the length of the interval''' |
| 91 | |
| 92 >>> TimeInterval(0,1).length() | |
| 93 2 | |
| 94 >>> TimeInterval(10,8).length() | |
| 95 0 | |
| 96 ''' | |
| 97 return max(0,self.last-self.first+1) | 77 return max(0,self.last-self.first+1) |
| 98 | 78 |
| 99 # class BoundingPolygon: | 79 # class BoundingPolygon: |
| 100 # '''Class for a polygon bounding a set of points | 80 # '''Class for a polygon bounding a set of points |
| 101 # with methods to create intersection, unions... | 81 # with methods to create intersection, unions... |
| 121 return self.timeInterval.first | 101 return self.timeInterval.first |
| 122 | 102 |
| 123 def getLastInstant(self): | 103 def getLastInstant(self): |
| 124 return self.timeInterval.last | 104 return self.timeInterval.last |
| 125 | 105 |
| 106 def getTimeInterval(self): | |
| 107 return self.timeInterval | |
| 108 | |
| 109 def commonTimeInterval(self, obj2): | |
| 110 return self.getTimeInterval().intersection(obj2.getTimeInterval()) | |
| 111 | |
| 126 class Point: | 112 class Point: |
| 127 def __init__(self, x, y): | 113 def __init__(self, x, y): |
| 128 self.x = x | 114 self.x = x |
| 129 self.y = y | 115 self.y = y |
| 130 | 116 |
| 133 | 119 |
| 134 def __repr__(self): | 120 def __repr__(self): |
| 135 return str(self) | 121 return str(self) |
| 136 | 122 |
| 137 def __sub__(self, other): | 123 def __sub__(self, other): |
| 138 ''' | |
| 139 >>> Point(3,4)-Point(1,7) | |
| 140 (2.000000,-3.000000) | |
| 141 ''' | |
| 142 return Point(self.x-other.x, self.y-other.y) | 124 return Point(self.x-other.x, self.y-other.y) |
| 143 | 125 |
| 144 def draw(self, options = ''): | 126 def draw(self, options = ''): |
| 145 from matplotlib.pylab import plot | 127 from matplotlib.pylab import plot |
| 146 plot([self.x], [self.y], 'x'+options) | 128 plot([self.x], [self.y], 'x'+options) |
| 147 | 129 |
| 148 def norm2Squared(self): | 130 def norm2Squared(self): |
| 149 '''2-norm distance (Euclidean distance) | 131 '''2-norm distance (Euclidean distance)''' |
| 150 >>> Point(3,2).norm2Squared() | |
| 151 13 | |
| 152 ''' | |
| 153 return self.x*self.x+self.y*self.y | 132 return self.x*self.x+self.y*self.y |
| 154 | 133 |
| 155 def norm2(self): | 134 def norm2(self): |
| 156 '2-norm distance (Euclidean distance)' | 135 '2-norm distance (Euclidean distance)' |
| 157 return sqrt(self.norm2Squared()) | 136 return sqrt(self.norm2Squared()) |
| 158 | 137 |
| 159 def distanceNorm2(p1, p2): | 138 def distanceNorm2(p1, p2): |
| 160 ''' | |
| 161 >>> Point.distanceNorm2(Point(3,4),Point(1,7)) | |
| 162 3.6055512754639891 | |
| 163 ''' | |
| 164 return (p1-p2).norm2() | 139 return (p1-p2).norm2() |
| 165 | 140 |
| 166 def aslist(self): | 141 def aslist(self): |
| 167 return [self.x, self.y] | 142 return [self.x, self.y] |
| 168 | 143 |
| 170 '''Class for trajectories | 145 '''Class for trajectories |
| 171 i.e. a temporal sequence of positions | 146 i.e. a temporal sequence of positions |
| 172 | 147 |
| 173 the class is iterable.''' | 148 the class is iterable.''' |
| 174 | 149 |
| 175 def __init__(self, line1, line2): | 150 def __init__(self, positions): |
| 176 self.positions = [[float(n) for n in line1.split(' ')], | 151 self.positions = positions |
| 177 [float(n) for n in line2.split(' ')]] | 152 |
| 153 @staticmethod | |
| 154 def load(line1, line2): | |
| 155 return Trajectory([[float(n) for n in line1.split(' ')], | |
| 156 [float(n) for n in line2.split(' ')]]) | |
| 178 | 157 |
| 179 def __str__(self): | 158 def __str__(self): |
| 180 return ' '.join([self.__getitem__(i).__str__() for i in xrange(self.length())]) | 159 return ' '.join([self.__getitem__(i).__str__() for i in xrange(self.length())]) |
| 181 | 160 |
| 182 def __getitem__(self, i): | 161 def __getitem__(self, i): |
| 219 | 198 |
| 220 def yBounds(self): | 199 def yBounds(self): |
| 221 # look for function that does min and max in one pass | 200 # look for function that does min and max in one pass |
| 222 return [min(self.getYCoordinates()), max(self.getYCoordinates())] | 201 return [min(self.getYCoordinates()), max(self.getYCoordinates())] |
| 223 | 202 |
| 203 def add(self, traj2): | |
| 204 '''Returns a new trajectory of the same length''' | |
| 205 if self.length() != traj2.length(): | |
| 206 print 'Trajectories of different lengths' | |
| 207 return None | |
| 208 else: | |
| 209 return Trajectory([[a+b for a,b in zip(self.getXCoordinates(),traj2.getXCoordinates())], | |
| 210 [a+b for a,b in zip(self.getYCoordinates(),traj2.getYCoordinates())]]) | |
| 211 | |
| 212 def subtract(self, traj2): | |
| 213 '''Returns a new trajectory of the same length''' | |
| 214 if self.length() != traj2.length(): | |
| 215 print 'Trajectories of different lengths' | |
| 216 return None | |
| 217 else: | |
| 218 return Trajectory([[a-b for a,b in zip(self.getXCoordinates(),traj2.getXCoordinates())], | |
| 219 [a-b for a,b in zip(self.getYCoordinates(),traj2.getYCoordinates())]]) | |
| 220 | |
| 224 def norm(self): | 221 def norm(self): |
| 225 '''Returns the list of the norms at each instant''' | 222 '''Returns the list of the norms at each instant''' |
| 226 # def add(x, y): return x+y | 223 # def add(x, y): return x+y |
| 227 # sq = map(add, [x*x for x in self.positions[0]], [y*y for y in self.positions[1]]) | 224 # sq = map(add, [x*x for x in self.positions[0]], [y*y for y in self.positions[1]]) |
| 228 # return sqrt(sq) | 225 # return sqrt(sq) |
| 229 return [hypot(x,y) for x,y in zip(self.positions[0], self.positions[1])] | 226 return [hypot(x,y) for x,y in zip(self.positions[0], self.positions[1])] |
| 230 | 227 |
| 228 def getTrajectoryInInterval(self, inter): | |
| 229 if inter.first >=0 and inter.last<= self.length(): | |
| 230 return Trajectory([self.positions[0][inter.first:inter.last], | |
| 231 self.positions[1][inter.first:inter.last]]) | |
| 232 else: | |
| 233 return None | |
| 234 | |
| 231 def getTrajectoryInPolygon(self, polygon): | 235 def getTrajectoryInPolygon(self, polygon): |
| 232 'Returns the set of points inside the polygon' | 236 'Returns the set of points inside the polygon' |
| 233 # use shapely polygon contains | 237 # use shapely polygon contains |
| 234 pass | 238 pass |
| 235 | 239 |
| 243 STObject.__init__(self, num, timeInterval) | 247 STObject.__init__(self, num, timeInterval) |
| 244 self.positions = positions | 248 self.positions = positions |
| 245 self.geometry = geometry | 249 self.geometry = geometry |
| 246 self.type = type | 250 self.type = type |
| 247 # compute bounding polygon from trajectory | 251 # compute bounding polygon from trajectory |
| 252 | |
| 253 def getObjectInTimeInterval(self, inter): | |
| 254 '''Returns a new object extracted from self, existing at time interval inter''' | |
| 255 if inter.inside(self.timeInterval): | |
| 256 inter = TimeInterval(inter.first-self.getFirstInstant(), inter.last-self.getFirstInstant()) | |
| 257 obj = MovingObject(self.num, inter, self.positions.getTrajectoryInInterval(inter), self.geometry, self.type) | |
| 258 if self.velocities: | |
| 259 obj.velocities = self.velocities.getTrajectoryInInterval(inter) | |
| 260 return obj | |
| 261 else: | |
| 262 print 'The object does not exist at '+str(inter) | |
| 263 return None | |
| 248 | 264 |
| 249 def length(self): | 265 def length(self): |
| 250 return self.timeInterval.length() | 266 return self.timeInterval.length() |
| 251 | 267 |
| 252 def getPositions(self): | 268 def getPositions(self): |
| 301 self.values = values | 317 self.values = values |
| 302 | 318 |
| 303 if __name__ == "__main__": | 319 if __name__ == "__main__": |
| 304 import doctest | 320 import doctest |
| 305 import unittest | 321 import unittest |
| 306 #suite = doctest.DocFileSuite('tests/ubc_utils.txt') | 322 suite = doctest.DocFileSuite('tests/moving.txt') |
| 307 suite = doctest.DocTestSuite() | 323 #suite = doctest.DocTestSuite() |
| 308 unittest.TextTestRunner().run(suite) | 324 unittest.TextTestRunner().run(suite) |
| 309 #doctest.testmod() | 325 #doctest.testmod() |
| 310 #doctest.testfile("example.txt") | 326 #doctest.testfile("example.txt") |
