def visit(self, u, target): u.setVisited(True) v = self.findNeighbor(u) while v is not None: # Printando o segmento atual do grafo seg = Segment(Point(u.x, u.y), Point(v.x, v.y)) seg.plot('cyan') control.sleep() # Continuar o DFS if (v == target): self.solved = True return 1 self.visit(v, target) # Condicao de parada do DFS if(self.solved): return 1 # Retirando o print do segmento seg.hide() control.sleep() # Pegar o próximo vizinho v = self.findNeighbor(u)
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 classify(convex, points, start): "Associa cada ponto em points a uma aresta visivel do triangulo convex" first = convex.pts second = first.next third = second.next first.L = [] second.L = [] third.L = [] # O e' um ponto dentro do fecho convexo (que ainda e' um triangulo) Ox = (first.x + second.x + third.x) / 3.0 Oy = (first.y + second.y + third.y) / 3.0 O = Point(Ox, Oy) O.hilight(config.COLOR_ALT2) for i in range(start, len(points)): for p in (first, second, third): points[i].interior = 1 if intersect_restricted(points[i], O, p, p.next): p.L.append(points[i]) points[i].intersect = p points[i].interior = 0 points[i].lineto(p, config.COLOR_ALT1) break return O
def eventos (circulos): "Função que retorna uma ABBB de pontos-eventos, que são os extremos horizontais dos circulos" Q = Abbb () # Abbb dos pontos eventos for c in circulos: p_esq = c.center - Point (c.r, 0) p_dir = c.center + Point (c.r, 0) baixo = Node_Semi_Circle (c, True, p_esq) cima = Node_Semi_Circle (c, False, p_esq) p1 = Node_Point_Circle (p_esq, ini = [baixo, cima], fim = [], inter = [], inter_unico = []) p2 = Node_Point_Circle (p_dir, ini = [], fim = [baixo, cima], inter = [], inter_unico = []) no1 = Q.busca (p1) no2 = Q.busca (p2) # Se os pontos já estão inseridos, só atualiza, se não, insere if no1.elemento != None: no1.elemento.ini.append (baixo) no1.elemento.ini.append (cima) else: Q.insere (p1) p_esq.plot (color = 'red') if no2.elemento != None: no2.elemento.fim.append (baixo) no1.elemento.fim.append (cima) else: Q.insere (p2) p_dir.plot (color = 'red') return Q
def classify (convex, points, start): "Associa cada ponto em points a uma aresta visivel do triangulo convex" first = convex.pts second = first.next third = second.next first.L = [] second.L = [] third.L = [] # O e' um ponto dentro do fecho convexo (que ainda e' um triangulo) Ox = (first.x + second.x + third.x) / 3.0 Oy = (first.y + second.y + third.y) / 3.0 O = Point (Ox, Oy) O.hilight (config.COLOR_ALT2) for i in range (start, len (points)): for p in (first, second, third): points[i].interior = 1 if intersect_restricted (points[i], O, p, p.next): p.L.append (points[i]) points[i].intersect = p points[i].interior = 0 points[i].lineto (p, config.COLOR_ALT1) break return O
class Disc: "Um Disco representado por suas coordenadas cartesianas" def __init__ (self, x, y, r): "Para criar um ponto, passe suas coordenadas." self.center = Point(x, y) self.r = r self.seg = Segment(Point(x-r, y), Point(x+r,y)) self.lineto_id = {} def __repr__ (self): "Retorna uma string da forma '( x, y, r )'" return '( ' + repr(self.center.x) + ', ' + repr(self.center.y) + ', ' + repr(self.r) + ' )' def plot (self, color = config.COLOR_DISC): "Desenha o disco na cor especificada" self.plot_id = control.plot_disc_grande (self.center.x, self.center.y, color, self.r) self.center.plot() return self.plot_id ################### VICTOR MUDOU (Edu- talvez n precise disso) ####################### def unplot(self, id = None): if id == None: id = self.plot_id control.plot_delete(id) ################## FIM ############################ def hilight (self, color=config.COLOR_HI_POINT): "Desenha o disco com 'destaque' (com cor diferente)" self.hi = control.plot_disc (self.center.x, self.center.y, color, self.r) return self.hi def unhilight (self, id = None): "Apaga o 'destaque' do ponto" if id == None: id = self.hi control.plot_delete (id) def lineto (self, p, color=config.COLOR_LINE): "Desenha uma linha do centro até o ponto especificado" self.lineto_id[p] = control.plot_line (self.center.x, self.center.y, p.x, p.y, color) return self.lineto_id[p] def remove_lineto (self, p, id = None): "Remove a linha ate o ponto p" if id == None: id = self.lineto_id[p] control.plot_delete (id) def extremes(self): offsets = [self.r, - self.r] return [ self.center + Point(0, off) for off in offsets] + [ self.center + Point(off, 0) for off in offsets]
def newEdge(self, x1, y1, x2, y2): vertex1 = self.findVertex(x1, y1) vertex2 = self.findVertex(x2, y2) if (vertex1 != None) and (vertex2 != None): self.allEdge.append(Edge(vertex1, vertex2)) point1 = Point(vertex1.getX(), vertex1.getY()) point2 = Point(vertex2.getX(), vertex2.getY()) Printo(Segment(point1, point2)) else: print("Falhou em newEdge -- vertices errados!")
def intersection (self, other): "Retorna uma lista com o(s) ponto(s) de interseção entre os dois círculos" if not self.intersects_circ (other): return [] # Um pouco de geometria: Montando a esquação do circulo # Temos: self: (x - x1)^2 + (y - y1)^2 = r1^2 # other: (x - x2)^2 + (y - y2)^2 = r2^2 x1, y1 = self.center.x, self.center.y x2, y2 = other.center.x, other.center.y r1, r2 = self.r, other.r # Depois de subtrair as duas equações, teremos uma reta # 2x*(x2 - x1) + 2y*(y2 - y1) + x1^2 - x2^2 + y1^2 - y2^2 = r1^2 - r2^2 # Isolando o x para a resposta, temos essa grande conta: # x = [ r1^2 - r2^2 + x2^2 - x1^2 + y2^2 - x1^2 + 2y*(y2 - y1) ] / 2*(x2 - x1) # se x1 = x2, temos um caso mais simples, basta encontrar y if x1 == x2: if y1 == y2: # supondo que não há circulos iguais return [] res_y1 = (r1**2 - r2**2 + y2**2 - y1**2) / (2*(y2 - y1)) res_y2 = res_y1 res_x1 = (r1**2 - (res_y1 - y1)**2 )**(0.5) + x1 res_x2 = -(r1**2 - (res_y1 - y1)**2 )**(0.5) + x1 # Se não, temos que colocar o x em alguma das equações dos circulos e criar uma equação de 2º grau # Depois de (( muitas )) continhas ... # conclui que os valores de a, b e c para nossa equação ay^2 + by + c = 0 são else: const = r1**2 - r2**2 + y2**2 - y1**2 + x2**2 + x1**2 - 2*x1*x2 a = (y1 - y2)**2 / (x1 - x2)**2 + 1 b = (y1 - y2)*const / (x1 - x2)**2 - 2*y1 c = const**2 / (4*(x1 - x2)**2) + y1**2 - r1**2 # Agora a gente aplica um super bhaskara delta = b**2 - 4*a*c res_y1 = (-b + delta**(0.5)) / (2*a) res_y2 = (-b - delta**(0.5)) / (2*a) # Aplica os valores na reta para descobir os x res_x1 = ( r1**2 - r2**2 + y2**2 - y1**2 + x2**2 - x1**2 + 2*res_y1*(y1 - y2) ) / (2*(x2 - x1)) res_x2 = ( r1**2 - r2**2 + y2**2 - y1**2 + x2**2 - x1**2 + 2*res_y2*(y1 - y2) ) / (2*(x2 - x1)) p1 = Point (res_x1, res_y1) p2 = Point (res_x2, res_y2) if p1.approx_equals (p2): return [p1] return [p1, p2] ################### FIM PEDRO ######################################
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 menorAnguloX(v1,v2, w1, w2): a = Point(v2.x - v1.x, v2.y - v1.y) b = Point(w2.x - w1.x, w2.y - w1.y) if((a.y >= 0) != (b.y >= 0)): if(a.y >= 0): return -1 else: return 1 else: if(left(Point(0,0), a, b)): return -1; elif(right(Point(0,0), a, b)): return 1; else: return 0;
def read_segments(filename): if filename is None: raise ValueError("File name is None") with open(filename) as file: segments = set() for line in file: line = line.split() if len(line) != 4: raise ValueError("Invalid input from file: {}: {}".format( filename, line)) segments.add( Segment(Point(float(line[0]), float(line[1])), Point(float(line[2]), float(line[3])))) return segments
def read_point_link(filename): if filename is None: raise ValueError("File name is None") with open(filename) as file: link = {} for line in file: line = line.split() if len(line) != 4: raise ValueError("Invalid input from file: {}: {}".format( filename, line)) key = Point(float(line[0]), float(line[1])) adj = Point(float(line[2]), float(line[3])) if key not in link: link[key] = set() link[key].add(adj) return link
def __gt__ (self, other): if self.circ == other.circ: return self.baixo and not other.baixo ref = other.ref x = self.circ.center.x y = self.circ.center.y # Se o ponto de referencia é uma interseção, if abs((ref.x - x)**2 + (ref.y - y)**2 - self.circ.r**2) < eps: # então eu pego um ponto um pouco posterior pra ser o ponto de refencia, # aplicando a formula do circulo pra 2*epsilon pra frente if other.baixo: sinal = -1 else: sinal = 1 # Formula do circulo x_novo = ref.x + 2*eps x_novo = min (x_novo, other.circ.center.x + other.circ.r) y_novo = other.circ.center.y y_novo += sinal*(other.circ.r**2 - (x_novo - other.circ.center.x)**2)**0.5 ref = Point (x_novo, y_novo) # Self > other <=> other está a esquerda do self return self.esquerda (ref, other.baixo)
def read_intersections(filename): if filename is None: raise ValueError("File name is None") with open(filename) as file: intersections = {} point = None for line in file: line = line.split() if len(line) == 2: point = Point(float(line[0]), float(line[1])) intersections[point] = set() if len(line) == 4: intersections[point].add( Segment(Point(float(line[0]), float(line[1])), Point(float(line[2]), float(line[3])))) return intersections
def somaMinkowski(lista1, lista2): n = len(lista1); m = len(lista2); #l1 e l2 serão as listas deslocadas de forma que #o primeiro ponto tenha coordenada minima dentre os #pontos do polígono pmin = lista1[0] imin = 0 for i in range(len(lista1)): p = lista1[i] if(p.y < pmin.y): pmin = p imin = i elif(p.y == pmin.y and p.x < pmin.x): pmin = p imin = i l1 = shift(lista1, imin) pmin = lista2[0] imin = 0 for i in range(len(lista2)): p = lista2[i] if(p.y < pmin.y): pmin = p imin = i elif(p.y == pmin.y and p.x < pmin.x): pmin = p imin = i l2 = shift(lista2, imin) # adicionando sentinelas... l2.append(l2[0]); l2.append(l2[1]); l1.append(l1[0]); l1.append(l1[1]); i = 0; j = 0; soma = [] while True: soma.append(Point(l1[i].x + l2[j].x, l1[i].y + l2[j].y)) ### condições de parada if(i == n): j = j + 1 elif(j == m): i = i + 1 ##### elif(menorAnguloX(l1[i],l1[i+1],l2[j],l2[j+1]) == -1): i = i + 1 elif(menorAnguloX(l1[i],l1[i+1],l2[j],l2[j+1]) == 1): j = j + 1 else: i = i + 1 j = j + 1 if(i == n and j == m): break; return soma
def Brute(list_polygon): ##################################################################################################### "Coloque aqui o ponto que o robô está e o ponto que o robô quer ir, respectivamente." "O primeiro argumento é o x do ponto e o segundo é o y do ponto" box = Box_Box() print(box.sx, box.sy, box.ex, box.ey) start = SPoint(int(box.sx), int(box.sy)) target = SPoint(int(box.ex), int(box.ey)) ##################################################################################################### mapa = Incremental(list_polygon) # Parte 1.3 - Removendo as extensões vérticais dentro dos polígonos mapa.checking() # Achando o grafo de locomoção startTrap = mapa.query(mapa.node_list[0], start) targetTrap = mapa.query(mapa.node_list[0], target) # Parte 2.1 - Transformando em grafo grafo = mapa.make_graph() #start = Point(0, 0) grafo.newVertex(start.x, start.y) #target = Point(10, 10) grafo.newVertex(target.x, target.y) grafo.newEdge(start.x, start.y, startTrap.info.center().x, startTrap.info.center().y) grafo.newEdge(target.x, target.y, targetTrap.info.center().x, targetTrap.info.center().y) Print_S_and_T(Point(start.x, start.y)) Print_S_and_T(Point(target.x, target.y)) grafo.DFS(grafo.findVertex(target.x, target.y), grafo.findVertex(start.x, start.y)) '''
def read_points(filename): with open(filename) as file: points = set() for line in file: line = line.split() if len(line) != 2: raise ValueError("Invalid input from file: {}: {}".format( filename, line)) points.add(Point(float(line[0]), float(line[1]))) return points
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 angle_from_origin(origin_point: Point, test_point: Point) -> float: ''' Returns the angle, in radians, of the test point from the origin point, sweeping like a clock, starting from the right and working counter-clockwise, just like the sine/cosine unit cicle. ''' # shifts so that the origin point is at 0,0 shifted_test_point = Point(test_point.x - origin_point.x, test_point.y - origin_point.y) angle = math.atan2(shifted_test_point.y, shifted_test_point.x) return angle if angle >= 0 else angle + 2 * math.pi
def Generate(l): # Dado a lista de pontos do poligono e gera todos os segmentos de retas lsegments = [] n = len(l) if (n == 2): lsegments.append( SSegment(SPoint(l[0].x, l[0].y), SPoint(l[1].x, l[1].y))) seg = Segment(Point(l[0].x, l[0].y), Point(l[1].x, l[1].y)) seg.plot('green') control.sleep() else: for i in range(n): lsegments.append( SSegment(SPoint(l[i % n].x, l[i % n].y), SPoint(l[(i + 1) % n].x, l[(i + 1) % n].y))) seg = Segment(Point(l[i % n].x, l[i % n].y), Point(l[(i + 1) % n].x, l[(i + 1) % n].y)) seg.plot('green') control.sleep() return lsegments
def desenha (self): cima = self.sup.y baixo = max (self.a_esq.to.y, self.a_dir.to.y) # Acha os dois pontos da esquerda x1, y1 = self.a_esq.init.x, self.a_esq.init.y x2, y2 = self.a_esq.to.x, self.a_esq.to.y cima_esq = Point ((x2*y1 - x1*y2 + cima*(x1 - x2))/(y1 - y2), cima) baixo_esq = Point ((x2*y1 - x1*y2 + baixo*(x1 - x2))/(y1 - y2), baixo) # Acha os dois pontos da direita x1, y1 = self.a_dir.init.x, self.a_dir.init.y x2, y2 = self.a_dir.to.x, self.a_dir.to.y cima_dir = Point ((x2*y1 - x1*y2 + cima*(x1 - x2))/(y1 - y2), cima) baixo_dir = Point ((x2*y1 - x1*y2 + baixo*(x1 - x2))/(y1 - y2), baixo) self.aresta_cima = (Segment (cima_esq, cima_dir)).plot('green') self.aresta_baixo = (Segment (baixo_esq, baixo_dir)).plot('green') self.aresta_esq = (Segment (baixo_esq, cima_esq)).plot('green') self.aresta_dir = (Segment (baixo_dir, cima_dir)).plot('green')
def pontos_infinitos(p): " Devolve três pontos fictícios tais que o triangulo formado por eles " " contém todos os pontos de p " # Vou montar um quadradão que contém todos os pontos cima = baixo = direito = esquerdo = p[0] for i in range(1, len(p)): if p[i].y > cima.y: cima = p[i] if p[i].y < baixo.y: baixo = p[i] if p[i].x < esquerdo.x: esquerdo = p[i] if p[i].x > direito.x: direito = p[i] # Agora monto um triângulão que contém esse quadrado p1 = Point(esquerdo.x - 10 * (direito.x - esquerdo.x), baixo.y - 10 * (cima.y - baixo.y)) p2 = Point(esquerdo.x + (direito.x - esquerdo.x) / 2, cima.y + 10 * (cima.y - baixo.y)) p3 = Point(esquerdo.x + 10 * (direito.x - esquerdo.x), baixo.y - 10 * (cima.y - baixo.y)) return p1, p2, p3
def intersection_point(s1, s2): x1, y1 = s1.init.x, s1.init.y x2, y2 = s1.to.x, s1.to.y x3, y3 = s2.init.x, s2.init.y x4, y4 = s2.to.x, s2.to.y if vertical(s1): x = s1.init.x m2 = (y4 - y3) / (x4 - x3) y = m2 * (x - x3) + y3 p = Point(x, y) return p if vertical(s2): x = s2.init.x m1 = (y2 - y1) / (x2 - x1) y = m1 * (x - x1) + y1 p = Point(x, y) return p m1 = (y2 - y1) / (x2 - x1) m2 = (y4 - y3) / (x4 - x3) x = (m1 * x1 - m2 * x3 - y1 + y3) / (m1 - m2) y = m1 * x + (-m1 * x1 + y1) p = Point(x, y) return p
def Quickhull(P): '''Recebe uma coleção de pontos P e devolve seu fecho convexo''' n = len(P) if n == 1: return [P[0]] # encontra primeiro ponto extremo k = 0 for i in range(n): # desempata por x if P[i].y < P[k].y or (P[i].y == P[k].y and P[i].x < P[k].x): k = i P[0], P[k] = P[k], P[0] # encontra extremo consecutivo ao primeiro i = 1 dist = 0 for j in range(2, n): if right(P[0], P[i], P[j]): i = j # desempata pelo mais distante elif collinear(P[0], P[i], P[j]) and dist2(P[0], P[i]) < dist2(P[0], P[j]): i = j P[n - 1], P[i] = P[i], P[n - 1] P[0].lineto(P[n - 1], 'cyan') control.thaw_update() control.update() control.freeze_update() control.sleep() quick = quickhull_rec(P, 0, n - 1, Point(P[0].x, P[0].y), Point(P[n - 1].x, P[n - 1].y)) for p in quick: p.hilight('yellow') return quick
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 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 pre_process(points): global DG, dcel, root shuffle(points) inside = [] not_inside = [i for i in range(len(points))] min_x = min_y = float('inf') max_x = max_y = -float('inf') for i, pt in enumerate(points): if pt.x < min_x: min_x = pt.x if pt.x > max_x: max_x = pt.x if pt.y > max_y: max_y = pt.y if pt.y < min_y: min_y = pt.y points[i] = Point(pt[0], pt[1]) mid_hor = (max_x + min_x) / 2.0 #fixed left_hor = mid_hor - (max_x - min_x) * 0.75 #fixed hor_fact = (max_x - min_x) #variable mid_ver = (max_y + min_y) / 2.0 #fixed len_ver = (max_y - min_y) #variable node = None while (len(not_inside) > 0): node = Node( Point(left_hor, mid_ver + len_ver), #top left Point(left_hor, mid_ver - len_ver), #bottom left Point(mid_hor + hor_fact, mid_ver)) #center right for i in range(len(not_inside)): if node.contains_proper(points[not_inside[i]]) or\ node.is_on_edge(points[not_inside[i]]): inside.append(i) for ind in reversed(inside): not_inside.pop(ind) inside = [] hor_fact *= 1.15 len_ver *= 1.5 DG = nx.DiGraph() dcel = DCEL() root = node DG.add_node(root) vtcs = root.get_vertices() ext1 = hedge(vtcs[1], vtcs[0]) ext2 = hedge(vtcs[0], vtcs[2]) ext3 = hedge(vtcs[2], vtcs[1]) int1 = hedge(vtcs[0], vtcs[1]) int2 = hedge(vtcs[2], vtcs[0]) int3 = hedge(vtcs[1], vtcs[2]) ext1.next = ext2 ext1.prev = ext3 ext1.twin = int1 ext2.next = ext3 ext2.prev = ext1 ext2.twin = int2 ext3.next = ext1 ext3.prev = ext2 ext3.twin = int3 int1.next = int3 int1.prev = int2 int1.twin = ext1 int1.face = root int2.next = int1 int2.prev = int3 int2.twin = ext2 int2.face = root int3.next = int2 int3.prev = int1 int3.twin = ext3 int3.face = root dcel.add_hedge(ext1) dcel.add_hedge(ext2) dcel.add_hedge(ext3) dcel.add_hedge(int1) dcel.add_hedge(int2) dcel.add_hedge(int3)
class Disc: "Um Disco representado por suas coordenadas cartesianas" def __init__ (self, x, y, r): "Para criar um disco, passe suas coordenadas." self.center = Point(x, y) self.r = r self.seg = Segment(Point(x-r, y), Point(x+r,y)) self.lineto_id = {} def __repr__ (self): "Retorna uma string da forma '( x, y, r )'" return '( ' + repr(self.center.x) + ', ' + repr(self.center.y) + ', ' + repr(self.r) + ' )' def plot (self, color = config.COLOR_DISC): "Desenha o disco na cor especificada" self.plot_id = control.plot_disc_grande (self.center.x, self.center.y, color, self.r) self.center.plot() return self.plot_id ################### VICTOR MUDOU (Edu- talvez n precise disso) ####################### def unplot(self, id = None): if id == None: id = self.plot_id control.plot_delete(id) ################## FIM ############################ def hilight (self, color=config.COLOR_HI_POINT): "Desenha o disco com 'destaque' (com cor diferente)" self.hi = control.plot_disc (self.center.x, self.center.y, color, self.r) return self.hi def unhilight (self, id = None): "Apaga o 'destaque' do disco" if id == None: id = self.hi control.plot_delete (id) def lineto (self, p, color=config.COLOR_LINE): "Desenha uma linha do centro até o ponto especificado" self.lineto_id[p] = control.plot_line (self.center.x, self.center.y, p.x, p.y, color) return self.lineto_id[p] def remove_lineto (self, p, id = None): "Remove a linha ate o ponto p" if id == None: id = self.lineto_id[p] control.plot_delete (id) def extremes(self): offsets = [self.r, - self.r] return [ self.center + Point(0, off) for off in offsets] + [ self.center + Point(off, 0) for off in offsets] ################ PEDRO GF MUDOU ########################################## def hilight_circ (self, color = "yellow", width = 2): "Desenha a circunferência (contorno) com destaque" self.circ_id = control.plot_circle (self.center.x, self.center.y, color, self.r, width = width) return self.circ_id def unhilight_circ (self, id = None): "Apaga o destaque da circunferência (contorno)" if id == None: id = self.circ_id control.plot_delete (id) def hilight_semi_circle (self, up, color="red", width = 2): "Desenha o meio circulo, up indica se é a metade de cima ou de baixo" if up: self.id_semi_up = control.plot_semi_circle (self.center.x, self.center.y, self.r, up, color, width = width) return self.id_semi_up self.id_semi_down = control.plot_semi_circle (self.center.x, self.center.y, self.r, up, color, width = width) return self.id_semi_down def unhilight_semi_circle (self, up): "Apaga o semi_circulo" if up: return control.plot_delete (self.id_semi_up) return control.plot_delete (self.id_semi_down) def intersects_circ (self, other): "Confere se a circunferência do disco intersecta com a circunferência do other" d = (prim.dist2 (self.center, other.center))**0.5 sum_r = self.r + other.r # Deixa o menor no self if self.r > other.r: self, other = other, self # Confere se o menor não está dentro do maior if d + self.r < other.r: return False # Confere se os discos se intersectam if d <= sum_r and d : return True else: return False def intersection (self, other): "Retorna uma lista com o(s) ponto(s) de interseção entre os dois círculos" if not self.intersects_circ (other): return [] # Um pouco de geometria: Montando a esquação do circulo # Temos: self: (x - x1)^2 + (y - y1)^2 = r1^2 # other: (x - x2)^2 + (y - y2)^2 = r2^2 x1, y1 = self.center.x, self.center.y x2, y2 = other.center.x, other.center.y r1, r2 = self.r, other.r # Depois de subtrair as duas equações, teremos uma reta # 2x*(x2 - x1) + 2y*(y2 - y1) + x1^2 - x2^2 + y1^2 - y2^2 = r1^2 - r2^2 # Isolando o x para a resposta, temos essa grande conta: # x = [ r1^2 - r2^2 + x2^2 - x1^2 + y2^2 - x1^2 + 2y*(y2 - y1) ] / 2*(x2 - x1) # se x1 = x2, temos um caso mais simples, basta encontrar y if x1 == x2: if y1 == y2: # supondo que não há circulos iguais return [] res_y1 = (r1**2 - r2**2 + y2**2 - y1**2) / (2*(y2 - y1)) res_y2 = res_y1 res_x1 = (r1**2 - (res_y1 - y1)**2 )**(0.5) + x1 res_x2 = -(r1**2 - (res_y1 - y1)**2 )**(0.5) + x1 # Se não, temos que colocar o x em alguma das equações dos circulos e criar uma equação de 2º grau # Depois de (( muitas )) continhas ... # conclui que os valores de a, b e c para nossa equação ay^2 + by + c = 0 são else: const = r1**2 - r2**2 + y2**2 - y1**2 + x2**2 + x1**2 - 2*x1*x2 a = (y1 - y2)**2 / (x1 - x2)**2 + 1 b = (y1 - y2)*const / (x1 - x2)**2 - 2*y1 c = const**2 / (4*(x1 - x2)**2) + y1**2 - r1**2 # Agora a gente aplica um super bhaskara delta = b**2 - 4*a*c res_y1 = (-b + delta**(0.5)) / (2*a) res_y2 = (-b - delta**(0.5)) / (2*a) # Aplica os valores na reta para descobir os x res_x1 = ( r1**2 - r2**2 + y2**2 - y1**2 + x2**2 - x1**2 + 2*res_y1*(y1 - y2) ) / (2*(x2 - x1)) res_x2 = ( r1**2 - r2**2 + y2**2 - y1**2 + x2**2 - x1**2 + 2*res_y2*(y1 - y2) ) / (2*(x2 - x1)) p1 = Point (res_x1, res_y1) p2 = Point (res_x2, res_y2) if p1.approx_equals (p2): return [p1] return [p1, p2] ################### FIM PEDRO ######################################
def extremes(self): offsets = [self.r, - self.r] return [ self.center + Point(0, off) for off in offsets] + [ self.center + Point(off, 0) for off in offsets]
def visGraphAlg(l): print "HUE" poligs = leEntrada(l) robo = poligs[0] if(len(robo) == 1): print "Robo ponto na posicao ", robo[0] probo = robo[0] else: print "Busca de rotas para robos não pontuais não implementado ainda" def leEntrada(l): poligs = [] temp = [] for i in range(len(l)): if( len(temp) == 0 ): temp.append(l[i]) elif( l[i].x == temp[0].x and l[i].y == temp[0].y ): poligs.append(temp) temp = [] else: temp.append(l[i]) return poligs pontos = [Point(-2,-2),Point(-2,-2),Point(0,0),Point(1,1),Point(2,0),Point(-1,-1),Point(0,0)] visGraphAlg(pontos)
def __init__ (self, x, y, r): "Para criar um disco, passe suas coordenadas." self.center = Point(x, y) self.r = r self.seg = Segment(Point(x-r, y), Point(x+r,y)) self.lineto_id = {}