Skip to content

Instantly share code, notes, and snippets.

@allyourcode
Created August 24, 2015 23:39
Show Gist options
  • Select an option

  • Save allyourcode/26699abc6240a1b33168 to your computer and use it in GitHub Desktop.

Select an option

Save allyourcode/26699abc6240a1b33168 to your computer and use it in GitHub Desktop.
Seems to work. Haven't tested thoroughly though.
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