def distancia_rec_sh(pts, l, r, best): ''' pts: array de pontos l: limite esquerdo da recursão r: limite direito da recursão best: melhores pontos encontrados ''' # força bruta / base da recursão if r-l <= 3: for i in range(l, r): for j in range(i+1, r): update(pts[i], pts[j], best) pts[l:r] = sorted(pts[l:r], key=cmp_to_key(compare_y)) return m = int((l+r)/2) m_point = pts[m] m_line = control.plot_vert_line(m_point[0], color='red') # divisão distancia_rec_sh(pts, l, m, best) distancia_rec_sh(pts, m, r, best) intercala(pts, l, m, r) # conquista control.plot_delete(m_line) m_line = control.plot_vert_line(m_point[0], color='yellow') combine(pts, l, r, m_point, best) control.plot_delete(m_line)
def Bent_ott(segments): ''' Rotina principal de execução do algoritmo de Bentley and Ottmman. ''' # Ordenando os pontos do segmento for s in segments: if s[0] > s[1]: s.to, s.init = s.init, s.to s.plot() bag = EventBag(segments) sweep_line = SweepLine(bag) line = None while not bag.event_bag.is_empty(): p, e_tuple = bag.next_events() # Andando com a linha de varredura if line: control.plot_delete(line) sweep_line.current_x = p[0] line = control.plot_vert_line(p[0], color='yellow') control.sleep() # Processando cada tupla de eventos do mesmo tipo for t in [END, INTERSECTION, START, VERTICAL]: for e in e_tuple[t]: sweep_line.process_event(e) intersections = sweep_line.get_intersections() print("Numero de interseções: " + str(len(intersections)))
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 draw_interval(should_plot=True): control.thaw_update() for i in range(2): if not ids[i] == None: control.plot_delete(ids[i]) if T[i] != -inf and T[i] != +inf and should_plot: ids[i] = control.plot_vert_line(T[i], 'yellow') control.sleep() control.freeze_update()
def mergehull_rec(l): """Funcao recursiva que implementa o Merge Hull Retorna os pontos com coordenada x minima e maxima do fecho convexo encontrado, alem do proprio fecho. """ n = len(l) if n == 1: #l[0].prev = l[0].next = l[0] pol = Polygon([l[0]]) pol.plot() #control.sleep () return (l[0], l[0], pol) # Divisao l1 = l[:n // 2] l2 = l[n // 2:] id = control.plot_vert_line((l2[0].x + l1[-1].x) / 2.) control.sleep() # Conquista ch1 = mergehull_rec(l1) ch2 = mergehull_rec(l2) v = ch1[1] u = ch2[0] control.plot_delete(id) # Combinar sup = superior_tangent(v, u) id_sup = sup[0].lineto(sup[1], config.COLOR_ALT1) inf = inferior_tangent(v, u) id_inf = inf[0].lineto(inf[1], config.COLOR_ALT1) control.freeze_update() control.plot_delete(id_sup) control.plot_delete(id_inf) ch1[2].hide() ch2[2].hide() sup[0].prev = sup[1] sup[1].next = sup[0] inf[0].next = inf[1] inf[1].prev = inf[0] ch1[2].pts = inf[0] ch1[2].plot() control.thaw_update() return (ch1[0], ch2[1], ch1[2])
def mergehull_rec (l): """Funcao recursiva que implementa o Merge Hull Retorna os pontos com coordenada x minima e maxima do fecho convexo encontrado, alem do proprio fecho. """ n = len (l) if n == 1: #l[0].prev = l[0].next = l[0] pol = Polygon ( [ l[0] ] ) pol.plot () #control.sleep () return (l[0], l[0], pol) # Divisao l1 = l[:n/2] l2 = l[n/2:] id = control.plot_vert_line ((l2[0].x + l1[-1].x) / 2.) control.sleep () # Conquista ch1 = mergehull_rec (l1) ch2 = mergehull_rec (l2) v = ch1[1] u = ch2[0] control.plot_delete (id) # Combinar sup = superior_tangent (v, u) id_sup = sup[0].lineto (sup[1], config.COLOR_ALT1) inf = inferior_tangent (v, u) id_inf = inf[0].lineto (inf[1], config.COLOR_ALT1) control.freeze_update () control.plot_delete (id_sup) control.plot_delete (id_inf) ch1[2].hide () ch2[2].hide () sup[0].prev = sup[1] sup[1].next = sup[0] inf[0].next = inf[1] inf[1].prev = inf[0] ch1[2].pts = inf[0] ch1[2].plot () control.thaw_update () return (ch1[0], ch2[1], ch1[2])
def Bentley_Ottmann (l): L = Abbb () # Linha de varredura resp = [] # Os nós com os pontos de interseção que retornaremos # Pré-processamento - Transforma cada circulo em pontos-eventos # pontos é a ABBB de pontos eventos pontos = eventos (l) control.sleep() while not pontos.vazia(): p = pontos.deleta_min() # desenha a linha id_linha = control.plot_vert_line (p.ponto.x) id_evento = p.ponto.hilight() control.sleep() "------------------------- Pontos da esquerda --------------------------------" for seg in p.ini: seg.seg.plot ("green") control.sleep() insere_na_linha (L, seg, pontos, p.ponto.x) "------------------------- Pontos de interseção ------------------------------" if len (p.inter) > 0 or (len (p.ini) + len (p.fim) > 1): p.ponto.hilight('yellow') resp.append (p) # Troca a ordem dos segmentos (do p.inter[]) trocados = [] # Remove todos for seg in p.inter: seg.ref = Point (p.ponto.x - 10*eps, ((seg.seg.to.x*seg.seg.init.y) - (seg.seg.init.x*seg.seg.to.y) - (p.ponto.x - 10*eps)*(seg.seg.init.y - seg.seg.to.y)) / (seg.seg.to.x - seg.seg.init.x)) trocados.append (seg) L.deleta (seg) # Insere denovo com o novo ponto de referencia for seg in trocados: seg.ref = p.ponto #print("reinserindo " + str(seg)) insere_na_linha (L, seg, pontos, p.ponto.x, trocados) "------------------------- Pontos da direita --------------------------------" for seg in p.fim: deleta_da_linha (L, seg, pontos, p.ponto.x) # apaga a linha control.plot_delete (id_linha) control.plot_delete (id_evento) p.ponto.unplot() return resp
def sweep_line(input_segments): bst = BinarySearchTree() event_queue = EventQueue(input_segments) for event_point in event_queue: sweep_line_id = control.plot_vert_line( event_point.segment.init.x if event_point.is_left else event_point.segment.to.x, color="cyan") bst.reset_above_below_state() if event_point.is_left: event_point.segment.hilight(color_line="blue", color_point="blue") control.sleep() bst.insert(event_point.segment) bst.find_above_below(event_point.segment) intersect_above = event_point.segment.intersects( bst.above.data) if bst.above is not None else False intersect_below = event_point.segment.intersects( bst.below.data) if bst.below is not None else False if (intersect_above or intersect_below): event_point.segment.hilight(color_line="yellow", color_point="yellow") if intersect_above: bst.above.data.hilight(color_line="yellow", color_point="yellow") elif intersect_below: bst.below.data.hilight(color_line="yellow", color_point="yellow") return True elif not event_point.is_left: control.sleep() bst.find_above_below(event_point.segment) intersect_above_below = bst.below.data.intersects( bst.above.data) if (bst.below is not None and bst.above is not None) else False if intersect_above_below: bst.above.data.hilight(color_line="yellow", color_point="yellow") bst.below.data.hilight(color_line="yellow", color_point="yellow") return True event_point.segment.unhilight() bst.delete(event_point.segment) control.plot_delete(sweep_line_id) return False
def Bentley_Ottmann_Mod (l): L = Abbb () # Linha de varredura resp = [] # Os nós com os pontos de interseção que retornaremos # Pré-processamento - Transforma cada circulo em pontos-eventos # pontos é a ABBB de pontos eventos pontos = eventos (l) control.sleep() while not pontos.vazia(): p = pontos.deleta_min() # desenha a linha id_linha = control.plot_vert_line (p.ponto.x) id_evento = p.ponto.hilight() control.sleep() "------------------------- Pontos da esquerda --------------------------------" for arco in p.ini: insere_na_linha (L, arco, pontos) "------------------------- Pontos de interseção ------------------------------" if len (p.inter) > 0 or len (p.inter_unico) > 0: p.ponto.hilight('yellow') resp.append (p) # Troca a ordem dos arcos (do p.inter[]) # (Não troco a ordem do p.inter_unico[] porque os circulos não se "penetram") trocados = [] # Remove todos for arco in p.inter: trocados.append (arco) L.deleta (trocados[-1]) # Insere denovo com o novo ponto de referencia for arco in trocados: arco.ref = p.ponto insere_na_linha (L, arco, pontos, p.ponto.x, trocados) "------------------------- Pontos da direita --------------------------------" for arco in p.fim: deleta_da_linha (L, arco, pontos, p.ponto.x) # apaga a linha control.plot_delete (id_linha) control.plot_delete (id_evento) p.ponto.unplot() return resp
def build_animation_lines(self): ''' controi as linhas imaginarias que dividem o plano em quadrados ''' delta = self.delta / 2.0 for il in self.id_lines: control.plot_delete(il) self.id_lines.clear() r = self.bl[1] c = self.bl[0] while r < self.ur[1]: self.id_lines.append(control.plot_horiz_line(r, color='blue')) r += delta while c < self.ur[0]: self.id_lines.append(control.plot_vert_line(c, color='blue')) c += delta 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 treat_event(event, queue, sweep_line): v = control.plot_vert_line(event.point.x, 'blue', 2) p = event.point.hilight('cyan') for s in event.right: s.hilight('yellow', None) control.sleep() treat_right(event, queue, sweep_line, s) s.unhilight() for s in event.left: s.hilight('yellow', None) control.sleep() treat_left(event, queue, sweep_line, s) s.unhilight() if (not event.middle.is_empty()): treat_middle(event, queue, sweep_line) if (event.lines > 1): event.print_lines() control.sleep() control.plot_delete(v) event.point.unhilight(p)
def plot_vertical_lines(pm, dmin): vl1 = control.plot_vert_line(pm.x, "orange", 2) vl2 = control.plot_vert_line(pm.x - dmin, "orange", 2) vl3 = control.plot_vert_line(pm.x + dmin, "orange", 2) return vl1, vl2, vl3
def treat_event(p, Q, T): ''' Recebe o ponto evento e o trata conforme seu tipo: extremo esquerdo, extremo direito e ponto de intersecção. ''' event = p[1] point = p[0] print(event, end="\n\n") print("ANTES") # print(dic) for seg in T: print(f"key: {T.key(seg)}, value: {seg}") linea = 0 point.hilight("green") if event.t == "left": s = event.s T.add((s, s)) linea = control.plot_vert_line(s.lower.x, "cyan") control.sleep() control.update() try: prev_index = T.bisect_left((s, s)) prev_index -= 1 if prev_index >= 0: pred = T[prev_index][1] print("PRED: ", pred) if s.intersects(pred): print("INTERSECTA!!!!") verify_new_event(point, Q, s, pred) except IndexError: pass try: next_index = T.bisect_right(s) if next_index <= len(T): succ = T[next_index][1] print("SUCC: ", succ) if s.intersects(succ): verify_new_event(point, Q, s, succ) except IndexError: pass if event.t == "right": s = dic[event.s] segmnt = s[1] linea = control.plot_vert_line(segmnt.upper.x, "cyan") control.sleep() control.update() try: print(s) prev_index = T.bisect_left(s) next_index = T.bisect_right(s) prev_index -= 1 if prev_index >= 0 and next_index <= len(T): pred = T[prev_index][1] succ = T[next_index][1] print("PRED: ", pred) print("SUCC: ", succ) T.pop(T.index(s)) if pred.intersects(succ): verify_new_event(point, Q, succ, pred) except IndexError: T.pop(T.index(s)) if event.t == "inter": s1 = event.s1 s2 = event.s2 if right(s2.lower, s2.upper, s1.lower): s1, s2 = s2, s1 rs1 = dic[s1] rs2 = dic[s2] intersection = intersection_point(s1, s2) intersections.append(intersection) intersections[len(intersections) - 1].hilight("yellow") print(len(intersections)) linea = control.plot_vert_line(intersection.x, "cyan") control.sleep() control.update() try: prev_index = T.bisect_left(rs1) prev_index -= 1 if prev_index < 0: pred = None if rs1 == T[prev_index]: prev_index -= 1 elif prev_index >= 0: pred = T[prev_index][1] print("PRED: ", pred) except IndexError: pred = None try: next_index = T.bisect_right(rs2) if next_index >= len(T): succ = None if rs2 == T[next_index]: next_index += 1 elif next_index < len(T): succ = T[next_index][1] print("SUCC: ", succ) except IndexError: succ = None print("s1: ", s1, " rs1: ", rs1) print("s2: ", s2, " rs2: ", rs2, "\n") T.pop(T.index(rs1)) T.pop(T.index(rs2)) # Insere ao contrário new_s1 = segment.Segment(intersection, s1.upper) new_s2 = segment.Segment(intersection, s2.upper) print(f"new_s1: {new_s1}, new_s2:{new_s2}") T.add((new_s2, s2)) T.add((new_s1, s1)) dic[s1] = (new_s1, s1) dic[s2] = (new_s2, s2) if pred != None and pred.intersects(s2): verify_new_event(point, Q, pred, s2, intersection) if succ != None and s1.intersects(succ): verify_new_event(point, Q, s1, succ, intersection) control.plot_delete(linea) control.sleep() control.update() point.unhilight() print("DEPOIS") for seg in T: print("key: ", str(seg)) print("")
def Bentley_ottman (segments_list): points_list = filter_points(segments_list) intersection_points = [] event_queue = PBST.PointBST() segment_tree = SBST.SegmentBST() sweepline_id = None for s in segments_list: s.plot() insert_point_segment(event_queue, points_list, segments_list) while(not event_queue.isEmpty()): event_node = event_queue.removeMinKey() control.plot_delete(sweepline_id) sweepline_id = control.plot_vert_line(event_node.key.x, color='blue') print("~~~O ponto evento é: (" + str(event_node.key.x) + ", " + str(event_node.key.y) + ")") print("Sua lista de inserções é: ") print(event_node.segment[0]) print("Sua lista de interseções é: ") event_node.segment[1].imprime() print("Sua lista de remoções é: ") print(event_node.segment[2]) if (len(event_node.segment[0]) + event_node.segment[1].size() + len(event_node.segment[2]) > 1): print("Entrei no primeiro if") segment_tree.imprime() intersection_points.append(event_node.key) for segment in event_node.segment[0]: segment.hilight(color_line="yellow") event_node.segment[1].plot_segments("yellow") for segment in event_node.segment[2]: segment.hilight(color_line="yellow") event_node.segment[1].remove_from_sweepline(segment_tree, event_node.key) for segment in event_node.segment[2]: segment_tree.remove(segment, event_node.key) for segment in event_node.segment[0]: segment_tree.insert(segment, event_node.key) event_node.segment[1].insert_in_sweepline(segment_tree, event_node.key) segment_tree.imprime() control.sleep() for segment in event_node.segment[0]: segment.plot() event_node.segment[1].plot_segments("red") for segment in event_node.segment[2]: segment.plot() if (len(event_node.segment[0]) + event_node.segment[1].size() == 0): print("Entrei no segundo if") lower = event_node.segment[2][0] upper = event_node.segment[2][len(event_node.segment[2]) - 1] if(lower): print("O lower é: ") print(lower) print("O upper é: ") print(upper) lower.hilight(color_line="green") upper.hilight(color_line="green") control.sleep() print("Vou imprimir a SegmentBST: ") segment_tree.imprime() pred = segment_tree.get_predecessor(lower, event_node.key) succ = segment_tree.get_sucessor(upper, event_node.key) if (pred and succ): pred.key.hilight(color_line="magenta") succ.key.hilight(color_line="magenta") find_new_event(pred.key, succ.key, event_node.key, event_queue) control.sleep() if(succ): succ.key.plot() if(pred): pred.key.plot() lower.plot() upper.plot() for segment in event_node.segment[2]: segment_tree.remove(segment, event_node.key) else: print("Entrei no else") if (len(event_node.segment[0]) == 1 and len(event_node.segment[0]) + event_node.segment[1].size() + len(event_node.segment[2]) <= 1): print("Tenho um segmento para inserir") segment_tree.insert(event_node.segment[0][0], event_node.key) print("Vou imprimir a SegmentBST: ") segment_tree.imprime() lower = get_lower_segment(event_node.segment[0], event_node.segment[1]) print("O lower é: ") print(lower) lower.hilight(color_line="green") pred = segment_tree.get_predecessor(lower, event_node.key) if (pred): pred.key.hilight(color_line="magenta") find_new_event(pred.key, lower, event_node.key, event_queue) control.sleep() if(pred): pred.key.plot() lower.plot() upper = get_upper_segment(event_node.segment[0], event_node.segment[1]) print("O upper é: ") print(upper) upper.hilight(color_line="green") succ = segment_tree.get_sucessor(upper, event_node.key) if (succ): succ.key.hilight(color_line="magenta") find_new_event(upper, succ.key, event_node.key, event_queue) control.sleep() if(succ): succ.key.plot() upper.plot() for segment in event_node.segment[2]: segment_tree.remove(segment, event_node.key) for point in intersection_points: point.plot("yellow")
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")