Comment dois-je remplir une forme composée de courbes de Bézier et de lignes droites?

8

Je travaille sur une bibliothèque graphique depuis un certain temps maintenant et j'en suis arrivé au point où je dois dessiner des polices Bézier et basées sur des lignes. Jusqu'à ce point, je suis coincé avec ceci:

je

une

Les lignes vertes sont les chemins de Bézier et la partie blanche est ce qui est rendu.

Le code que j'utilise pour Béziers est ici . Celui pour les lignes est ici . Pour ceux qui ne le savent pas, c'est Lua.

Rendu du chemin (lignes): 32 - 39 L'algorithme est le suivant:

  1. Itération de 0 à 1 à certains intervalles
  2. calculer le x et y avec cette formule: (1-index)^2*x1+2*(1-index)*index*x2+index^2*x3

Jusqu'à ce point, tout fonctionne bien. Les lignes vertes sont générées à l'aide de la méthode du chemin.

La partie blanche est rendue d'une manière complètement différente:

  1. J'obtiens les coordonnées x des Béziers et des lignes à un Y particulier, puis je les mets dans un tableau.
  2. Je parcours le tableau et chaque fois que je rencontre un point, je change la valeur de l'état. De même, la boucle for vérifie également si l'état est activé. Si c'est le cas, je dessine un pixel à l'écran.

Pour trouver les valeurs x de ay, j'utilise la méthode getX (ligne 46 dans Bézier et ligne 31 dans Line).

Le code que j'utilise pour le dessin lui-même est celui-ci:

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

Explication rapide: pour i, v par paires, parcourt le tableau donné en argument aux paires. love.graphics.points (x, y) définit un point à x, y.

Merci d'avance.

Créateur
la source
Y a-t-il une raison pour laquelle personne ne répond? Dois-je reformuler la question?
Créateur
1
À ses débuts, il n'y a que peu de gens qui ont le temps de répondre et vous n'avez jusqu'à présent atteint que 5 vues. Ce stackexchange est encore un bébé et n'a pas beaucoup de temps pour lui.
joojaa
D'ACCORD. Merci. Je ne savais pas que si peu de gens étaient là.
Créateur

Réponses:

6

Si vous êtes pressé de faire fonctionner votre moteur de rendu et que la routine polygonale remplie fonctionne correctement , puis-je suggérer une approche alternative, peut-être plus simple? Bien que je ne connaisse pas Lua, il semble que vous résolviez l'intersection exacte d'une ligne de balayage avec le Bézier quadratique qui, bien qu'admirable, est peut-être exagéré.

Au lieu de cela, tesselez vos Béziers en segments de ligne, puis jetez-les dans le convertisseur de balayage polygonal. Je suggère d'utiliser simplement une subdivision binaire (récursive): ie le Bézier quadratique avec des points de contrôle,(UNE¯,B¯,C¯) peut être divisé en deux Béziers, (UNE¯,¯,E¯) et (E¯,F¯,C¯)

¯=UNE¯+B¯2E¯=UNE¯+2B¯+C¯4F¯=B¯+C¯2
(ce qui est également très bien si vous ne disposez que de mathématiques à virgule fixe).

IIRC, chaque fois que vous subdivisez, l'erreur entre le Bézier et juste un segment de ligne droite joignant les points d'extrémité diminue d'un facteur de ~ 4x, donc il ne faut pas beaucoup de subdivisions avant que l'approximation linéaire par morceaux soit indiscernable de la vraie courbe. Vous pouvez également utiliser le cadre de délimitation des points de contrôle pour décider si vous pouvez ignorer le processus de subdivision tôt car ce sera également une limite conservatrice sur la courbe.

Simon F
la source
1
Merci! A, B, C sont des vecteurs à droite? De plus, j'utilise la méthode scanline car elle me permet d'obtenir le nombre exact de points dont j'ai besoin. Pourriez-vous jeter un œil au code et deviner pourquoi il ne fonctionne pas? Juste les formules. De plus, je voterais pour la réponse, mais je n'ai pas 15 réputation.
Créateur
Oui, AB & C sont des vecteurs; 2D dans votre cas mais cela s'applique tout aussi bien à N dimensions. Quant à parcourir le code ... comme je l'ai dit, je ne connais pas Lua et même obtenir un rendu de ligne de balayage polygonal standard correct peut être délicat - par exemple, vous devez être très prudent lorsque vous comptez les croisements qui se trouvent exactement sur les positions des sommets. Lorsque vous étendez cela à la gestion directe de Béziers (ce que j'ai fait il y a environ 20 ans), c'est encore plus difficile. Je suis désolé de ne pas avoir le temps.
Simon F
1
Merci pour l'aide. Je viens de trouver le problème. Les a et c de l'équation quadratique ont été inversés.
Créateur