コード例 #1
0
ファイル: lee_preparata.py プロジェクト: pepedrog/Gema
def trata_ponta_pra_cima(p, L, dcel, diags):
    viz_esq = p.next
    viz_dir = p.prev
    if left(p, viz_dir, viz_esq):
        viz_esq, viz_dir = viz_dir, viz_esq

    t = Trapezio(p)
    removido = (L.busca(t)).elemento

    if removido == None:
        t.a_esq = Segment(p, viz_esq)
        t.a_dir = Segment(p, viz_dir)
        t.desenha()
        L.insere(t)

    else:
        L.deleta(t)
        removido.apaga()
        d = Segment(p, removido.sup)
        d.plot('firebrick')
        dcel.add_edge(d.init, d.to)
        diags.append(d)
        desenhos.sleep()

        t1 = Trapezio(p, removido.a_esq, Segment(p, viz_esq))
        t2 = Trapezio(p, Segment(p, viz_dir), removido.a_dir)
        t1.desenha()
        t2.desenha()
        L.insere(t1)
        L.insere(t2)

    desenhos.sleep()
コード例 #2
0
ファイル: forca_bruta.py プロジェクト: pepedrog/Gema
def forca_bruta(l):
    "Algoritmo forca bruta para encontrar o par de pontos mais proximo"
    "Recebe uma lista de pontos l"

    if len(l) < 2: return None

    closest = float("inf")
    a = b = None

    for i in range(len(l)):
        for j in range(i + 1, len(l)):
            l[i].lineto(l[j], 'firebrick')
            sleep()
            l[i].remove_lineto(l[j])

            dist = dist2(l[i], l[j])
            if dist < closest:
                if a is not None:
                    a.unhilight()
                    b.unhilight()
                    a.remove_lineto(b)

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

                a.hilight("orange")
                b.hilight("orange")
                a.lineto(b, "orange")
                sleep()

    ret = Segment(a, b)
    return ret
コード例 #3
0
ファイル: lee_preparata.py プロジェクト: pepedrog/Gema
def monotonos(d, P, diags):
    """ Função que recebe um polígono P e particiona P em vários polígonos monótonos
        Através da inserção de diagonais
        Coloca as diagonais na DCEL d
    """
    # Ordena os vértices pela Y-coordenada
    v = P.vertices()
    v = sorted(v, key=lambda x: (-x.y * 10000 + x.x))

    L = Abbb()

    # os vértices são os pontos eventos da linha de varredura
    for p in v:
        p.hilight()
        h = desenhos.plot_horiz_line(p.y, 'green')
        desenhos.sleep()

        viz_cima = p.next
        viz_baixo = p.prev
        if viz_cima.y < viz_baixo.y:
            viz_cima, viz_baixo = viz_baixo, viz_cima

        if ((viz_cima.y > p.y and p.y > viz_baixo.y)
                or (viz_cima.y == p.y and viz_cima.x < p.x)
                or (viz_baixo.y == p.y and viz_baixo.x > p.x)):
            trata_caso_meio(p, viz_baixo, L, d, diags)
        elif viz_cima.y <= p.y:
            trata_ponta_pra_cima(p, L, d, diags)
        else:
            trata_ponta_pra_baixo(p, L, d, diags)

        desenhos.plot_delete(h)
        p.unhilight()
コード例 #4
0
ファイル: lee_preparata.py プロジェクト: pepedrog/Gema
def trata_caso_meio(p, viz_baixo, L, dcel, diags):
    # Remove da linha o trapésio que tem o p
    t = Trapezio(p)
    removido = (L.busca(t)).elemento
    removido.apaga()
    L.deleta(t)

    if ponta_pra_baixo(removido.sup):
        d = Segment(removido.sup, p)
        d.plot('firebrick')
        dcel.add_edge(d.init, d.to)
        diags.append(d)
        desenhos.sleep()

    # Insere um novo trapésio com o p
    # Se o removido estava a direita
    if (p == removido.a_dir.to):
        t.a_dir = Segment(p, viz_baixo)
        t.a_esq = removido.a_esq
    # Se estava a esquerda
    else:
        t.a_esq = Segment(p, viz_baixo)
        t.a_dir = removido.a_dir
    t.desenha()
    L.insere(t)
    desenhos.sleep()
