def q_hull(points): n = len(points) if n == 1: return set(points) f_ind = 0 for i, pt in enumerate(points): if pt.y < points[f_ind].y or\ (pt.y == points[f_ind].y and pt.x < points[f_ind].x): f_ind = i swap(points, 0, f_ind) s_ind = 1 for i in range(1, len(points)): if prim.right(points[0], points[s_ind], points[i]) or\ (prim.collinear(points[0], points[s_ind], points[i]) and\ (prim.dist2(points[0], points[s_ind]) < prim.dist2(points[0], points[i]))): s_ind = i swap(points, n - 1, s_ind) hull = q_hull_rec(points, 0, n - 1) for pt in hull: pt.hilight("blue") return hull
def q_hull_rec(points, start, end): if end - start == 1: # two points ret_val = set([points[end], points[start]]) else: part1, part2 = partition(points, start, end) #hilights points in current recursive call hilight_rec_call(points, start, end, part1, part2) res1 = q_hull_rec(points, part1, part2) res2 = q_hull_rec(points, part2, end) ret_val = res1.union(res2) # treats degenerated case if len(ret_val) == 3: ret_val = list(ret_val) if prim.collinear(ret_val[0], ret_val[1], ret_val[2]): if prim.on_segment(ret_val[0], ret_val[1], ret_val[2]): ret_val = set([ret_val[0], ret_val[1]]) elif prim.on_segment(ret_val[0], ret_val[2], ret_val[1]): ret_val = set([ret_val[0], ret_val[2]]) else: ret_val = set([ret_val[1], ret_val[2]]) else: ret_val = set(ret_val) return ret_val
def __merge(self, startIndex, midIndex, endIndex): leftCopy = self.pointList[startIndex:midIndex + 1] rightCopy = self.pointList[midIndex + 1:endIndex + 1] leftIndex = 0 rightIndex = 0 sortIndex = startIndex while leftIndex < len(leftCopy) and rightIndex < len(rightCopy): if not left_on(self.pointList[0], rightCopy[rightIndex], leftCopy[leftIndex]): self.pointList[sortIndex] = leftCopy[leftIndex] leftIndex = leftIndex + 1 elif collinear(self.pointList[0], leftCopy[leftIndex], rightCopy[rightIndex]): if dist2(self.pointList[0], leftCopy[leftIndex]) < dist2( self.pointList[0], rightCopy[rightIndex]): self.pointList[sortIndex] = leftCopy[leftIndex] leftIndex = leftIndex + 1 else: self.pointList[sortIndex] = rightCopy[rightIndex] rightIndex = rightIndex + 1 else: self.pointList[sortIndex] = rightCopy[rightIndex] rightIndex = rightIndex + 1 sortIndex = sortIndex + 1 while leftIndex < len(leftCopy): self.pointList[sortIndex] = leftCopy[leftIndex] leftIndex = leftIndex + 1 sortIndex = sortIndex + 1 while rightIndex < len(rightCopy): self.pointList[sortIndex] = rightCopy[rightIndex] rightIndex = rightIndex + 1 sortIndex = sortIndex + 1
def Quickhull(P): '''Recebe uma coleção de pontos P e devolve seu fecho convexo''' n = len(P) if n == 1: return [P[0]] # encontra primeiro ponto extremo k = 0 for i in range(n): # desempata por x if P[i].y < P[k].y or (P[i].y == P[k].y and P[i].x < P[k].x): k = i P[0], P[k] = P[k], P[0] # encontra extremo consecutivo ao primeiro i = 1 dist = 0 for j in range(2, n): if right(P[0], P[i], P[j]): i = j # desempata pelo mais distante elif collinear(P[0], P[i], P[j]) and dist2(P[0], P[i]) < dist2(P[0], P[j]): i = j P[n - 1], P[i] = P[i], P[n - 1] P[0].lineto(P[n - 1], 'cyan') control.thaw_update() control.update() control.freeze_update() control.sleep() quick = quickhull_rec(P, 0, n - 1, Point(P[0].x, P[0].y), Point(P[n - 1].x, P[n - 1].y)) for p in quick: p.hilight('yellow') return quick
def collinear (a, b, c): "retorna verdadeiro se a, b, c sao colineares" ret = prim.collinear (a, b, c) #triang (a, b, c) return ret
def collinear(a, b, c): "retorna verdadeiro se a, b, c sao colineares" ret = prim.collinear(a, b, c) #triang (a, b, c) return ret
def _succ_comp(self, seg, reference): return right(seg.init, seg.to, reference) or\ collinear(seg.init, seg.to, reference)
def _pred_comp(self, seg, reference): return left(seg.init, seg.to, reference) or\ collinear(seg.init, seg.to, reference)
def _del_comp(self, seg1, seg2, reference): return left(seg1.init, seg1.to, reference) or\ (collinear(seg1.init, seg1.to, reference) and #if ties left(seg1.init, seg1.to, seg2.init)) # looks at starting point
def _ins_comp(self, seg1, seg2, reference): return left(seg1.init, seg1.to, reference) or\ (collinear(seg1.init, seg1.to, reference) and #if ties left(seg1.init, seg1.to, seg2.to)) # looks at endpoint
def __collinearWrap(self, i, j, k): return collinear(self.pointList[i], self.pointList[j], self.pointList[k])