Mercurial Hosting > traffic-intelligence
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''' |