コード例 #5
0
def marca_intersec(no1, no2, pontos, p_x=None):
    "Testa se há interseção entre o nó1 e o nó2 e adiciona em pontos, se houver"
    "E só marca as interseções que ocorrem do p_x pra direita"
    # Despinta de verde e pinta de amarelo
    no1.seg.hide()
    no2.seg.hide()
    no1.seg.plot('yellow')
    no2.seg.plot('yellow')
    desenhos.sleep()
    # despinta de amarelo e pinta de verde denovo
    no1.seg.hide()
    no2.seg.hide()
    no1.seg.plot('green')
    no2.seg.plot('green')

    p = no1.seg.intersection(no2.seg)
    # Só marco se o o ponto esta pra frente do x especificado
    if (p != None and (p_x == None or p.x > p_x.x or
                       (p.x == p_x.x and p.y > p_x.y))):
        # Crio o nó
        p_no = Node_Point(p, ini=[], fim=[], inter=[no1, no2])
        # insere o ponto na arvore, ou só atualiza se ele já existir
        p_no_abb = pontos.busca(p_no)
        if p_no_abb.elemento == None:
            pontos.insere(p_no)
            p_no.ponto.plot('red')
        else:
            if no1 not in p_no_abb.elemento.inter:
                p_no_abb.elemento.inter.append(no1)
            if no2 not in p_no_abb.elemento.inter:
                p_no_abb.elemento.inter.append(no2)
    desenhos.sleep()
コード例 #6
0
def orelhas(poligono):
    """ Algoritmo que usa a estratégia de encontrar e remover orelhas para
        triangular o polígono
    """
    # Cria uma cópia pra não zoar o input original
    novo = []
    for p in poligono.vertices():
        novo.append(Point(p.x, p.y))
    P = Polygon(novo)

    n = len(P.vertices())

    # Dicionario que relaciona os vértices a um booleano que indica se é orelha
    # Aproveitando que os pontos são 'hashables'
    orelha = dict()

    #PreProcessamento dos vértices
    v = P.pts
    orelha[v] = is_orelha(v, P)
    v = v.next
    while v != P.pts:
        orelha[v] = is_orelha(v, P)
        v = v.next

    while n > 3:
        # Procura uma orelha
        while not orelha[v]:
            v = v.next

        # Sinaliza qual orelha eu escolhi
        v.hilight('firebrick')
        # Desenha a diagonal e desmarca a orelha
        v.prev.lineto(v.next, 'orange')
        orelha[v] = False
        sleep()

        # Tira v do polígono
        u = v.prev
        w = v.next
        w.prev = u
        u.next = w
        # Essa parte é pra lista sempre ficar circular
        # (P.pts podia ficar inacessivel dai o algoritmo entrava em loop)
        if v == P.pts:
            P.pts = P.pts.next

        # Confere se não criei nenhuma orelha
        orelha[u] = is_orelha(u, P)
        orelha[w] = is_orelha(w, P)

        v.unhilight()
        n -= 1

    # Despinta alguma orelha que tenha sobrado
    while not orelha[v]:
        v = v.next
    v.unhilight()
コード例 #7
0
def deleta_da_linha(L, no, pontos, p_x=None):
    "Deleta o nó da linha de varredura L e testa a interseção entre os que ficaram consecutivos"
    "Mas só marca as interseções que ocorrem do x pra frente"
    pred = L.predecessor(no)
    suc = L.sucessor(no)
    L.deleta(no)
    no.seg.hide()
    desenhos.sleep()
    if pred != None and suc != None and pred != suc:
        marca_intersec(pred, suc, pontos, p_x)
コード例 #8
0
def is_orelha(v, P):
    " Função que recebe um vértice v do polígono P e retorna se v é uma ponta de orelha "
    v.hilight('green')

    resposta = is_diagonal(v.prev, v.next, P)
    v.unhilight()

    if resposta:
        v.hilight()
    sleep()
    return resposta
