Beispiel #1
0
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()
Beispiel #2
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
Beispiel #3
0
 def hilight(self, cor=desenhos.cor_destaque):
     "Desenha o ponto com 'destaque' (raio maior e cor diferente)"
     if self.hi != None: desenhos.plot_delete(self.hi)
     self.hi = desenhos.plot_point(self.x,
                                   self.y,
                                   cor,
                                   r=desenhos.raio_ponto_destaque)
     return self.hi
Beispiel #4
0
    def hide(self):
        "Apaga o poligono na tela"
        p = self.pts
        while p.next != self.pts:
            if p in self.cid:
                desenhos.plot_delete(self.cid[p])
                del (self.cid[p])
            p = p.next

        if p in self.cid:
            desenhos.plot_delete(self.cid[p])
            del (self.cid[p])
Beispiel #5
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
Beispiel #6
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
Beispiel #7
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
Beispiel #8
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
Beispiel #9
0
 def apaga(self):
     desenhos.plot_delete(self.aresta_cima)
     desenhos.plot_delete(self.aresta_baixo)
     desenhos.plot_delete(self.aresta_esq)
     desenhos.plot_delete(self.aresta_dir)
Beispiel #10
0
 def unplot(self):
     if self.plot_id is not None: desenhos.plot_delete(self.plot_id)
Beispiel #11
0
def varre(l):
    "Algoritmo de divisão e conquista para encontrar o par de pontos mais proximo"
    "Recebe uma lista de pontos l"

    if len(l) < 2: return None

    d = float('inf')

    l = sorted(l, key=lambda x: x.x)

    par_min = None
    faixa = Abbb()

    p_min = 0

    for i in range(len(l)):
        p = l[i]
        no_p = Node_point(p)

        # Caso degenerado -> pontos coincidentes
        # (não conseguimos adicionar na abbb, pois ja tem um clone dele)
        repetido = faixa.busca(no_p).elemento
        if repetido != None:
            if par_min != None:
                par_min.hide()
            par_min = Segment(p, repetido.p)
            break

        faixa.insere(no_p)
        p.hilight()

        # Remove os pontos fora da faixa
        while p.x - l[p_min].x > d:
            l[p_min].unhilight()
            if l[p_min] in par_min.endpoints():
                l[p_min].hilight('orange')
            no_p_min = Node_point(l[p_min])
            faixa.deleta(no_p_min)
            p_min += 1

        # Desenha o quadradinho de candidatos
        linha_frente = desenhos.plot_vert_line(p.x, 'orange')
        if i > 1:
            linha_tras = desenhos.plot_vert_line(p.x - d, cor='firebrick')
            linha_cima = Segment(Point(p.x, p.y + d), Point(p.x - d, p.y + d))
            linha_baixo = Segment(Point(p.x, p.y - d), Point(p.x - d, p.y - d))
            linha_cima.plot('firebrick')
            linha_baixo.plot('firebrick')
        desenhos.sleep()

        # Extrai os pontos da abbb até a distancia vertical ficar maior que d
        # Primeiro com os vizinhos de cima
        vizinho = faixa.sucessor(no_p)
        while vizinho != None and vizinho.p.y - p.y < d:
            d2 = dist2(p, vizinho.p)
            p.hilight()
            vizinho.p.hilight('firebrick')
            if d2 < d * d:
                d = d2**0.5

                if par_min is not None:
                    par_min.unhilight()
                par_min = Segment(p, vizinho.p)
                par_min.hilight('orange')
                desenhos.sleep()

            vizinho = faixa.sucessor(vizinho)
        # Depois com os vizinhos de baixo
        vizinho = faixa.predecessor(no_p)
        while vizinho is not None and p.y - vizinho.p.y < d:
            d2 = dist2(p, vizinho.p)
            p.hilight()
            vizinho.p.hilight('firebrick')
            if d2 < d * d:
                d = d2**0.5

                if par_min is not None:
                    par_min.unhilight()
                par_min = Segment(p, vizinho.p)
                par_min.hilight('orange')
                desenhos.sleep()

            vizinho = faixa.predecessor(vizinho)

        # Apaga o quadradinho
        desenhos.plot_delete(linha_frente)
        if (i > 1):
            desenhos.plot_delete(linha_tras)
            linha_cima.hide()
            linha_baixo.hide()

        p.unhilight()
        l[i].hilight('firebrick')

    "despinta quem sobrou na faixa"
    while (not faixa.vazia()):
        faixa.deleta_min().p.unhilight()
    par_min.hilight('orange')
Beispiel #12
0
 def remove_lineto(self, p):
     "Apaga a linha ate o ponto p"
     if p in self.lineto_id.keys() and self.lineto_id[p] is not None:
         desenhos.plot_delete(self.lineto_id[p])
Beispiel #13
0
 def hide(self):
     if self.draw_id != None:
         plot_delete(self.draw_id)
         self.draw_id = self.twin.draw_id = None
Beispiel #14
0
 def hide(self):
     "apaga o segmento de reta da tela"
     if self.plot_id != None: desenhos.plot_delete(self.plot_id)
Beispiel #15
0
 def unhilight(self):
     desenhos.plot_delete(self.hi_id)
     self.init.unhilight()
     self.to.unhilight()
Beispiel #16
0
 def unhilight_semi_circle(self, up):
     "Apaga o semi_circulo"
     if up: return desenhos.plot_delete(self.id_up)
     return desenhos.plot_delete(self.id_down)
Beispiel #17
0
 def unhilight(self):
     "Apaga o 'destaque' do disco"
     if self.hi is not None: desenhos.plot_delete(self.hi)