Beispiel #1
0
 def edges(self):
     edges = []
     p = self.pts
     while p.next != self.pts:
         edges.append(Segment(p, p.next))
         p = p.next
     edges.append(Segment(p, p.next))
     return edges
Beispiel #2
0
 def __init__ (self, p1, p2, p3, a):
     if left (p1, p2, p3):
         self.p1 = p1
         self.p2 = p2
     else:
         self.p1 = p2
         self.p2 = p1
     self.p3 = p3
     self.a = a # Alguma aresta da DCEL que faz parte desse triangulo
     self.filhos = [] # Node_Triangs que são filhos do self no DAG
     # arestas
     self.a1 = Segment (self.p1, self.p2)
     self.a2 = Segment (self.p2, self.p3)
     self.a3 = Segment (self.p3, self.p1)
Beispiel #3
0
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()
Beispiel #4
0
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()
Beispiel #5
0
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
Beispiel #6
0
def input_aleatorio(tipo, n, max_x, max_y):
    " Retorna n objetos na área dada por (0, max_x, 0, max_y) "
    ret = []
    if tipo == 0:
        for i in range(n):
            ret.append(Point(randint(25, max_x - 25), randint(25, max_y - 25)))
    elif tipo == 2:
        for i in range(n):
            ret.append(
                Segment(
                    Point(randint(25, max_x - 25), randint(25, max_y - 25)),
                    Point(randint(25, max_x - 25), randint(25, max_y - 25))))
    elif tipo == 3:
        for i in range(n):
            x = randint(50, max_x - 50)
            y = randint(50, max_y - 50)
            ret.append(
                Disc(x, y, randint(5,
                                   min([x, y, max_x - x, max_y - y]) - 10)))
    elif tipo == 1:
        x = max_x / 2
        y = max_y / 2
        v = randomPolygon(x, y,
                          min(x, y) / 2, uniform(0, 1), uniform(.2, .3), n)
        ret = Polygon(v)
    return ret
Beispiel #7
0
 def get_plot_input(self, tipo, arq):
     " Salva o objeto correspondente ao arquivo arq no self.input "
     " E desenha ele no canvas "
     self.rodei_logo = False
     f = open(tipos_input[tipo][1] + "/" + arq, "r")
     self.input = []
     self.novo_input.delete(0, END)
     self.novo_input.insert(0, arq)
     desenhos.clear()
     # Pontos
     if tipo == 0:
         for p in f:
             x, y = float(p.split()[0]), float(p.split()[1])
             self.input.append(Point(x, y))
     # Poligono
     elif tipo == 1:
         vertices = []
         for p in f:
             x, y = float(p.split()[0]), float(p.split()[1])
             vertices.append(Point(x, y))
         p = Polygon(vertices)
         self.input = p
     # Segmentos
     elif tipo == 2:
         for p in f:
             x1, y1 = float(p.split()[0]), float(p.split()[1])
             x2, y2 = float(p.split()[2]), float(p.split()[3])
             self.input.append(Segment(Point(x1, y1), Point(x2, y2)))
     # Círculos
     elif tipo == 3:
         for p in f:
             x, y, r = float(p.split()[0]), float(p.split()[1]), float(
                 p.split()[2])
             self.input.append(Disc(x, y, r))
     self.plot_input()
Beispiel #8
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
Beispiel #9
0
    def __init__(self, x, y, r):
        "Para criar um disco, passe suas coordenadas."
        self.center = Point(x, y)
        self.r = r
        self.seg = Segment(Point(x - r, y), Point(x + r, y))
        self.lineto_id = {}

        self.plot_id = None
        self.plot_up = None
        self.plot_down = None
        self.hi = None