コード例 #9
0
def marca_intersec(no1, no2, pontos, x=None):
    "Testa se há interseções entre o nó 1 e o nó 2 e adiciona em pontos, se houver"
    "E só marca as interseções que ocorrem do x pra direita"
    # Despinta de verde e pinta de amarelo
    no1.apaga()
    no2.apaga()
    no1.desenha("yellow")
    no2.desenha("yellow")
    desenhos.sleep()
    # despinta de amarelo e pinta de verde denovo
    no1.apaga()
    no2.apaga()
    no1.desenha()
    no2.desenha()

    inter = no1.circ.intersection(no2.circ)
    for p in inter:
        # Só marco se o o ponto esta pra frente do x especificado
        # e se faz parte das metades correspondentes
        #(se intersecta a metade de cima e eu sou a de baixo eu não marco)
        if ((x == None or p.x > x)
                and ((no1.baixo and p.y <= no1.circ.center.y) or
                     (not no1.baixo and p.y >= no1.circ.center.y))
                and ((no2.baixo and p.y <= no2.circ.center.y) or
                     (not no2.baixo and p.y >= no2.circ.center.y))):
            # Crio o nó
            # Caso degenerado onde os arcos se intersectam em 1 só ponto, que eu guardo no inter_unico[]
            if len(inter) == 1:
                p_no = Node_Point_Circle(p,
                                         ini=[],
                                         fim=[],
                                         inter=[],
                                         inter_unico=[no1, no2])
            # caso geral onde os arcos se intersectam em 2 pontos
            else:
                p_no = Node_Point_Circle(p,
                                         ini=[],
                                         fim=[],
                                         inter=[no1, no2],
                                         inter_unico=[])

            # insere o nó na linha, ou só atualiza se ele já existir
            p_no_abb = pontos.busca(p_no)
            if p_no_abb.elemento == None:
                pontos.insere(p_no)
                p_no.ponto.plot('red')
            else:
                if len(inter) == 1:
                    p_no_abb.elemento.inter_unico.append(no1)
                    p_no_abb.elemento.inter_unico.append(no2)
                else:
                    p_no_abb.elemento.inter.append(no1)
                    p_no_abb.elemento.inter.append(no2)
    desenhos.sleep()
コード例 #10
0
def add_triangs_dcel (d, p, triang):
    " Adiciona o P na dcel d e uma aresta de p pra cada ponta do triang "
    d.add_vertex (p)
    e1 = d.add_edge (p, triang.p1, triang.a.f)
    e2 = d.add_edge (p, triang.p2, triang.a.f)
    e3 = d.add_edge (p, triang.p3, e2.f)
    e1.draw(color_novo)
    e2.draw(color_novo)
    e3.draw(color_novo)
    sleep()
    return e1, e2, e3
コード例 #11
0
ファイル: incremental_dag.py プロジェクト: pepedrog/Gema
def ilegal(e):
    " Devolve se a aresta dada pela meia aresta 'e' é ilegal "
    # As arestas do triangulão infinito não podem ser ilegais
    global infs
    if e.init in infs and e.to in infs:
        return False

    e.draw(color_legalizaveis)
    sleep()
    # O quadrilatero precisa ser convexo
    if left(e.twin.prox.to, e.to, e.prox.to) == left(e.twin.prox.to, e.init,
                                                     e.prox.to):
        return False

    def angulo(p1, p2, p3):
        " Devolve algo proporcional ao angulo em p2 de p1-p2-p3 "
        # Na verdade, devolve o -2*cosseno do angulo com a lei do cosseno
        a2 = (p3.x - p1.x)**2 + (p3.y - p1.y)**2
        b2 = (p3.x - p2.x)**2 + (p3.y - p2.y)**2
        c2 = (p1.x - p2.x)**2 + (p1.y - p2.y)**2
        ang = ((b2 + c2 - a2) / (2 * ((b2 * c2)**0.5)))
        return -ang
        # Como cosseno é descrescente para angulos menores que pi,
        # Então posso comparar dois angulos a e b pelos seus cossenos
        # a > b <=> cos(a) < cos(b)

    # Acha o menor angulo do triangulo com a aresta e
    min_ang1 = min([
        angulo(e.prev.init, e.init, e.to),
        angulo(e.init, e.to, e.prev.init),
        angulo(e.to, e.prev.init, e.init)
    ])
    # Acha o menor angulo do triangulo com a aresta e.twin
    min_ang2 = min([
        angulo(e.twin.prev.init, e.init, e.to),
        angulo(e.init, e.to, e.twin.prev.init),
        angulo(e.init, e.twin.prev.init, e.to)
    ])
    min_ang_legal = min(min_ang1, min_ang2)

    # Acha o menor angulo dos triangulos com a outra diagonal
    min_ang1 = min([
        angulo(e.prev.init, e.init, e.twin.prev.init),
        angulo(e.init, e.prev.init, e.twin.prev.init),
        angulo(e.prev.init, e.twin.prev.init, e.init)
    ])
    min_ang2 = min([
        angulo(e.prev.init, e.to, e.twin.prev.init),
        angulo(e.to, e.prev.init, e.twin.prev.init),
        angulo(e.prev.init, e.twin.prev.init, e.to)
    ])
    min_ang_ilegal = min(min_ang1, min_ang2)
    return min_ang_legal < min_ang_ilegal
