comparison python/moving.py @ 1019:5d2f6afae35b

work on object concatenation
author Nicolas Saunier <nicolas.saunier@polymtl.ca>
date Mon, 04 Jun 2018 23:35:50 -0400
parents d7afc59f6966
children
comparison
equal deleted inserted replaced
1018:d7afc59f6966 1019:5d2f6afae35b
381 381
382 @staticmethod 382 @staticmethod
383 def midPoint(p1, p2): 383 def midPoint(p1, p2):
384 'Returns the middle of the segment [p1, p2]' 384 'Returns the middle of the segment [p1, p2]'
385 return Point(0.5*p1.x+0.5*p2.x, 0.5*p1.y+0.5*p2.y) 385 return Point(0.5*p1.x+0.5*p2.x, 0.5*p1.y+0.5*p2.y)
386
387 @staticmethod
388 def agg(points, aggFunc = mean):
389 return Point(aggFunc([p.x for p in points]), aggFunc([p.y for p in points]))
386 390
387 if shapelyAvailable: 391 if shapelyAvailable:
388 def pointsInPolygon(points, polygon): 392 def pointsInPolygon(points, polygon):
389 '''Optimized tests of a series of points within (Shapely) polygon (not prepared)''' 393 '''Optimized tests of a series of points within (Shapely) polygon (not prepared)'''
390 if type(polygon) == PreparedGeometry: 394 if type(polygon) == PreparedGeometry:
1144 self.userType = userType 1148 self.userType = userType
1145 self.features = None 1149 self.features = None
1146 # compute bounding polygon from trajectory 1150 # compute bounding polygon from trajectory
1147 1151
1148 @staticmethod 1152 @staticmethod
1149 def aggregateTrajectory(features, aggFunc = mean): 1153 def aggregateTrajectories(features, interval = None, aggFunc = mean):
1150 'Computes the aggregate trajectory from list of MovingObject features' 1154 'Computes the aggregate trajectory from list of MovingObject features'
1151 return None 1155 positions = Trajectory()
1156 velocities = Trajectory()
1157 if interval is None:
1158 inter = TimeInterval.unionIntervals([f.getTimeInterval() for f in features])
1159 else:
1160 inter = interval
1161 for t in inter:
1162 points = []
1163 vels = []
1164 for f in features:
1165 if f.existsAtInstant(t):
1166 points.append(f.getPositionAtInstant(t))
1167 vels.append(f.getVelocityAtInstant(t))
1168 positions.addPosition(Point.agg(points, aggFunc))
1169 velocities.addPosition(Point.agg(vels, aggFunc))
1170 return inter, positions, velocities
1152 1171
1153 @staticmethod 1172 @staticmethod
1154 def generate(num, p, v, timeInterval): 1173 def generate(num, p, v, timeInterval):
1155 positions, velocities = Trajectory.generate(p, v, int(timeInterval.length())) 1174 positions, velocities = Trajectory.generate(p, v, int(timeInterval.length()))
1156 return MovingObject(num = num, timeInterval = timeInterval, positions = positions, velocities = velocities) 1175 return MovingObject(num = num, timeInterval = timeInterval, positions = positions, velocities = velocities)
1157 1176
1158 @staticmethod 1177 def updatePositions(self):
1159 def generateWithFeatures(num, features, userType): 1178 inter, self.positions, self.velocities = MovingObject.aggregateTrajectories(self.features, self.getTimeInterval())
1160 newObjectTMP = MovingObject.concatenateWith(features[0],features[1:],num) 1179
1161 newObject = MovingObject(newObjectTMP.getNum() if num is None else num, newObjectTMP.getTimeInterval(), newObjectTMP.positions, newObjectTMP.velocities, userType = userType) 1180 @staticmethod
1162 newObject.features = [copy.deepcopy(f) for f in features] 1181 def concatenate(obj1, obj2, num = None, newFeatureNum = None, computePositions = False):
1163 return newObject
1164
1165 @staticmethod
1166 def concatenateWith(obj1, ObjectList=[], num = None):
1167 if len(ObjectList)==0:
1168 newObject = MovingObject(obj1.getNum() if num is None else num, obj1.getTimeInterval(), obj1.positions, obj1.velocities, userType = obj1.getUserType())
1169 if obj1.hasFeatures() :
1170 newObject.features = list(obj1.features)
1171 else:
1172 def getKey(item):
1173 return 0 if not obj1.commonTimeInterval(item).empty() else max(obj1.getFirstInstant(),item.getFirstInstant())-min(obj1.getLastInstant(),item.getLastInstant())
1174 Order = min(ObjectList , key=getKey)
1175 newObject = MovingObject.concatenate(obj1, Order, num)
1176 ObjectList.remove(Order)
1177 newObject = MovingObject.concatenateWith(newObject,ObjectList)
1178 return newObject
1179
1180 def updatePosition(self):
1181 if self.features is not None:
1182 positions = Trajectory()
1183 for t in self.getTimeInterval():
1184 nTotal = 0.
1185 p = Point(0.,0.)
1186 for obj in self.features:
1187 if obj.existsAtInstant(t):
1188 if obj.hasFeatures():
1189 n = len([f for f in obj.getFeatures() if f.existsAtInstant(t)])
1190 else:
1191 n = 1.
1192 p += obj.getPositionAtInstant(t).__mul__(n)
1193 nTotal += n
1194 assert nTotal>0, 'there should be at least one point for each instant'
1195 positions.addPosition(p.divide(nTotal))
1196 self.positions = positions
1197
1198 @staticmethod
1199 def concatenate(obj1, obj2, num = None, computePositions = False):
1200 '''Concatenates two objects, whether overlapping temporally or not 1182 '''Concatenates two objects, whether overlapping temporally or not
1201 1183
1202 Positions will be recomputed only if computePositions is True 1184 Positions will be recomputed only if computePositions is True
1203 Otherwise, only featureNumbers and/or features will be merged''' 1185 Otherwise, only featureNumbers and/or features will be merged'''
1204 if num is None: 1186 if num is None:
1213 firstObject = obj2 1195 firstObject = obj2
1214 secondObject = obj1 1196 secondObject = obj1
1215 else: 1197 else:
1216 firstObject = obj1 1198 firstObject = obj1
1217 secondObject = obj2 1199 secondObject = obj2
1218 v = (secondObject.getPositionAtInstant(emptyInterval.last)-firstObject.getPositionAtInstant(emptyInterval.first)).divide(emptyInterval.length()) 1200 v = (secondObject.getPositionAtInstant(emptyInterval.last)-firstObject.getPositionAtInstant(emptyInterval.first)).divide(emptyInterval.length()-1)
1219 positions = copy.deepcopy(firstObject.getPositions()) 1201 positions = copy.deepcopy(firstObject.getPositions())
1220 velocities = copy.deepcopy(firstObject.getPositions()) 1202 velocities = copy.deepcopy(firstObject.getPositions())
1221 featurePositions = Trajectory() 1203 featurePositions = Trajectory()
1222 featureVelocities = Trajectory() 1204 featureVelocities = Trajectory()
1223 #newFeature = MovingObject(-1, TimeInterval(emptyInterval.first+1, emptyInterval.last-1))# what feature number to choose?
1224 p = firstObject.getPositionAtInstant(emptyInterval.first)+v 1205 p = firstObject.getPositionAtInstant(emptyInterval.first)+v
1225 for t in range(emptyInterval.first+1, emptyInterval.last): 1206 for t in range(emptyInterval.first+1, emptyInterval.last):
1226 positions.addPosition(p) 1207 positions.addPosition(p)
1227 velocities.addPosition(v) 1208 velocities.addPosition(v)
1228 featurePositions.addPosition(p) 1209 featurePositions.addPosition(p)
1229 featureVelocities.addPosition(v) 1210 featureVelocities.addPosition(v)
1230 p=p+v 1211 p=p+v
1231 # continue 1212 for t in secondObject.getTimeInterval():
1232 newObject = MovingObject(newNum, emptyInterval, positions, velocities, userType = obj1.getUserType()) 1213 positions.addPosition(secondObject.getPositionAtInstant(t))
1233 newObject.features = [MovingObject(newNum, emptyInterval, positions, velocities, userType = obj1.getUserType())] #In case there is features to add when we recursively call concatenate 1214 velocities.addPosition(secondObject.getVelocityAtInstant(t))
1234 return MovingObject.concatenate(MovingObject.concatenate(obj1, newObject),obj2) 1215 newObject = MovingObject(newNum, TimeInterval(firstObject.getFirstInstant(), secondObject.getLastInstant()), positions, velocities)
1235 else: 1216 if hasattr(obj1, 'featureNumbers') and hasattr(obj2, 'featureNumbers'):
1217 if newFeatureNum is not None:
1218 newObject.featureNumbers = obj1.featureNumbers+obj2.featureNumbers+[newFeatureNum]
1219 else:
1220 print('Issue, new created feature has no num id')
1221 if obj1.hasFeatures() and obj2.hasFeatures():
1222 newObject.features = obj1.getFeatures()+obj2.getFeatures()+[MovingObject(newFeatureNum, TimeInterval(emptyInterval.first+1, emptyInterval.last-1), featurePositions, featureVelocities)]
1223 else: # time intervals overlap
1236 newTimeInterval = TimeInterval.union(obj1.getTimeInterval(), obj2.getTimeInterval()) 1224 newTimeInterval = TimeInterval.union(obj1.getTimeInterval(), obj2.getTimeInterval())
1237 # positions 1225 newObject = MovingObject(newNum, newTimeInterval)
1238 positions = Trajectory() 1226 if hasattr(obj1, 'featureNumbers') and hasattr(obj2, 'featureNumbers'):
1239 for t in newTimeInterval: 1227 newObject.featureNumbers = obj1.featureNumbers+obj2.featureNumbers
1240 nTotal = 0. 1228 if obj1.hasFeatures() and obj2.hasFeatures():
1241 p = Point(0.,0.) 1229 newObject.features = obj1.getFeatures()+obj2.getFeatures()
1242 for obj in [obj1, obj2]: 1230 newObject.updatePositions()
1243 if obj.existsAtInstant(t):
1244 if obj.hasFeatures():
1245 n = len([f for f in obj.getFeatures() if f.existsAtInstant(t)])
1246 else:
1247 n = 1.
1248 p += obj.getPositionAtInstant(t).__mul__(n)
1249 nTotal += n
1250 assert nTotal>0, 'there should be at least one point for each instant'
1251 positions.addPosition(p.divide(nTotal))
1252 # velocities: if any
1253 if hasattr(obj1, 'velocities') and hasattr(obj2, 'velocities'):
1254 velocities = Trajectory()
1255 for t in newTimeInterval:
1256 nTotal = 0.
1257 p = Point(0.,0.)
1258 for obj in [obj1, obj2]:
1259 if obj.existsAtInstant(t):
1260 if obj.hasFeatures():
1261 n = len([f for f in obj.getFeatures() if f.existsAtInstant(t)])
1262 else:
1263 n = 1.
1264 p += obj.getVelocityAtInstant(t).__mul__(n)
1265 nTotal += n
1266 assert nTotal>0, 'there should be at least one point for each instant'
1267 velocities.addPosition(p.divide(nTotal))
1268 else: 1231 else:
1269 velocities = None 1232 print('Cannot update object positions without features')
1270 # user type 1233 # user type
1271 if obj1.getUserType() != obj2.getUserType(): 1234 if obj1.getUserType() != obj2.getUserType():
1272 print('The two moving objects have different user types: obj1 {} obj2 {}'.format(userTypeNames[obj1.getUserType()], userTypeNames[obj2.getUserType()])) 1235 print('The two moving objects have different user types: obj1 {} obj2 {}'.format(userTypeNames[obj1.getUserType()], userTypeNames[obj2.getUserType()]))
1273 1236 newObject.setUserType(obj1.getUserType())
1274 newObject = MovingObject(newNum, newTimeInterval, positions, velocities, userType = obj1.getUserType())
1275 if hasattr(obj1, 'featureNumbers') and hasattr(obj2, 'featureNumbers'):
1276 newObject.featureNumbers = obj1.featureNumbers+obj2.featureNumbers
1277 if obj1.hasFeatures() and obj2.hasFeatures():
1278 newObject.features = obj1.getFeatures()+obj2.getFeatures()
1279 return newObject 1237 return newObject
1280 1238
1281 def getObjectInTimeInterval(self, inter): 1239 def getObjectInTimeInterval(self, inter):
1282 '''Returns a new object extracted from self, 1240 '''Returns a new object extracted from self,
1283 restricted to time interval inter''' 1241 restricted to time interval inter'''