def test_left_right(self): p = Point2D(0, 0) q = Point2D(1, 0) r = Point2D(0, 1) self.assertTrue(left(p, q, r)) self.assertFalse(left(p, r, q)) self.assertFalse(right(p, q, r)) self.assertTrue(right(p, r, q))
def find(S: List[Point2D]) -> List[int]: S1 = [Point2D(*i) for i in S] # lo mismo que S1=S=[Point2D(x, y) for x,y in S] # Eleccion punto inicial y ordenacion min_y = min(p.y for p in S1) p = argmax((pt for pt in S1 if min_y == pt.y), lambda pt: pt.x) S1 = [p] + sorted((q for q in S1 if q != p), key=lambda q: (atan2(p.y - q.y, p.x - q.x), q.x)) Q = Lifo() Q.push(0), Q.push(1), Q.push(2) for pi in range(3, len(S1)): pj, pk = Q[-1], Q[-2] while not left(S1[pk], S1[pj], S1[pi]): Q.pop() pj, pk = Q[-1], Q[-2] Q.push(pi) return [S.index(S1[Q.pop()]) for i in range(len(Q))]
def find(self, S: "IList<Point2D>") -> "IList<int>": S1 = S = [Point2D(*p) for p in S] min_y = min(pt.y for pt in S) p = argmax((pt for pt in S if pt.y == min_y), lambda pt: pt.x) S = [p] + sorted((q for q in S if q != p), key=lambda q: (atan2(p.y - q.y, p.x - q.x), q.x)) Q = Lifo() Q.push(0) Q.push(1) Q.push(2) for pi in range(3, len(S)): pj, pk = Q[-1], Q[-2] while not left(S[pk], S[pj], S[pi]): Q.pop() pj, pk = Q[-1], Q[-2] Q.push(pi) return [S1.index(S[Q.pop()]) for i in range(len(Q))] #> graham
def quickhull(self, S: "IList<(T, T)>") -> "Iterable<int>": if len(S) <= 2: return list(S) p, q = min(S), max(S) qhull = self._quickhull(p, [z for z in S if z != p and z != q and left(p, q, z)], q)[1:] + \ self._quickhull(q, [z for z in S if z != p and z != q and right(p, q, z)], p)[1:] return qhull
def _quickhull(self, p, A, q): if len(A) == 0: return [p, q] h = argmax(A, lambda z: triangle_area(p, q, z)) return self._quickhull(p, [z for z in A if left(p, h, z)],h) + \ self._quickhull(h, [z for z in A if left(h, q, z)],q)[1:]