コード例 #12
0
ファイル: forca_bruta.py プロジェクト: pepedrog/Gema
def forca_bruta(l):
    "Algoritmo força bruta para encontrar todos as interseções entre uma lista de círculos"

    for i in range(len(l)):
        l[i].hilight(cor_borda='orange', grossura=2)
        sleep()
        for j in l[i + 1:]:
            j.hilight(cor_borda='green')
            sleep()
            for p in l[i].intersection(j):
                p.hilight('yellow')
            j.unhilight()
        l[i].unhilight()
コード例 #13
0
ファイル: graham.py プロジェクト: pepedrog/Gema
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
コード例 #14
0
def mergehull_rec(P):
    """ Função que faz a divisão e conquista, principal do algoritmo """
    if len(P) == 1: return [P[0]]
    q = int(len(P) / 2)
    h_esq = mergehull_rec(P[:q])
    draw_hull(h_esq, 'green')
    h_dir = mergehull_rec(P[q:])
    draw_hull(h_dir, 'red')
    sleep()
    m = merge(h_esq, h_dir)
    hide_hull(h_esq)
    hide_hull(h_dir)
    return m
コード例 #15
0
def is_diagonal(u, w, P):
    """ Função que recebe dois vértices u e w do polígono P e retorna se uw é 
        uma diagonal de P
    """
    # colore a candidata a diagonal
    uw = Segment(u, w)
    uw.plot('green')
    sleep()

    # Como o dentroDoPoligono é O(1) é muito prudente fazer esse teste primeiro
    result = dentro_do_poligono(u, w, P) and (not intersecta_borda(u, w, P))
    uw.hide()
    return result
コード例 #16
0
def insere_na_linha(L, no, pontos, x=None, trocados=[]):
    "Insere o nó na linha de varredura L e testa as interseções com consecutivos "
    "Mas só marca as interseções que ocorrem do x pra frente e que não se repetem nos trocados"
    L.insere(no)
    if x == None:
        no.desenha()
        desenhos.sleep()
    pred = L.predecessor(no)
    suc = L.sucessor(no)

    if pred != None and (trocados == [] or pred not in trocados):
        marca_intersec(no, pred, pontos, x)
    if suc != None and (trocados == [] or suc not in trocados):
        marca_intersec(no, suc, pontos, x)
