Created
August 24, 2015 23:39
-
-
Save allyourcode/26699abc6240a1b33168 to your computer and use it in GitHub Desktop.
Seems to work. Haven't tested thoroughly though.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import math | |
| import operator | |
| def normalize_azimuth_radians(angle): | |
| positive = (angle % 2 * math.pi) | |
| return positive if positive <= math.pi else positive - 2 * math.pi | |
| class Vector(object): | |
| def __init__(self, x, y): | |
| self.x = x | |
| self.y = y | |
| def __str__(self): | |
| return '(%f, %f)' % (self.x, self.y) | |
| @property | |
| def length(self): | |
| return math.sqrt(self.dot(self)) | |
| @property | |
| def azimuth_radians(self): | |
| return math.atan2(self.y, self.x) | |
| @property | |
| def normalized(self): | |
| return Vector(self.x / self.length, self.y / self.length) | |
| def _operate_componentwise(self, other, operator): | |
| return Vector(operator(self.x, other.x), | |
| operator(self.y, other.y)) | |
| def __add__(self, other): | |
| return self._operate_componentwise(other, operator.add) | |
| def __sub__(self, other): | |
| return self._operate_componentwise(other, operator.sub) | |
| def dot(self, other): | |
| return self.x * other.x + self.y * other.y | |
| def TurnRadians(source, pivot, destination): | |
| source_ray = source - pivot | |
| destination_ray = destination - pivot | |
| return normalize_azimuth_radians( | |
| destination_ray.azimuth_radians - source_ray.azimuth_radians) | |
| def Reflect(fixed, satelite): | |
| diff = satelite - fixed | |
| return fixed - diff | |
| def ConvexHull(points): | |
| # Phase 1: Find right-most point to use as starting point. | |
| first = max(points, key=lambda p: (p.x, p.y)) | |
| # Phase 2: Wrap around. | |
| result = [first] | |
| remaining = set(points) | |
| current = first | |
| previous = first + Vector(0, 1) | |
| def TurnAngle(p): | |
| reflected = Reflect(current, previous) | |
| return TurnRadians(reflected, current, p) % (2 * math.pi) | |
| def Distance(p): | |
| return (p - current).length | |
| while remaining: | |
| next = min(remaining, | |
| key=lambda p: (TurnAngle(p), -Distance(p))) | |
| if next == first: | |
| return result | |
| result.append(next) | |
| remaining -= set([next]) | |
| previous, current = current, next | |
| # This is supposed to be unreachable! | |
| assert False, "Failed to terminate while calculating convex hull :(" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment