示例#1
0
def Brute (l):
	"Algoritmo forca bruta para encontrar o par de pontos mais distante"

	if len (l) < 2: return None
	
	farthest = 0
	a = b = None
	id = None

	for i in range (len(l)):
		for j in range (i + 1, len (l)):
			dist = dist2 (l[i], l[j])
			if dist > farthest:
				control.freeze_update ()
				if a != None: a.unhilight (hia)
				if b != None: b.unhilight (hib)
				if id != None: control.plot_delete (id)

				farthest = dist
				a = l[i]
				b = l[j]

				hia = a.hilight ()
				hib = b.hilight ()
				id = a.lineto (b)
				control.thaw_update ()
				control.update ()
	
	ret = Segment (a, b)
	ret.extra_info = 'distancia: %.2f'%math.sqrt (dist2 (a, b))
	return ret
示例#2
0
def recursive_ham_sandwich(G1, G2, p1, p2, T):
    if len(G1) < len(G2):
        return recursive_ham_sandwich(G2, G1, p2, p1, T)
    T, is_base = new_interval(G1, G2, p1, p2, T)

    if is_base:
        valid_answers = []
        for g in G1:
            for h in G2:
                p = g.intersect(h)
                if p and isinstance(p.dual(), Line):
                    valid_answers.append(p.dual())
        return valid_answers, G1 + G2

    t = new_trapezoid(G1, p1, T)
    t_ids = []
    control.freeze_update()
    for i in range(4):
        j = (i + 1) % 4
        t_ids.append(
            control.plot_segment(t[i].x, t[i].y, t[j].x, t[j].y, 'yellow'))
    control.sleep()
    control.thaw_update()

    G1, p1 = discard_lines(G1, p1, t)
    G2, p2 = discard_lines(G2, p2, t)

    for id in t_ids:
        control.plot_delete(id)

    return recursive_ham_sandwich(G1, G2, p1, p2, T)
示例#3
0
def Brute (l):
	"Algoritmo forca bruta para encontrar o par de pontos mais proximo"

	if len (l) < 2: return None
	
	closest = float("inf")
	a = b = None
	id = None

	for i in range (len(l)):
		for j in range (i + 1, len (l)):
			dist = dist2 (l[i], l[j])
			if dist < closest:
				control.freeze_update ()
				if a != None: a.unhilight (hia)
				if b != None: b.unhilight (hib)
				if id != None: control.plot_delete (id)

				closest = dist
				a = l[i]
				b = l[j]

				hia = a.hilight ()
				hib = b.hilight ()
				id = a.lineto (b)
				control.thaw_update() 
				control.update ()

	a.hilight('green')
	b.hilight('green')
	ret = Segment (a, b)
	ret.extra_info = 'distancia: %.2f'%math.sqrt (dist2 (a, b))
	print(math.sqrt (dist2 (a, b)))
	return ret
def destaca_segs(lista_segs, string_cor): # pinta segmentos com cores do passado, presente, vizinho ou intersectado
    global cores
    control.freeze_update ()

    for seg in lista_segs:
        if seg != None:
            seg.hilight2(cores[string_cor])

    control.thaw_update ()
示例#5
0
 def draw_interval(should_plot=True):
     control.thaw_update()
     for i in range(2):
         if not ids[i] == None:
             control.plot_delete(ids[i])
         if T[i] != -inf and T[i] != +inf and should_plot:
             ids[i] = control.plot_vert_line(T[i], 'yellow')
     control.sleep()
     control.freeze_update()
示例#6
0
 def plot(self):
     if self.rank != 0:
         return
     self.drawing = []
     for i in range(3):
         self.drawing.append(self.P[i - 1].inner.lineto(
             self.P[i].inner, COLOR_TRIANG))
     control.thaw_update()
     control.update()
     control.freeze_update()
示例#7
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])
示例#8
0
def e_lineto(p, q, color=config.COLOR_PRIM):
    if max(p.inf, q.inf) > 0:
        return
    keep = p.inner.lineto(q.inner, color)

    control.thaw_update()
    control.update()
    control.freeze_update()
    control.sleep()

    p.inner.remove_lineto(q, keep)
