Пример #1
0
def embrulho(P):
    """ Função principal do algoritmo """
    p_esq = P[0]
    for p in P:
        if p.x < p_esq.x or (p.x == p_esq.x and p.y < p_esq.y):
            p_esq = p 
    p_esq.hilight('orange')
    sleep()
    H = [p_esq]
    while True:
        if P[0] == H[-1]: p_i = P[1]
        else: p_i = P[0]
        p_i.hilight('firebrick')
        H[-1].lineto(p_i, 'firebrick')
        sleep()
        for p_j in P:
            if p_j == H[-1] or p_j == p_i: continue
            H[-1].lineto(p_j, 'gray')
            sleep()
            H[-1].remove_lineto(p_j)
            if (right(H[-1], p_i, p_j) or 
               (collinear(H[-1], p_i, p_j) and dist2(H[-1], p_i) < dist2(H[-1], p_j))):
                H[-1].remove_lineto(p_i)
                p_i.unhilight()
                if p_i in H: p_i.hilight('orange')
                p_i = p_j
                H[-1].lineto(p_i, 'firebrick')
                p_i.hilight('firebrick')
        H[-1].lineto(p_i, 'orange')
        p_i.hilight('orange')
        if p_i == H[0]: break
        H.append(p_i)
    return H            
Пример #2
0
def tangente_inferior(h_esq, h_dir):
    """ Encontra os pontos i, j tais que a linha h_esq[i] - h_dir[j]
        deixa todos os demais pontos acima dela """
    n_esq = len(h_esq)
    n_dir = len(h_dir)
    i = j = 0
    for k in range(len(h_esq)):
        if h_esq[k].x > h_esq[i].x or (h_esq[k].x == h_esq[i].x
                                       and h_esq[k].y > h_esq[i].y):
            i = k
    for k in range(len(h_dir)):
        if h_dir[k].x < h_dir[j].x or (h_dir[k].x == h_dir[j].x
                                       and h_dir[k].y < h_dir[j].y):
            j = k

    h_esq[i].remove_lineto(h_dir[j])
    h_esq[i].lineto(h_dir[j], 'blue')
    sleep()
    prox_i = (i - 1 + n_esq) % n_esq
    prox_j = (j + 1) % n_dir
    desceu = True
    while desceu:
        desceu = False
        while (right(h_esq[i], h_dir[j], h_esq[prox_i]) or
               (collinear(h_esq[i], h_dir[j], h_esq[prox_i]) and
                dist2(h_esq[i], h_dir[j]) < dist2(h_esq[prox_i], h_dir[j]))):
            desceu = True
            h_esq[i].remove_lineto(h_dir[j])
            i = prox_i
            prox_i = (i - 1 + n_esq) % n_esq
            h_esq[i].lineto(h_dir[j], 'blue')
            sleep()
        while (right(h_esq[i], h_dir[j], h_dir[prox_j]) or
               (collinear(h_esq[i], h_dir[j], h_dir[prox_j]) and
                dist2(h_dir[j], h_esq[i]) < dist2(h_dir[prox_j], h_esq[i]))):
            desceu = True
            h_esq[i].remove_lineto(h_dir[j])
            j = prox_j
            prox_j = (j + 1) % n_dir
            h_esq[i].lineto(h_dir[j], 'blue')
            sleep()
    h_esq[i].remove_lineto(h_dir[j])
    h_esq[i].lineto(h_dir[j], 'firebrick')
    sleep()
    return i, j
Пример #3
0
 def angulo(v3):
     " Devolve algo proporcional ao angulo em v2 de v1-v2-v3 "
     # Vou achar, na verdade, o cosseno do angulo com a lei do cosseno
     a2 = (v3.x - v1.x)**2 + (v3.y - v1.y)**2
     b2 = (v3.x - v2.x)**2 + (v3.y - v2.y)**2
     c2 = (v1.x - v2.x)**2 + (v1.y - v2.y)**2
     ang = ((b2 + c2 - a2) / (2 * ((b2 * c2)**0.5)))
     if right(v1, v2, v3):
         ang = -ang - 1000
     return -ang
