def is_diagonal(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('green') sleep() # Como o dentroDoPoligono é O(1) é muito prudente fazer esse teste primeiro result = dentro_do_poligono(u, w, P) and (not intersecta_borda(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 par_min " d = math.sqrt(dist(par_min)) # desenha a faixa que eu estou procurando v1 = desenhos.plot_vert_line(meio.x - d, 'orange', grossura=1) v2 = desenhos.plot_vert_line(meio.x + d, 'orange', grossura=1) cand = candidatos(l, i, j, meio) par_inter = None for k in range(len(cand)): cand[k].plot('red') desenhos.sleep() 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('red') desenhos.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 is not None: par_inter.unhilight() par_min.unhilight() par_inter = cand_inter par_inter.hilight('orange') desenhos.sleep() cand[k].unplot() desenhos.plot_delete(v1) desenhos.plot_delete(v2) desenhos.sleep() return par_inter
def dentro_do_poligono(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('red') sleep() uw.hide() return resposta
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 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() if l[p_min] in par_min.endpoints(): l[p_min].hilight('orange') no_p_min = Node_point(l[p_min]) faixa.deleta(no_p_min) p_min += 1 # Desenha o quadradinho de candidatos linha_frente = desenhos.plot_vert_line(p.x, 'orange') if i > 1: linha_tras = desenhos.plot_vert_line(p.x - d, cor='firebrick') 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('firebrick') linha_baixo.plot('firebrick') desenhos.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: d2 = dist2(p, vizinho.p) p.hilight() vizinho.p.hilight('firebrick') if d2 < d * d: d = d2**0.5 if par_min is not None: par_min.unhilight() par_min = Segment(p, vizinho.p) par_min.hilight('orange') desenhos.sleep() vizinho = faixa.sucessor(vizinho) # Depois com os vizinhos de baixo vizinho = faixa.predecessor(no_p) while vizinho is not None and p.y - vizinho.p.y < d: d2 = dist2(p, vizinho.p) p.hilight() vizinho.p.hilight('firebrick') if d2 < d * d: d = d2**0.5 if par_min is not None: par_min.unhilight() par_min = Segment(p, vizinho.p) par_min.hilight('orange') desenhos.sleep() vizinho = faixa.predecessor(vizinho) # Apaga o quadradinho desenhos.plot_delete(linha_frente) if (i > 1): desenhos.plot_delete(linha_tras) linha_cima.hide() linha_baixo.hide() p.unhilight() l[i].hilight('firebrick') "despinta quem sobrou na faixa" while (not faixa.vazia()): faixa.deleta_min().p.unhilight() par_min.hilight('orange')