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 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 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 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 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
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 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 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 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 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