Пример #4
0
def compara (p_min, p1, p2):
    " Comparação angular para pré-processamento dos pontos "
    p_min.lineto(p1, 'gray')
    p_min.lineto(p2, 'gray')
    p1.lineto(p2, 'gray')
    sleep()
    p_min.remove_lineto(p1)
    p_min.remove_lineto(p2)
    p1.remove_lineto(p2)
    if (right(p_min, p1, p2) or 
       (abs(area2(p_min, p1, p2)) < eps and dist2(p_min, p1) < dist2(p_min, p2))): 
        return 1
    return 0
Пример #5
0
def quickhull(P):
    if len(P) <= 1: return P
    # Ponto mais baixo
    for i in range(len(P)):
        if P[i].y < P[0].y or (P[i].y == P[0].y and P[i].x > P[0].x):
            P[0], P[i] = P[i], P[0]
    # Ponto mais a direita do ponto mais baixo
    for i in range(len(P)):
        if (right(P[0], P[-1], P[i]) or (abs(
                area2(P[0], P[-1], P[i]) < eps
                and dist2(P[0], P[-1]) < dist2(P[0], P[i])))):
            P[-1], P[i] = P[i], P[-1]
    P[0].hilight("green")
    P[-1].hilight("red")
    P[0].lineto(P[-1], "orange")
    sleep()
    return quickhull_rec(P, 0, len(P) - 1)
Пример #6
0
def particione(P, l, r):
    """ Particiona o conjunto de pontos P em 3 partes:
        A esquerda do triangulo l-r-x
        A direita do triangulo l-r-x
        Dentro do triangulo l-r-x, 
        onde x é o ponto em P que maximiza a área do triangulo """
    # Desenha o triangulo
    if hasattr(P[l + 1], 'hi'): P[l + 1].unhilight()
    P[l + 1].hilight("firebrick")
    linha_esq = P[l].lineto(P[l + 1], "green")
    linha_dir = P[r].lineto(P[l + 1], "red")
    sleep()
    p = q = r
    for k in range(r - 1, l + 1, -1):
        if hasattr(P[k], 'hi'): P[k].unhilight()
        P[k].hilight("yellow")
        sleep()
        P[k].unhilight()
        if left(P[l], P[l + 1], P[k]):
            # ponto da partição esquerda (verde)
            p -= 1
            P[p], P[k] = P[k], P[p]
            P[p].hilight("green")
            sleep()
        elif right(P[r], P[l + 1], P[k]):
            # ponto da partição direita (vermelho)
            p -= 1
            q -= 1
            P[q], P[k] = P[k], P[q]
            if p != q: P[p], P[k] = P[k], P[p]
            P[q].hilight("red")
            sleep()
    # Ajustes finais no vetor
    p -= 1
    q -= 1
    P[q], P[l + 1] = P[l + 1], P[q]
    if p != q:
        P[p], P[l + 1] = P[l + 1], P[p]
    p -= 1
    P[l], P[p] = P[p], P[l]

    return p, q, linha_esq, linha_dir
Пример #7
0
def graham (P):
    """ Função principal do algooritmo """
    P = pre_processa(P)
    if len(P) < 3: return P
    P[1].hilight('orange')
    P[0].lineto(P[1], 'orange')
    P[2].hilight('orange')
    P[1].lineto(P[2], 'orange')
    sleep()
    H = P[:3]
    
    for p in P[3:]:
        p.hilight ('orange')
        H[-1].lineto (p, 'orange')
        sleep()
        while (right (H[-2], H[-1], p) or
              (abs(area2(H[-2], H[-1], p)) < eps and dist2(H[-2], H[-1]) < dist2(H[-2], p))):
            H[-1].hilight ('firebrick')
            H[-2].remove_lineto (H[-1])
            H[-1].remove_lineto (p)
            H[-2].lineto (H[-1], 'firebrick')
            H[-1].lineto (p, 'firebrick')
            sleep()
            H[-1].unhilight()
            H[-2].remove_lineto (H[-1])
            H[-1].remove_lineto (p)
            H.pop()
            H[-1].lineto (p, 'orange')
            sleep()
        H.append(p)
    if collinear (H[-2], H[-1], H[0]):
        H[-2].remove_lineto(H[-1])
        H[-1].unhilight()
        H.pop()
    H[-1].lineto (H[0], 'orange')
    return H
Пример #8
0
def convexo(a, b, c, borda):
    " Decide se o ângulo em b é convexo no polígono "
    # Caso borda direita
    if borda == 0: return left(a, b, c)
    # Caso borda esquerda
    return right(a, b, c)