コード例 #17
0
def bentley_ottmann_mod(l):
    L = Abbb()  # Linha de varredura
    resp = []  # Os nós com os pontos de interseção que retornaremos
    # Pré-processamento - Transforma cada circulo em pontos-eventos
    # pontos é a ABBB de pontos eventos
    pontos = eventos(l)
    desenhos.sleep()

    while not pontos.vazia():
        p = pontos.deleta_min()
        # desenha a linha
        id_linha = desenhos.plot_vert_line(p.ponto.x, 'green')
        id_evento = p.ponto.hilight('green')
        desenhos.sleep()

        "------------------------- Pontos da direita --------------------------------"
        for arco in p.fim:
            deleta_da_linha(L, arco, pontos, p.ponto.x)

        "------------------------- Pontos da esquerda --------------------------------"
        for arco in p.ini:
            insere_na_linha(L, arco, pontos)

        "------------------------- Pontos de interseção ------------------------------"
        if len(p.inter) > 0 or len(
                p.inter_unico) > 0 or (len(p.ini) + len(p.fim) >= 4):
            p.ponto.hilight('yellow')
            resp.append(p)

        # Troca a ordem dos arcos (do p.inter[])
        # (Não troco a ordem do p.inter_unico[] porque os circulos não se "penetram")
        trocados = []
        # Remove todos
        for arco in p.inter:
            if (arco not in trocados and arco not in p.fim
                    and p.ponto.x < arco.circ.center.x + arco.circ.r - eps):
                trocados.append(arco)
                L.deleta(arco)
        # Insere denovo com o novo ponto de referencia
        for arco in trocados:
            arco.ref = p.ponto
            insere_na_linha(L, arco, pontos, p.ponto.x, trocados)
        # apaga a linha
        desenhos.plot_delete(id_linha)
        desenhos.plot_delete(id_evento)
        p.ponto.unplot()

    return resp
コード例 #18
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)
コード例 #19
0
def quickhull_rec(P, l, r):
    """ Função principal do algoritmo """
    if r - l == 1:
        P[l].hilight()
        P[r].hilight()
        P[l].lineto(P[r], "orange")
        sleep()
        return [P[r], P[l]]
    # P[l + 1] recebe ponto extremo
    for i in range(l + 1, r):
        P[i].lineto(P[l], "gray")
        P[i].lineto(P[r], "gray")
        sleep()
        P[i].remove_lineto(P[l])
        P[i].remove_lineto(P[r])
        if (abs(area2(P[i], P[l], P[r])) > abs(area2(P[l + 1], P[l], P[r]))
                or (abs(
                    abs(area2(P[i], P[l], P[r])) -
                    abs(area2(P[l + 1], P[l], P[r]))) < eps
                    and left(P[l], P[l + 1], P[i]))):
            P[i], P[l + 1] = P[l + 1], P[i]
    # caso degenerado: pontos colineares
    if abs(area2(P[l], P[l + 1], P[r])) < eps:
        P[l].hilight()
        P[r].hilight()
        P[l].lineto(P[r], "orange")
        sleep()
        return [P[r], P[l]]

    p, q, linha_esq, linha_dir = particione(P, l, r)
    P[p].unhilight()
    P[q].unhilight()
    P[p].hilight("green")
    P[q].hilight("red")
    sleep()
    fecho_esq = quickhull_rec(P, p, q)
    fecho_dir = quickhull_rec(P, q, r)
    plot_delete(linha_esq)
    plot_delete(linha_dir)
    sleep()

    for e in range(1, len(fecho_esq)):
        fecho_dir.append(fecho_esq[e])
    return fecho_dir
コード例 #20
0
def dentro_do_poligono(u, w, P):
    """ Função que recebe dois vértices u e w do polígono P e retorna se a 
        candidata a diagonal uw está pra dentro do polígono
        (equivalente a função NoCone dos slides)
    """
    prevU = u.prev
    nextU = u.next
    if (left_on(prevU, u, nextU)):
        resposta = (left(u, w, prevU) and left(w, u, nextU))
    else:
        resposta = not (left_on(u, w, nextU) and left_on(w, u, prevU))

    if not resposta:
        uw = Segment(u, w)
        uw.plot('red')
        sleep()
        uw.hide()

    return resposta
