Beispiel #1
0
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
Beispiel #2
0
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
Beispiel #3
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 #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 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
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 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 #13
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