Präziser Subpixel-Linienzeichnungsalgorithmus (Rasterisierungsalgorithmus)

9

Ich brauche einen Algorithmus, der (ein bisschen) langsamer sein kann als der Bresenham-Linienzeichnungsalgorithmus , muss aber ein viel genauer. Mit 'genau' meine ich: Jeder berührte Pixel sollte gedruckt werden. Nicht mehr, aber auch nicht weniger! Das bedeutet, dass die Verwendung einer dickeren Linie oder ähnlichem keine Option ist, da zu viele Pixel beteiligt sind. Ich brauche auch kein grafisches Framework oder ähnliches, wie es gefragt vorher , ich brauche die Algorithmus! Die Anwendung ist nicht wirklich in 'Grafiken' ist es in der Geografiebereich , wobei Pixel" Kacheln "sind.

Das Hauptproblem für mich ist, dass ich Subpixel-Präzision brauche, was bedeutet, dass eine Linie bei 0,75 / 0,33 und nicht nur bei 0/0 beginnen könnte, wie es bei Integer-Werten der Fall ist. Ich habe versucht, eine funktionierende Lösung für die letzten Stunden zu erstellen, kann aber nicht funktionieren - es gibt zu viele Randfälle.

Zuerst dachte ich eine Anti-Alias-Version wie der Algorithmus von Wu sollte es machen, aber es druckt zu viele Pixel (insbesondere für Start- und Endpunkte) und in bestimmten Fällen fehlen noch einige Pixel z für sehr kurze Zeilen.

Dann habe ich versucht, Bresenham zum Laufen zu bringen, wo ich das zweite "if" durch "else if" ersetzt habe, wie hier , und es ist näher, aber immer noch nicht da. Dann habe ich versucht, den Bresenham von Integer- in Float-Präzision zu bewegen, was zu einer Endlosschleife führte (da die x, y-Werte über die Endbedingung if (y1 == y2 && x1 == x2) gesprungen sind).

Ich könnte die naive Linienzeichnung verwenden, aber welche delta sollte ich verwenden? Z.B. Wenn ich 0.1 benutze, werde ich immer noch einige Pixel vermissen und kleinere Werte werden wahrscheinlich zu lange dauern (und immer noch Pixel vermissen).

Eine funktionierende Lösung in C / Java / ... wäre willkommen. Zumindest sollte es für Octant 1 funktionieren, aber eine vollständige Lösung wäre noch schöner.

Update : Ich habe folgende Idee: Mit der naiven Linienrasterisierung können Sie für jeden Punkt 4 Pixel-Kandidaten berechnen. Überprüfen Sie dann diese 4 Pixel, wenn die Linie sie wirklich kreuzt. Aber ich bin mir nicht sicher, ob die Linie / Kasten-Kreuzung schnell genug sein kann.

    
Karussell 10.07.2014, 15:02
quelle

2 Antworten

4

Wenn Ihre Linie dünn ist und die Pixel rechteckig (quadratisch) sind:

Ziehen Sie dann die Verwendung von Voxel-Grid-Traversal-Algorithmen in Betracht, siehe z. B. den Artikel " Fast Voxel Traversal Algorithm. .. "von Woo und Amanatides.

Praktische Implementierung (im Gitter-Traversal-Abschnitt)

Antwort auf Kommentar:
Richtige Initialisierung für X-Koordinaten-Variablen (das gleiche für Y)

%Vor%

Beispiel in meiner Antwort hier

    
MBo 10.07.2014 15:46
quelle
4

Wenn Sie nur eine konstante Farbe benötigen (nicht durch die Pixelfläche interpoliert), verwenden Sie DDA :

%Vor%

wo:

%Vor%

ist eine Routine, die Pixel (x,y) mit Farbe col rastert Die Quelle ist in C ++

Ich denke, es ist sowieso dringend, aber

DDA verwenden die parametrische Liniengleichung y=k*x+q oder x=ky+q abhängig von der Differenz (wenn größer x oder y Unterschied ist, so dass keine Löcher vorhanden sind). Die k ist dy/dx oder dx/dy und die gesamte Division reduziert sich auf Subtraktion + Addition innerhalb der Schleife (letzte Zeile jeder Schleife). Dies kann leicht auf eine beliebige Anzahl von Dimensionen geändert werden (normalerweise verwende ich 7D oder mehr). Bei modernen Maschinen ist die Geschwindigkeit manchmal besser als bei Bresenham (abhängig von der Plattform und der Nutzung).

So sieht es im Vergleich zu einfachem DDA

aus

[edit2] doppelte Koordinaten // ursprünglich [edit1]

OK, hier ist ein neuer Code:

%Vor%

Und so sieht es aus:

Der Winkel sollte jetzt in double precision sein, aber pnt (x, y, col) steht immer noch auf ganzen Zahlen !!!

[edit3] Pixelrasterkreuzung

%Vor%

Endlich hatte ich etwas Zeit dafür, also habe ich DDA ein wenig optimiert, aber ich habe zu vielen if s geführt, also ändere ich die Rasterisierung ziemlich. Jetzt werden alle Pixelgitter-Kreuzungen (Schnittpunkte) berechnet und dann wird für jeden der rechte Subpixel hinzugefügt. So sieht es aus (keine falschen Subpixel):

Für jede x oder y Gitterlinien ist der erste Kreuzpunkt berechnet (a,b) und step ist in einer Achse 1 Pixel und in Sekunde der Rest nach dy/dx oder dx/dy . Danach füllt die for-Schleife die Sub-Pixel ...

    
Spektre 10.07.2014 16:59
quelle