Wie soll ich eine Form aus Bezier-Kurven und geraden Linien füllen?

8

Ich arbeite seit einiger Zeit an einer Grafikbibliothek und bin an einem Punkt angelangt, an dem ich Bezier- und linienbasierte Schriftarten zeichnen muss. Bis zu diesem Punkt stecke ich fest:

ich

ein

Die grünen Linien sind die Bezier-Pfade, und der weiße Teil wird gerendert.

Der Code, den ich für Beziers verwende, ist hier . Der für Linien ist hier . Für diejenigen, die das nicht wissen, ist Lua.

Pfadwiedergabe (Linien): 32 - 39 Der Algorithmus lautet wie folgt:

  1. Iteration von 0 nach 1 in bestimmten Intervallen
  2. Berechnen von x und y mit dieser Formel: (1-index)^2*x1+2*(1-index)*index*x2+index^2*x3

Bis zu diesem Punkt funktioniert alles gut. Die grünen Linien werden mit der Pfadmethode generiert.

Der weiße Teil wird ganz anders gerendert:

  1. Ich bekomme die x-Koordinaten der Beziers und Linien bei einem bestimmten Y, die sie in eine Tabelle einfügen.
  2. Ich durchlaufe die Tabelle und ändere jedes Mal, wenn ich auf einen Punkt stoße, den Wert des Status. In der gleichen for-Schleife wird auch geprüft, ob der Status aktiviert ist. Wenn ja, zeichne ich ein Pixel auf den Bildschirm.

Um die x-Werte von ay zu finden, verwende ich die getX-Methode (Zeile 46 in Bezier und Zeile 31 in Zeile).

Der Code, den ich für die Zeichnung selbst verwende, ist folgender:

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

Kurze Erklärung: Für i durchläuft v paarweise die Tabelle, die Paaren als Argument gegeben wurde. love.graphics.points (x, y) setzt einen Punkt auf x, y.

Danke im Voraus.

Schöpfer
quelle
Gibt es einen Grund, warum niemand antwortet? Soll ich die Frage neu formulieren?
Schöpfer
1
In den Anfängen gibt es nur so viele Leute, die Zeit haben zu antworten, und Sie haben bisher nur 5 Aufrufe erreicht. Dieser Stapelaustausch ist noch ein Kind und hat nicht viele Benutzer, die ihm Zeit geben.
Joojaa
OK. Vielen Dank. Ich wusste nicht, dass so kleine Leute hier waren.
Schöpfer

Antworten:

6

Wenn Sie es eilig haben, Ihren Renderer zum Laufen zu bringen, und die bereits ausgefüllte polygonale Routine bereits ordnungsgemäß funktioniert , kann ich einen alternativen, möglicherweise einfacheren Ansatz vorschlagen? Obwohl ich mit Lua nicht vertraut bin, scheinen Sie nach dem genauen Schnittpunkt einer Scanlinie mit dem quadratischen Bezier zu suchen, was zwar bewundernswert, aber möglicherweise übertrieben ist.

(A¯,B¯,C¯)(A¯,D¯,E¯)(E¯,F¯,C¯)

D¯=A¯+B¯2E¯=A¯+2B¯+C¯4F¯=B¯+C¯2

IIRC verringert sich bei jeder Unterteilung der Fehler zwischen dem Bezier und nur einem geraden Liniensegment, das die Endpunkte verbindet, um den Faktor ~ 4x, sodass nicht viele Unterteilungen erforderlich sind, bis die stückweise lineare Approximation nicht mehr von der wahren zu unterscheiden ist Kurve. Sie können auch den Begrenzungsrahmen der Kontrollpunkte verwenden, um zu entscheiden, ob Sie den Unterteilungsprozess frühzeitig verlassen können, da dies auch eine konservative Begrenzung der Kurve ist.

Simon F.
quelle
1
Vielen Dank! A, B, C sind Vektoren richtig? Außerdem verwende ich die Scanline-Methode, da ich so genau die Anzahl der Punkte erhalten kann, die ich benötige. Könnten Sie sich den Code ansehen und erraten, warum er nicht funktioniert? Nur die Formeln. Auch ich würde die Antwort positiv bewerten, aber ich habe keinen Ruf.
Schöpfer
Ja, AB & C sind Vektoren; 2D in Ihrem Fall, aber es gilt genauso gut für N Dimensionen. Was das Durchgehen des Codes angeht ... wie gesagt, ich kenne Lua nicht und es kann schwierig sein, einen Standard-Polygon-Scanline-Renderer korrekt zu machen - z. B. müssen Sie beim Zählen von Kreuzungen, die genau auf Scheitelpunktpositionen liegen, sehr vorsichtig sein. Wenn Sie das auf den direkten Umgang mit Beziers ausweiten (was ich vor über 20 Jahren getan habe), ist es noch schwieriger. Es tut mir leid, dass ich keine Zeit habe.
Simon F
1
Danke für die Hilfe. Habe gerade das Problem gefunden. A und c in der quadratischen Gleichung wurden invertiert.
Schöpfer