Beispiel #1
0
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")
Beispiel #2
0
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])
Beispiel #3
0
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])
Beispiel #4
0
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
Beispiel #5
0
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 (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
Beispiel #8
0
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
Beispiel #10
0
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
Beispiel #11
0
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
Beispiel #12
0
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
Beispiel #13
0
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
Beispiel #14
0
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
Beispiel #15
0
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