def divide_rec(p, l, r, compare): #base if r - l == 2: sort_rec(p, l, r, compare) guiprim.dist2(p[l], p[l + 1]) update_points(p[l], p[l + 1]) return p[l], p[l + 1] if r - l == 3: sort_rec(p, l, r, compare) d1 = guiprim.dist2(p[l], p[l + 1]) d2 = guiprim.dist2(p[l], p[l + 2]) d3 = guiprim.dist2(p[l + 1], p[l + 2]) if (d1 <= d2 and d1 <= d3): update_points(p[l], p[l + 1]) return p[l], p[l + 1] if (d2 <= d1 and d2 <= d3): update_points(p[l], p[l + 2]) return p[l], p[l + 2] if (d3 <= d1 and d3 <= d2): update_points(p[l + 1], p[l + 2]) return p[l + 1], p[l + 2] # 4 points or more q = (l + r) // 2 pm = p[q] #median point p1, p2 = divide_rec(p, l, q, compare) de = prim.dist2(p1, p2) p3, p4 = divide_rec(p, q, r, compare) dr = prim.dist2(p3, p4) p1, p2 = (p1, p2) if (de <= dr) else (p3, p4) update_points(p1, p2) merge(p, l, q, r, compare) return combine(p, l, r, p1, p2, pm)
def update_points(p1, p2): global a, b, id, hia, hib if (a != None and b != None): if (prim.dist2(p1, p2) >= prim.dist2(a, b)): return control.freeze_update() if a != None: a.unhilight(hia) if b != None: b.unhilight(hib) if id != None: control.plot_delete(id) a = p1 b = p2 hia = a.hilight() hib = b.hilight() id = a.lineto(b) control.thaw_update() control.update()
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 __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 dist2 (a, b): "retorna o quadrado da distancia entre a e b" return prim.dist2(a, b)
def dist2(a, b): "retorna o quadrado da distancia entre a e b" return prim.dist2(a, b)
def __distanceWrap(self, i, j): return dist2(self.pointList[i], self.pointList[j])
def distance_to_origin(origin_point: Point, test_point: Point) -> float: ''' returns the distance of a point to the origin point. ''' return dist2(origin_point, test_point)**0.5
def above(self, l): "Verifica se o ponto está acima da reta" prim.dist2(self, self) return self.y > l.m * self.x + l.b - epsilon