def Brute (l): "Algoritmo forca bruta para encontrar o par de pontos mais distante" if len (l) < 2: return None farthest = 0 a = b = None id = None for i in range (len(l)): for j in range (i + 1, len (l)): dist = dist2 (l[i], l[j]) if dist > farthest: control.freeze_update () if a != None: a.unhilight (hia) if b != None: b.unhilight (hib) if id != None: control.plot_delete (id) farthest = dist a = l[i] b = l[j] hia = a.hilight () hib = b.hilight () id = a.lineto (b) control.thaw_update () control.update () ret = Segment (a, b) ret.extra_info = 'distancia: %.2f'%math.sqrt (dist2 (a, b)) return ret
def Brute (l): "Algoritmo forca bruta para encontrar o par de pontos mais proximo" if len (l) < 2: return None closest = float("inf") a = b = None id = None for i in range (len(l)): for j in range (i + 1, len (l)): dist = dist2 (l[i], l[j]) if dist < closest: control.freeze_update () if a != None: a.unhilight (hia) if b != None: b.unhilight (hib) if id != None: control.plot_delete (id) closest = dist a = l[i] b = l[j] hia = a.hilight () hib = b.hilight () id = a.lineto (b) control.thaw_update() control.update () a.hilight('green') b.hilight('green') ret = Segment (a, b) ret.extra_info = 'distancia: %.2f'%math.sqrt (dist2 (a, b)) print(math.sqrt (dist2 (a, b))) return ret
def plot(self): if self.rank != 0: return self.drawing = [] for i in range(3): self.drawing.append(self.P[i - 1].inner.lineto( self.P[i].inner, COLOR_TRIANG)) control.thaw_update() control.update() control.freeze_update()
def e_lineto(p, q, color=config.COLOR_PRIM): if max(p.inf, q.inf) > 0: return keep = p.inner.lineto(q.inner, color) control.thaw_update() control.update() control.freeze_update() control.sleep() p.inner.remove_lineto(q, keep)
def Fortune(P): Q = event_queue(P) V = DCEL() T = BST() for event in Q.keys(): V.add_face(event.face) while Q: q = Q.pop() q.point.hilight() par_plots, sweep = plot_all(T.all_leaves(), V, q.point.y) control.sleep() if q.is_site_event: handle_site_event(q, T, Q, V) else: handle_circle_event(q, T, Q, V) q.point.unplot() control.sleep() if len(Q) > 0: next_y = Q.top().point.y line_y = q.point.y leaves = T.all_leaves() # while not math.isclose(line_y, next_y, rel_tol=4*FORTUNE_PLOT_RATE): # FORTUNE_PLOT_RATE = abs(line_y - next_y)/100 while line_y > next_y: control.thaw_sleep() if abs(line_y - next_y) > FORTUNE_PLOT_RATE * 10**3: line_y -= abs(line_y - next_y) / 10 else: line_y -= FORTUNE_PLOT_RATE unplot_all(par_plots, V.hedges, sweep) par_plots, sweep = plot_all(leaves, V, line_y) control.thaw_update() control.update() control.freeze_update() unplot_all(par_plots, V.hedges, sweep) q.point.unhilight() control.update() vertices = [v.p for v in V.vertices] borders = find_borders(P + vertices) finalize_voronoi(V, T, borders) for h in V.hedges: h.segment.plot() return V
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 partition(P, p, r, point_p, point_r): '''Recebe uma coleção de pontos em posição geral, com pelo menos 3 pontos tal que os pontos de índice p e r são extremos consecutivos na fronteira do fecho convexo da coleção no sentido anti-horário. Rearranja a coleção de pontos e devolve (s,q) para o algoritmo do QuickHull.''' q = extreme(P, p, r) points[(point_r, P[q])] = point_r.lineto(P[q], 'cyan') points[(P[q], point_p)] = P[q].lineto(point_p, 'cyan') control.thaw_update() control.update() control.freeze_update() control.sleep() P[p + 1], P[q] = P[q], P[p + 1] s = q = r for point, id in ids: point.unhilight(id) for k in range(r - 1, p + 1, -1): if left(P[p], P[p + 1], P[k]): id = P[k].hilight('green') ids.append((P[k], id)) s -= 1 P[s], P[k] = P[k], P[s] elif left(P[p + 1], P[r], P[k]): id = P[k].hilight('red') ids.append((P[k], id)) s -= 1 q -= 1 P[k], P[q] = P[q], P[k] if s != q: P[k], P[s] = P[s], P[k] control.thaw_update() control.update() control.freeze_update() control.sleep() s -= 1 q -= 1 P[q], P[p + 1] = P[p + 1], P[q] if s != q: P[s], P[p + 1] = P[p + 1], P[s] s -= 1 P[s], P[p] = P[p], P[s] return s, q
def triang (a, b, c): "desenha (e apaga) os lados do triangulo abc" a.lineto (c, config.COLOR_PRIM) #b.lineto (a, config.COLOR_PRIM) c.lineto (b, config.COLOR_PRIM) c.hilight () control.thaw_update () control.update () control.freeze_update () control.sleep () c.unhilight () a.remove_lineto (c) #b.remove_lineto (a) c.remove_lineto (b)
def triang(a, b, c): "desenha (e apaga) os lados do triangulo abc" a.lineto(c, config.COLOR_PRIM) #b.lineto (a, config.COLOR_PRIM) c.lineto(b, config.COLOR_PRIM) c.hilight() control.thaw_update() control.update() control.freeze_update() control.sleep() c.unhilight() a.remove_lineto(c) #b.remove_lineto (a) c.remove_lineto(b)
def ear_tip(P, v): '''Recebe um polígono P e um vértice v desse polígono, e decide se ele é uma ponta de orelha''' u = P.prev(v) w = P.next(v) v.hilight('green') u.hilight('yellow') w.hilight('yellow') control.sleep() control.thaw_update() control.update() diag = diagonal(P, u, w) u.unhilight() w.unhilight() if not diag: v.unhilight() control.sleep() control.thaw_update() control.update() return diag
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 triangulation(n, P): '''Recebe um polígono P com n lados e devolve a triangulação de P''' ears = find_ears(P) v3 = P.pts while n > 3: v2 = v3 while not ears[v2]: v2 = P.next(v2) v2.hilight("blue") v1 = P.prev(v2) v3 = P.next(v2) v1.lineto(v3, "blue") control.sleep() control.thaw_update() control.update() print(v1, v3) v2.unhilight() control.sleep() control.thaw_update() control.update() P.remove_vertex(v2) n -= 1 ears[v1] = ear_tip(P, v1) ears[v3] = ear_tip(P, v3)
def __update(self): control.thaw_update() control.update() control.freeze_update() control.sleep()
def treat_event(p, Q, T): ''' Recebe o ponto evento e o trata conforme seu tipo: extremo esquerdo, extremo direito e ponto de intersecção. ''' event = p[1] point = p[0] print(event, end="\n\n") print("ANTES") # print(dic) for seg in T: print(f"key: {T.key(seg)}, value: {seg}") linea = 0 point.hilight("green") if event.t == "left": s = event.s T.add((s, s)) linea = control.plot_vert_line(s.lower.x, "cyan") control.sleep() control.update() try: prev_index = T.bisect_left((s, s)) prev_index -= 1 if prev_index >= 0: pred = T[prev_index][1] print("PRED: ", pred) if s.intersects(pred): print("INTERSECTA!!!!") verify_new_event(point, Q, s, pred) except IndexError: pass try: next_index = T.bisect_right(s) if next_index <= len(T): succ = T[next_index][1] print("SUCC: ", succ) if s.intersects(succ): verify_new_event(point, Q, s, succ) except IndexError: pass if event.t == "right": s = dic[event.s] segmnt = s[1] linea = control.plot_vert_line(segmnt.upper.x, "cyan") control.sleep() control.update() try: print(s) prev_index = T.bisect_left(s) next_index = T.bisect_right(s) prev_index -= 1 if prev_index >= 0 and next_index <= len(T): pred = T[prev_index][1] succ = T[next_index][1] print("PRED: ", pred) print("SUCC: ", succ) T.pop(T.index(s)) if pred.intersects(succ): verify_new_event(point, Q, succ, pred) except IndexError: T.pop(T.index(s)) if event.t == "inter": s1 = event.s1 s2 = event.s2 if right(s2.lower, s2.upper, s1.lower): s1, s2 = s2, s1 rs1 = dic[s1] rs2 = dic[s2] intersection = intersection_point(s1, s2) intersections.append(intersection) intersections[len(intersections) - 1].hilight("yellow") print(len(intersections)) linea = control.plot_vert_line(intersection.x, "cyan") control.sleep() control.update() try: prev_index = T.bisect_left(rs1) prev_index -= 1 if prev_index < 0: pred = None if rs1 == T[prev_index]: prev_index -= 1 elif prev_index >= 0: pred = T[prev_index][1] print("PRED: ", pred) except IndexError: pred = None try: next_index = T.bisect_right(rs2) if next_index >= len(T): succ = None if rs2 == T[next_index]: next_index += 1 elif next_index < len(T): succ = T[next_index][1] print("SUCC: ", succ) except IndexError: succ = None print("s1: ", s1, " rs1: ", rs1) print("s2: ", s2, " rs2: ", rs2, "\n") T.pop(T.index(rs1)) T.pop(T.index(rs2)) # Insere ao contrário new_s1 = segment.Segment(intersection, s1.upper) new_s2 = segment.Segment(intersection, s2.upper) print(f"new_s1: {new_s1}, new_s2:{new_s2}") T.add((new_s2, s2)) T.add((new_s1, s1)) dic[s1] = (new_s1, s1) dic[s2] = (new_s2, s2) if pred != None and pred.intersects(s2): verify_new_event(point, Q, pred, s2, intersection) if succ != None and s1.intersects(succ): verify_new_event(point, Q, s1, succ, intersection) control.plot_delete(linea) control.sleep() control.update() point.unhilight() print("DEPOIS") for seg in T: print("key: ", str(seg)) print("")
def fortune(l, triang): # Inicializa as estruturas de dados Q = EventQueue() Beach = BeachLine() Vor = dcel() CircDraw = draw_circ_events() # # Remove pontos repetidos na entrada l = unique_points(l) # Inicializa as variáveis global DelaunayTriangDraw DelaunayTriangDraw = triang lineid = None partiallines = None parabola_list = None max_x = min_x = l[0].x max_y = min_y = l[0].y first_y = None high_y = None cur_c = None y_count = 1 last_y = None # # Busca a bounding box dos pontos, e insere os pontos na fila for p in l: if p.x > max_x: max_x = p.x if p.x < min_x: min_x = p.x if p.y > max_y: max_y = p.y if p.y < min_y: min_y = p.y if high_y is None: high_y = p.y elif p.y > high_y: high_y = p.y y_count = 1 elif p.y == high_y: y_count = y_count + 1 Q.put(Ponto(p.x, p.y), Ponto(p.x, p.y)) # Desenhas os pontos um pouco maiores control.plot_disc(p.x, p.y, config.COLOR_POINT, 4) # # Define os bounds da tela yd = max_y - min_y xd = max_x - min_x dd = max(yd, xd) mfactor = 0.7 bounds = { "maxx": (max_x + min_x) / 2 + dd * mfactor, "minx": (max_x + min_x) / 2 - dd * mfactor, "maxy": (max_y + min_y) / 2 + dd * mfactor, "miny": (max_y + min_y) / 2 - dd * mfactor } Beach.bounds = bounds # Caso os primeiros pontos tenham a mesma y-coordenada, trata este caso particular if y_count > 1: aligned = [] for i in range(y_count): aligned.append(Q.takeHighest()) aligned = list(reversed(aligned)) for i in range(len(aligned) - 1): drawDelaunayEdge(aligned[i].x, aligned[i].y, aligned[i + 1].x, aligned[i + 1].y) Beach.create_particular(aligned) # Loop principal while Q.n > 0: atual = Q.takeHighest() ## Remove o desenho do ponto evento círculo da iteração anterior, e desenha a nova posição da linha de varredura control.freeze_update() if cur_c is not None: control.plot_delete(cur_c) cur_c = None lineid = control.plot_horiz_line(atual.y) ## # Trata evento ponto ou círculo if atual.isPonto: trataPonto(atual, Q, Beach, CircDraw) else: cur_c = control.plot_disc(atual.x, atual.y, config.COLOR_ALT5, 4) CircDraw.rem_point(atual.x, atual.y) trataCirculo(atual, Q, Beach, CircDraw) # # Desenha as parábolas e as arestas de Voronoi parciais parabola_list = Beach.draw_parabolas(atual.y) partiallines = Beach.draw_partial(atual.y) control.thaw_update() control.update() control.sleep() # Remove o desenho das parábolas e da linha de varredura desta iteração if lineid is not None: control.plot_delete(lineid) if parabola_list is not None: for i in parabola_list: control.plot_delete(i) # Remove as parábolas que 'sairam da tela', remove seus respectivos eventos e o desenho destes eventos evlist = Beach.trata_extremos(atual.y) for ev in evlist: CircDraw.rem_point(ev.x, ev.y) Q.take(ev) last_y = atual.y # Atualiza o desenho para a última iteração lower = last_y - 2 * (Beach.bounds["maxy"] - Beach.bounds["miny"]) partiallines = Beach.draw_partial(lower) if cur_c is not None: control.plot_delete(cur_c) cur_c = None # Desenha as arestas de Delaunay que não foram consideradas durante o algoritmo (por conta das parabolas serem removidas) if Beach.llist: for i in range(len(Beach.llist) - 1): p1, q1 = Beach.llist[i] p2, q2 = Beach.llist[i + 1] x, y = lineIntersect(p1, q1, p2, q2) if x is not None and x < Beach.bounds["minx"]: Beach.llist[i + 1] = [p1, q1] if q1 == p2: drawDelaunayEdge(p1.x, p1.y, q2.x, q2.y) elif q1 == p1: drawDelaunayEdge(p2.x, p2.y, q2.x, q2.y) elif q2 == p2: drawDelaunayEdge(p1.x, p1.y, q1.x, q1.y) else: drawDelaunayEdge(p2.x, p2.y, q1.x, q1.y) if Beach.rlist: for i in range(len(Beach.rlist) - 1): p1, q1 = Beach.rlist[i] p2, q2 = Beach.rlist[i + 1] x, y = lineIntersect(p1, q1, p2, q2) if x is not None and x > Beach.bounds["maxx"]: Beach.rlist[i + 1] = [p1, q1] if q1 == p2: drawDelaunayEdge(p1.x, p1.y, q2.x, q2.y) elif q1 == p1: drawDelaunayEdge(p2.x, p2.y, q2.x, q2.y) elif q2 == p2: drawDelaunayEdge(p1.x, p1.y, q1.x, q1.y) else: drawDelaunayEdge(p2.x, p2.y, q1.x, q1.y) # Constroi a DCEL Vor.constroi(edges) return Vor