コード例 #21
0
def ShamosRec(l, i, j):
    " Função que faz o serviço recursivo "
    " recebe uma lista de pontos l[i:j] ordenados pela coordenada x "
    # Base da recursão, 2 ou 1 ponto
    if j - i < 3:
        # registra o par mais proximo
        par_min = Segment(l[i], l[j - 1])
        par_min.hilight('green')
        desenhos.sleep()
        # Ordena pelo eixo y
        if (l[i].y > l[j - 1].y):
            l[i], l[j - 1] = l[j - 1], l[i]
    else:
        q = (i + j) // 2
        meio = l[q]

        vert_id = desenhos.plot_vert_line(meio.x, 'firebrick', grossura=1)
        meio.hilight('firebrick')
        desenhos.sleep()

        # Calcula o menor das duas metades
        par_esq = ShamosRec(l, i, q)
        par_dir = ShamosRec(l, q, j)

        desenhos.plot_delete(vert_id)
        meio.unhilight()

        par_min = minPar(par_esq, par_dir)
        par_esq.unhilight()
        par_dir.unhilight()
        par_esq.hilight('red')
        par_dir.hilight('red')
        desenhos.sleep()
        par_esq.unhilight()
        par_dir.unhilight()
        par_min.hilight('orange')
        desenhos.sleep()

        # Intercala do mergeSort escondido
        intercalaY(l, i, j)

        # Calcula o menor entre as duas metade
        par_inter = menorInter(l, i, j, meio, par_min)
        if par_inter != None:
            par_min = minPar(par_inter, par_min)
            par_inter.hide()

    global d
    dnovo = math.sqrt(dist(par_min))
    d = min(d, dnovo)

    return par_min
コード例 #22
0
def intersecta_borda(u, w, P):
    """ Função que recebe dois vértices u e w do polígono P e retorna se o 
        segmento uw intersecta alguma aresta de P
        (equivalente a função QuaseDiagonal dos slides)
    """
    borda = P.edges()
    uw = Segment(u, w)
    for aresta in borda:
        aresta.plot('green')
        sleep()
        if (u not in aresta.endpoints()) and (w not in aresta.endpoints()):
            if (uw.intersects(aresta)):
                aresta.hide()
                aresta.plot('red')
                sleep()
                aresta.hide()
                return True
        aresta.hide()

    return False
コード例 #23
0
ファイル: lee_preparata.py プロジェクト: pepedrog/Gema
def trata_ponta_pra_baixo(p, L, dcel, diags):
    t = Trapezio(p)
    removido1 = (L.busca(t)).elemento
    removido1.apaga()
    L.deleta(t)

    if ponta_pra_baixo(removido1.sup):
        d = Segment(removido1.sup, p)
        d.plot('firebrick')
        desenhos.sleep()
        dcel.add_edge(d.init, d.to)
        diags.append(d)

    # Se tem outro polígono
    removido2 = (L.busca(t)).elemento
    if removido2 != None:
        L.deleta(t)
        removido2.apaga()

        if ponta_pra_baixo(removido2.sup):
            d = Segment(removido2.sup, p)
            d.plot('firebrick')
            desenhos.sleep()
            dcel.add_edge(d.init, d.to)
            diags.append(d)

        if removido2.a_esq.to == p:
            t = Trapezio(p, removido1.a_esq, removido2.a_dir)
        else:
            t = Trapezio(p, removido2.a_esq, removido1.a_dir)
        L.insere(t)
        t.desenha()
        desenhos.sleep()
コード例 #24
0
ファイル: embrulho_presente.py プロジェクト: pepedrog/Gema
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            
コード例 #25
0
def bentley_ottmann(l):
    L = Abbb()  # Linha de varredura
    resp = []  # Os nós com os pontos de interseção que retornaremos
    # Pré-processamento - Transforma cada circulo em pontos-eventos
    # pontos é a ABBB de pontos eventos
    pontos = eventos(l)
    desenhos.sleep()

    while not pontos.vazia():
        p = pontos.deleta_min()
        # desenha a linha
        id_linha = desenhos.plot_vert_line(p.ponto.x, 'green')
        id_evento = p.ponto.hilight('green')
        desenhos.sleep()

        "------------------------- Pontos da direita --------------------------------"
        for seg in p.fim:
            seg.ref = seg.seg.to
            deleta_da_linha(L, seg, pontos, p.ponto)

        "------------------------- Pontos da esquerda --------------------------------"
        for seg in p.ini:
            seg.seg.plot('green')
            desenhos.sleep()
            insere_na_linha(L, seg, pontos)

        "------------------------- Pontos de interseção ------------------------------"
        if len(p.inter) > 0 or (len(p.ini) + len(p.fim)) > 1:
            p.ponto.hilight('yellow')
            resp.append(p)

        # Troca a ordem dos segmentos (do p.inter[])
        trocados = []
        # Remove todos
        for seg in p.inter:
            if seg not in p.fim:
                if seg.seg.to.x != seg.seg.init.x:
                    y_ref = (((seg.seg.to.x * seg.seg.init.y) -
                              (seg.seg.init.x * seg.seg.to.y) -
                              (p.ponto.x - 10 * eps) *
                              (seg.seg.init.y - seg.seg.to.y)) /
                             (seg.seg.to.x - seg.seg.init.x))
                    seg.ref = Point(p.ponto.x - 10 * eps, y_ref)
                else:
                    seg.ref = Point(p.ponto.x, p.ponto.y + 10 * eps)
                trocados.append(seg)
                L.deleta(seg)
        # Insere denovo com o novo ponto de referencia
        for seg in trocados:
            seg.ref = p.ponto
            #print("reinserindo " + str(seg))
            insere_na_linha(L, seg, pontos, p.ponto, trocados)

        # apaga a linha
        desenhos.plot_delete(id_linha)
        desenhos.plot_delete(id_evento)
        p.ponto.unplot()

    return resp
