Beispiel #1
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 #2
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')