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 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)
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 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")
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")