comparison python/moving.py @ 290:df58d361f19e

refactoring of Interval and TimeInterval using class methods (intersection, union)
author Nicolas Saunier <nicolas.saunier@polymtl.ca>
date Tue, 29 Jan 2013 18:23:47 -0500
parents e0d41c7f53d4
children d280b881e860
comparison
equal deleted inserted replaced
289:e56c34c1ebac 290:df58d361f19e
8 8
9 #from shapely.geometry import Polygon 9 #from shapely.geometry import Polygon
10 10
11 __metaclass__ = type 11 __metaclass__ = type
12 12
13 class Interval: 13 class Interval(object):
14 '''Generic interval: a subset of real numbers (not iterable)''' 14 '''Generic interval: a subset of real numbers (not iterable)'''
15 def __init__(self, first=0, last=-1, revert = False): 15 def __init__(self, first=0, last=-1, revert = False):
16 if revert and last<first: 16 if revert and last<first:
17 self.first=last 17 self.first=last
18 self.last=first 18 self.last=first
44 44
45 def inside(self, interval2): 45 def inside(self, interval2):
46 '''Indicates if the temporal interval of self is comprised in interval2''' 46 '''Indicates if the temporal interval of self is comprised in interval2'''
47 return (self.first >= interval2.first) and (self.last <= interval2.last) 47 return (self.first >= interval2.first) and (self.last <= interval2.last)
48 48
49 def union(self, interval2): 49 @classmethod
50 def union(cls, interval1, interval2):
50 '''Smallest interval comprising self and interval2''' 51 '''Smallest interval comprising self and interval2'''
51 return Interval(min(self.first, interval2.first), max(self.last, interval2.last)) 52 return cls(min(interval1.first, interval2.first), max(interval2.last, interval2.last))
52 53
53 def intersection(self, interval2): 54 @classmethod
55 def intersection(cls, interval1, interval2):
54 '''Largest interval comprised in both self and interval2''' 56 '''Largest interval comprised in both self and interval2'''
55 return Interval(max(self.first, interval2.first), min(self.last, interval2.last)) 57 return cls(max(interval1.first, interval2.first), min(interval1.last, interval2.last))
56 58
57 def distance(self, interval2): 59 def distance(self, interval2):
58 if not self.intersection(interval2).empty(): 60 if not Interval.intersection(self, interval2).empty():
59 return 0 61 return 0
60 elif self.first > interval2.last: 62 elif self.first > interval2.last:
61 return self.first - interval2.last 63 return self.first - interval2.last
62 elif self.last < interval2.first: 64 elif self.last < interval2.first:
63 return interval2.first - self.last 65 return interval2.first - self.last
67 69
68 def unionIntervals(intervals): 70 def unionIntervals(intervals):
69 'returns the smallest interval containing all intervals' 71 'returns the smallest interval containing all intervals'
70 inter = intervals[0] 72 inter = intervals[0]
71 for i in intervals[1:]: 73 for i in intervals[1:]:
72 inter = inter.union(i) 74 inter = Interval.union(inter, i)
73 return inter 75 return inter
74 76
75 77
76 class TimeInterval(Interval): 78 class TimeInterval(Interval):
77 '''Temporal interval: set of instants at fixed time step, between first and last, included 79 '''Temporal interval: set of instants at fixed time step, between first and last, included
78 80
79 For example: based on frame numbers (hence the modified length method) 81 For example: based on frame numbers (hence the modified length method)
80 It may be modified directly by setting first and last''' 82 It may be modified directly by setting first and last'''
81 83
82 def __init__(self, first=0, last=-1): 84 def __init__(self, first=0, last=-1):
83 Interval.__init__(self, first, last, False) 85 super(TimeInterval, self).__init__(first, last, False)
86
87 @staticmethod
88 def fromInterval(inter):
89 return TimeInterval(inter.first, inter.last)
84 90
85 def __getitem__(self, i): 91 def __getitem__(self, i):
86 if not self.empty(): 92 if not self.empty():
87 return self.first+i 93 return self.first+i
88 94
105 # '''Class for a polygon bounding a set of points 111 # '''Class for a polygon bounding a set of points
106 # with methods to create intersection, unions... 112 # with methods to create intersection, unions...
107 # ''' 113 # '''
108 # We will use the polygon class of Shapely 114 # We will use the polygon class of Shapely
109 115
110 class STObject: 116 class STObject(object):
111 '''Class for spatio-temporal object, i.e. with temporal and spatial existence 117 '''Class for spatio-temporal object, i.e. with temporal and spatial existence
112 (time interval and bounding polygon for positions (e.g. rectangle)). 118 (time interval and bounding polygon for positions (e.g. rectangle)).
113 119
114 It may not mean that the object is defined 120 It may not mean that the object is defined
115 for all time instants within the time interval''' 121 for all time instants within the time interval'''
136 142
137 def existsAtInstant(self, t): 143 def existsAtInstant(self, t):
138 return self.timeInterval.contains(t) 144 return self.timeInterval.contains(t)
139 145
140 def commonTimeInterval(self, obj2): 146 def commonTimeInterval(self, obj2):
141 return self.getTimeInterval().intersection(obj2.getTimeInterval()) 147 return TimeInterval.intersection(self.getTimeInterval(), obj2.getTimeInterval())
142 148
143 class Point: 149 class Point(object):
144 def __init__(self, x, y): 150 def __init__(self, x, y):
145 self.x = x 151 self.x = x
146 self.y = y 152 self.y = y
147 153
148 def __str__(self): 154 def __str__(self):
233 @staticmethod 239 @staticmethod
234 def plotAll(points, color='r'): 240 def plotAll(points, color='r'):
235 from matplotlib.pyplot import scatter 241 from matplotlib.pyplot import scatter
236 scatter([p.x for p in points],[p.y for p in points], c=color) 242 scatter([p.x for p in points],[p.y for p in points], c=color)
237 243
238 class NormAngle: 244 class NormAngle(object):
239 '''Alternate encoding of a point, by its norm and orientation''' 245 '''Alternate encoding of a point, by its norm and orientation'''
240 246
241 def __init__(self, norm, angle): 247 def __init__(self, norm, angle):
242 self.norm = norm 248 self.norm = norm
243 self.angle = angle 249 self.angle = angle
272 predictedSpeedTheta.norm = min(predictedSpeedTheta.norm, maxSpeed) 278 predictedSpeedTheta.norm = min(predictedSpeedTheta.norm, maxSpeed)
273 predictedPosition = position+predictedSpeedTheta.getPoint() 279 predictedPosition = position+predictedSpeedTheta.getPoint()
274 return predictedPosition, predictedSpeedTheta 280 return predictedPosition, predictedSpeedTheta
275 281
276 282
277 class FlowVector: 283 class FlowVector(object):
278 '''Class to represent 4-D flow vectors, 284 '''Class to represent 4-D flow vectors,
279 ie a position and a velocity''' 285 ie a position and a velocity'''
280 def __init__(self, position, velocity): 286 def __init__(self, position, velocity):
281 'position and velocity should be Point instances' 287 'position and velocity should be Point instances'
282 self.position = position 288 self.position = position
300 def segmentIntersection(p1, p2, p3, p4): 306 def segmentIntersection(p1, p2, p3, p4):
301 '''Returns the intersecting point of the segments [p1, p2] and [p3, p4], None otherwise''' 307 '''Returns the intersecting point of the segments [p1, p2] and [p3, p4], None otherwise'''
302 from numpy import matrix 308 from numpy import matrix
303 from numpy.linalg import linalg, det 309 from numpy.linalg import linalg, det
304 310
305 if (Interval(p1.x,p2.x, True).intersection(Interval(p3.x,p4.x, True)).empty() 311 if (Interval.intersection(Interval(p1.x,p2.x,True), Interval(p3.x,p4.x,True)).empty()) or (Interval.intersection(Interval(p1.y,p2.y,True), Interval(p3.y,p4.y,True)).empty()):
306 or Interval(p1.y,p2.y, True).intersection(Interval(p3.y,p4.y, True)).empty()):
307 return None 312 return None
308 else: 313 else:
309 dp1 = p2-p1#[s1[0][1]-s1[0][0], s1[1][1]-s1[1][0]] 314 dp1 = p2-p1#[s1[0][1]-s1[0][0], s1[1][1]-s1[1][0]]
310 dp2 = p4-p3#[s2[0][1]-s2[0][0], s2[1][1]-s2[1][0]] 315 dp2 = p4-p3#[s2[0][1]-s2[0][0], s2[1][1]-s2[1][0]]
311 316
326 else: 331 else:
327 return None 332 return None
328 333
329 # TODO: implement a better algorithm for intersections of sets of segments http://en.wikipedia.org/wiki/Line_segment_intersection 334 # TODO: implement a better algorithm for intersections of sets of segments http://en.wikipedia.org/wiki/Line_segment_intersection
330 335
331 class Trajectory: 336 class Trajectory(object):
332 '''Class for trajectories: temporal sequence of positions 337 '''Class for trajectories: temporal sequence of positions
333 338
334 The class is iterable''' 339 The class is iterable'''
335 340
336 def __init__(self, positions=None): 341 def __init__(self, positions=None):
529 '''Class for moving objects: a spatio-temporal object 534 '''Class for moving objects: a spatio-temporal object
530 with a trajectory and a geometry (constant volume over time) and a usertype (e.g. road user) 535 with a trajectory and a geometry (constant volume over time) and a usertype (e.g. road user)
531 ''' 536 '''
532 537
533 def __init__(self, num = None, timeInterval = None, positions = None, geometry = None, userType = None): 538 def __init__(self, num = None, timeInterval = None, positions = None, geometry = None, userType = None):
534 STObject.__init__(self, num, timeInterval) 539 super(MovingObject, self).__init__(num, timeInterval)
535 self.positions = positions 540 self.positions = positions
536 self.geometry = geometry 541 self.geometry = geometry
537 self.userType = userType 542 self.userType = userType
538 # compute bounding polygon from trajectory 543 # compute bounding polygon from trajectory
539 544
540 def getObjectInTimeInterval(self, inter): 545 def getObjectInTimeInterval(self, inter):
541 '''Returns a new object extracted from self, 546 '''Returns a new object extracted from self,
542 restricted to time interval inter''' 547 restricted to time interval inter'''
543 intersection = inter.intersection(self.getTimeInterval()) 548 intersection = TimeInterval.intersection(inter, self.getTimeInterval())
544 if not intersection.empty(): 549 if not intersection.empty():
545 trajectoryInterval = TimeInterval(intersection.first-self.getFirstInstant(), intersection.last-self.getFirstInstant()) 550 trajectoryInterval = TimeInterval(intersection.first-self.getFirstInstant(), intersection.last-self.getFirstInstant())
546 obj = MovingObject(self.num, intersection, self.positions.getTrajectoryInInterval(trajectoryInterval), self.geometry, self.userType) 551 obj = MovingObject(self.num, intersection, self.positions.getTrajectoryInInterval(trajectoryInterval), self.geometry, self.userType)
547 if self.velocities: 552 if self.velocities:
548 obj.velocities = self.velocities.getTrajectoryInInterval(trajectoryInterval) 553 obj.velocities = self.velocities.getTrajectoryInInterval(trajectoryInterval)