Loading AI tools
Aufgabe der Computergrafik Aus Wikipedia, der freien Enzyklopädie
Unter der Rasterung von Kreisen versteht man in der Computergrafik das Zeichnen (Rastern) eines Kreises auf dem Punktraster einer Rastergrafik oder eines Raster-Grafikgeräts durch Einfärben entsprechender Pixel. Es gibt hierfür sowohl Algorithmen zur einfarbigen Rasterung als auch zum Antialiasing.
Eine einfache Möglichkeit, Kreise zu zeichnen, basiert auf der Parameterdarstellung von Kreisen:
Für jedes zwischen 0 und werden in bestimmten Abständen die (x, y)-Koordinaten gemäß dieser Formel berechnet und die entsprechenden Pixel eingefärbt. Kreise mit beliebigem Mittelpunkt können durch eine einfache Koordinatenverschiebung gezeichnet werden. Diese Methode ist sehr ineffizient, da sie die langsamen Cosinus- und Sinusfunktionen verwendet.
Eine andere Möglichkeit ist, die Koordinatengleichung des Kreises () nach aufzulösen:
Hier wird für jedes zwischen und berechnet. Diese Methode ist wegen der Wurzel ebenfalls ineffizient und lässt zudem für nahe Lücken.
Die soeben beschriebenen Algorithmen können durch die Nutzung von Symmetrieeigenschaften verbessert werden. Tatsächlich besitzt jedes Pixel auf dem Kreis sieben weitere symmetrische Pixel, die sich trivial berechnen lassen. Es genügt demnach, nur einen Achtelkreis zu zeichnen und anstatt nur einem Pixel folgende acht Pixel einzufärben:
(x, y) | (y, x) | (y, −x) | (x, −y) | (−x, −y) | (−y, −x) | (−y, x) | (−x, y) |
Diese Methode löst außerdem das Problem der Lücken bei der eben beschriebenen Methode.
Eine frühe Methode zum Rastern von Kreisen wurde 1969 von Metzger vorgestellt.[1] Hierbei wird ausgehend vom aktuellen Pixel der Koordinaten zwischen den beiden Pixeln, die sich außerhalb und innerhalb des Kreises befinden, gewählt. Wenn der Abstand des inneren und der Abstand des äußeren Pixels zum Kreismittelpunkt ist, so wird dasjenige Pixel gewählt, dessen Abstand näher am Kreisradius liegt. Beispielsweise wird das äußere Pixel gewählt, falls .
Unter Anwendung des Satzes des Pythagoras lässt sich letztere Bedingung folgendermaßen umformen:
Mit Hilfe der Dreiecksungleichung, die hier für alle gültig ist, ergibt sich:
Zur Umsetzung der Quadrierungen sind allerdings langsame Multiplikationen erforderlich. Diese würden sich durch die inkrementelle Berechnung der Bedingung vermeiden lassen; Metzger formulierte allerdings keine derartige Lösung.
Ein Algorithmus, der nur Additionen und Subtraktionen verwendet, wurde 1976 von Horn vorgestellt.[2] Bei Horns Verfahren befinden sich die einzufärbenden Pixel innerhalb eines ein Pixel breiten Bereichs um den idealen Kreisbogen. Wenn das aktuelle Pixel ist, dann wird die Position des direkt darüberliegenden Pixels mit dem rechten Rand dieses Bereichs verglichen. Liegt es innerhalb des Bereichs, wird dieses Pixel gewählt. Liegt das Pixel außerhalb, so wird das links liegende Pixel gewählt. Auf letzteren Fall lässt sich unter Einführung der Kontrollvariable folgendermaßen testen:
Ein inkrementeller Algorithmus ergibt sich durch die Betrachtung der Differenz bei beiden möglichen Fällen. Bei jedem Schritt wird um erhöht; wenn das linke Pixel gewählt wird, subtrahiert man . Der Anfangswert der Kontrollvariable beträgt , kann aber für Kreise mit ganzzahligen Mittelpunkten und Radien auf gerundet werden.
Der komplette Algorithmus lautet damit:
d = −r x = r y = 0 Wiederhole bis y > x Pixel (x, y) sowie symmetrische Pixel einfärben d = d + 2×y + 1 y = y + 1 Wenn d > 0 d = d - 2×x + 2 x = x - 1
Optimierung für den Schritt :
Wenn man die Zeile mit der darüberliegenden vertauscht, kann man die Operation einsparen.
Wenn zuvor also um 1 erniedrigt wurde, ist das automatisch schon enthalten.
Von wird in beiden Versionen 1 abgezogen. Trotz Vertauschung der Zeilen bleibt also das Endergebnis für gleich.
Für ändert sich jetzt aber etwas: Statt mit dem einfachen wird in dieser Zeile mit dem um 1 reduzierten gearbeitet, mit . Von wird jetzt abgezogen:
Klammern entfernen, entspricht:
Man kann also sehen, dass für der gleiche Wert, wie in der unoptimierten Version errechnet wird. Damit ist gezeigt, dass das Endergebnis sich algorithmisch nicht von der unoptimierten Version unterscheidet.
Optimiert sieht das dann so aus:
d = −r x = r y = 0 Wiederhole bis y > x Pixel (x, y) sowie symmetrische Pixel einfärben d = d + 2×y + 1 y = y + 1 Wenn d > 0 x = x - 1 d = d - 2×x
1964 und 1977 stellte Bresenham einen weiteren Algorithmus vor[3][4][5] (siehe auch Bresenham-Algorithmus). Ähnlich wie Metzger wählt er Pixel auf der Basis ihrer Entfernung zum Kreismittelpunkt aus. Ein einfacherer, äquivalenter Algorithmus bedient sich der Midpoint-Formulierung, bei der der Mittelpunkt zwischen den beiden nächsten Pixeln betrachtet wird.[6]
Der Midpoint-Algorithmus rastert den Kreisbogen ausgehend vom Pixel mit größter y-Koordinate. Ausgegangen wird von einer impliziten Form der Koordinatengleichung des Kreises:
ist 0 auf dem Kreis, positiv außerhalb und negativ innerhalb des Kreises. Bei jedem Schritt wird zwischen dem „östlichen“ und dem „südöstlichen“ Pixel gewählt. In diese Gleichung werden die Koordinaten des Mittelpunkts eingesetzt:
Bei wird Pixel O gewählt, im anderen Fall SO.
Auch hier ist ein inkrementeller Algorithmus möglich. Die Änderung der Kontrollvariable hängt von der Wahl des Pixels ab:
Der Anfangswert der Kontrollvariable beträgt . Für die ganzzahlige Rasterung lässt sich der Bruch vermeiden, indem von d abgezogen wird. Dadurch ändert sich der Anfangswert in und der Vergleich in , welcher sich durch Rundung in umwandeln lässt.
Der resultierende Algorithmus ist Horns Methode sehr ähnlich.
Im Gegensatz zum Midpoint-Algorithmus für Linien (siehe Rasterung von Linien) sind und nicht konstant, sondern hängen von der aktuellen Position ab. Es ist daher möglich, Differenzen „zweiter Ordnung“ zu betrachten, bei der und selbst inkrementell berechnet werden. Mit diesem Algorithmus wird die Initialisierung aufwändiger; innerhalb der Schleife spart man im Falle der Wahl von SO eine Addition. Auf dieses Verfahren hat IBM, Bresenhams damaliger Arbeitgeber, in mehreren Staaten Softwarepatente eingereicht, darunter auch 1982 beim Europäischen Patentamt.[7][8][9]
Eine mögliche Implementierung des Midpoint-Algorithmus vom Bresenham in der Programmiersprache C# zeigt das folgende Beispiel:[10]
public void DrawCircle(Color[,] image, int centerX, int centerY, int radius, Color color)
{
int d = (5 - radius * 4) / 4; // Kontrollvariable
int x = 0;
int y = radius;
do
{
// Prüft, ob das Pixel innerhalb der Grenzen des Bilds liegt und setzt gegebenenfalls ein Pixel in jedem Oktanten
if (centerX + x >= 0 && centerX + x <= image.Width - 1 && centerY + y >= 0 && centerY + y <= image.Height - 1) image[centerX + x, centerY + y] = color; // 7. Oktant
if (centerX + x >= 0 && centerX + x <= image.Width - 1 && centerY - y >= 0 && centerY - y <= image.Height - 1) image[centerX + x, centerY - y] = color; // 2. Oktant
if (centerX - x >= 0 && centerX - x <= image.Width - 1 && centerY + y >= 0 && centerY + y <= image.Height - 1) image[centerX - x, centerY + y] = color; // 6. Oktant
if (centerX - x >= 0 && centerX - x <= image.Width - 1 && centerY - y >= 0 && centerY - y <= image.Height - 1) image[centerX - x, centerY - y] = color; // 3. Oktant
if (centerX + y >= 0 && centerX + y <= image.Width - 1 && centerY + x >= 0 && centerY + x <= image.Height - 1) image[centerX + y, centerY + x] = color; // 8. Oktant
if (centerX + y >= 0 && centerX + y <= image.Width - 1 && centerY - x >= 0 && centerY - x <= image.Height - 1) image[centerX + y, centerY - x] = color; // 1. Oktant
if (centerX - y >= 0 && centerX - y <= image.Width - 1 && centerY + x >= 0 && centerY + x <= image.Height - 1) image[centerX - y, centerY + x] = color; // 4. Oktant
if (centerX - y >= 0 && centerX - y <= image.Width - 1 && centerY - x >= 0 && centerY - x <= image.Height - 1) image[centerX - y, centerY - x] = color; // 5. Oktant
if (d < 0)
{
// Pixel O wählen
d += 2 * x + 1;
}
else
{
// Pixel SO wählen
d += 2 * (x - y) + 1;
y--;
}
x++;
}
while (x <= y);
}
Die Algorithmik ist weitestgehend schon erklärt, jedoch gibt es noch weitere Optimierungen.
Die neue vorgestellte Methode[11] kommt mit nur 5 Rechenoperationen pro Schritt (für 8 Pixel) aus und ist damit gerade für niedrigperformante Systeme bestens geeignet. In der "Wenn" Operation wird nur das Vorzeichen geprüft (positiv? Ja oder Nein) und es gibt eine Variablenzuweisung, was auch nicht als Rechenoperation gilt. Die Initialisierung in der ersten Zeile (Geschiebe um 4 Bits nach rechts) ist nur der Schönheit geschuldet und nicht wirklich nötig.
Also bleibt (zählbare Operationen in der Hauptschleife):
Operationen: 5
t1 = r / 16 x = r y = 0 Wiederhole solange x >= y Pixel (x, y) sowie symmetrische Pixel einfärben y = y + 1 t1 = t1 + y t2 = t1 - x Wenn t2 >= 0 t1 = t2 x = x - 1
Im Folgenden eine einfache Beispielimplementierung in C. Einfach als "main.c" zu speichern und zu kompilieren. Zur Kontrolle werden die Koordinaten der gesetzten Pixel ausgegeben.
#include <stdio.h>
void
plot( int x, int y )
{
printf( "x=%3d, y=%3d\n", x, y );
}
void
circle( int mx, int my, int r )
{
int t1 = r / 16;
int t2 = 0;
int x = r;
int y = 0;
while ( x >= y )
{
plot( mx + x, my + y );
plot( mx + x, my - y );
plot( mx - x, my + y );
plot( mx - x, my - y );
plot( mx + y, my + x );
plot( mx + y, my - x );
plot( mx - y, my + x );
plot( mx - y, my - x );
y = y + 1;
t1 = t1 + y;
t2 = t1 - x;
if ( t2 >= 0 )
{
t1 = t2;
x = x - 1;
}
}
}
int
main()
{
circle( 20, 30, 10 );
return 0;
}
Die Anzahl der arithmetischen Operationen bei Bresenhams Algorithmus lässt sich weiter verringern.[12] Es wurden noch andere, schnellere Methoden zur Rasterung vorgestellt, die mehrere Pixel auf einmal zeichnen. Wu und Rokne stellten 1987 ein Doppelschrittverfahren vor, bei dem je Schleifendurchlauf zwei Pixel eingefärbt werden.[13] Yao und Rokne zeigten 1995, wie auch bei der Rasterung von Kreisen ganze Pixelreihen auf einmal eingefärbt werden können.[14]
Es gibt mehrere Methoden, gefüllte Kreise zu zeichnen. Eine triviale Methode besteht darin, beim Zeichnen eines Oktanten nicht nur ein Pixel pro Schleifendurchlauf, sondern alle Pixel einer Reihe zu zeichnen. Durch die Symmetrie wird der gesamte Kreis gefüllt.[15] Ebenfalls möglich ist das Zeichnen einer minimalen Anzahl von Rechtecken; Nachteil ist hier, dass viele Pixel mehrmals eingefärbt werden.[16]
Anstatt einen Kreis durch seinen Mittelpunkt und seinen Radius zu definieren, ist es auch möglich, einen Mittelpunkt und einen beliebigen auf dem Kreis liegenden Punkt anzugeben. Dabei muss aber beachtet werden, dass bestimmte Punkte des Rasters gar nicht auf einem Kreis mit ganzzahligem Radius liegen. Algorithmen, die Kreise nach diesem Schema zeichnen, müssen auf ungültige Anfangspunkte testen.[17]
Field stellte eine Methode zum Antialiasing von Kreisen mittels ungewichteter Flächenabtastung vor, bei der der Kreis für jedes Pixel mit einem Trapez angenähert wird.[18] Der Flächenanteil des Trapezes innerhalb eines Quadrats mit einem Pixel Kantenlänge bestimmt den Farbwert. Dank inkrementeller Berechnung benötigt der Algorithmus nur Multiplikationen und Additionen.
Auch der Gupta-Sproull-Algorithmus für Linien kann auf Kreise erweitert werden.[19] Im Gegensatz zu Linien hängt der Wert des Glättungskerns nicht nur von der Distanz zur Kurve, sondern auch vom Radius ab. Daher sind verschiedene Tabellen für verschiedene Radien notwendig. Für größere Kreise kann eine einzige Tabelle verwendet werden, bei der die Krümmung vernachlässigt wird.
Seamless Wikipedia browsing. On steroids.
Every time you click a link to Wikipedia, Wiktionary or Wikiquote in your browser's search results, it will show the modern Wikiwand interface.
Wikiwand extension is a five stars, simple, with minimum permission required to keep your browsing private, safe and transparent.