def jarvis(points, cutoff=False): if cutoff: points = interior_elimination(points) #removing duplicate points pts = list(set(points)) P0 = min(pts, key=lambda p: (p[1], p[0])) H = [P0] # Since 'for loops' works as generators, 'H' is gonna be # populated within the loop and 'h' will always be # the most recent added. In the last iteration, 'H' won't # be updated (case when P0 is reached again) # and the 'for loop' ends. for h in H: a = h for b in pts: if ccw(h, a, b) < 0 or (ccw(h, a, b) == 0 and \ distance(h, b) > distance(h, a)): a = b if a is not P0: H.append(a) assert is_convex(H) return H
def half_hull(pts): h = [] for p in pts: while len(h) >= 2 and ccw(h[-2], h[-1], p) <= 0: h.pop() h.append(p) return h
def compare(P0, B, C, to_ignore): d = ccw(P0, C, B) if d is not 0: return 1 if d > 0 else -1 if distance(P0, B) > distance(P0, C): to_ignore[C] = True return -1 to_ignore[B] = True return 1
def inside_triangle(n, v1=(500, 500), v2=(1000, 0)): "http://mathworld.wolfram.com/TrianglePointPicking.html" #pts = [(0, 0), (500, 500), (1000, 0)] pts = [] for i in range(n): while True: a1 = random.random() a2 = random.random() pt = (a1*v1[0]+ a2*v2[0], a1*v1[1] + a2*v2[1]) if ccw(v2, v1, pt) > 0: break #skipping when it's in the other side of paralelogram pts.append(pt) return pts
def graham(points, cutoff=False): if cutoff: points = interior_elimination(points) #removing duplicate points pts = list(set(points)) P0 = min(pts, key=lambda p: (p[1], p[0])) pts.remove(P0) # sorting by polar angles and ignoring collinear points # (keeping the farthest one) to_ignore = {} pts.sort(lambda B, C: compare(P0, B, C, to_ignore)) H = [P0] + pts[:2] for i in range(2, len(pts)): if pts[i] in to_ignore: continue while ccw(H[-2], H[-1], pts[i]) <= 0: H.pop() H.append(pts[i]) assert is_convex(H) return H