Mercurial Hosting > traffic-intelligence
changeset 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 | e62c2f5e25e6 |
children | a68e01bc3aa5 |
files | trafficintelligence/moving.py trafficintelligence/tests/moving.txt |
diffstat | 2 files changed, 55 insertions(+), 14 deletions(-) [+] |
line wrap: on
line diff
--- a/trafficintelligence/moving.py Thu Mar 14 17:08:05 2019 -0400 +++ b/trafficintelligence/moving.py Fri Mar 15 15:58:37 2019 -0400 @@ -229,6 +229,14 @@ def __neg__(self): return Point(-self.x, -self.y) + def __mul__(self, alpha): + 'Warning, returns a new Point' + return Point(self.x*alpha, self.y*alpha) + + def divide(self, alpha): + 'Warning, returns a new Point' + return Point(self.x/alpha, self.y/alpha) + def __getitem__(self, i): if i == 0: return self.x @@ -244,23 +252,18 @@ else: return Point(-self.y, self.x) + def normalize(self): + return self.divide(self.norm2()) + def projectLocal(self, v, clockwise = True): 'Projects point projected on v, v.orthogonal()' - e1 = v/v.norm2() + e1 = v.normalize() e2 = e1.orthogonal(clockwise) return Point(Point.dot(self, e1), Point.dot(self, e2)) def rotate(self, theta): return Point(self.x*cos(theta)-self.y*sin(theta), self.x*sin(theta)+self.y*cos(theta)) - def __mul__(self, alpha): - 'Warning, returns a new Point' - return Point(self.x*alpha, self.y*alpha) - - def divide(self, alpha): - 'Warning, returns a new Point' - return Point(self.x/alpha, self.y/alpha) - def plot(self, options = 'o', **kwargs): plot([self.x], [self.y], options, **kwargs) @@ -353,9 +356,8 @@ return (p1-p2).norm2() @staticmethod - def plotAll(points, **kwargs): - from matplotlib.pyplot import scatter - scatter([p.x for p in points],[p.y for p in points], **kwargs) + def plotAll(points, options = '', **kwargs): + plot([p.x for p in points],[p.y for p in points], options, **kwargs) def similarOrientation(self, refDirection, cosineThreshold): 'Indicates whether the cosine of the vector and refDirection is smaller than cosineThreshold' @@ -398,6 +400,27 @@ def agg(points, aggFunc = mean): return Point(aggFunc([p.x for p in points]), aggFunc([p.y for p in points])) + @staticmethod + def boundingRectangle(points, v): + '''Returns the bounding rectangle of the points, aligned on the vector v + A list of points is returned: front left, front right, rear right, rear left''' + e1 = v.normalize() + e2 = e1.orthogonal() + xCoords = [] + yCoords = [] + for p in points: + xCoords.append(Point.dot(e1, p)) + yCoords.append(Point.dot(e2, p)) + xmin = min(xCoords) + xmax = max(xCoords) + ymin = min(yCoords) + ymax = max(yCoords) + frontLeft = Point(xmax, ymin) + frontRight = Point(xmax, ymax) + rearLeft = Point(xmin, ymin) + rearRight = Point(xmin, ymax) + return [Point(Point.dot(e1, p), Point.dot(e2, p)) for p in [frontLeft, frontRight, rearRight, rearLeft]] + if shapelyAvailable: def pointsInPolygon(points, polygon): '''Optimized tests of a series of points within (Shapely) polygon (not prepared)''' @@ -509,8 +532,8 @@ d = s - alignment.getCumulativeDistance(i-1) # distance on subsegment #Get difference vector and then snap dv = alignment[i] - alignment[i-1] - magnitude = dv.norm2() - normalizedV = dv.divide(magnitude) + #magnitude = dv.norm2() + normalizedV = dv.normalize() #snapped = alignment[i-1] + normalizedV*d # snapped point coordinate along alignment # add offset finally orthoNormalizedV = normalizedV.orthogonal() @@ -1761,6 +1784,18 @@ relativePositions[(i,j)] = Point(median(xj-xi), median(yj-yi)) relativePositions[(j,i)] = -relativePositions[(i,j)] + def computeBoundingPolygon(self, instant): + '''Returns a bounding box for the feature positions at instant + bounding box format is a list of points (4 in this case for a rectangle) + + TODO add method argument if using different methods/shapes''' + if self.hasFeatures(): + positions = [f.getPositionAtInstant(instant) for f in self.getFeatures() if f.existsAtInstant(instant)] + return Point.boundingRectangle(positions, self.getVelocityAtInstant(instant)) + else: + print('Object {} has no features'.format(self.getNum())) + return None + ### # User Type Classification ###
--- a/trafficintelligence/tests/moving.txt Thu Mar 14 17:08:05 2019 -0400 +++ b/trafficintelligence/tests/moving.txt Fri Mar 15 15:58:37 2019 -0400 @@ -75,6 +75,12 @@ >>> Point.distanceNorm2(Point(3,4),Point(1,7)) 3.605551275463989 +>>> Point.boundingRectangle([Point(0,0), Point(1,0), Point(0,1), Point(1,1)], Point(1, 1)) +[(0.500000,1.500000), (1.500000,0.500000), (0.500000,-0.500000), (-0.500000,0.500000)] +>>> Point.boundingRectangle([Point(0,0), Point(1,0), Point(0,1), Point(1,1)], Point(-1, -1)) +[(0.500000,-0.500000), (-0.500000,0.500000), (0.500000,1.500000), (1.500000,0.500000)] + + >>> Point(3,2).inPolygon(np.array([[0,0],[1,0],[1,1],[0,1]])) False >>> Point(3,2).inPolygon(np.array([[0,0],[4,0],[4,3],[0,3]]))