示例#9
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])
示例#10
0
def Fortune(P):
    Q = event_queue(P)
    V = DCEL()
    T = BST()

    for event in Q.keys():
        V.add_face(event.face)

    while Q:
        q = Q.pop()
        q.point.hilight()
        par_plots, sweep = plot_all(T.all_leaves(), V, q.point.y)
        control.sleep()

        if q.is_site_event:
            handle_site_event(q, T, Q, V)
        else:
            handle_circle_event(q, T, Q, V)
            q.point.unplot()
        control.sleep()

        if len(Q) > 0:
            next_y = Q.top().point.y
            line_y = q.point.y
            leaves = T.all_leaves()
            # while not math.isclose(line_y, next_y, rel_tol=4*FORTUNE_PLOT_RATE):
            # FORTUNE_PLOT_RATE = abs(line_y - next_y)/100
            while line_y > next_y:
                control.thaw_sleep()
                if abs(line_y - next_y) > FORTUNE_PLOT_RATE * 10**3:
                    line_y -= abs(line_y - next_y) / 10
                else:
                    line_y -= FORTUNE_PLOT_RATE

                unplot_all(par_plots, V.hedges, sweep)

                par_plots, sweep = plot_all(leaves, V, line_y)
                control.thaw_update()
                control.update()
                control.freeze_update()

        unplot_all(par_plots, V.hedges, sweep)

        q.point.unhilight()
        control.update()

    vertices = [v.p for v in V.vertices]
    borders = find_borders(P + vertices)
    finalize_voronoi(V, T, borders)

    for h in V.hedges:
        h.segment.plot()
    return V
示例#11
0
def points_to_lines(P, color):
    G = []
    for p in P:
        control.thaw_update()
        p.tk.hilight(color)
        control.sleep()
        control.freeze_update()
        g = p.dual()
        g.plot_id = control.plot_line(0, g(0), 1, g(1), color)
        G.append(g)
        p.tk.unhilight()
        p.tk.unplot()
        control.sleep()
    return G
示例#12
0
def update_points(p1, p2):
    global a, b, id, hia, hib
    if (a != None and b != None):
        if (prim.dist2(p1, p2) >= prim.dist2(a, b)): return
    control.freeze_update()
    if a != None: a.unhilight(hia)
    if b != None: b.unhilight(hib)
    if id != None: control.plot_delete(id)
    a = p1
    b = p2
    hia = a.hilight()
    hib = b.hilight()
    id = a.lineto(b)
    control.thaw_update()
    control.update()
示例#13
0
def partition(P, p, r, point_p, point_r):
    '''Recebe uma coleção de pontos em posição geral, com pelo menos 3 pontos tal
    que os pontos de índice p e r são extremos consecutivos na fronteira do fecho
    convexo da coleção no sentido anti-horário. Rearranja a coleção de pontos e
    devolve (s,q) para o algoritmo do QuickHull.'''
    q = extreme(P, p, r)
    points[(point_r, P[q])] = point_r.lineto(P[q], 'cyan')
    points[(P[q], point_p)] = P[q].lineto(point_p, 'cyan')
    control.thaw_update()
    control.update()
    control.freeze_update()
    control.sleep()

    P[p + 1], P[q] = P[q], P[p + 1]
    s = q = r

    for point, id in ids:
        point.unhilight(id)

    for k in range(r - 1, p + 1, -1):
        if left(P[p], P[p + 1], P[k]):
            id = P[k].hilight('green')
            ids.append((P[k], id))
            s -= 1
            P[s], P[k] = P[k], P[s]
        elif left(P[p + 1], P[r], P[k]):
            id = P[k].hilight('red')
            ids.append((P[k], id))
            s -= 1
            q -= 1
            P[k], P[q] = P[q], P[k]
            if s != q:
                P[k], P[s] = P[s], P[k]

    control.thaw_update()
    control.update()
    control.freeze_update()
    control.sleep()

    s -= 1
    q -= 1
    P[q], P[p + 1] = P[p + 1], P[q]

    if s != q:
        P[s], P[p + 1] = P[p + 1], P[s]
    s -= 1
    P[s], P[p] = P[p], P[s]
    return s, q
示例#14
0
def triang (a, b, c):
	"desenha  (e apaga) os lados do triangulo abc"
	a.lineto (c, config.COLOR_PRIM)
	#b.lineto (a, config.COLOR_PRIM)
	c.lineto (b, config.COLOR_PRIM)
	c.hilight ()
	control.thaw_update ()
	control.update ()
	control.freeze_update ()

	control.sleep ()

	c.unhilight ()
	a.remove_lineto (c)
	#b.remove_lineto (a)
	c.remove_lineto (b)
