def trata_caso_meio (p, viz_baixo, L, dcel, diags): # Remove da linha o trapésio que tem o p t = Trapezio (p) removido = (L.busca (t)).elemento removido.apaga() L.deleta (t) if ponta_pra_baixo (removido.sup): d = Segment (removido.sup, p) d.plot('blue') dcel.add_edge (d.init, d.to) diags.append(d) control.sleep() # Insere um novo trapésio com o p # Se o removido estava a direita if (p == removido.a_dir.to): t.a_dir = Segment (p, viz_baixo) t.a_esq = removido.a_esq # Se estava a esquerda else: t.a_esq = Segment (p, viz_baixo) t.a_dir = removido.a_dir t.desenha() L.insere (t) control.sleep()
def trata_ponta_pra_cima (p, L, dcel, diags): viz_esq = p.next viz_dir = p.prev if left (p, viz_dir, viz_esq): viz_esq, viz_dir = viz_dir, viz_esq t = Trapezio (p) removido = (L.busca (t)).elemento if removido == None: t.a_esq = Segment (p, viz_esq) t.a_dir = Segment (p, viz_dir) t.desenha() L.insere (t) else: L.deleta (t) removido.apaga() d = Segment (p, removido.sup) d.plot('blue') dcel.add_edge (d.init, d.to) diags.append(d) control.sleep() t1 = Trapezio (p, removido.a_esq, Segment (p, viz_esq)) t2 = Trapezio (p, Segment (p, viz_dir), removido.a_dir) t1.desenha() t2.desenha() L.insere (t1) L.insere (t2) control.sleep()
def visit(self, u, target): u.setVisited(True) v = self.findNeighbor(u) while v is not None: # Printando o segmento atual do grafo seg = Segment(Point(u.x, u.y), Point(v.x, v.y)) seg.plot('cyan') control.sleep() # Continuar o DFS if (v == target): self.solved = True return 1 self.visit(v, target) # Condicao de parada do DFS if(self.solved): return 1 # Retirando o print do segmento seg.hide() control.sleep() # Pegar o próximo vizinho v = self.findNeighbor(u)
def trata_ponta_pra_baixo (p, L, dcel, diags): t = Trapezio (p) removido1 = (L.busca (t)).elemento removido1.apaga() L.deleta (t) if ponta_pra_baixo (removido1.sup): d = Segment (removido1.sup, p) d.plot('blue') control.sleep() dcel.add_edge (d.init, d.to) diags.append(d) # Se tem outro polígono removido2 = (L.busca (t)).elemento if removido2 != None: L.deleta (t) removido2.apaga() if ponta_pra_baixo (removido2.sup): d = Segment (removido2.sup, p) d.plot('blue') control.sleep() dcel.add_edge (d.init, d.to) diags.append(d) if removido2.a_esq.to == p: t = Trapezio (p, removido1.a_esq, removido2.a_dir) else: t = Trapezio (p, removido2.a_esq, removido1.a_dir) L.insere (t) t.desenha() control.sleep()
def isDiagonal(u, w, P): """ Função que recebe dois vértices u e w do polígono P e retorna se uw é uma diagonal de P """ # colore a candidata a diagonal uw = Segment(u, w) uw.plot('blue') sleep() # Como o dentroDoPoligono é O(1) é muito prudente fazer esse teste primeiro result = dentroDoPoligono(u, w, P) and (not intersectaBorda(u, w, P)) uw.hide() return result
def menorInter(l, i, j, meio, par_min): " Retorna o par de pontos mais proximo dentro da faixa dada pelo ponto meio da lista " " e a distancia do min_par " global d blue = meio.hilight("blue") # desenha a faixa que eu estou procurando v1 = control.plot_vert_line(meio.x - d, "blue") v2 = control.plot_vert_line(meio.x + d, "blue") control.sleep() par_inter = None cand = candidatos(l, i, j, meio) for k in range(len(cand)): cyan = cand[k].hilight("cyan") for l in range(k + 1, len(cand)): # Se os pontos já estão distantes, posso parar de olhar if (cand[l].y - cand[k].y > d): break cand_inter = Segment(cand[k], cand[l]) cand_inter.plot("cyan") control.sleep() cand_inter.hide() dcand = math.sqrt(dist2(cand[k], cand[l])) # Se achei um novo par, apaga o outro e pinta esse if (dcand < d): d = dcand if par_inter != None: par_inter.hide() par_inter = cand_inter par_inter.plot("blue") control.sleep() cand[k].unhilight(id=cyan) control.plot_delete(v1) control.plot_delete(v2) meio.unhilight(id=blue) control.sleep() return par_inter
def dentroDoPoligono(u, w, P): """ Função que recebe dois vértices u e w do polígono P e retorna se a candidata a diagonal uw está pra dentro do polígono (equivalente a função NoCone dos slides) """ prevU = u.prev nextU = u.next if (left_on(prevU, u, nextU)): resposta = (left(u, w, prevU) and left(w, u, nextU)) else: resposta = not (left_on(u, w, nextU) and left_on(w, u, prevU)) if not resposta: uw = Segment(u, w) uw.plot("yellow") sleep() uw.hide() return resposta
def Generate(l): # Dado a lista de pontos do poligono e gera todos os segmentos de retas lsegments = [] n = len(l) if (n == 2): lsegments.append( SSegment(SPoint(l[0].x, l[0].y), SPoint(l[1].x, l[1].y))) seg = Segment(Point(l[0].x, l[0].y), Point(l[1].x, l[1].y)) seg.plot('green') control.sleep() else: for i in range(n): lsegments.append( SSegment(SPoint(l[i % n].x, l[i % n].y), SPoint(l[(i + 1) % n].x, l[(i + 1) % n].y))) seg = Segment(Point(l[i % n].x, l[i % n].y), Point(l[(i + 1) % n].x, l[(i + 1) % n].y)) seg.plot('green') control.sleep() return lsegments
class Node_Triang: " Classe que será o nó do DAG, guarda os triângulos que fazem parte da triangulação " def __init__(self, p1, p2, p3, a): if left(p1, p2, p3): self.p1 = p1 self.p2 = p2 else: self.p1 = p2 self.p2 = p1 self.p3 = p3 self.a = a # Alguma aresta da DCEL que faz parte desse triangulo self.filhos = [] # Node_Triangs que são filhos do self no DAG # arestas self.a1 = Segment(self.p1, self.p2) self.a2 = Segment(self.p2, self.p3) self.a3 = Segment(self.p3, self.p1) def draw(self): self.a1.plot("gray") self.a2.plot("gray") self.a3.plot("gray") sleep() def hide(self): self.a1.hide() self.a2.hide() self.a3.hide() def busca(self, ponto): " Retorna o nó folha em que o ponto está " if desenha_busca: self.draw() for f in self.filhos: if (left_on(f.p1, f.p2, ponto) and left_on(f.p2, f.p3, ponto) and left_on(f.p3, f.p1, ponto)): if desenha_busca: self.hide() return f.busca(ponto) if desenha_busca: self.hide() return self
def Monotono(p): # Essa é a forma que eu recebo o polígono do front-end :/ P = p[0] # lista com as diagonais, nosso return resp = [] v = ordenaY(P) n = len(v) s = [v[0], v[1]] # pilha v[0].hilight('blue') v[1].hilight('blue') t = 1 # index do fim da pilha for i in range(2, n): v[i].hilight('green') sleep() vizinho_ultimo = adj(v[i], s[t]) vizinho_primeiro = adj(v[i], s[0]) if vizinho_ultimo and not vizinho_primeiro: while t > 0: a = s[t - 1] b = s[t] if a.x > b.x: a, b = b, a if right(a, b, v[i]): s[t].unhilight() s.pop() t -= 1 # acrescenta a nova diagonal d = Segment(s[t], v[i]) d.plot('green') sleep() resp.append(d) else: break t += 1 s.append(v[i]) v[i].unhilight() v[i].hilight('blue') elif vizinho_primeiro and not vizinho_ultimo: aux = s[t] while t > 0: # acrescenta a nova diagonal d = Segment(s[t], v[i]) d.plot('green') sleep() resp.append(d) s.pop() t -= 1 s[t].unhilight() s = [] s.append(aux) s.append(v[i]) v[i].unhilight() v[i].hilight('blue') t = 1 else: while t > 1: s[t].unhilight() t -= 1 # acrescenta a nova diagonal d = Segment(s[t], v[i]) d.plot('green') sleep() resp.append(d) s[0].unhilight() s[1].unhilight() v[i].unhilight() return resp
def Varre(l): "Algoritmo de divisão e conquista para encontrar o par de pontos mais proximo" "Recebe uma lista de pontos l" if len(l) < 2: return None d = float("inf") l = sorted(l, key=lambda x: x.x) par_min = None faixa = Abbb() p_min = 0 for i in range(len(l)): p = l[i] no_p = Node_point(p) # Caso degenerado -> pontos coincidentes # (não conseguimos adicionar na abbb, pois ja tem um clone dele) repetido = faixa.busca(no_p).elemento if repetido != None: if par_min != None: par_min.hide() par_min = Segment(p, repetido.p) break faixa.insere(no_p) p.hilight() # Remove os pontos fora da faixa while p.x - l[p_min].x > d: l[p_min].unhilight() no_p_min = Node_point(l[p_min]) faixa.deleta(no_p_min) p_min += 1 # Desenha o quadradinho de candidatos linha_frente = control.plot_vert_line(p.x) if i > 1: linha_tras = control.plot_vert_line(p.x - d, color="blue") linha_cima = Segment(Point(p.x, p.y + d), Point(p.x - d, p.y + d)) linha_baixo = Segment(Point(p.x, p.y - d), Point(p.x - d, p.y - d)) linha_cima.plot("blue") linha_baixo.plot("blue") control.sleep() # Extrai os pontos da abbb até a distancia vertical ficar maior que d # Primeiro com os vizinhos de cima vizinho = faixa.sucessor(no_p) while vizinho != None and vizinho.p.y - p.y < d: # Despinta das cores atuais, dai o dist2 pinta de amarelo, depois repinta de novo p.unhilight() vizinho.p.unhilight() d2 = dist2(p, vizinho.p) p.hilight() vizinho.p.hilight("blue") if d2 < d * d: d = d2**0.5 if par_min != None: par_min.hide() par_min = Segment(p, vizinho.p) par_min.plot("red") control.sleep() vizinho = faixa.sucessor(vizinho) # Depois com os vizinhos de baixo vizinho = faixa.predecessor(no_p) while vizinho != None and p.y - vizinho.p.y < d: # Despinta das cores atuais, dai o dist2 pinta de amarelo, depois repinta de novo p.unhilight() vizinho.p.unhilight() d2 = dist2(p, vizinho.p) p.hilight() vizinho.p.hilight("blue") if d2 < d * d: d = d2**0.5 if par_min != None: par_min.hide() par_min = Segment(p, vizinho.p) par_min.plot("red") control.sleep() vizinho = faixa.predecessor(vizinho) # Apaga o quadradinho control.plot_delete(linha_frente) if (i > 1): control.plot_delete(linha_tras) linha_cima.hide() linha_baixo.hide() p.unhilight() l[i].hilight("blue") "despinta quem sobrou na faixa" while (not faixa.vazia()): faixa.deleta_min().p.unhilight() par_min.hilight("red", "red")