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 monotonos (d, P, diags): """ Função que recebe um polígono P e particiona P em vários polígonos monótonos Através da inserção de diagonais Coloca as diagonais na DCEL d """ # Ordena os vértices pela Y-coordenada v = P.vertices() v = sorted(v, key = lambda x:(-x.y)) L = Abbb() # os vértices são os pontos eventos da linha de varredura for p in v: p.hilight() h = control.plot_horiz_line (p.y) control.sleep() viz_cima = p.next viz_baixo = p.prev if viz_cima.y < viz_baixo.y: viz_cima, viz_baixo = viz_baixo, viz_cima if viz_cima.y > p.y and p.y > viz_baixo.y: trata_caso_meio (p, viz_baixo, L, d, diags) elif viz_cima.y < p.y: trata_ponta_pra_cima (p, L, d, diags) else: trata_ponta_pra_baixo (p, L, d, diags) control.plot_delete (h) p.unhilight()
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 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 recursive_ham_sandwich(G1, G2, p1, p2, T): if len(G1) < len(G2): return recursive_ham_sandwich(G2, G1, p2, p1, T) T, is_base = new_interval(G1, G2, p1, p2, T) if is_base: valid_answers = [] for g in G1: for h in G2: p = g.intersect(h) if p and isinstance(p.dual(), Line): valid_answers.append(p.dual()) return valid_answers, G1 + G2 t = new_trapezoid(G1, p1, T) t_ids = [] control.freeze_update() for i in range(4): j = (i + 1) % 4 t_ids.append( control.plot_segment(t[i].x, t[i].y, t[j].x, t[j].y, 'yellow')) control.sleep() control.thaw_update() G1, p1 = discard_lines(G1, p1, t) G2, p2 = discard_lines(G2, p2, t) for id in t_ids: control.plot_delete(id) return recursive_ham_sandwich(G1, G2, p1, p2, T)
def process_intersection(self, a, b): ''' Usada para processar a interseção entre dois eventos. ''' if a == None or b == None or a == b: return if a.type == INTERSECTION or b.type == INTERSECTION: return a_line = a.segment.plot(cor='blue') b_line = b.segment.plot(cor='blue') control.sleep() control.plot_delete(a_line) control.plot_delete(b_line) # Ponto de interseção p = segment_intersection(a, b) if p == None: return # Ponto ja foi processado, adiciono possiveis novos segmentos a inter if p in self.intersections: self.intersections[p].add(a) self.intersections[p].add(b) return p_plot = point.Point(p[0], p[1]) p_plot.plot('white') # Cria conjunto com os segmentos que compõem aquela interseção self.intersections[p] = {a, b} # Adiciono a interseção na fila de eventos se ela esta a direita if p[0] >= self.current_x: new_event = Event(INTERSECTION, p, None) self.bag.insert(p, new_event)
def quickhull_rec(P, p, r, point_p, point_r): '''Miolo recursivo da função Quickhull. Recebe uma coleção de pontos P, um início p e um fim r dados por meio da função partition. Devolve os hulls gerados a cada chamada recursiva.''' if p == r - 1: return [P[r], P[p]] if (point_r, point_p) in points.keys(): id = points.pop((point_r, point_p)) control.plot_delete(id) if (point_p, point_r) in points.keys(): id = points.pop((point_p, point_r)) control.plot_delete(id) s, q = partition(P, p, r, point_p, point_r) new_q = Point(P[q].x, P[q].y) new_r = Point(P[r].x, P[r].y) new_s = Point(P[s].x, P[s].y) hull = quickhull_rec(P, q, r, new_q, new_r) hull2 = quickhull_rec(P, s, q, new_s, new_q) # junta os hulls e remove uma cópia do q for i in range(1, len(hull2)): hull.append(hull2[i]) return hull
def __triangulate(self): self.__stack.append(self.__sortedVertexes[0]) self.__stack.append(self.__sortedVertexes[1]) for i in range(2, len(self.__sortedVertexes)): adjacentVertexes = self.__getAdjacentVertexes(i) currentVertex = self.__sortedVertexes[i] suppPointId = currentVertex.coordinates.hilight(color="white") stackBase = self.__stackBase() stackTop = self.__stackTop() neighborFromBase = self.__isVertexNeighborFrom( adjacentVertexes, stackBase) neighborFromTop = self.__isVertexNeighborFrom( adjacentVertexes, stackTop) if (neighborFromTop and not neighborFromBase): self.__caseA(currentVertex) elif (not neighborFromTop and neighborFromBase): self.__caseB(currentVertex) elif (neighborFromTop and neighborFromBase): self.__caseC(currentVertex) control.sleep() control.plot_delete(suppPointId)
def __partitionatePolygon(self): BST = bst.SplayTree() for eventVertex in sorted(self.dcel.vertex): vertexNumber = eventVertex.vertexNumber() previousVertexNumber = self.dcel.iterateVertex(vertexNumber - 1) nextVertexNumber = self.dcel.iterateVertex(vertexNumber + 1) previousVertex = self.dcel.getVertex(previousVertexNumber) nextVertex = self.dcel.getVertex(nextVertexNumber) sweepLineId = control.plot_horiz_line(eventVertex.y, color="cyan") suppPointId = eventVertex.coordinates.hilight(color="white") control.sleep() if (previousVertex.y > eventVertex.y and nextVertex.y > eventVertex.y) or\ (eventVertex.y == nextVertex.y and nextVertex.x < eventVertex.x and previousVertex.y > eventVertex.y) or\ (eventVertex.y == previousVertex.y and previousVertex.x < eventVertex.x and nextVertex.y > eventVertex.y): self.__caseThree(BST, eventVertex) elif (previousVertex.y < eventVertex.y and nextVertex.y < eventVertex.y) or\ (eventVertex.y == nextVertex.y and eventVertex.y > previousVertex.y and eventVertex.x < nextVertex.x) or\ (eventVertex.y == previousVertex.y and eventVertex.y > nextVertex.y and eventVertex.x < previousVertex.x): self.__caseTwo(BST, previousVertex, eventVertex, nextVertex) else: self.__caseOne(BST, previousVertex, eventVertex, nextVertex) control.plot_delete(sweepLineId) control.plot_delete(suppPointId)
def rem_point(self, x, y): key = (x, y) if key not in self.points.keys(): return if self.points[key][1] == 1: control.plot_delete(self.points[key][0]) self.points[key][0] = None self.points[key][1] = self.points[key][1] - 1
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 delete_stuff(stuff): control.freeze_update() for s in stuff: if isinstance(s, Line): control.plot_delete(s.plot_id) else: s.tk.unplot() control.sleep() control.thaw_update
def unplot_all(par_plots, hedges, sweep): for par in par_plots: control.plot_delete(par) for h in hedges: if h.segment.lid is None: continue h.segment.hide() control.plot_delete(sweep)
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 needs_fix(self, other): # inter are the edges self and other have in common inter, dif = self.get_relative_vertices(other) # check if quad is convex if (len(inter) != 2 or len(dif) != 2): print("ERRO NA LEGALIZACAO") exit(1) if self.v1 in inter: if self.v2 in inter: inter_0 = self.v1 inter_1 = self.v2 dif_0 = self.v3 else: inter_0 = self.v3 inter_1 = self.v1 dif_0 = self.v2 else: inter_0 = self.v2 inter_1 = self.v3 dif_0 = self.v1 if other.v1 in inter: if other.v2 in inter: dif_1 = other.v3 else: dif_1 = other.v2 else: dif_1 = other.v1 if not left(inter_0, inter_1, dif_1): aux = dif_0 dif_0 = dif_1 dif_1 = aux convex = left(inter_0, dif_0, inter_1) and\ left(dif_0, inter_1, dif_1) and\ left(inter_1, dif_1, inter_0) and\ left(dif_1, inter_0, dif_0) if not convex: return False # check if inter is best # only draws if passes convex self.draw("#ffaa33") other.draw("#ffaa33") did = control.plot_segment(inter_0.x, inter_0.y, inter_1.x,\ inter_1.y, color="#ffffff") control.sleep() control.plot_delete(did) self.remove_draw() other.remove_draw() C = Circle(inter_0, inter_1, dif_0) C.draw() control.sleep() C.remove_draw() return C.is_inside(dif_1)
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 partitionatePoly(self): for diagonal in self.diagonalQueue: u = self.dcel.originVertex(diagonal[0]).coordinates v = self.dcel.endVertex(diagonal[0]).coordinates seg = segment.Segment(u, v) seg.hilight(color_line="cyan", color_point="cyan") if not self.essentialEdge(diagonal[0]): self.dcel.removeHalfEdge(diagonal[0]) control.plot_delete(diagonal[1]) control.sleep() seg.unhilight()
def graham(self): if len(self.convexHull) > 0: return self.__sortPointList() self.convexHull = [0, 1, 2] hullSegmentIdList = [] hullSize = len(self.convexHull) for hullPointIndex in range(hullSize): hullSegmentIdList.append( self.__hilightSegment( self.convexHull[hullPointIndex % hullSize], self.convexHull[(hullPointIndex + 1) % hullSize], lineColor="cyan", pointColor="cyan")) if hullPointIndex < 2: control.sleep() for pointIndex in range(3, self.pointListSize): pointPlotId = self.pointList[pointIndex].hilight(color="red") control.sleep() while self.__rightOnWrap(self.convexHull[-2], self.convexHull[-1], pointIndex) and\ len(self.convexHull) > 2: linePlotId = self.__hilightLine(self.convexHull[-2], self.convexHull[-1]) control.sleep() self.convexHull.pop() self.__unhilightSegment(hullSegmentIdList.pop()) control.plot_delete(linePlotId) control.sleep() self.__unhilightSegment(hullSegmentIdList.pop()) hullSegmentIdList.append( self.__hilightSegment(self.convexHull[-1], pointIndex, lineColor="cyan", pointColor="cyan")) control.sleep() hullSegmentIdList.append( self.__hilightSegment(pointIndex, self.convexHull[0], lineColor="cyan", pointColor="cyan")) self.convexHull.append(pointIndex) control.plot_delete(pointPlotId) if pointIndex < self.pointListSize - 1: control.sleep()
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 __caseThree(self, BST, v): control.sleep() firstTrap = BST.getTrapAndRemove(v) x = firstTrap.topSuppVertex if self.__interiorDownCusp(x): xNumber = x.vertexNumber() vNumber = v.vertexNumber() diagonal = (xNumber, vNumber) self.dcel.addHalfEdge(diagonal) self.partitionDiagonalList.append([ (xNumber, vNumber), control.plot_segment(x.x, x.y, v.x, v.y, "yellow") ]) if (firstTrap.leftEdge[1] != v) or (firstTrap.rightEdge[1] != v): secondTrap = BST.getTrapAndRemove(v) y = secondTrap.topSuppVertex if self.__interiorDownCusp(y): yNumber = y.vertexNumber() vNumber = v.vertexNumber() diagonal = (yNumber, vNumber) self.dcel.addHalfEdge(diagonal) self.partitionDiagonalList.append([ (yNumber, vNumber), control.plot_segment(y.x, y.y, v.x, v.y, "yellow") ]) if firstTrap.rightEdge[1] == v: newTrap = bst.Trap(firstTrap.leftEdge, v, secondTrap.rightEdge) BST.insert(newTrap) leftId = self.dcel.buildSegmentFromEdge(firstTrap.leftEdge).hilight( color_line="blue", color_point="red") rightId = self.dcel.buildSegmentFromEdge(secondTrap.rightEdge).hilight( color_line="blue", color_point="red") else: newTrap = bst.Trap(secondTrap.leftEdge, v, firstTrap.rightEdge) BST.insert(newTrap) leftId = self.dcel.buildSegmentFromEdge(secondTrap.leftEdge).hilight( color_line="blue", color_point="red") rightId = self.dcel.buildSegmentFromEdge(firstTrap.rightEdge).hilight( color_line="blue", color_point="red") control.sleep() control.plot_delete(leftId) control.plot_delete(rightId)
def update_points(p1, p2): global a, b, id, hia, hib if (a != None and b != None): if (prim.dist2(p1, p2) >= prim.dist2(a, b)): return control.freeze_update() if a != None: a.unhilight(hia) if b != None: b.unhilight(hib) if id != None: control.plot_delete(id) a = p1 b = p2 hia = a.hilight() hib = b.hilight() id = a.lineto(b) control.thaw_update() control.update()
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 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 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 sweepline(segments): global event_heap, bst fix_segments(segments) bst = sweep_bst() segments = sorted(segments, key=functools.cmp_to_key(compare_segments)) #testa_bst(bst, segments) make_event_points(segments) while (not event_heap.empty()): pt = event_heap.get() circ = control.plot_circle(pt.node.x, pt.node.y, "green", 2) control.sleep() if len(pt.intersections) + len(pt.right) == 0: seg = bst.search(pt.node.get_point()) if seg is not None: # um único segmento na árvore contem pt # e pt é extremo esquerdo de alguns segmentos pt.add_to_segment([seg], -1) update_bst(pt) find_collision(pt) print_intersection(pt) control.plot_delete(circ)
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 discard_lines(G, p, t): nG = [] b = 0 for l in G: control.freeze_update() new_plot_id = control.plot_line(0, l(0), 1, l(1), 'cyan') control.sleep() control.thaw_update() control.freeze_update() is_under, is_above = intersects_trapezoid(l, t) if not (is_under or is_above): nG.append(l) elif is_under: b += 1 if (is_under or is_above): delete_stuff([l]) control.plot_delete(new_plot_id) control.sleep() control.thaw_update() return nG, p - b
def add_circle_event(leaf1, leaf2, leaf3, node1, node2, q, Q): p1, p2, p3 = leaf1.point, leaf2.point, leaf3.point p2.hilight('yellow') p3.hilight('yellow') center = circumcenter(p1, p2, p3) radius = distance(center, p1) circle = control.plot_circle(center.x, center.y, 'blue', radius) is_convergent = not (is_divergent(node1, center) and is_divergent(node2, center)) if is_valid_event(center, radius, q) and is_convergent: point = Point(center.x, center.y - radius) leaf2.event = Event(point, False, leaf2, center) Q.additem(leaf2.event, point) point.plot(color='cyan') control.sleep() control.plot_delete(circle) p2.unhilight() p3.unhilight()
def check(self, p, q, r): ''' Faz a checagem de atualização, checando se o ponto 'r' esta a direita de p-q ou se 'q' esta na reta definida por q-r. ''' a = p.lineto(q, color='blue') b = r.lineto(p, color='blue') c = r.lineto(q, color='blue') control.sleep() flag = False if self.left_test(p, q, r) == -1: flag = True elif self.left_test(p, q, r) == 0 and \ min(p.x, r.x) <= q.x <= max(p.x, r.x) and \ min(p.y, r.y) <= q.y <= max(p.y, r.y): flag = True for aux in [a, b, c]: control.plot_delete(aux) return flag
def find_hull(self): ''' Metodo que efetivamente implementa o algoritmo de Jarvis. Retorna uma lista contendo os pontos do convex hull, no senti anti-horario do fecho. ''' # numero de pontos na coleção n = len(self.p) # armazena os indices dos pontos no fecho, é inicializado com o indice # do ponto mais esquerda e baixo da colecao hull = [min(zip(self.p, range(n)))[1]] # ponto extremo do fecho self.p[hull[0]].hilight(color='yellow') control.sleep() while (True): i = (hull[-1] + 1) % n id_h = self.p[i].hilight(color='yellow') control.sleep() # econtrando o proximo ponto do fecho for j in range(n): if self.p[j] == self.p[hull[-1]] or self.p[j] == self.p[i]: continue if self.check(self.p[hull[-1]], self.p[i], self.p[j]): control.plot_delete(id_h) i = j id_h = self.p[i].hilight(color='yellow') # poligono esta completo self.p[hull[-1]].lineto(self.p[i], color='yellow') if self.p[i] == self.p[hull[0]]: break hull.append(i) # fazendo com que hull seja uma lista de pontos for i in range(len(hull)): hull[i] = self.p[hull[i]] return hull
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 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 bhatta_sen_upper_rec (a, b, S): """Constroi a parte superior do fecho convexo""" # step 1/2/3 again = 1 while again: if len (S) == 1: return [ S[0] ] j = int (random.uniform (0, len (S)/2)) again = 0 p1 = S[2*j+1] p2 = S[2*j] p1.hilight () p2.hilight () if inside_restricted (b, a, S[2*j+1], S[2*j]): S.remove (S[2*j]) again = 1 elif inside_restricted (b, a, S[2*j], S[2*j+1]): S.remove (S[2*j+1]) again = 1 p1.unhilight () p2.unhilight () # step 4 m = 0 if left (S[2*j], S[2*j+1], a): p1 = S[2*j+1] p2 = S[2*j] else: p1 = S[2*j] p2 = S[2*j+1] id = p1.lineto (p2, config.COLOR_ALT4) area_m = area2 (p1, p2, S[m]) for i in range (1, len(S)): area_i = area2 (p1, p2, S[i]) if area_i > area_m: m = i area_m = area_i pm = S[m] control.plot_delete (id) id = pm.hilight (config.COLOR_ALT1) control.sleep () S1 = [] S2 = [] # step 5 i = j #map (lambda p: p.hilight (config.COLOR_ALT2), S) #control.sleep () #map (lambda p: p.unhilight (), S) control.sleep () cont = [] for j in range (0, len(S)/2): cont.extend ([2*j, 2*j+1]) if S[2*j].x < S[2*j+1].x: p1 = S[2*j] p2 = S[2*j+1] else: p1 = S[2*j+1] p2 = S[2*j] p1.hilight () p2.hilight (config.COLOR_ALT3) if p2.x <= pm.x: if left (pm, p2, p1): S1.append (p1) S1.append (p2) else: S1.append (p1) elif pm.x <= p1.x: if left (pm, p1, p2): S2.append (p2) else: S2.append (p1) S2.append (p2) else: # p1.x < pm.x < p2.x control.sleep () S1.append (p1) S2.append (p2) p1.unhilight () p2.unhilight () pm.unhilight (id) if len (S) % 2 == 1: S1.append (S[-1]) S2.append (S[-1]) control.sleep () map (lambda p: p.hilight (), S1) control.sleep () # step 6 for p in S1[:]: if not left (b, pm, p): S1.remove (p) p.unhilight () control.sleep () map (lambda p: p.unhilight (), S1) control.sleep () map (lambda p: p.hilight (), S2) control.sleep () for p in S2[:]: if not left (pm, a, p): S2.remove (p) p.unhilight () control.sleep () map (lambda p: p.unhilight (), S2) # step 7 ret1 = [] ret2 = [] if len (S2) != 0: id = a.lineto (pm, config.COLOR_ALT4) ret2 = bhatta_sen_upper_rec (a, pm, S2) a.remove_lineto (pm, id) ret2[-1].lineto (pm) ret2.append (pm) if len (S1) != 0: id = pm.lineto (b, config.COLOR_ALT4) ret1 = bhatta_sen_upper_rec (pm, b, S1) pm.remove_lineto (b, id) pm.lineto (ret1[0]) ret2.extend (ret1) return ret2
def Hull2D (P, m, H): #print m, H lines = [] n = len (P) CHs = [] num = n/m a = 0 while a < n: b = min (a+m, n) l = P[a:b] ids = [] for p in l: ids.append (p.hilight ()) ch = Graham (l) #ch.hide () for p in P[a:b]: p.unhilight (ids.pop ()) CHs.append (ch) a = b i0 = 0 # encontrando o ponto mais a direita p0 = CHs[0].pts for ch in CHs: for p in ch.to_list (): if p.x > p0.x: p0 = p elif p.x == p0.x: if p.x > p0.x: p0 = p fecho = [ p0 ] for ch in CHs: ch.hide () #control.sleep (2) for k in range (0, H): Q = [] for ch in CHs: ch.plot () p = ch.pts initial = 1 while 1: direction = area2 (fecho[-1], p, p.next) if direction < 0: p = p.next initial = 0 elif direction == 0 \ and dist2 (fecho[-1], p) \ < dist2 (fecho[-1], p.next): p = p.next initial = 0 elif initial: p = p.next else: Q.append (p) p.hilight () control.sleep () ch.pts = p.prev ch.hide () break control.sleep () p = Q[0] for q in Q[1:]: direction = area2 (fecho[-1], p, q) if direction < 0: p = q elif direction == 0: if (dist2 (fecho[-1], p) < dist2 (fecho[-1], q)): p = q for q in Q: q.unhilight () lines.append (fecho[-1].lineto (p, 'green')) fecho.append (p) if p == p0: #for ch in CHs: ch.hide () #print 'fecho =',`fecho` fecho.pop () for i in lines: control.plot_delete (i) poly = Polygon (fecho) poly.plot () return poly #for ch in CHs: ch.hide () for i in lines: control.plot_delete (i) return None