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]) par_min.hilight('green') desenhos.sleep() # 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 = desenhos.plot_vert_line(meio.x, 'firebrick', grossura=1) meio.hilight('firebrick') desenhos.sleep() # Calcula o menor das duas metades par_esq = ShamosRec(l, i, q) par_dir = ShamosRec(l, q, j) desenhos.plot_delete(vert_id) meio.unhilight() par_min = minPar(par_esq, par_dir) par_esq.unhilight() par_dir.unhilight() par_esq.hilight('red') par_dir.hilight('red') desenhos.sleep() par_esq.unhilight() par_dir.unhilight() par_min.hilight('orange') desenhos.sleep() # Intercala do mergeSort escondido intercalaY(l, i, j) # 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() global d dnovo = math.sqrt(dist(par_min)) d = min(d, dnovo) return par_min
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')