示例#15
0
def triang(a, b, c):
    "desenha  (e apaga) os lados do triangulo abc"
    a.lineto(c, config.COLOR_PRIM)
    #b.lineto (a, config.COLOR_PRIM)
    c.lineto(b, config.COLOR_PRIM)
    c.hilight()
    control.thaw_update()
    control.update()
    control.freeze_update()

    control.sleep()

    c.unhilight()
    a.remove_lineto(c)
    #b.remove_lineto (a)
    c.remove_lineto(b)
示例#16
0
def ham_sandwich(P1, P2):
    G1 = points_to_lines(P1, 'red')
    G2 = points_to_lines(P2, 'blue')
    valid_answers, missing_lines = recursive_ham_sandwich(
        G1, G2,
        len(G1) // 2,
        len(G2) // 2, (-inf, inf))
    for l in valid_answers:
        if verify_solution(P1, P2, l):
            control.freeze_update()
            p = l.dual()
            p.tk = pt(p.x, p.y)
            p.tk.plot('green')
            control.sleep()
            control.thaw_update()
            delete_stuff(missing_lines + [p])
            return l
    return None
示例#17
0
def ear_tip(P, v):
    '''Recebe um polígono P e um vértice v desse polígono, e decide se ele é
    uma ponta de orelha'''
    u = P.prev(v)
    w = P.next(v)
    v.hilight('green')
    u.hilight('yellow')
    w.hilight('yellow')
    control.sleep()
    control.thaw_update()
    control.update()
    diag = diagonal(P, u, w)
    u.unhilight()
    w.unhilight()
    if not diag:
        v.unhilight()
    control.sleep()
    control.thaw_update()
    control.update()
    return diag
示例#18
0
def discard_lines(G, p, t):
    nG = []
    b = 0
    for l in G:
        control.freeze_update()
        new_plot_id = control.plot_line(0, l(0), 1, l(1), 'cyan')
        control.sleep()
        control.thaw_update()
        control.freeze_update()
        is_under, is_above = intersects_trapezoid(l, t)
        if not (is_under or is_above):
            nG.append(l)
        elif is_under:
            b += 1
        if (is_under or is_above):
            delete_stuff([l])
        control.plot_delete(new_plot_id)
        control.sleep()
        control.thaw_update()

    return nG, p - b
def Brute_Force(segmentos):
    
    cores = (config.COLOR_ALT1, config.COLOR_ALT7, config.COLOR_ALT6)
    
    for segmento in segmentos:
        segmento.intersected = False
    
    for i in range (len(segmentos)):
        control.freeze_update ()
        hii = segmentos[i].hilight2 (cores[1])
        control.thaw_update ()
        control.sleep()
        for j in range (i + 1, len (segmentos)):
            control.freeze_update ()
            hij = segmentos[j].hilight2(cores[0])
            control.thaw_update ()
            control.sleep()
            if prim.inter(segmentos[i],segmentos[j]):
                control.freeze_update ()
                segmentos[i].hilight2 (cores[2])
                segmentos[j].hilight2 (cores[2])
                segmentos[i].intersected = True
                segmentos[j].intersected = True
                control.thaw_update ()
            segmentos[j].unhilight (hij)
        segmentos[i].unhilight (hii)
示例#20
0
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
示例#21
0
def triangulation(n, P):
    '''Recebe um polígono P com n lados e devolve a triangulação de P'''
    ears = find_ears(P)
    v3 = P.pts
    while n > 3:
        v2 = v3
        while not ears[v2]:
            v2 = P.next(v2)
        v2.hilight("blue")
        v1 = P.prev(v2)
        v3 = P.next(v2)
        v1.lineto(v3, "blue")
        control.sleep()
        control.thaw_update()
        control.update()
        print(v1, v3)
        v2.unhilight()
        control.sleep()
        control.thaw_update()
        control.update()
        P.remove_vertex(v2)
        n -= 1
        ears[v1] = ear_tip(P, v1)
        ears[v3] = ear_tip(P, v3)
示例#22
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
示例#23
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
示例#24
0
 def __update(self):
     control.thaw_update()
     control.update()
     control.freeze_update()
     control.sleep()
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
示例#26
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
示例#27
0
def fortune(l, triang):
    # Inicializa as estruturas de dados
    Q = EventQueue()
    Beach = BeachLine()
    Vor = dcel()
    CircDraw = draw_circ_events()
    #
    # Remove pontos repetidos na entrada
    l = unique_points(l)
    # Inicializa as variáveis
    global DelaunayTriangDraw
    DelaunayTriangDraw = triang
    lineid = None
    partiallines = None
    parabola_list = None
    max_x = min_x = l[0].x
    max_y = min_y = l[0].y
    first_y = None
    high_y = None
    cur_c = None
    y_count = 1
    last_y = None
    #
    # Busca a bounding box dos pontos, e insere os pontos na fila
    for p in l:
        if p.x > max_x:
            max_x = p.x
        if p.x < min_x:
            min_x = p.x
        if p.y > max_y:
            max_y = p.y
        if p.y < min_y:
            min_y = p.y
        if high_y is None:
            high_y = p.y
        elif p.y > high_y:
            high_y = p.y
            y_count = 1
        elif p.y == high_y:
            y_count = y_count + 1
        Q.put(Ponto(p.x, p.y), Ponto(p.x, p.y))
        # Desenhas os pontos um pouco maiores
        control.plot_disc(p.x, p.y, config.COLOR_POINT, 4)
    #
    # Define os bounds da tela
    yd = max_y - min_y
    xd = max_x - min_x
    dd = max(yd, xd)
    mfactor = 0.7
    bounds = {
        "maxx": (max_x + min_x) / 2 + dd * mfactor,
        "minx": (max_x + min_x) / 2 - dd * mfactor,
        "maxy": (max_y + min_y) / 2 + dd * mfactor,
        "miny": (max_y + min_y) / 2 - dd * mfactor
    }
    Beach.bounds = bounds

    # Caso os primeiros pontos tenham a mesma y-coordenada, trata este caso particular
    if y_count > 1:
        aligned = []
        for i in range(y_count):
            aligned.append(Q.takeHighest())
        aligned = list(reversed(aligned))
        for i in range(len(aligned) - 1):
            drawDelaunayEdge(aligned[i].x, aligned[i].y, aligned[i + 1].x,
                             aligned[i + 1].y)
        Beach.create_particular(aligned)

    # Loop principal
    while Q.n > 0:
        atual = Q.takeHighest()
        ## Remove o desenho do ponto evento círculo da iteração anterior, e desenha a nova posição da linha de varredura
        control.freeze_update()
        if cur_c is not None:
            control.plot_delete(cur_c)
            cur_c = None
        lineid = control.plot_horiz_line(atual.y)
        ##

        # Trata evento ponto ou círculo
        if atual.isPonto:
            trataPonto(atual, Q, Beach, CircDraw)
        else:
            cur_c = control.plot_disc(atual.x, atual.y, config.COLOR_ALT5, 4)
            CircDraw.rem_point(atual.x, atual.y)
            trataCirculo(atual, Q, Beach, CircDraw)
        #

        # Desenha as parábolas e as arestas de Voronoi parciais
        parabola_list = Beach.draw_parabolas(atual.y)
        partiallines = Beach.draw_partial(atual.y)
        control.thaw_update()
        control.update()
        control.sleep()
        # Remove o desenho das parábolas e da linha de varredura desta iteração
        if lineid is not None: control.plot_delete(lineid)
        if parabola_list is not None:
            for i in parabola_list:
                control.plot_delete(i)

        # Remove as parábolas que 'sairam da tela', remove seus respectivos eventos e o desenho destes eventos
        evlist = Beach.trata_extremos(atual.y)
        for ev in evlist:
            CircDraw.rem_point(ev.x, ev.y)
            Q.take(ev)
        last_y = atual.y

    # Atualiza o desenho para a última iteração
    lower = last_y - 2 * (Beach.bounds["maxy"] - Beach.bounds["miny"])
    partiallines = Beach.draw_partial(lower)
    if cur_c is not None:
        control.plot_delete(cur_c)
        cur_c = None

    # Desenha as arestas de Delaunay que não foram consideradas durante o algoritmo (por conta das parabolas serem removidas)
    if Beach.llist:
        for i in range(len(Beach.llist) - 1):
            p1, q1 = Beach.llist[i]
            p2, q2 = Beach.llist[i + 1]
            x, y = lineIntersect(p1, q1, p2, q2)
            if x is not None and x < Beach.bounds["minx"]:
                Beach.llist[i + 1] = [p1, q1]
                if q1 == p2:
                    drawDelaunayEdge(p1.x, p1.y, q2.x, q2.y)
                elif q1 == p1:
                    drawDelaunayEdge(p2.x, p2.y, q2.x, q2.y)
                elif q2 == p2:
                    drawDelaunayEdge(p1.x, p1.y, q1.x, q1.y)
                else:
                    drawDelaunayEdge(p2.x, p2.y, q1.x, q1.y)

    if Beach.rlist:
        for i in range(len(Beach.rlist) - 1):
            p1, q1 = Beach.rlist[i]
            p2, q2 = Beach.rlist[i + 1]
            x, y = lineIntersect(p1, q1, p2, q2)
            if x is not None and x > Beach.bounds["maxx"]:
                Beach.rlist[i + 1] = [p1, q1]
                if q1 == p2:
                    drawDelaunayEdge(p1.x, p1.y, q2.x, q2.y)
                elif q1 == p1:
                    drawDelaunayEdge(p2.x, p2.y, q2.x, q2.y)
                elif q2 == p2:
                    drawDelaunayEdge(p1.x, p1.y, q1.x, q1.y)
                else:
                    drawDelaunayEdge(p2.x, p2.y, q1.x, q1.y)

    # Constroi a DCEL
    Vor.constroi(edges)

    return Vor
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
示例#29
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
def Diameter (l):
	"""Algoritmo Diametro para encontrar o par de pontos mais distantes

	Ele consiste de:
	- determinar o fecho convexo dos pontos passados
	- determinar o conjunto de pares antipodas do fecho convexo
	- determinar o par antipoda cujos pontos estao a uma distancia maxima
	"""

	if len (l) < 2: return None
	if len (l) == 2:
		ret = Segment (l[0], l[1])
		ret.extra_info = 'distancia: %.2f'%math.sqrt (dist2 (l[0], l[1]))
		return ret
	
	ch = Graham (l)
	ch.hide ()
	ch.plot (config.COLOR_ALT4)

	control.sleep ()

	pairs = antipodes (ch)
	cores = (config.COLOR_ALT1,)

	#print `pairs`

	i=0
	for p,q in pairs:
		p.hilight (cores[i])
		q.hilight (cores[i])
		p.lineto (q, cores[i])
		i = (i+1) % len (cores)

	control.sleep ()

	farthest = dist2 (pairs[0][0], pairs[0][1])
	a = pairs[0][0]
	b = pairs[0][1]
	hia = a.hilight ()
	hib = b.hilight ()
	id = a.lineto (b)

	for i in range (1, len (pairs)):
		dist = dist2 (pairs[i][0], pairs[i][1])
		if dist > farthest:
			control.freeze_update ()
			a.unhilight (hia)
			b.unhilight (hib)
			control.plot_delete (id)

			farthest = dist
			a = pairs[i][0]
			b = pairs[i][1]

			hia = a.hilight ()
			hib = b.hilight ()
			id = a.lineto (b)
			control.thaw_update ()
	
	ret = Segment (a, b)
	ret.extra_info = 'distancia: %.2f'%math.sqrt (farthest)
	return ret
示例#31
0
def Diameter(l):
    """Algoritmo Diametro para encontrar o par de pontos mais distantes

	Ele consiste de:
	- determinar o fecho convexo dos pontos passados
	- determinar o conjunto de pares antipodas do fecho convexo
	- determinar o par antipoda cujos pontos estao a uma distancia maxima
	"""

    if len(l) < 2: return None
    if len(l) == 2:
        ret = Segment(l[0], l[1])
        ret.extra_info = 'distancia: %.2f' % math.sqrt(dist2(l[0], l[1]))
        return ret

    ch = Graham(l)
    ch.hide()
    ch.plot(config.COLOR_ALT4)

    control.sleep()

    pairs = antipodes(ch)
    cores = (config.COLOR_ALT1, )

    #print `pairs`

    i = 0
    for p, q in pairs:
        p.hilight(cores[i])
        q.hilight(cores[i])
        p.lineto(q, cores[i])
        i = (i + 1) % len(cores)

    control.sleep()

    farthest = dist2(pairs[0][0], pairs[0][1])
    a = pairs[0][0]
    b = pairs[0][1]
    hia = a.hilight()
    hib = b.hilight()
    id = a.lineto(b)

    for i in range(1, len(pairs)):
        dist = dist2(pairs[i][0], pairs[i][1])
        if dist > farthest:
            control.freeze_update()
            a.unhilight(hia)
            b.unhilight(hib)
            control.plot_delete(id)

            farthest = dist
            a = pairs[i][0]
            b = pairs[i][1]

            hia = a.hilight()
            hib = b.hilight()
            id = a.lineto(b)
            control.thaw_update()

    ret = Segment(a, b)
    ret.extra_info = 'distancia: %.2f' % math.sqrt(farthest)
    return ret