def desenhaTudo(l): poligs = leEntrada(l) robo = poligs[0] probo = destino = None if (len(robo) == 1): print("Robo ponto na posicao ", robo[0]) probo = robo[0] probo.hilight('yellow') destino = poligs[1][0] #Suponho ser um ponto else: for p in robo: p.plot("black") robo = Robo(robo) probo = poligs[1][0] # Suponho ser um ponto Polygon(robo.getPontos(probo.x, probo.y)).plot("yellow") poligs.pop( 0 ) #Removo o polígono do robo da lista, iremos tratar só com o ponto destino = poligs[1][0] # Suponho ser um ponto for i in range(len(poligs)): for p in poligs[i]: p.plot() if (len(poligs[i]) > 1): Polygon(poligs[i]).plot("cyan") probo.hilight("green") destino.hilight("red")
def Quickhull (l): "Algoritmo Quick Hull para achar o fecho convexo da lista de pontos l" south = north = east = west = 0 # encontrando o ponto mais baixo for i in range (1, len(l)): if l[i].y < l[south].y: south = i elif l[i].y == l[south].y: if l[i].x > l[south].x: south = i if l[i].y > l[north].y: north = i elif l[i].y == l[north].y: if l[i].x > l[north].x: north = i if l[i].x < l[west].x: west = i elif l[i].x == l[west].x: if l[i].y > l[west].y: west = i if l[i].x > l[east].x: east = i elif l[i].x == l[east].x: if l[i].y > l[east].y: east = i fecho = [] dirs = [ south, east, north, west ] for i in range (0, len (dirs)): j = (i+1) % 4 if dirs[i] == dirs[j]: continue S1 = [] a = l[dirs[i]] b = l[dirs[j]] id = a.lineto (b, config.COLOR_ALT5) for p in l: if right (a, b, p): S1.append (p) a.remove_lineto (b, id) id = a.lineto (b, config.COLOR_ALT4) aux = quickhull_rec (a, b, S1) a.remove_lineto (b, id) fecho.extend (aux) if len (l) == 1: fecho = [ l[0] ] hull = Polygon (fecho) hull.extra_info = 'vertices: %d'%len (hull.to_list ()) 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 Quickhull(l): "Algoritmo Quick Hull para achar o fecho convexo da lista de pontos l" south = north = east = west = 0 # encontrando o ponto mais baixo for i in range(1, len(l)): if l[i].y < l[south].y: south = i elif l[i].y == l[south].y: if l[i].x > l[south].x: south = i if l[i].y > l[north].y: north = i elif l[i].y == l[north].y: if l[i].x > l[north].x: north = i if l[i].x < l[west].x: west = i elif l[i].x == l[west].x: if l[i].y > l[west].y: west = i if l[i].x > l[east].x: east = i elif l[i].x == l[east].x: if l[i].y > l[east].y: east = i fecho = [] dirs = [south, east, north, west] for i in range(0, len(dirs)): j = (i + 1) % 4 if dirs[i] == dirs[j]: continue S1 = [] a = l[dirs[i]] b = l[dirs[j]] id = a.lineto(b, config.COLOR_ALT5) for p in l: if right(a, b, p): S1.append(p) a.remove_lineto(b, id) id = a.lineto(b, config.COLOR_ALT4) aux = quickhull_rec(a, b, S1) a.remove_lineto(b, id) fecho.extend(aux) if len(l) == 1: fecho = [l[0]] hull = Polygon(fecho) hull.extra_info = 'vertices: %d' % len(hull.to_list()) 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 visGraphAlg(l): poligs = leEntrada(l) robo = poligs[0] destino = None desenhaTudo(l) #Muito codigo igual ao de baixo...mas deixa if (len(robo) == 1): print("Robo ponto na posicao ", robo[0]) probo = robo[0] destino = poligs[1][0] #Suponho ser um ponto else: robo = Robo(robo) probo = poligs[1][0] # Suponho ser um ponto poligs.pop( 0 ) #Removo o polígono do robo da lista, iremos tratar só com o ponto destino = poligs[1][0] # Suponho ser um ponto for i in range(len(poligs)): if (len(poligs[i]) > 1): poligs[i] = robo.deformaPolig(poligs[i]) Polygon(poligs[i]).plot() control.sleep() pontos = [] for i in range(len(poligs)): poligs[i] = Polygon(poligs[i]) poligs[i].hilight() pontos.extend(poligs[i].to_list()) control.sleep() probo.prev = probo.__next__ = probo compara = criaCompara(probo) pontos.sort(key=cmp_to_key(compara), reverse=True) #Grafo G = Grafo(len(pontos)) #Numerando os pontos for i in range(len(pontos)): pontos[i].i = i for pi in pontos: W = verticesVisiveis(pi, poligs) for pj in W: G.addAresta(pi.i, pj.i, dist2(pi, pj)**0.5) path, dist = G.dijkstra(probo.i, destino.i) for i in range(len(path) - 1): v = path[i] u = path[i + 1] pontos[v].lineto(pontos[u], 'red')
def read_polygons(filename): if filename is None: raise ValueError("File name is None") with open(filename) as file: polygons = [] vertices = [] for line in file: line = line.split() if len(line) == 0: polygons.append(Polygon(vertices)) vertices = [] continue if len(line) != 2: raise ValueError("Invalid input from file: {}: {}".format( filename, line)) vertices.append(Point(float(line[0]), float(line[1]))) polygons.append(Polygon(vertices)) return polygons
def Chan (l): n = len (l) if n == 0: return None if n == 1 or n == 2: ret = Polygon (l) ret.plot () ret.extra_info = 'vertices: %d'%n return ret i = 2 while 1: H = min (1<< (1<<i), n) m = H ch = Hull2D (l, m, H) #print ch if ch != None: ch.extra_info = 'vertices: %d'%len (ch.to_list ()) return ch i = i + 1
def Incremental(list_polygon): # Criando e printando o retangulo externo oeste = list_polygon[0].pts.x leste = list_polygon[0].pts.x norte = list_polygon[0].pts.y sul = list_polygon[0].pts.y for polygon in list_polygon: for point in polygon.vertices(): if point.x < oeste: oeste = point.x if point.x > leste: leste = point.x if point.y < sul: sul = point.y if point.y > norte: norte = point.y exterior = [] exterior.append(Point(oeste - 1, sul - 1)) exterior.append(Point(leste + 1, sul - 1)) exterior.append(Point(leste + 1, norte + 1)) exterior.append(Point(oeste - 1, norte + 1)) ext = Polygon(exterior) Print(ext) # Printando os polígonos simples for polygon in list_polygon: Print(polygon) # Parte 1.1 - Transformando os polígonos iniciais em arestas(segmentos de retas) lsegments = [] for polygon in list_polygon: foo = Generate(polygon.vertices()) for x in foo: p1 = x.p_left p2 = x.p_right x.swap = 0 if p1.x > p2.x or (p1.x == p2.x and p1.y > p2.y): x.p_left = p2 x.p_right = p1 x.swap = 1 if len(polygon.vertices()) == 2: x.swap = 0 lsegments.append(x) # Parte 1.2 - Criando o mapa de trapezoidação print("lsegments size is " + str(len(lsegments))) mapa = STrapezoidMap(lsegments) mapa.construct() return mapa
def Lee_Preparata (p): P = p[0] diags = [] d = Dcel () d.initPolygon (P) # Atualiza a DCEL colocando as diagonais parar a partição em monótonos monotonos (d, P, diags) n_face_externa = len(P.vertices()) divisoras = len(diags) # Para cada face, constrói um polígono e triangula ele if len (d.f) == 2: return Monotono([P]) for e in d.f: vertices = [e.init] while e.to != vertices[0]: vertices.append (e.to) e = e.prox if len(vertices) != n_face_externa: new_p = Polygon (vertices) new_p.plot("orange") control.sleep() # Triangula o new_p e adiciona as novas diagonais no diags diags.extend (Monotono ([new_p])) new_p.hide() # despinta as arestas for i in range(divisoras): diags[i].hide() diags[i].plot("green")
def Gift (l): "Algoritmo Embrulho para Presente para encontrar o fecho convexo de uma lista l de pontos" # achando ponto mais baixo i0 = 0 for i in range (1, len(l)): if l[i].y < l[i0].y: i0 = i elif l[i].y == l[i0].y: if l[i].x > l[i0].x: i0 = i fecho = [ l[i0] ] n = len (l) i = i0 while 1: # passo embrulho para presente j0 = 0 for j in range (1,n): if j == i: continue direction = area2 (l[i], l[j0], l[j]) if direction < 0: j0 = j elif direction == 0: if dist2 (l[i], l[j0]) < dist2 (l[i], l[j]): j0 = j i = j0 fecho[-1].lineto (l[j0]) if (i == i0): break fecho.append (l[j0]) ch = Polygon (fecho) ch.extra_info = 'vertices: %d'%len (fecho) return ch
def Graham(l): "Algoritmo de Graham para achar o fecho convexo de uma lista l de pontos" if len(l) == 0: return None # So um ponto foi passado. Retorna um fecho c/ apenas um ponto if len(l) == 1: ret = Polygon(l) ret.plot() ret.extra_info = 'vertices: 1' return ret p0 = l[0] # acha o ponto mais baixo for i in range(1, len(l)): if l[i].y < p0.y: p0 = l[i] elif l[i].y == p0.y: if l[i].x > p0.x: p0 = l[i] l.remove(p0) def cmp(x, y, z=p0): """Funcao para ordenar os pontos ao redor de z Usada com a funcao sort, ordena os pontos de uma lista de acordo com o angulo que cada ponto forma com o ponto z e a reta horizontal. Em caso de empate, o ponto mais distante aparece primeiro.""" area = area2(z, x, y) if area > 0: return -1 elif area < 0: return 1 else: dist_z_x = dist2(z, x) dist_z_y = dist2(z, y) if dist_z_y < dist_z_x: return -1 return dist_z_y > dist_z_x # Ordena os pontos pelo seus angulos l.sort(cmp) # eliminando pontos colineares l2 = [l[0]] for i in range(1, len(l)): if collinear(p0, l[i - 1], l[i]): continue l2.append(l[i]) l = l2 # So sobraram dois pontos -> retorna fecho c/ os dois if len(l) < 2: ret = Polygon([p0, l[0]]) ret.plot() ret.extra_info = 'vertices: 2' return ret pilha = [p0, l[0], l[1]] p0.lineto(l[0]) l[0].lineto(l[1]) control.sleep() for i in range(2, len(l)): l[i].hilight() pilha[-1].lineto(l[i]) control.sleep() while not left(pilha[-2], pilha[-1], l[i]): pilha[-2].remove_lineto(pilha[-1]) pilha[-1].remove_lineto(l[i]) pilha.pop() pilha[-1].lineto(l[i]) control.sleep() pilha.append(l[i]) l[i].unhilight() pilha[-1].lineto(pilha[0]) for i in range(0, len(pilha) - 1): pilha[i].remove_lineto(pilha[i + 1]) pilha[-1].remove_lineto(pilha[0]) poligono = Polygon(pilha) poligono.plot() control.thaw_update() poligono.extra_info = 'vertices: %d' % len(poligono.to_list()) return poligono
def IncrProb (l): "Algoritmo incremental probabilistico para encontrar o fecho convexo" if len (l) == 0: return None # Embaralhando o vetor de entrada for i in range (len (l) -1, -1, -1): index = int (random.uniform (0, i+1)) aux = l[i] l[i] = l[index] l[index] = aux # Inicializando alguns campos... for i in range (0, len(l)): l[i].L = [] l[i].interior = 0 # Criando um fecho convexo com 1 ponto fecho = Polygon ([ l[0] ]) fecho.plot () length = 1 k = 0 hi = l[k].hilight () # Como nao posso admitir que os pontos estao em posicao geral, # preciso tomar cuidado ate' conseguir um fecho convexo com # 3 pontos for k in range (1, len (l)): pts = fecho.pts l[k-1].unhilight (hi) hi = l[k].hilight () control.thaw_update () if length == 1: if l[k].x == pts.x and l[k].y == pts.y: continue fecho.hide () pts.next = pts.prev = l[k] l[k].next = l[k].prev = pts fecho.pts = pts fecho.plot () length = length + 1 elif length == 2: next = pts.next dir = area2 (pts, next, l[k]) if dir == 0: #Mais um ponto colinear -> pega o par mais distante fecho.hide () dist_pts_next = dist2 (pts, next) dist_pts_lk = dist2 (pts, l[k]) dist_next_lk = dist2 (next, l[k]) if dist_pts_next >= dist_pts_lk and dist_pts_next >= dist_next_lk: a = pts b = next elif dist_pts_lk >= dist_pts_next and dist_pts_lk >= dist_next_lk: a = pts b = l[k] elif dist_next_lk >= dist_pts_lk and dist_next_lk >= dist_pts_next: a = next b = l[k] else: print('pau!!!') a.next = a.prev = b b.next = b.prev = a fecho.pts = a fecho.plot () continue fecho.hide () # Um ponto /nao/ colinear :) -> tomar cuidado com a # orientacao if dir > 0: pts.prev = next.next = l[k] l[k].next = pts l[k].prev = next else: pts.next = next.prev = l[k] l[k].prev = pts l[k].next = next length = length + 1 fecho.pts = pts fecho.plot () O = classify (fecho, l, k) break # Ja temos um fecho com 3 pontos -> basta cresce-lo for k in range (k+1, len (l)): pts = fecho.pts l[k-1].unhilight (hi) hi = l[k].hilight () control.thaw_update () if l[k].interior: control.sleep () continue l[k].remove_lineto (l[k].intersect) control.sleep () tan = vertices_tangentes (l[k].intersect, l[k]) l[k].intersect.L.remove (l[k]) l0 = [] l1 = [] # atualizando a classificacao dos pontos vertex = tan[0] while vertex != tan[1]: for p in vertex.L: id = p.hilight (config.COLOR_ALT3) p.remove_lineto (p.intersect) if p == l[k]: p.unhilight (id) continue if left (l[k], O, p): if left_on (tan[0], l[k], p): p.interior = 1 p.intersect = None else: p.intersect = tan[0] p.lineto (p.intersect, config.COLOR_ALT1) l0.append (p) else: if left_on (l[k], tan[1], p): p.interior = 1 p.intersect = None else: p.intersect = l[k] p.lineto (p.intersect, config.COLOR_ALT1) l1.append (p) p.unhilight (id) vertex = vertex.next tan[0].L = l0 l[k].L = l1 # atualizando o fecho control.freeze_update () fecho.hide () tan[0].next.prev = None tan[0].next = l[k] l[k].prev = tan[0] if tan[1].prev: tan[1].prev.next = None tan[1].prev = l[k] l[k].next = tan[1] fecho.pts = tan[0] fecho.plot () control.thaw_update () l[k].unhilight (hi) fecho.plot () fecho.extra_info = 'vertices: %d'%len (fecho.to_list ()) return fecho
def IncrProb(l): "Algoritmo incremental probabilistico para encontrar o fecho convexo" if len(l) == 0: return None # Embaralhando o vetor de entrada for i in range(len(l) - 1, -1, -1): index = int(random.uniform(0, i + 1)) aux = l[i] l[i] = l[index] l[index] = aux # Inicializando alguns campos... for i in range(0, len(l)): l[i].L = [] l[i].interior = 0 # Criando um fecho convexo com 1 ponto fecho = Polygon([l[0]]) fecho.plot() length = 1 k = 0 hi = l[k].hilight() # Como nao posso admitir que os pontos estao em posicao geral, # preciso tomar cuidado ate' conseguir um fecho convexo com # 3 pontos for k in range(1, len(l)): pts = fecho.pts l[k - 1].unhilight(hi) hi = l[k].hilight() control.thaw_update() if length == 1: if l[k].x == pts.x and l[k].y == pts.y: continue fecho.hide() pts.next = pts.prev = l[k] l[k].next = l[k].prev = pts fecho.pts = pts fecho.plot() length = length + 1 elif length == 2: next = pts.next dir = area2(pts, next, l[k]) if dir == 0: #Mais um ponto colinear -> pega o par mais distante fecho.hide() dist_pts_next = dist2(pts, next) dist_pts_lk = dist2(pts, l[k]) dist_next_lk = dist2(next, l[k]) if dist_pts_next >= dist_pts_lk and dist_pts_next >= dist_next_lk: a = pts b = next elif dist_pts_lk >= dist_pts_next and dist_pts_lk >= dist_next_lk: a = pts b = l[k] elif dist_next_lk >= dist_pts_lk and dist_next_lk >= dist_pts_next: a = next b = l[k] else: print('pau!!!') a.next = a.prev = b b.next = b.prev = a fecho.pts = a fecho.plot() continue fecho.hide() # Um ponto /nao/ colinear :) -> tomar cuidado com a # orientacao if dir > 0: pts.prev = next.next = l[k] l[k].next = pts l[k].prev = next else: pts.next = next.prev = l[k] l[k].prev = pts l[k].next = next length = length + 1 fecho.pts = pts fecho.plot() O = classify(fecho, l, k) break # Ja temos um fecho com 3 pontos -> basta cresce-lo for k in range(k + 1, len(l)): pts = fecho.pts l[k - 1].unhilight(hi) hi = l[k].hilight() control.thaw_update() if l[k].interior: control.sleep() continue l[k].remove_lineto(l[k].intersect) control.sleep() tan = vertices_tangentes(l[k].intersect, l[k]) l[k].intersect.L.remove(l[k]) l0 = [] l1 = [] # atualizando a classificacao dos pontos vertex = tan[0] while vertex != tan[1]: for p in vertex.L: id = p.hilight(config.COLOR_ALT3) p.remove_lineto(p.intersect) if p == l[k]: p.unhilight(id) continue if left(l[k], O, p): if left_on(tan[0], l[k], p): p.interior = 1 p.intersect = None else: p.intersect = tan[0] p.lineto(p.intersect, config.COLOR_ALT1) l0.append(p) else: if left_on(l[k], tan[1], p): p.interior = 1 p.intersect = None else: p.intersect = l[k] p.lineto(p.intersect, config.COLOR_ALT1) l1.append(p) p.unhilight(id) vertex = vertex.next tan[0].L = l0 l[k].L = l1 # atualizando o fecho control.freeze_update() fecho.hide() tan[0].next.prev = None tan[0].next = l[k] l[k].prev = tan[0] if tan[1].prev: tan[1].prev.next = None tan[1].prev = l[k] l[k].next = tan[1] fecho.pts = tan[0] fecho.plot() control.thaw_update() l[k].unhilight(hi) fecho.plot() fecho.extra_info = 'vertices: %d' % len(fecho.to_list()) return fecho
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 Bhatta_Sen (l): """Algoritmo otimo proposto por Bhattacharya e Sen para encontrar o fecho convexo de l""" south = north = east = west = 0 # encontrando o ponto mais baixo for i in range (1, len(l)): if l[i].y < l[south].y: south = i elif l[i].y == l[south].y: if l[i].x > l[south].x: south = i if l[i].y > l[north].y: north = i elif l[i].y == l[north].y: if l[i].x > l[north].x: north = i if l[i].x < l[west].x: west = i elif l[i].x == l[west].x: if l[i].y > l[west].y: west = i if l[i].x > l[east].x: east = i elif l[i].x == l[east].x: if l[i].y > l[east].y: east = i fecho = [] dirs = [ south, east, north, west ] for i in range (0, len (dirs)): j = (i+1) % 4 if dirs[i] == dirs[j]: continue fecho.append (l[dirs[i]]) S1 = [] a = l[dirs[i]] b = l[dirs[j]] for p in l: if right (a, b, p): S1.append (p) id = a.lineto (b, config.COLOR_ALT4) aux = [] if len (S1) > 0: if dirs[i] == south or dirs[i] == west: aux = bhatta_sen_lower_rec (a, b, S1) else: aux = bhatta_sen_upper_rec (a, b, S1) a.remove_lineto (b, id) if len (aux) > 0: a.lineto (aux[0]) aux[-1].lineto (b) else: a.lineto (b) fecho.extend (aux) if len (l) == 1: fecho = [ l[0] ] pol = Polygon (fecho) pol.plot () pol.extra_info = "vertices: %d" %len (fecho) return pol
def Bhatta_Sen(l): """Algoritmo otimo proposto por Bhattacharya e Sen para encontrar o fecho convexo de l""" south = north = east = west = 0 # encontrando o ponto mais baixo for i in range(1, len(l)): if l[i].y < l[south].y: south = i elif l[i].y == l[south].y: if l[i].x > l[south].x: south = i if l[i].y > l[north].y: north = i elif l[i].y == l[north].y: if l[i].x > l[north].x: north = i if l[i].x < l[west].x: west = i elif l[i].x == l[west].x: if l[i].y > l[west].y: west = i if l[i].x > l[east].x: east = i elif l[i].x == l[east].x: if l[i].y > l[east].y: east = i fecho = [] dirs = [south, east, north, west] for i in range(0, len(dirs)): j = (i + 1) % 4 if dirs[i] == dirs[j]: continue fecho.append(l[dirs[i]]) S1 = [] a = l[dirs[i]] b = l[dirs[j]] for p in l: if right(a, b, p): S1.append(p) id = a.lineto(b, config.COLOR_ALT4) aux = [] if len(S1) > 0: if dirs[i] == south or dirs[i] == west: aux = bhatta_sen_lower_rec(a, b, S1) else: aux = bhatta_sen_upper_rec(a, b, S1) a.remove_lineto(b, id) if len(aux) > 0: a.lineto(aux[0]) aux[-1].lineto(b) else: a.lineto(b) fecho.extend(aux) if len(l) == 1: fecho = [l[0]] pol = Polygon(fecho) pol.plot() pol.extra_info = "vertices: %d" % len(fecho) return pol
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
def Incremental (l): "Algoritmo incremental para o problema do fecho convexo de uma lista de pontos" if len (l) == 0: return None # crio um fecho c/ um ponto fecho = Polygon ([ l[0] ]) fecho.plot () # Como nao posso admitir que os pontos estao em posicao geral, # preciso tomar cuidado ate encontrar tres pontos nao colineares # :-( length = 1 k = 0 hi = l[k].hilight () for k in range (1, len (l)): pts = fecho.pts l[k-1].unhilight (hi) hi = l[k].hilight () control.thaw_update () if length == 1: if l[k].x == pts.x and l[k].y == pts.y: continue fecho.hide () pts.next = pts.prev = l[k] l[k].next = l[k].prev = pts fecho.pts = pts fecho.plot () length = length + 1 elif length == 2: next = pts.next dir = area2 (pts, next, l[k]) if dir == 0: #Mais um ponto colinear -> pega o par mais distante fecho.hide () dist_pts_next = dist2 (pts, next) dist_pts_lk = dist2 (pts, l[k]) dist_next_lk = dist2 (next, l[k]) if dist_pts_next >= dist_pts_lk and dist_pts_next >= dist_next_lk: a = pts b = next elif dist_pts_lk >= dist_pts_next and dist_pts_lk >= dist_next_lk: a = pts b = l[k] elif dist_next_lk >= dist_pts_lk and dist_next_lk >= dist_pts_next: a = next b = l[k] else: print 'pau!!!' a.next = a.prev = b b.next = b.prev = a fecho.pts = a fecho.plot () continue fecho.hide () # Ponto nao colinear :) - basta tomar cuidado p/ # construir o poligono c/ a direcao certa if dir > 0: pts.prev = next.next = l[k] l[k].next = pts l[k].prev = next else: pts.next = next.prev = l[k] l[k].prev = pts l[k].next = next length = length + 1 fecho.pts = pts fecho.plot () break # Ja tenho um fecho com 3 pontos -> basta "cresce-lo" for k in range (k+1, len (l)): pts = fecho.pts l[k-1].unhilight (hi) hi = l[k].hilight () control.thaw_update () tan = vertices_tangentes (fecho, l[k]) # l[k] esta fora do fecho atual <=> len (tan) == 2 if len (tan) == 2: control.freeze_update () fecho.hide () tan[0].next.prev = None tan[0].next = l[k] l[k].prev = tan[0] if tan[1].prev: tan[1].prev.next = None tan[1].prev = l[k] l[k].next = tan[1] fecho.pts = tan[0] fecho.plot () control.thaw_update () l[k].unhilight (hi) fecho.plot () fecho.extra_info = 'vertices: %d'%len (fecho.to_list ()) return fecho
def Graham (l): "Algoritmo de Graham para achar o fecho convexo de uma lista l de pontos" if len (l) == 0: return None # So um ponto foi passado. Retorna um fecho c/ apenas um ponto if len (l) == 1: ret = Polygon (l) ret.plot () ret.extra_info = 'vertices: 1' return ret p0 = l[0] # acha o ponto mais baixo for i in range (1, len(l)): if l[i].y < p0.y: p0 = l[i] elif l[i].y == p0.y: if l[i].x > p0.x: p0 = l[i] l.remove (p0) def cmp (x, y, z = p0): """Funcao para ordenar os pontos ao redor de z Usada com a funcao sort, ordena os pontos de uma lista de acordo com o angulo que cada ponto forma com o ponto z e a reta horizontal. Em caso de empate, o ponto mais distante aparece primeiro.""" area = area2 (z, x, y) if area > 0: return -1 elif area < 0: return 1 else: dist_z_x = dist2 (z, x) dist_z_y = dist2 (z, y) if dist_z_y < dist_z_x: return -1 return dist_z_y > dist_z_x # Ordena os pontos pelo seus angulos l.sort (cmp) # eliminando pontos colineares l2 = [ l[0] ] for i in range (1, len (l)): if collinear (p0, l[i-1], l[i]): continue l2.append (l[i]) l = l2 # So sobraram dois pontos -> retorna fecho c/ os dois if len (l) < 2: ret = Polygon ( [ p0, l[0] ] ) ret.plot () ret.extra_info = 'vertices: 2' return ret pilha = [ p0, l[0], l[1] ] p0.lineto (l[0]) l[0].lineto (l[1]) control.sleep () for i in range (2, len(l)): l[i].hilight () pilha[-1].lineto (l[i]) control.sleep () while not left (pilha[-2], pilha[-1], l[i]): pilha[-2].remove_lineto (pilha[-1]) pilha[-1].remove_lineto (l[i]) pilha.pop () pilha[-1].lineto (l[i]) control.sleep () pilha.append (l[i]) l[i].unhilight () pilha[-1].lineto (pilha[0]) for i in range (0, len(pilha)-1): pilha[i].remove_lineto (pilha[i+1]) pilha[-1].remove_lineto (pilha[0]) poligono = Polygon (pilha) poligono.plot () control.thaw_update () poligono.extra_info = 'vertices: %d'%len (poligono.to_list ()) return poligono