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 edges(self): edges = [] p = self.pts while p.next != self.pts: edges.append(Segment(p, p.next)) p = p.next edges.append(Segment(p, p.next)) return edges
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 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 ShamosRec(l, i, j): " Função que faz o serviço recursivo " " recebe uma lista de pontos l[i:j] ordenados pela coordenada x " # Base da recursão, 2 ou 1 ponto if j - i < 3: # registra o par mais proximo par_min = Segment(l[i], l[j - 1]) # Ordena pelo eixo y if (l[i].y > l[j - 1].y): l[i], l[j - 1] = l[j - 1], l[i] else: q = (i + j) // 2 meio = l[q] vert_id = control.plot_vert_line(meio.x) verde = meio.hilight() control.sleep() # Calcula o menor das duas metades par_esq = ShamosRec(l, i, q) par_dir = ShamosRec(l, q, j) par_min = minPar(par_esq, par_dir) # Intercala do mergeSort escondido intercalaY(l, i, j) control.plot_delete(vert_id) meio.unhilight(id=verde) # Calcula o menor entre as duas metade par_inter = menorInter(l, i, j, meio, par_min) if par_inter != None: par_min = minPar(par_inter, par_min) par_inter.hide() par_esq.unhilight() par_dir.unhilight() global d dnovo = math.sqrt(dist(par_min)) d = min(d, dnovo) par_min.hilight("red") control.sleep() return par_min
def visivel(T, S, p, i): a = S[i] a.visivel = False #Até que se prove o contrário if (a is p): a.visivel = True return a.visivel #Testa se a reta p->s[i] passa por dentro do polígono # de p. if (p.prev != p): #p está em algum polígono if (noCone(p.prev, p, p.next, a)): a.visivel = False #Falhou no cone return a.visivel if (i == 0 or not collinear(p, S[i - 1], a)): segMin = T.getMin() if (segMin is None): a.visivel = True #seg min é null return a.visivel #Testando intersec com min a.visivel = not intersectaProp(segMin, Segment(p, a)) elif (not S[i - 1].visivel): # Anterior não é visível a.visivel = False else: if (S[i - 1].prev != S[i - 1]): #S[i-1] esta em um polígono if (noCone(S[i - 1].prev, S[i - 1], S[i - 1].next, a)): a.visivel = False print("Falhou no cone 2") return a.visivel segTemp = Segment(S[i - 1], a) seg2 = T.getProx(S[i - 1]) # Testando o segmento do meio # if (seg2 is None): a.visivel = True else: a.visivel = not intersectaProp(seg2, segTemp) return a.visivel
def __init__(self, u, v): self.origin = u self.dest = v self.twin = None self.face = None self.next_hedge = None self.segment = Segment(u.p, v.p) self.segment.lid = None u.hedge = self
def newEdge(self, x1, y1, x2, y2): vertex1 = self.findVertex(x1, y1) vertex2 = self.findVertex(x2, y2) if (vertex1 != None) and (vertex2 != None): self.allEdge.append(Edge(vertex1, vertex2)) point1 = Point(vertex1.getX(), vertex1.getY()) point2 = Point(vertex2.getX(), vertex2.getY()) Printo(Segment(point1, point2)) else: print("Falhou em newEdge -- vertices errados!")
def desenha (self): cima = self.sup.y baixo = max (self.a_esq.to.y, self.a_dir.to.y) # Acha os dois pontos da esquerda x1, y1 = self.a_esq.init.x, self.a_esq.init.y x2, y2 = self.a_esq.to.x, self.a_esq.to.y cima_esq = Point ((x2*y1 - x1*y2 + cima*(x1 - x2))/(y1 - y2), cima) baixo_esq = Point ((x2*y1 - x1*y2 + baixo*(x1 - x2))/(y1 - y2), baixo) # Acha os dois pontos da direita x1, y1 = self.a_dir.init.x, self.a_dir.init.y x2, y2 = self.a_dir.to.x, self.a_dir.to.y cima_dir = Point ((x2*y1 - x1*y2 + cima*(x1 - x2))/(y1 - y2), cima) baixo_dir = Point ((x2*y1 - x1*y2 + baixo*(x1 - x2))/(y1 - y2), baixo) self.aresta_cima = (Segment (cima_esq, cima_dir)).plot('green') self.aresta_baixo = (Segment (baixo_esq, baixo_dir)).plot('green') self.aresta_esq = (Segment (baixo_esq, cima_esq)).plot('green') self.aresta_dir = (Segment (baixo_dir, cima_dir)).plot('green')
def intersectaBorda(u, w, P): """ Função que recebe dois vértices u e w do polígono P e retorna se o segmento uw intersecta alguma aresta de P (equivalente a função QuaseDiagonal dos slides) """ borda = P.edges() uw = Segment(u, w) for aresta in borda: aresta.plot('cyan') sleep() if (u not in aresta.endpoints()) and (w not in aresta.endpoints()): if (uw.intersects(aresta)): aresta.hide() aresta.plot('yellow') sleep() aresta.hide() return True aresta.hide() return False
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 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 read_segments(filename): if filename is None: raise ValueError("File name is None") with open(filename) as file: segments = set() for line in file: line = line.split() if len(line) != 4: raise ValueError("Invalid input from file: {}: {}".format( filename, line)) segments.add( Segment(Point(float(line[0]), float(line[1])), Point(float(line[2]), float(line[3])))) return segments
def read_intersections(filename): if filename is None: raise ValueError("File name is None") with open(filename) as file: intersections = {} point = None for line in file: line = line.split() if len(line) == 2: point = Point(float(line[0]), float(line[1])) intersections[point] = set() if len(line) == 4: intersections[point].add( Segment(Point(float(line[0]), float(line[1])), Point(float(line[2]), float(line[3])))) return intersections
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
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 __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 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 Diameter (l): """Algoritmo Diametro para encontrar o par de pontos mais distantes Ele consiste de: - determinar o fecho convexo dos pontos passados - determinar o conjunto de pares antipodas do fecho convexo - determinar o par antipoda cujos pontos estao a uma distancia maxima """ if len (l) < 2: return None if len (l) == 2: ret = Segment (l[0], l[1]) ret.extra_info = 'distancia: %.2f'%math.sqrt (dist2 (l[0], l[1])) return ret ch = Graham (l) ch.hide () ch.plot (config.COLOR_ALT4) control.sleep () pairs = antipodes (ch) cores = (config.COLOR_ALT1,) #print `pairs` i=0 for p,q in pairs: p.hilight (cores[i]) q.hilight (cores[i]) p.lineto (q, cores[i]) i = (i+1) % len (cores) control.sleep () farthest = dist2 (pairs[0][0], pairs[0][1]) a = pairs[0][0] b = pairs[0][1] hia = a.hilight () hib = b.hilight () id = a.lineto (b) for i in range (1, len (pairs)): dist = dist2 (pairs[i][0], pairs[i][1]) if dist > farthest: control.freeze_update () a.unhilight (hia) b.unhilight (hib) control.plot_delete (id) farthest = dist a = pairs[i][0] b = pairs[i][1] hia = a.hilight () hib = b.hilight () id = a.lineto (b) control.thaw_update () ret = Segment (a, b) ret.extra_info = 'distancia: %.2f'%math.sqrt (farthest) return ret
def intersects(seg1: Segment, seg2: Segment) -> bool: ''' Returns whether two segments intersect or not. ''' return seg1.intersects(seg2)
def read(filename): """Reads any type of geometric primitive data structures (Point, Polygon, Segment) from a file and returns it as a list. This method reads geometric data from a file. Any empty line or any line started by '#' (considered a commentary) is ignored. The input can be mixed, it can contains a set of Polygons, Points and Segments and not necessarily only one type of data. The following patterns are required during the input operation: Point: defined by two floating point coordinates, on a line, separated by whitespaces. For example: 0 0 0.5 1.5 1.5 3 Polygon: defined by a list of adjacent points, enclosed by '[' at the beginning and ']' at the end, in the order that they appear in the polygon boundary, i.e., any pair of consecutive points defines an edge on the polygon boundary. For example, the following input defines a square: [ 0 0 1 0 1 1 0 1 ] Segment: defined by four floating point coordinates, on a line, separated by whitespaces. Each pair of consecutive coordinates defines a segment endpoint. For example, the following input defines a segment from (0, 0) to (0.5, 1.5): 0 0 0.5 1.5 Disc: Atualmente, ele espera que o arquivo contenha uma lista de discos, um disco por linha, as 3 coordenadas em cada linha (x, y, r). Exemplo: 0 0 0 0 1 2 10 100 50 :param filename: (str) The name of the file that will be read :return: (list) A list of geometric primitive data structures read from the file Raises: FileNotFoundError: if file could not be found TypeError: if 'filename' is None ValueError: if some input from the file does not follow the required patterns """ with open(filename) as file: i = 0 vertices = [] data = [] expecting_polygon = False for line in file: i += 1 line = line.split() if len(line) == 0 or line[0] == "#": continue if line[0] == "[": expecting_polygon = True elif line[0] == "]": expecting_polygon = False data.append(Polygon(vertices)) vertices = [] elif len(line) == 3: data.append(Disc(float(line[0]), float(line[1]), float(line[2]))) elif len(line) == 4: data.append( Segment( Point(float(line[0]), float(line[1])), Point(float(line[2]), float(line[3])) ) ) elif len(line) == 2: if expecting_polygon: vertices.append(Point(float(line[0]), float(line[1]))) else: data.append(Point(float(line[0]), float(line[1]))) else: raise ValueError( "Invalid input from file: {}: line: {}: {}".format(filename, i, line)) return data
def shamos_hoey(segmentos, estrutura): global cores if len(segmentos) == 0: return None # Abaixo, redefinimos as funcoes de comparacao de segmentos para nosso proposito Segment.__lt__ = lambda s1, s2: prim.compara_segmentos(x_linha_varredura, s1, s2) == -1 Segment.__ge__ = lambda s1, s2: prim.compara_segmentos(x_linha_varredura, s1, s2) >= 0 E = [] # inicializa fila de eventos for i, segmento in enumerate(segmentos): # se e_x > d_x, entao inverte os pontos que determinam o segmento # (pontos da esquerda nao podem ter x-coordenada maior que pontos da direita) if (segmento.init.x > segmento.to.x): segmento.reverse() # tambem inverte se for segmento vertical com inicio (init) com menor y-coordenada do que fim (to) elif (segmento.init.x == segmento.to.x and segmento.init.y < segmento.to.y): segmento.reverse() segmento.id = i segmento.intersected = False # coloca na fila de eventos E E.append(PontoEvento(segmento.init, 'esquerdo', i)) E.append(PontoEvento(segmento.to, 'direito', i)) E.sort() # ordena pontos eventos por x-coordenada global x_linha_varredura pred,suc = None, None for ponto_evento in E: x_linha_varredura = ponto_evento.ponto.x #Remove o destaque da iteracao passada destaca_segs( [pred, suc], 'presente') seg = segmentos[ponto_evento.id_segmento] pred = estrutura.predecessor(seg) suc = estrutura.sucessor(seg) #Destaca os segmentos que serao analisados destaca_segs( [pred, suc], 'vizinho') if ponto_evento.tipo == 'esquerdo': destaca_segs([seg], 'presente') estrutura.insere(seg) if pred != None: if prim.inter(seg,pred) == True: # Detectou interseccao do seg com o pred destaca_segs([seg,pred], 'intersectado') seg.intersected, pred.intersected = True, True break if suc != None: if prim.inter(seg,suc) == True: # Detectou interseccao do seg com o suc destaca_segs([seg,suc], 'intersectado') seg.intersected, suc.intersected = True, True break elif ponto_evento.tipo == 'direito': destaca_segs([seg], 'passado') estrutura.remove(seg) if (pred != None and suc != None): if prim.inter(pred,suc) == True: # Detectou interseccao do pred com o suc destaca_segs([pred,suc], 'intersectado') pred.intersected, suc.intersected = True, True break linha_varredura_plotada_id = control.gui.plot_vert_line (x_linha_varredura, config.COLOR_LINE_SPECIAL, 1) # plota a linha de varredura control.sleep() # dorme control.gui.plot_delete(linha_varredura_plotada_id) # desplota a linha de varredura if estrutura.__class__.__name__ == 'Skiplist': ret = Segment() # pequeno hack, porque resolvemos um problema de decisão, e não temos nada (nenhum polígono, por exemplo) para retornar # e para o algoritmo de Skip List queremos devolver essa informacao extra abaixo ret.extra_info = 'SL: p = ' + str(estrutura.p) + ' nivelmax = ' + str(estrutura.maxnivel) + ' (media de niveis = ' + str( (estrutura.somaniveis / (2*len(segmentos)))) + ')' return ret
def Diameter(l): """Algoritmo Diametro para encontrar o par de pontos mais distantes Ele consiste de: - determinar o fecho convexo dos pontos passados - determinar o conjunto de pares antipodas do fecho convexo - determinar o par antipoda cujos pontos estao a uma distancia maxima """ if len(l) < 2: return None if len(l) == 2: ret = Segment(l[0], l[1]) ret.extra_info = 'distancia: %.2f' % math.sqrt(dist2(l[0], l[1])) return ret ch = Graham(l) ch.hide() ch.plot(config.COLOR_ALT4) control.sleep() pairs = antipodes(ch) cores = (config.COLOR_ALT1, ) #print `pairs` i = 0 for p, q in pairs: p.hilight(cores[i]) q.hilight(cores[i]) p.lineto(q, cores[i]) i = (i + 1) % len(cores) control.sleep() farthest = dist2(pairs[0][0], pairs[0][1]) a = pairs[0][0] b = pairs[0][1] hia = a.hilight() hib = b.hilight() id = a.lineto(b) for i in range(1, len(pairs)): dist = dist2(pairs[i][0], pairs[i][1]) if dist > farthest: control.freeze_update() a.unhilight(hia) b.unhilight(hib) control.plot_delete(id) farthest = dist a = pairs[i][0] b = pairs[i][1] hia = a.hilight() hib = b.hilight() id = a.lineto(b) control.thaw_update() ret = Segment(a, b) ret.extra_info = 'distancia: %.2f' % math.sqrt(farthest) return ret
def __init__ (self, x, y, r): "Para criar um disco, passe suas coordenadas." self.center = Point(x, y) self.r = r self.seg = Segment(Point(x-r, y), Point(x+r,y)) self.lineto_id = {}
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")
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 triangulaMonotono2(l,diagonais):#Os pontos devem vir em ordem anti-horária pontos = [] #lista com os pontos,juntamente com seus indices verts = [] #lista com os pontos ordenados pilha = [] #pilha usada no algoritmo lado = [] for x in range(len(l)):#desenha poligono if(x != len(l)-1): l[x].lineto(l[(x+1)],'red') else: l[x].lineto(l[0],'red') N = len(l) for i in range(N): pontos.append((l[i],i)) #transforma cada ponto numa dupla (ponto,indice) lado.append(True) ########################################### #Esse pedaço acha o vertice mais alto e o mais baixo e realiza o merge yMax = -20000000 yMin = 2000000 vMax = pontos[0] vMin = pontos[N-1] for i in range(N): if(pontos[i][0].y == yMax and pontos[i][0].x < vMax[0].x): vMax = pontos[i] if(pontos[i][0].y == yMin and pontos[i][0].x > vMin[0].x): vMin = pontos[i] if(pontos[i][0].y > yMax): vMax = pontos[i] yMax = vMax[0].y if(pontos[i][0].y < yMin): vMin = pontos[i] yMin = vMin[0].y if(vMax[1] != N-1):v = pontos[vMax[1]+1] else: v = pontos[0] if(vMax[1]!= 0): i = vMax[1]-1 else: i = N-1 if(vMax[1]!= N-1):j = vMax[1]+1 else: j = 0 lado[vMin[1]] = False if(vMax[1]!= 0): i = vMax[1]-1 else: i = N-1 if(vMax[1]!= N-1):j = vMax[1]+1 else: j = 0 verts.append(vMax); while(len(verts) < N): #Merge if(pontos[j] == vMin): while(pontos[i] != vMin): verts.append(pontos[i]) if(i!=0):i -= 1 else: i = N-1 elif(pontos[i] == vMin): while(pontos[j] != vMin): lado[pontos[j][1]] = False verts.append(pontos[j]) if(j != N-1):j += 1 else: j = 0 if((pontos[j][0].y >= pontos[i][0].y)): lado[pontos[j][1]] = False verts.append(pontos[j]) if(j != N-1): j+= 1 else: j = 0 else: verts.append(pontos[i]) if(i!=0):i -= 1 else: i = N-1 ######################################## #verts = sorted(pontos,key=lambda x: (x[0].y,-x[0].x), reverse=True) print verts pilha.append(verts[0]) pilha.append(verts[1]) for i in range(2,N): t = len(pilha) print "____________________" print pilha verts[i][0].hilight("yellow") control.sleep() if(verts[i][1] == 0): ant = len(l)-1 else: ant = verts[i][1]-1 if(verts[i][1] == len(l)-1): prox = 0 else: prox = verts[i][1]+1 #aqui pilha[t-1][1] é o St e pilha[0][1] o S1, de acordo com os slides #Caso A ######################## if((ant == pilha[t-1][1] and prox != pilha[0][1]) or (ant != pilha[0][1] and prox == pilha[t-1][1])): #adjacente a St mas nao a S1 print "Entrei no caso A" , "no vertice ",verts[i][0] if(lado[pilha[t-1][1]] == True): while(t>1 and left_on(pilha[t-1][0],pilha[t-2][0],verts[i][0]) ): pilha.pop() t -= 1 diagonais.append(Segment(verts[i][0],pilha[t-1][0])) d = Segment(verts[i][0],pilha[t-1][0]) d.hilight("blue") control.sleep() print "Adicionei a diagonal ", d elif(t>1): while(t>1 and right_on(pilha[t-1][0],pilha[t-2][0],verts[i][0])): pilha.pop() t -= 1 diagonais.append(Segment(verts[i][0],pilha[t-1][0])) d = Segment(verts[i][0],pilha[t-1][0]) d.hilight("blue") control.sleep() print "Adicionei a diagonal ", d pilha.append(verts[i]) #Caso B ######################## if((ant != pilha[t-1][1] and prox == pilha[0][1]) or (ant == pilha[0][1] and prox != pilha[t-1][1])): #adjacente a S1 mas nao a St print "Entrei no caso B" , "no vertice ",verts[i][0] aux = pilha[t-1] while(t>1): diagonais.append(Segment(verts[i][0],pilha[t-1][0])) d = Segment(verts[i][0],pilha[t-1][0]) d.hilight("blue") control.sleep() print "Adicionei a diagonal ", d pilha.pop() t -= 1 pilha.pop() pilha.append(aux) pilha.append(verts[i]) #Caso C ######################## if((ant == pilha[t-1][1] and prox == pilha[0][1]) or (ant == pilha[0][1] and prox == pilha[t-1][1])): #adjacente a St e S1 print "Entrei no caso C", "no vertice ",verts[i][0] pilha.pop() while(t>2): t -= 1 diagonais.append(Segment(verts[i][0],pilha[t-1][0])) d = Segment(verts[i][0],pilha[t-1][0]) d.hilight("blue") control.sleep() print "Adicionei a diagonal ", d pilha.pop() verts[i][0].hilight("red") print "--------------------" return diagonais
def verticesVisiveis(p, poligs): pontos = [] for i in range(len(poligs)): pontos.extend(poligs[i].to_list()) compara = criaCompara(p) #Intersecta p.x -> inf+ T = Tree() pontos.sort(key=cmp_to_key(compara), reverse=True) for i in range(len(poligs)): listaPs = poligs[i].to_list() n = len(listaPs) for j in range(n): a = listaPs[j] b = listaPs[(j + 1) % n] if (passaEixoX(a, b, p)): if (left_on(p, b, a)): T.insert(Segment(a, b)) else: T.insert(Segment(b, a)) W = [] for i in range(len(pontos)): a = pontos[i] idBranco = p.lineto(a, 'white') a.hilight('yellow') control.sleep() a.hilight('red') a.unhilight() if (visivel(T, pontos, p, i)): if (a is not p): W.append(a) p.remove_lineto(a, idBranco) p.lineto(a, 'blue') else: continue else: p.remove_lineto(a, idBranco) b = a.prev c = a.next if (a.x == b.x and a.y == b.y): continue #a não está em um #polígono if (left_on(p, a, b)): T.delete(Segment(b, a)) if (left_on(p, a, c)): T.delete(Segment(c, a)) else: T.insert(Segment(a, c)) #else do primeiro if #Tentando evitar q na hora da inserção tenha segmentos terminando #na linha de varredura. if (right(p, a, b)): T.insert(Segment(a, b)) return W
def triangulaMonotono(l):#Os pontos devem vir em ordem anti-horária pontos = [] #lista com os pontos,juntamente com seus indices verticesOrdenados = [] #lista com os pontos ordenados pilha = [] #pilha usada no algoritmo diagonais = [] #lista de diagonais da triangulação lado = [] for x in range(len(l)):#desenha poligono if(x != len(l)-1): l[x].lineto(l[(x+1)],'red') else: l[x].lineto(l[0],'red') N = len(l) for i in range(N): pontos.append((l[i],i)) #transforma cada ponto numa dupla (ponto,indice) lado.append(True) ##################################### verticesDCEL = [] arestas = [] arestas2 = [] for a in range(N): if(a != N-1): ar = Aresta() ar.setAresta(Segment(pontos[a],pontos[a+1])) ar2 = Aresta() ar2.setAresta(Segment(pontos[a+1],pontos[a])) ar.setGemeo(ar2) ar2.setGemeo(ar) arestas.append(ar) arestas2.append(ar2) else: ar = Aresta() ar.setAresta(Segment(pontos[a],pontos[0])) ar2 = Aresta() ar2.setAresta(Segment(pontos[0],pontos[a])) ar.setGemeo(ar2) ar2.setGemeo(ar) arestas.append(ar) arestas2.append(ar2) for k in range(len(arestas)): if(k!= 0 and k!= len(arestas)-1): arestas[k].setProx(arestas[k+1]) arestas[k].setAnt(arestas[k-1]) arestas2[k].setProx(arestas2[k-1]) arestas2[k].setAnt(arestas2[k+1]) elif(k == 0): arestas[k].setProx(arestas[k+1]) arestas[k].setAnt(arestas[len(arestas)-1]) arestas2[k].setProx(arestas2[len(arestas)-1]) arestas2[k].setAnt(arestas2[k+1]) else: arestas[k].setProx(arestas[0]) arestas[k].setAnt(arestas[k-1]) arestas2[k].setProx(arestas2[k-1]) arestas2[k].setAnt(arestas2[0]) for a in range(N): bla = Vertice(aresta=arestas2[a]) verticesDCEL.append(bla) face = Face(arestas2[0]) faces = [] faces.append(face) ###################################### verticesOrdenados = merge(pontos,lado) ###################################### pilha.append(verticesOrdenados[0]) pilha.append(verticesOrdenados[1]) for i in range(2,N): t = len(pilha) verticesOrdenados[i][0].hilight("yellow") control.sleep() if(verticesOrdenados[i][1] == 0): ant = len(l)-1 else: ant = verticesOrdenados[i][1]-1 if(verticesOrdenados[i][1] == len(l)-1): prox = 0 else: prox = verticesOrdenados[i][1]+1 #aqui pilha[t-1][1] é o St e pilha[0][1] o S1, de acordo com os slides #Caso A ######################## if((ant == pilha[t-1][1] and prox != pilha[0][1]) or (ant != pilha[0][1] and prox == pilha[t-1][1])): #adjacente a St mas nao a S1 if(lado[pilha[t-1][1]] == True): while(t>1 and left_on(pilha[t-1][0],pilha[t-2][0],verticesOrdenados[i][0]) and not (pilha[t-1][0].y == pilha[t-2][0].y and verticesOrdenados[i][0].y == pilha[t-1][0].y )): pilha.pop() t -= 1 d = Segment(verticesOrdenados[i][0],pilha[t-1][0]) d.hilight("green") control.sleep() diagonalASerInserida = criaAresta(verticesOrdenados[i],pilha[t-1]) diagonais.append(diagonalASerInserida) insere(verticesDCEL[verticesOrdenados[i][1]-1],verticesDCEL[pilha[t-1][1]-1],diagonalASerInserida,faces) elif(t>1): while(t>1 and right_on(pilha[t-1][0],pilha[t-2][0],verticesOrdenados[i][0]) and not (pilha[t-1][0].y == pilha[t-2][0].y and verticesOrdenados[i][0].y == pilha[t-1][0].y )): pilha.pop() t -= 1 d = Segment(verticesOrdenados[i][0],pilha[t-1][0]) d.hilight("green") control.sleep() diagonalASerInserida = criaAresta(verticesOrdenados[i],pilha[t-1]) diagonais.append(diagonalASerInserida) insere(verticesDCEL[verticesOrdenados[i][1]-1],verticesDCEL[pilha[t-1][1]-1],diagonalASerInserida,faces) pilha.append(verticesOrdenados[i]) #Caso B ######################## if((ant != pilha[t-1][1] and prox == pilha[0][1]) or (ant == pilha[0][1] and prox != pilha[t-1][1])): #adjacente a S1 mas nao a St aux = pilha[t-1] while(t>1): d = Segment(verticesOrdenados[i][0],pilha[t-1][0]) d.hilight("green") control.sleep() diagonalASerInserida = criaAresta(verticesOrdenados[i],pilha[t-1]) diagonais.append(diagonalASerInserida) insere(verticesDCEL[verticesOrdenados[i][1]-1],verticesDCEL[pilha[t-1][1]-1],diagonalASerInserida,faces) pilha.pop() t -= 1 pilha.pop() pilha.append(aux) pilha.append(verticesOrdenados[i]) #Caso C ######################## if((ant == pilha[t-1][1] and prox == pilha[0][1]) or (ant == pilha[0][1] and prox == pilha[t-1][1])): #adjacente a St e S1 pilha.pop() while(t>2): t -= 1 d = Segment(verticesOrdenados[i][0],pilha[t-1][0]) d.hilight("green") control.sleep() diagonalASerInserida = criaAresta(verticesOrdenados[i],pilha[t-1]) diagonais.append(diagonalASerInserida) insere(verticesDCEL[verticesOrdenados[i][1]-1],verticesDCEL[pilha[t-1][1]-1],diagonalASerInserida,faces) pilha.pop() verticesOrdenados[i][0].hilight("red") for d in diagonais: checaDiagonal(verticesDCEL[d.getAresta().init[1] -1 ],verticesDCEL[d.getAresta().to[1] -1 ],d)
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 triangulaMonotono(l):#Os pontos devem vir em ordem anti-horária pontos = [] #lista com os pontos,juntamente com seus indices verticesOrdenados = [] #lista com os pontos ordenados pilha = [] #pilha usada no algoritmo #diagonais = [] #lista de diagonais da triangulação lado = [] for x in range(len(l)):#desenha poligono if(x != len(l)-1): l[x].lineto(l[(x+1)],'red') else: l[x].lineto(l[0],'red') N = len(l) for i in range(N): pontos.append((l[i],i)) #transforma cada ponto numa dupla (ponto,indice) lado.append(True) ########################################### verticesOrdenados = merge(pontos,lado) ######################################## pilha.append(verticesOrdenados[0]) pilha.append(verticesOrdenados[1]) for i in range(2,N): t = len(pilha) verticesOrdenados[i][0].hilight("yellow") control.sleep() if(verticesOrdenados[i][1] == 0): ant = len(l)-1 else: ant = verticesOrdenados[i][1]-1 if(verticesOrdenados[i][1] == len(l)-1): prox = 0 else: prox = verticesOrdenados[i][1]+1 #aqui pilha[t-1][1] é o St e pilha[0][1] o S1, de acordo com os slides #Caso A ######################## if((ant == pilha[t-1][1] and prox != pilha[0][1]) or (ant != pilha[0][1] and prox == pilha[t-1][1])): #adjacente a St mas nao a S1 if(lado[pilha[t-1][1]] == True): while(t>1 and left_on(pilha[t-1][0],pilha[t-2][0],verticesOrdenados[i][0]) and not (pilha[t-1][0].y == pilha[t-2][0].y and verticesOrdenados[i][0].y == pilha[t-1][0].y )): pilha.pop() t -= 1 d = Segment(verticesOrdenados[i][0],pilha[t-1][0]) d.hilight("blue") control.sleep() elif(t>1): while(t>1 and right_on(pilha[t-1][0],pilha[t-2][0],verticesOrdenados[i][0]) and not (pilha[t-1][0].y == pilha[t-2][0].y and verticesOrdenados[i][0].y == pilha[t-1][0].y )): pilha.pop() t -= 1 d = Segment(verticesOrdenados[i][0],pilha[t-1][0]) d.hilight("blue") control.sleep() pilha.append(verticesOrdenados[i]) #Caso B ######################## if((ant != pilha[t-1][1] and prox == pilha[0][1]) or (ant == pilha[0][1] and prox != pilha[t-1][1])): #adjacente a S1 mas nao a St aux = pilha[t-1] while(t>1): d = Segment(verticesOrdenados[i][0],pilha[t-1][0]) d.hilight("blue") control.sleep() pilha.pop() t -= 1 pilha.pop() pilha.append(aux) pilha.append(verticesOrdenados[i]) #Caso C ######################## if((ant == pilha[t-1][1] and prox == pilha[0][1]) or (ant == pilha[0][1] and prox == pilha[t-1][1])): #adjacente a St e S1 pilha.pop() while(t>2): t -= 1 d = Segment(verticesOrdenados[i][0],pilha[t-1][0]) d.hilight("blue") control.sleep() pilha.pop() verticesOrdenados[i][0].hilight("red")