Beispiel #10
0
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()
Beispiel #11
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 #12
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
Beispiel #13
0
    def desenha(self):
        # Acha os dois pontos da esquerda
        x1, y1 = self.a_esq.init.x, self.a_esq.init.y
        x2, y2 = self.a_esq.to.x, self.a_esq.to.y

        # Caso degenerado
        if y1 == y2:
            s = Segment(Point(x1, y1), Point(x2, y2))
            self.aresta_cima = s
            self.aresta_baixo = s
            self.aresta_esq = s
            self.aresta_dir = s
            return

        cima = self.sup.y
        baixo = max(self.a_esq.to.y, self.a_dir.to.y)

        cima_esq = Point((x2 * y1 - x1 * y2 + cima * (x1 - x2)) / (y1 - y2),
                         cima)
        baixo_esq = Point((x2 * y1 - x1 * y2 + baixo * (x1 - x2)) / (y1 - y2),
                          baixo)

        # Acha os dois pontos da direita
        x1, y1 = self.a_dir.init.x, self.a_dir.init.y
        x2, y2 = self.a_dir.to.x, self.a_dir.to.y

        # Caso degenerado
        if y1 == y2:
            s = Segment(Point(x1, y1), Point(x2, y2))
            self.aresta_cima = s
            self.aresta_baixo = s
            self.aresta_esq = s
            self.aresta_dir = s
            return

        cima_dir = Point((x2 * y1 - x1 * y2 + cima * (x1 - x2)) / (y1 - y2),
                         cima)
        baixo_dir = Point((x2 * y1 - x1 * y2 + baixo * (x1 - x2)) / (y1 - y2),
                          baixo)

        self.aresta_cima = (Segment(cima_esq, cima_dir)).plot('orange')
        self.aresta_baixo = (Segment(baixo_esq, baixo_dir)).plot('orange')
        self.aresta_esq = (Segment(baixo_esq, cima_esq)).plot('orange')
        self.aresta_dir = (Segment(baixo_dir, cima_dir)).plot('orange')
Beispiel #14
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 #15
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
Beispiel #16
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 #17
0
class Node_Triang:
    " Classe que será o nó do DAG, guarda os triângulos que fazem parte da triangulação "
    def __init__ (self, p1, p2, p3, a):
        if left (p1, p2, p3):
            self.p1 = p1
            self.p2 = p2
        else:
            self.p1 = p2
            self.p2 = p1
        self.p3 = p3
        self.a = a # Alguma aresta da DCEL que faz parte desse triangulo
        self.filhos = [] # Node_Triangs que são filhos do self no DAG
        # arestas
        self.a1 = Segment (self.p1, self.p2)
        self.a2 = Segment (self.p2, self.p3)
        self.a3 = Segment (self.p3, self.p1)
    
    def draw (self):
        self.a1.plot("gray")
        self.a2.plot("gray")
        self.a3.plot("gray")
        sleep()
    
    def hide (self):
        self.a1.hide()
        self.a2.hide()
        self.a3.hide()
        
    def busca (self, ponto):
        " Retorna o nó folha em que o ponto está "
        if desenha_busca: self.draw()
        for f in self.filhos:
            if (left_on (f.p1, f.p2, ponto) and 
                left_on (f.p2, f.p3, ponto) and
                left_on (f.p3, f.p1, ponto)):
                if desenha_busca: self.hide()
                return f.busca (ponto)
        if desenha_busca: self.hide()
        return self 
Beispiel #18
0
def monotono(P):
    # lista com as diagonais, nosso return
    resp = []
    v = ordenaY(P)
    n = len(v)
    s = [v[0], v[1]]  # pilha
    v[0].hilight('firebrick')
    v[1].hilight('firebrick')
    t = 1  # index do fim da pilha
    if v[1] == v[0].next: borda = 1
    else: borda = 0
    for i in range(2, n):
        v[i].hilight('orange')
        sleep()
        vizinho_ultimo = adj(v[i], s[t])
        vizinho_primeiro = adj(v[i], s[0])

        if vizinho_ultimo and not vizinho_primeiro:
            while t > 0 and convexo(v[i], s[t], s[t - 1], borda):
                s[t].unhilight()
                s.pop()
                t -= 1
                # acrescenta a nova diagonal
                d = Segment(s[t], v[i])
                d.plot('orange')
                sleep()
                resp.append(d)
            t += 1
            s.append(v[i])
            v[i].unhilight()
            v[i].hilight('firebrick')
        elif vizinho_primeiro and not vizinho_ultimo:
            borda = 1 - borda
            aux = s[t]
            while t > 0:
                # acrescenta a nova diagonal
                d = Segment(s[t], v[i])
                d.plot('orange')
                sleep()
                resp.append(d)

                s.pop()
                t -= 1
                s[t].unhilight()
            s = []
            s.append(aux)
            s.append(v[i])
            v[i].unhilight()
            v[i].hilight('firebrick')
            t = 1
        else:
            while t > 1:
                s[t].unhilight()
                t -= 1
                # acrescenta a nova diagonal
                d = Segment(s[t], v[i])
                d.plot('orange')
                sleep()
                resp.append(d)
            s[0].unhilight()
            s[1].unhilight()
            v[i].unhilight()
    return resp