Mercurial Hosting > traffic-intelligence
comparison trafficintelligence/moving.py @ 1106:799ef82caa1a v0.2.4
added code to compute bounding rectangle around each user
author | Nicolas Saunier <nicolas.saunier@polymtl.ca> |
---|---|
date | Fri, 15 Mar 2019 15:58:37 -0400 |
parents | 1e833fd8490d |
children | 6e8ab471ebd4 |
comparison
equal
deleted
inserted
replaced
1105:e62c2f5e25e6 | 1106:799ef82caa1a |
---|---|
227 return Point(self.x-other.x, self.y-other.y) | 227 return Point(self.x-other.x, self.y-other.y) |
228 | 228 |
229 def __neg__(self): | 229 def __neg__(self): |
230 return Point(-self.x, -self.y) | 230 return Point(-self.x, -self.y) |
231 | 231 |
232 def __mul__(self, alpha): | |
233 'Warning, returns a new Point' | |
234 return Point(self.x*alpha, self.y*alpha) | |
235 | |
236 def divide(self, alpha): | |
237 'Warning, returns a new Point' | |
238 return Point(self.x/alpha, self.y/alpha) | |
239 | |
232 def __getitem__(self, i): | 240 def __getitem__(self, i): |
233 if i == 0: | 241 if i == 0: |
234 return self.x | 242 return self.x |
235 elif i == 1: | 243 elif i == 1: |
236 return self.y | 244 return self.y |
242 if clockwise: | 250 if clockwise: |
243 return Point(self.y, -self.x) | 251 return Point(self.y, -self.x) |
244 else: | 252 else: |
245 return Point(-self.y, self.x) | 253 return Point(-self.y, self.x) |
246 | 254 |
255 def normalize(self): | |
256 return self.divide(self.norm2()) | |
257 | |
247 def projectLocal(self, v, clockwise = True): | 258 def projectLocal(self, v, clockwise = True): |
248 'Projects point projected on v, v.orthogonal()' | 259 'Projects point projected on v, v.orthogonal()' |
249 e1 = v/v.norm2() | 260 e1 = v.normalize() |
250 e2 = e1.orthogonal(clockwise) | 261 e2 = e1.orthogonal(clockwise) |
251 return Point(Point.dot(self, e1), Point.dot(self, e2)) | 262 return Point(Point.dot(self, e1), Point.dot(self, e2)) |
252 | 263 |
253 def rotate(self, theta): | 264 def rotate(self, theta): |
254 return Point(self.x*cos(theta)-self.y*sin(theta), self.x*sin(theta)+self.y*cos(theta)) | 265 return Point(self.x*cos(theta)-self.y*sin(theta), self.x*sin(theta)+self.y*cos(theta)) |
255 | 266 |
256 def __mul__(self, alpha): | |
257 'Warning, returns a new Point' | |
258 return Point(self.x*alpha, self.y*alpha) | |
259 | |
260 def divide(self, alpha): | |
261 'Warning, returns a new Point' | |
262 return Point(self.x/alpha, self.y/alpha) | |
263 | |
264 def plot(self, options = 'o', **kwargs): | 267 def plot(self, options = 'o', **kwargs): |
265 plot([self.x], [self.y], options, **kwargs) | 268 plot([self.x], [self.y], options, **kwargs) |
266 | 269 |
267 @staticmethod | 270 @staticmethod |
268 def plotSegment(p1, p2, options = 'o', **kwargs): | 271 def plotSegment(p1, p2, options = 'o', **kwargs): |
351 @staticmethod | 354 @staticmethod |
352 def distanceNorm2(p1, p2): | 355 def distanceNorm2(p1, p2): |
353 return (p1-p2).norm2() | 356 return (p1-p2).norm2() |
354 | 357 |
355 @staticmethod | 358 @staticmethod |
356 def plotAll(points, **kwargs): | 359 def plotAll(points, options = '', **kwargs): |
357 from matplotlib.pyplot import scatter | 360 plot([p.x for p in points],[p.y for p in points], options, **kwargs) |
358 scatter([p.x for p in points],[p.y for p in points], **kwargs) | |
359 | 361 |
360 def similarOrientation(self, refDirection, cosineThreshold): | 362 def similarOrientation(self, refDirection, cosineThreshold): |
361 'Indicates whether the cosine of the vector and refDirection is smaller than cosineThreshold' | 363 'Indicates whether the cosine of the vector and refDirection is smaller than cosineThreshold' |
362 return Point.cosine(self, refDirection) >= cosineThreshold | 364 return Point.cosine(self, refDirection) >= cosineThreshold |
363 | 365 |
396 | 398 |
397 @staticmethod | 399 @staticmethod |
398 def agg(points, aggFunc = mean): | 400 def agg(points, aggFunc = mean): |
399 return Point(aggFunc([p.x for p in points]), aggFunc([p.y for p in points])) | 401 return Point(aggFunc([p.x for p in points]), aggFunc([p.y for p in points])) |
400 | 402 |
403 @staticmethod | |
404 def boundingRectangle(points, v): | |
405 '''Returns the bounding rectangle of the points, aligned on the vector v | |
406 A list of points is returned: front left, front right, rear right, rear left''' | |
407 e1 = v.normalize() | |
408 e2 = e1.orthogonal() | |
409 xCoords = [] | |
410 yCoords = [] | |
411 for p in points: | |
412 xCoords.append(Point.dot(e1, p)) | |
413 yCoords.append(Point.dot(e2, p)) | |
414 xmin = min(xCoords) | |
415 xmax = max(xCoords) | |
416 ymin = min(yCoords) | |
417 ymax = max(yCoords) | |
418 frontLeft = Point(xmax, ymin) | |
419 frontRight = Point(xmax, ymax) | |
420 rearLeft = Point(xmin, ymin) | |
421 rearRight = Point(xmin, ymax) | |
422 return [Point(Point.dot(e1, p), Point.dot(e2, p)) for p in [frontLeft, frontRight, rearRight, rearLeft]] | |
423 | |
401 if shapelyAvailable: | 424 if shapelyAvailable: |
402 def pointsInPolygon(points, polygon): | 425 def pointsInPolygon(points, polygon): |
403 '''Optimized tests of a series of points within (Shapely) polygon (not prepared)''' | 426 '''Optimized tests of a series of points within (Shapely) polygon (not prepared)''' |
404 if type(polygon) == PreparedGeometry: | 427 if type(polygon) == PreparedGeometry: |
405 prepared_polygon = polygon | 428 prepared_polygon = polygon |
507 i += 1 | 530 i += 1 |
508 if i < len(alignment): | 531 if i < len(alignment): |
509 d = s - alignment.getCumulativeDistance(i-1) # distance on subsegment | 532 d = s - alignment.getCumulativeDistance(i-1) # distance on subsegment |
510 #Get difference vector and then snap | 533 #Get difference vector and then snap |
511 dv = alignment[i] - alignment[i-1] | 534 dv = alignment[i] - alignment[i-1] |
512 magnitude = dv.norm2() | 535 #magnitude = dv.norm2() |
513 normalizedV = dv.divide(magnitude) | 536 normalizedV = dv.normalize() |
514 #snapped = alignment[i-1] + normalizedV*d # snapped point coordinate along alignment | 537 #snapped = alignment[i-1] + normalizedV*d # snapped point coordinate along alignment |
515 # add offset finally | 538 # add offset finally |
516 orthoNormalizedV = normalizedV.orthogonal() | 539 orthoNormalizedV = normalizedV.orthogonal() |
517 return alignment[i-1] + normalizedV*d + orthoNormalizedV*y | 540 return alignment[i-1] + normalizedV*d + orthoNormalizedV*y |
518 else: | 541 else: |
1759 xj = array(fj.getXCoordinates()[inter.first-fj.getFirstInstant():int(fj.length())-(fj.getLastInstant()-inter.last)]) | 1782 xj = array(fj.getXCoordinates()[inter.first-fj.getFirstInstant():int(fj.length())-(fj.getLastInstant()-inter.last)]) |
1760 yj = array(fj.getYCoordinates()[inter.first-fj.getFirstInstant():int(fj.length())-(fj.getLastInstant()-inter.last)]) | 1783 yj = array(fj.getYCoordinates()[inter.first-fj.getFirstInstant():int(fj.length())-(fj.getLastInstant()-inter.last)]) |
1761 relativePositions[(i,j)] = Point(median(xj-xi), median(yj-yi)) | 1784 relativePositions[(i,j)] = Point(median(xj-xi), median(yj-yi)) |
1762 relativePositions[(j,i)] = -relativePositions[(i,j)] | 1785 relativePositions[(j,i)] = -relativePositions[(i,j)] |
1763 | 1786 |
1787 def computeBoundingPolygon(self, instant): | |
1788 '''Returns a bounding box for the feature positions at instant | |
1789 bounding box format is a list of points (4 in this case for a rectangle) | |
1790 | |
1791 TODO add method argument if using different methods/shapes''' | |
1792 if self.hasFeatures(): | |
1793 positions = [f.getPositionAtInstant(instant) for f in self.getFeatures() if f.existsAtInstant(instant)] | |
1794 return Point.boundingRectangle(positions, self.getVelocityAtInstant(instant)) | |
1795 else: | |
1796 print('Object {} has no features'.format(self.getNum())) | |
1797 return None | |
1798 | |
1764 ### | 1799 ### |
1765 # User Type Classification | 1800 # User Type Classification |
1766 ### | 1801 ### |
1767 def classifyUserTypeSpeedMotorized(self, threshold, aggregationFunc = median, nInstantsIgnoredAtEnds = 0): | 1802 def classifyUserTypeSpeedMotorized(self, threshold, aggregationFunc = median, nInstantsIgnoredAtEnds = 0): |
1768 '''Classifies slow and fast road users | 1803 '''Classifies slow and fast road users |