コード例 #26
0
ファイル: lee_preparata.py プロジェクト: pepedrog/Gema
def lee_preparata(poligono):

    # Cria uma cópia pra não zoar o input original
    novo = []
    for p in poligono.vertices():
        novo.append(Point(p.x, p.y))
    P = Polygon(novo)

    diags = []
    d = Dcel()
    d.init_polygon(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('green')
            desenhos.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("orange")
コード例 #27
0
def tangente_superior(h_esq, h_dir):
    """ Encontra os pontos i, j tais que a linha h_esq[i] - h_dir[j]
        deixa todos os demais pontos abaixo 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_dir[j].remove_lineto(h_esq[i])
    h_dir[j].lineto(h_esq[i], 'blue')
    sleep()
    prox_i = (i + 1) % n_esq
    prox_j = (j - 1 + n_dir) % n_dir
    subiu = True
    while subiu:
        subiu = False
        while (left(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]))):
            subiu = True
            h_dir[j].remove_lineto(h_esq[i])
            i = prox_i
            prox_i = (i + 1) % n_esq
            h_dir[j].lineto(h_esq[i], 'blue')
            sleep()
        while (left(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]))):
            subiu = True
            h_dir[j].remove_lineto(h_esq[i])
            j = prox_j
            prox_j = (j - 1 + n_dir) % n_dir
            h_dir[j].lineto(h_esq[i], 'blue')
            sleep()
    h_dir[j].remove_lineto(h_esq[i])
    h_dir[j].lineto(h_esq[i], 'firebrick')
    sleep()
    return i, j
コード例 #28
0
def menorInter(l, i, j, meio, par_min):
    " Retorna o par de pontos mais proximo dentro da faixa dada pelo ponto meio da lista "
    " e a distancia do par_min "
    d = math.sqrt(dist(par_min))

    # desenha a faixa que eu estou procurando
    v1 = desenhos.plot_vert_line(meio.x - d, 'orange', grossura=1)
    v2 = desenhos.plot_vert_line(meio.x + d, 'orange', grossura=1)

    cand = candidatos(l, i, j, meio)
    par_inter = None

    for k in range(len(cand)):
        cand[k].plot('red')
        desenhos.sleep()
        for l in range(k + 1, len(cand)):

            # Se os pontos já estão distantes, posso parar de olhar
            if (cand[l].y - cand[k].y > d):
                break

            cand_inter = Segment(cand[k], cand[l])
            cand_inter.plot('red')
            desenhos.sleep()
            cand_inter.hide()

            dcand = math.sqrt(dist2(cand[k], cand[l]))
            # Se achei um novo par, apaga o outro e pinta esse
            if (dcand < d):
                d = dcand
                if par_inter is not None:
                    par_inter.unhilight()
                par_min.unhilight()
                par_inter = cand_inter
                par_inter.hilight('orange')
                desenhos.sleep()

        cand[k].unplot()

    desenhos.plot_delete(v1)
    desenhos.plot_delete(v2)
    desenhos.sleep()

    return par_inter
コード例 #29
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
コード例 #30
0
ファイル: graham.py プロジェクト: pepedrog/Gema
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