Como devo preencher uma forma que consiste em curvas de Bezier e linhas retas?


8

Estou trabalhando em uma biblioteca de gráficos há algum tempo e cheguei ao ponto em que tenho que desenhar fontes baseadas em Bezier e em linhas. Até este ponto, estou preso a isso:

Eu

uma

As linhas verdes são os caminhos de Bezier e a parte branca é o que é renderizado.

O código que eu uso para Beziers está aqui . O de linhas está aqui . Para quem não sabe, isso é Lua.

Renderização de caminho (linhas): 32 - 39 O algoritmo é o seguinte:

  1. Iterando de 0 para 1 em determinados intervalos
  2. calculando xey com esta fórmula: (1-index)^2*x1+2*(1-index)*index*x2+index^2*x3

Até este ponto, tudo funciona bem. As linhas verdes são geradas usando o método path.

A parte branca é renderizada de uma maneira completamente diferente:

  1. Pego as coordenadas x dos Beziers e as linhas em um Y específico e as coloco em uma mesa.
  2. Eu percorro a tabela e cada vez que encontro um ponto, altero o valor do estado. No mesmo loop for também é verificado se o estado está ativado. Se for, eu desenho um pixel na tela.

Para encontrar os valores x de ay, eu uso o método getX (linha 46 em Bezier e linha 31 na linha).

O código que eu uso para o desenho em si é este:

local xBuffer = {}
local state = false

for i=0,500 do
    for k,v in pairs(beziers) do
        a,b = v.getX(i)
        if a then
            xBuffer[round(a)] = 1
            if b then
                xBuffer[round(a)] = 1
            end
        end
    end
    for k,v in pairs(lines) do
        a = v.getX(i)
        if a then
            xBuffer[round(a)] = 1
        end
    end
    state = false
    for x=0,600 do
        if xBuffer[x] then
            state = not state
        end
        if state then
            love.graphics.points(x,i)
        end
    end
end

Explicação rápida: para i, v em pares itera pela tabela fornecida como argumento para pares. love.graphics.points (x, y) define um ponto em x, y.

Desde já, obrigado.


Existe uma razão para ninguém responder? Devo reformular a pergunta?
Criador

11
Nos primeiros dias, há apenas tantas pessoas que têm tempo para responder e você só alcançou 5 visualizações até o momento. Essa troca de pilha ainda é uma criança e não tem muitos usuários dando tempo.
joojaa

ESTÁ BEM. Obrigado. Eu não sabia que havia tão pouca gente aqui.
Criador

Respostas:


6

Se você estiver com pressa de fazer o renderizador funcionar e já tiver a rotina poligonal preenchida funcionando corretamente , posso sugerir uma abordagem alternativa e possivelmente mais fácil? Embora eu não esteja familiarizado com Lua, parece que você está resolvendo a interseção exata de uma linha de varredura com o Bezier quadrático que, embora admirável, é possivelmente um exagero.

Em vez disso, agrupe seus Beziers em segmentos de linha e jogue-os no conversor de varredura de polígonos. Sugiro apenas o uso de subdivisão binária (recursiva): ou seja, o Bezier quadrático com pontos de controle,(A¯,B¯,C¯) pode ser dividido em dois Beziers, (A¯,D¯,E¯) e (E¯,F¯,C¯) Onde

D¯=A¯+B¯2E¯=A¯+2B¯+C¯4F¯=B¯+C¯2
(o que também é ótimo se você tiver apenas matemática de pontos fixos).

IIRC, sempre que você subdividir, o erro entre o Bezier e apenas um segmento de linha reta que une os pontos finais diminui em um fator de ~ 4x, portanto, não são necessárias muitas subdivisões antes que a aproximação linear por partes seja indistinguível da verdadeira curva. Você também pode usar a caixa delimitadora dos pontos de controle para decidir se pode pular o processo de subdivisão mais cedo, pois também será um limite conservador na curva.


11
Obrigado! A, B, C são vetores, certo? Além disso, estou usando o método scanline porque ele permite obter o número exato de pontos necessários. Você poderia dar uma olhada no código e adivinhar por que ele não está funcionando? Apenas as fórmulas. Também aprovaria a resposta, mas não tenho 15 reputação.
Criador

Sim, AB e C são vetores; 2D no seu caso, mas se aplica igualmente a N dimensões. Quanto a passar pelo código ... como eu disse, não conheço Lua e até mesmo obter um renderizador de varredura de polígono padrão correto pode ser complicado - por exemplo, você deve ter muito cuidado ao contar cruzamentos que se encontram exatamente nas posições dos vértices. Quando você estende isso para lidar diretamente com Beziers (o que fiz há mais de 20 anos), é mais difícil ainda. Me desculpe, eu não tenho tempo.
Simon F

11
Obrigado pela ajuda. Acabei de encontrar o problema. Os a e c na equação quadrática foram invertidos.
Criador
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.