Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
    def intersects_inside(self, other_segment) -> bool:
        ''' returns whether the other segment intersects this segment
            (not counting border points) '''
        if self.colinear_with(other_segment.init)    \
           or self.colinear_with(other_segment.to)   \
           or other_segment.colinear_with(self.init) \
           or other_segment.colinear_with(self.to):
            return False

        return (left(self.init, self.to, other_segment.init)
                ^ left(self.init, self.to, other_segment.to))            \
               and (left(other_segment.init, other_segment.to, self.init)
                   ^ left(other_segment.init, other_segment.to, self.to))
Ejemplo n.º 3
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()
Ejemplo n.º 4
0
 def __gt__(self, other):
     ref = other.ref
     # Se o ponto de referencia é uma interseção,
     if abs(area2(self.seg.init, self.seg.to, ref)) < eps:
         # O ponto de referência vai ser o ponto da direita
         ref = other.seg.to
     # Self > other <=> other está a esquerda do self
     return left(self.seg.init, self.seg.to, ref)
Ejemplo n.º 5
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
Ejemplo n.º 6
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
Ejemplo n.º 7
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)
Ejemplo n.º 8
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
Ejemplo n.º 9
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
Ejemplo n.º 10
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)
Ejemplo n.º 11
0
 def __gt__(self, other):
     return left(self.a_esq.init, self.a_dir.to, other.sup)
Ejemplo n.º 12
0
 def has_left(self, point):
     return left(self.init, self.to, point)