Bresenham-Algorithmus

Wo Bresenham-Algorithmus ist ein Algorithmus in der Computergrafik zum Zeichnen ( Rastern ) von gerade oder Kreis auf Rasteranzeigen . Für Linienalgorithmen gibt es einen eigenen Übersichtsartikel , hier finden Sie die konkrete Umsetzung.

Es wurde Algorithmus Wurde 1962 von Jack Bresenham , Damals Programmerer IBM , entwickelt. [1] Das Besonderes ein Sein Algorithmus ist, that ist Rundungsfehler, sterben Durch Diskretisierung von kontinuierlichen Koordinaten entstehen stirbt, minimiert und gleichzeitig einfach implementierbar ist, mit der Zugabe von Ganzen Zahlen als komplexeste Betrieb, und SOMIT ohne Multiplikation, die Division und Gleitkommazahlen auskommen .

Durch eine geringfügige Erweiterung wird der Ursprung des Algorithmus, der verwirrt wurde, auch für die Rasterung von Kreisen. Sogar die Quadratterme, die beim Kreis kommt, schweißen sich rekursiv ohne jede Multiplikation aus{\ displaystyle (n + 1) ^ {2} = n ^ {2} +2 \ cdot n + 1}, wobei der Begriff {\ displaystyle 2 \ cdot n}Cousin als Multiplikation Zählt, wie in Hardware bzw. auf Assemblerbene als einfache Shift-Operation implementiert{\ displaystyle n ^ {2}} Im Vermeiden war ganz was.

In den Grafikchips sind folgende Eigenschaften enthalten: Bromsham-Algorithmus in Plottern , in den Grafikchips Grafikkarten und der Grafische Bibliotheken zur Verwendung. Dabei ist es so einfach, dass kein Mensch in der Firmware solche Geräte verwendet wird, ohne in Grafikchips direkt in Hardware umgesetzt zu werden.

Der Name „Bresenham“ wird heute zusätzlich für eine ganze Reihe von Algorithmen verwöhnt, die von anderen Spritzer entwickelt wurden, jedoch in der Nachfolge von Bresenham und ich bin verwirrt Ansatz. Siehe weiterführende Literaturhinweise unten.

Ansatz

Die gehostete Variante ist ein sehr praxisnaher Ansatz und wurde zuerst von Pitteway [2] veröffentlicht und von Aachen [3] verifiziert. Weiter unten wird die Variante mit der ursprunglichen Formulierung von Bresenham verhnlich und seigt, dass die Lösungen equivalente sind.

Zum Verständnis des Algorithmus wird einer der neuesten Romane beschrieben , der auch einer der folgenden ähnelt : 0 und 1 Hoffnung{\ displaystyle {x _ {\ mathrm {start}}, y _ {\ mathrm {start}}}} nach {\ displaystyle (x_ {\ mathrm {end}}, y _ {\ mathrm {end}}}}. Seien{\ displaystyle dx = x _ {\ mathrm {end}} -x _ {\ mathrm {start}}} und {\ displaystyle dy = y _ {\ mathrm {end}} -y _ {\ mathrm {start}}} mit {\ displaystyle 0 <dy \ leq dx}. Für andere Oktanten muss mann später Fallunterscheidungen über Vorzeichen von{\ displaystyle dx} und {\ displaystyle dy} und würfeln Enver Taus Chung von {\ Displaystyle x} und {\ displaystyle y} treffen.

Wo der Algorithmus so lernt, bist du in der „schnellen“ Richtung (hier die positive {\ Displaystyle x}-Richtung) nach der Macht und Sie finden die Steigung hin und wieder zusätzlich einen Schritt in der „langseren“ Richtung (hier {\ displaystyle y}). Man benutzt die Fehlervariable, die in Schritt geschrieben ist{\ Displaystyle x}-Richtung den (kleiner) Wert {\ displaystyle dy}subtrahiert Sorgen. Bei Unterschreitung des Nullwerts wird ein{\ displaystyle y}-Schritt fällig und der (größere) Wert {\ displaystyle dx}fügt Fehlervariablen addiert hinzu. Diese wirederholten „Überkreuz“ -Subtraktionen und -Additionen lösen de Division des Steigungsdreiecks{\ displaystyle m = dy / dx} in elementaren Rechenschritten auf.

Neben diesem Fehlerglied wurden unsere Gedanken initialisiert. Dazu verrät man den Sturz der Hoffnung{\ displaystyle dy = 1}, bei dem der Mitte {\ displaystyle dx}) Kredite {\ displaystyle y}-Schritt schlief ein. Außerdem initiieren Sie das Fehlerglied mit{\ displaystyle (dx / 2)}. (Obgleich zu einer Reihe, spielt kaum eine Rolle.)

Mathematisch sagte die Geradengleichung

{\ displaystyle y = y _ {\ mathrm {start}} + {x-x _ {\ mathrm {start}}) \ cdot {\ frac {dy} {dx}}}

aufgelöst in

{\ displaystyle 0 = dx \ cdot (y-y _ {\ mathrm {start}}) – dy \ cdot (x-x _ {\ mathrm {start}}}}

und de Null links durch das Fehlerglied ersetzt. Ein Schritt über 1 in{\ Displaystyle x}-Richtung (Variable {\ Displaystyle x}) Bewertung von Verminderung des Fehlerglieds um {\ displaystyle 1 \ cdot dy}. Wenn das Fehlerglied dabei unter Null gerät, wird es durch einen{\ displaystyle y}-Richtung (Variable {\ displaystyle y}) über {\ displaystyle 1 \ cdot dx} erhöht, war in der Nähe der Voraussetzung {\ displaystyle dx> = dy}Das ist ein Fehlerglied auf jeden Fall. Mehr auf Null gebracht.

Wo ursprünglichen Ansatz nach Bresenham (su) geht mehr Geometrisch vor, Wodurch in Seinen Iterationsformeln auf Seiten Beide (bis auf dem Fehlerglied) eine addition Factor 2 mitgeführt Wird und Auch sterben Fehlergliedinitialisierung anders hergeleitet Wird.

Einfache Implementierung

Eine erste Implementierung ist nicht sehr elegant, zeigt das Prinzip des Algorithmus aber sehr gut.

 REM Bresenham - Algorithmus f ü r Eine Linie im Ersten Oktanten in Pseudomonas - Grund dx = xend - xstart dy = y end - YStart REM im Ersten Oktanten Muss 0 < dy <= dx sein REM Initialisierungen x = xstart y = YStart SetPixel x , y fehler =
 dx / 2
REM Pixelschleife: immer ein schreiten in schnellen RICHTUNG , hin und wieder Auch Einer in Langsame WÄHREND x < xend REM schreiten in schnellen RICHTUNG x = x + 1 fehler = fehler - dy IF fehler < 0 THEN REM schreitet in Langsame RICHTUNG y = y
 + 1 fehler = fehler + dx ENDE WENN SETPIXEL x , y WEND

Vergleich mit der Original-Bresenham-Formulierung

 REM Quasi - Bresenham - Algorithmus REM Ursprüngliche - Bresenham dx = xend - xstart dx = xend - xstart dy = y end - YStart dy = y end - YStart d = 2 * dy - dx dO = 2 * dy DNO = 2 * ( dy - dx ) x = xstart x
 = Xstart y = ystart y = ystart SetPixel x , y SetPixel x , y fehler = dx / 2 Fehler = d WHILE x < xend WHILE x < xend x = x + 1 x = x + 1 fehler = fehler - dy IF Fehler < 0 THEN IF fehler <=
 0 THEN fehler = fehler + dO ELSE y = y + 1 y = y + 1 fehler = fehler + dx fehler = fehler + DNO END IF END IF SetPixel x , y SetPixel x , y Wender Wender

Abgesehen von der Anpassung und dem verdorbenen BASIC-Dialekt sind folgende Unterschiede bei originalen Formulierung zu stränder:

  • Der Fehler wird mit Umgekehrtem Vorzeichen verwirrt.
  • Das Fehlerglied Wird auf sein Vorzeichen abgefragt, Bevor es aktualisiert Wird, Wird Characterized addition Initialisierung with the sterben dy -Terme Notwendig.
  • Das Fehlerglied ist über den Faktor 2, also nicht bei der Initialisierung einer Division durch 2 vorhanden, für die aber die Schrittvariablen für die Fehleraktualisierungen doppelt so groß sind.

Wenn der Mensch sich unterscheidet, stellt sich heraus, dass beide Formulierungen identisch sind.

Elegantes Implementierungsteam

Als Eleganter formulierte beispiel folgen als erstes in dem Quellcode Eines BASIC Programme und anschließend Eines Unter Anwendungen in C , WELCHE sterben Fall Unter Scheidung in acht Oktanten nicht ausdrücklich Vornehm Müssen.

Es algorithm soll für alle Oktanten gelb Werden. Dabei Müssen sterben Vorzeichen wo Koordinatendistanzen und sterben jede Vertauschung wo Rolle von x und y berücksichtigt Werden. If Mann this Fall Unter Schei Dungen Innerhalb des innere Stein Schleife treffen Würde, auch in hohen Anzahl, Würde die geschwindigkeit , wo Berechnungen Deutlich verringern sterben. Eine Effizient Versucht Lösung, die alle this Fall Unter Schei Dungen in Initialisierungsphase der vor dem Dezember Elle Verfahren Innerer Hauptschleife abzuzuarbeiten, so that Innerhalb der Inneren Schleife weiterhin nur Das Eine Abfrage für den Bresenham-Fehlerglied ERFOLG Durcheinander.

This Formulierung Führt (wie schon Stockton [4] indirekte vorschlug) verschiedene Abstraktionen ein: Zunächst Wird der schritt in sterben schnelle RICHTUNG jetzt als Parallelschritt (parallel zu Einer Koordinatenachse) angesehen, und , ideal für addition Ein Schritt in sterben Langsame RICHTUNG erfolgt, Wird das zu ein Diagonalschritt. Dann kann man in der Initialisierung Variablenwerte ermitteln, sterben für this Fälle sterben Schrittweiten in den Beiden Koordinatenrichtungen vorab Partei Arzt und SOMIT sterben Verallgemeinerung für sterben acht Oktanten Motivation und andere Mentalität. Beispielsweise ist bei Einem Parallelschritt sterben Schrittweite in sterben dazu Senkrecht RICHTUNG eben Null. Zweiter Rechner zum Fehlerterm weiterhin Wie im Ersten Oktanten mit Absolutbeträgen wo distanz. In der inneren Steine ​​Schleife Wird Dann nicht mehr haben keinen Einfluss auf der schritt in der Schnellen RICHTUNG ausgeführt, Sondern als Erstes wo Fehlerterm aktualisiert, und DANACH erst Werden sterben Schrittweiten zu den bisherigen Koordinaten addiert, je Once, ob ein die parallel oder ein Diagonalschritt ERFOLGS Durcheinander:

BASIC-Implementierung

 REM Bresenham - Algorithmus f ü r Eine Linie in Einem belieber Oktanten in Pseudomonas - Grund dx = xend - xstart dy = y end - YStart REM Initialisierungen ADX = ABS ( dx ) : ady = ABS ( dy ) ‚Absolutbeträge distanz SDX = SGN ( dx ) : sdy
 = SGN ( dy ) 'Signum der Distanzen IF adx > ady DANN ' x ist schnell Richtung pdx = sdx: pdy = 0 'pd. ist Parallelschritt ddx = sdx: ddy = sdy 'dd. ist Diagonalschritt deltaslowdirection = ady: deltafastdirection = ADX 'Join in Langsamer RICHTUNG Delta in schneller RICHTUNG ELSE ' y ist schnelle RICHTUNG pdx = 0 : PDY = SDY
 'pd. ist Parallelschritt
DDX = sdx: ddy = SDY ‚dd. ist Diagonalschritt deltaslowdirection = ADX: deltafastdirection = Ady ‚Join in Langsamer RICHTUNG Delta in schneller RICHTUNG END IF x = xstart y = YStart SetPixel x , y fehler = deltafastdirection / 2 REM Pixelschleife: immer ein schritt in schnelle RICHTUNG , hin und
 wieder Auch Einer in Langsame FÜR in = 1 TO deltafastdirection 'Anzahl der zu zeichnenden Pixel REM Aktualisierung Fehlerterm fehler = fehler - deltaslowdirection IF fehler < 0 THEN fehler = fehler + deltafastdirection ' Fehlerterm wieder positiv machen REM schritt in Langsame RICHTUNG x = x + DDX : y = y +
 ddy 'Diagonalschritt ELSE REM schritt in schnelle RICHTUNG x = x + PDX: y = y + PDY ' Parallelschritt END IF SetPixel x , y NÄCHSTE

C-Implementierung

In dieser Implementierung wird von der Signumfunktion autorisiert .

/ * Signum - Funktion * /
int sgn ( int x ) {
 return ( x > 0 ) ? 1 : ( x < 0 ) ? - 1 : 0 ;
}
Void gbham ( int xstart , int YStart , int xend , int YEND )
/ * -------------------------------- ------------------------------
* Bresenham Algorithmus: Linien auf Rastergeräten zeichnen
*
* Eingabeparameter:
* int xstart, YStart = Koordinaten des Eintrittspunkte
* int xend, yend = Koordinaten des Endpoint
*
* Version:
* Leere SetPixel (int x, int y) Setzer ein Pixel in der Grafik
(wird in of this oder aehnlicher Formular vorausgesetzt )
* ------------------------------------------------ ---------------
* /
{
 int x , y , t , dx , dy , INCX , incy , PDX , PDY , DDX , ddy , deltaslowdirection, Deltafastdirection , err ;
/ * Entfernung in beiden Dimensionen berechnet * /
 dx = xend - xstart ;
 dy = yend - ystart ;
/ * Vorschau der Inkremente * /
 incx = sgn ( dx );
 incy = sgn ( dy );
 if ( dx < 0 ) dx = - dx ;
 if ( dy < 0 ) dy = -dy ;
/ * feststellen, welche nicht größer ist * /
 if ( dx > dy )
 {
 / * x ist schnelle Richtung * /
 pdx = incx ; pdy = 0 ; / * pd. ist Parallelschritt * /
 ddx = incx ; ddy = incy ; / * dd. ist Diagonalschritt * /
 Deltaslowdirection = dy ; deltafastdirection = dx ; / * Teilnehmen an Ramer Long, Delta in Schneller Richtung * /
 } sonst
 {
 / * ist sehr
 schnell * / pdx = 0 ; pdy = incy ; / * pd. ist Parallelschritt * /
 ddx = incx ; ddy = incy ; / * dd. ist Diagonalschritt * /
 Deltaslowdirection = dx ; deltafastdirection = dy ; / * Join Längere Richtung, Delta in Schneller Richtung * /
 }
/ * Initialisierungen vor Schleifenbeginn * /
 x = xstart ;
 y = ystart ;
 err = Delta-Fasten /2 ;
 SetPixel ( x , y );
/ * Pixel berechnen * /
 für ( t = 0 , t < deltafastdirection ; ++ t ) / * t zaehlt Pixel sterben, deltafastdirection ist Anzahl der Schritte * /
 {
 / * Aktualisierung Fehlerterm * /
 err - = deltaslowdirection ;
 wenn ( err < 0 )
 {
 / * Fehlerterm wieder positiv (> = 0) machen * /
 err + = deltafastdirection ;
 / * Schritt in Längsrichtung, Diagonalschritt * /
 x + = ddx ;
 y + = ddy ;
 } else
 {
 / * Schritt in Schnelle Richtung, Parallelschritt * /
 x + = pdx ;
 y + = pdy ;
 }
 SetPixel ( x , y );
 }
} / * gbham () * /

Kompakte Variante

Der Bresenham-Algorithmus kann in einer der folgenden Varianten implementiert werden: Variante in C wurde implementiert:

Leere Zeile ( int x0 , int y0 , int x1 , int y1 )
{
 int dx = abs ( x1 - x0 ), sx = x0 < x1 ? 1 : - 1 ;
 int dy = - abs ( y1 - y0 ), sy = y0 < y1 ? 1 : - 1 ;
 int err = dx + dy , e2 ; / * Fehlerwert e_xy * /
 while ( 1 ) {
 setPixel ( x0 , y0 );
 if ( x0 == x1 && y0 == y1 ) brechen ;
 e2 = 2 * err ;
 if ( e2 > dy ) { err + = dy ; x0 + = sx ; } / * e_xy + e_x> 0 * /
 wenn ( e2 < dx ) { err + = dx ; y0 + = nähen ; } / * e_xy + e_y <0 * /
 }
}

Das Fehlerglied Wird dabei Sowohl für sterben lange Sami als Auch sterben schnelle RICHTUNG als Schritterkennung used. Die vier Quadranten wurden in ihrem Vorzeichenincrement (sx, sy) abgedeckt. Die Akkumulation des Fehlerglieds Löst bei Überschreitung des Schwellwertes der Bedingt schritt aus, im Unterschieden zur simultanen Variante Ursprüngliche in Beide RICHTUNG: positive Fehlerwerte für x und negativen y-Achse für sterben. Das Beispiel sitzt dabei elegant auf der XY-Symmetrie des Bresenham-Algorithmus.

Kreisvariante des Algorithmus

Rastern einer Kreislinie in der Nähe von ihnen Bresenham-Verfahren

Der Ansatz für stirbt Kreisvariante Dezember Bresenham-Algorithmus geht auch nicht auf Bresenham selbst zurück, Ahnelt, wo Methode von Horn des Aus Übersichtsartikel , siehe auch Pitt Auffahrt und van Aken unten. Man geht entsprechend von der Kreisgleichung{\ displaystyle x ^ {2} + y ^ {2} = r ^ {2}}aus. Einer wurde bis zum letzten Oktober behandelt. Hier treffen Sie Ihre Kurven, die auf der rechten Seite sind, und Sie werden zurückgelassen, und Sie finden das Geschäft 45 ° befestigt.

Die „schnelle“ Richtung ist hier {\ displaystyle y}-Richtung. Die Kraft des Menschen ist immer positiv{\ displaystyle y}-Richtung, und ab und zu mussmann auch ein Schritt in der „Langfristigkeit“, negativ {\ Displaystyle x}-Richtung machen.

Stehen sterben Quadratberechnungen (siehe Kreisgleichung ) oder womöglich Sogara trigonometrische oder Wurzelberechnungen Vermeiden eines wieder Durch auflösen in Einzelschritte und rekursive Berechnung der Terme aus den Jeweils vorangehenden.

Mathematisch: Von der Kreisgleichung, eine von ihnen ist Gleichung

{\ displaystyle 0 = x ^ {2} + y ^ {2} -r ^ {2}}.

Wobei {\ displaystyle r ^ {2}} gar nicht explizit berechnet werden,

{\ Display x ^ {2} = (x _ {\ mathrm {vorher}} -1) ^ {2} = x _ {\ mathrm {vorher}} ^ {2} -2 \ cdot x _ {\ mathrm {vorher}} +1} (entsprechend für {\ displaystyle y})

wobei auch hier {\ displaystyle x _ {\ mathrm {vorher}} ^ {2}} Cousin als eigene Variable mitgeführt wurde, ohne die Differenz von einem Schritt zum nächsten {\ displaystyle (-2 \ cdot x _ {\ mathrm {vorher}} +1}}sie werden fehlerhaft aufgeschlagen. Wieder wird die Null in der Gleichung durch das Fehlerglied ersetzt.

Zusätzlich muss man beim Setzen des Pixels noch die Mittelpunktkoordinaten dazuaddieren. This Lage Festkommaadditionen Schrank sterben Leistung aber nicht ein bemerkbar , wenn man sich ja Quad Rier Kind oder gar Wurzelziehungen in der inneren Steine Schleife erspart.

Durch den Ansatz von der Kreisgleichung aus ist sichergestellt, that sterben Koordinaten maximal um 1 Pixel, die Digitalisierungsfehler, von der Idealkurve abweichen. Die Initialisierung Dezember Fehlerglieds soll nun bewirken, Dass die erste schreiten in sterben lang Sami RICHTUNG Dann erfolgt, Wenn Die echten Kreiskurve um einen Pixel in Halbe der lange Lapp-Koordinaten nach innerhalb gekommen ist. Details zur Rechnung weiter unten, es läuft Auf eine Initialisierung Dezember Fehlerglieds DM Radius r Hinaus MIT.

Das Sprichwort wird hier wieder nur für den ersten Oktanten gesehen, und die anderen Oktanten durch Vorzeichenwechsel in {\ displaystyle dx} und {\ displaystyle dy} und Rollenvertauschung von {\ Displaystyle x} und {\ displaystyle y}. Die Erweiterung auf den Vollkreis, der für Grafikdisplays zuständig ist, ist in Kommentaren beigefügt.

 REM Bresenham - Algorithmus f ü r EINEN Achtelkreis in Pseudomonas - Grund REM gegeben seien s , xmittel , ymittel REM Initialisierungen f ü r die Ersten Oktanten x = s y = 0 Fehler = r REM "Schnell" RICHTUNG ist hier y! SETPIXEL xmittel + x , ymittel
 + Y REM Pixelschleife: immer ein schreiten in schnellen RICHTUNG , hin und wieder Auch Einer in Langsame WHILE y < x REM schreitet in schnellen RICHTUNG dy = y * 2 + 1 : REM bei Assembler - Implementierung * 2 pro Umschalt y = y + 1 fehler =
 fehler - dy
IF fehler < 0 THEN REM schritt in Langsame RICHTUNG ( hier negativ x - RICHTUNG ) dx = 1 - x * 2 : REM bei Assembler - Implementierung * 2 pro Verschiebung x = x -1 fehler = fehler - dx END IF SetPixel xmittel + x ,
 ymittel + y
REM , ideal für es um EINEN Bildschirm und nicht Mechanisches aufgetragen geht , REM kann man sterben other Oktanten hier gleich mit abdecken: REM SetPixel xmittel - x , ymittel + y REM SetPixel xmittel - x , ymittel - y REM SetPixel xmittel + x , ymittel
 - y
REM SetPixel xmittel + y , ymittel + x REM SetPixel xmittel - y , ymittel + x REM SetPixel xmittel - y , ymittel - x REM SetPixel xmittel + y , ymittel - x Wender

Eine Möglich Implementierung Dezember Bresenham-Algorithmus Für einen Vollkreis in C. Hierbei Wird für quadratisch Terme Eine weitere Variable mitgeführt sterben, sterben sie Begriff {\ displaystyle 2 \ cdot n + 1}von obententspricht, Sie müssen von einem Schritt zum nächsten

 void rasterCircle ( int x0 , int y0 , int radius )
 {
 int f = 1 - Radius ;
 int ddF_x = 0 ;
 int ddF_y = - 2 * Radius ;
 int x = 0 ;
 int y = Radius ;
 setPixel ( x0 , y0 + Radius );
 setPixel ( x0 , y0 - Radius );
 setPixel ( x0 + Radius , y0 );
 setPixel ( x0 - Radius , y0 );
 while ( x < y )
 {
 if ( f > = 0 )
 {
 y - ;
 ddF_y + = 2 ;
 f + = ddF_y ;
 }
 x ++ ;
 ddF_x + = 2 ;
 f + = ddF_x + 1 ;
 setPixel ( x0 + x , y0 + y );
 setPixel ( x0 - x , y0 + y );
 setPixel ( x0 + x , y0 - y );
 setPixel ( x0 - x , y0 - y );
 setPixel ( x0 + y , y0 + x );
 setPixel ( x0 - y , y0 + x );
 setPixel ( x0 + y , y0 - x );
 setPixel ( x0 - y , y0 - x );
 }
 }

Herleitung der Fehlerglied-Initialisierung

Der Schnittpunkt, der etwa Kreislinie um 1/2 Pixel beträgt, ist nach innen gekommen ist, berechnet mann nach der Kreisgleichung:

{\ displaystyle \, x ^ {2} + y ^ {2} = r ^ {2}} oder {\ displaystyle y = {\ sqrt {r ^ {2} -x ^ {2}}}}

Bin gebrochener Punkt (x 1 , y 1 ) soll gelten:{\ displaystyle \, x_ {1} = r-1/2}, also ergibt sich:

{\displaystyle y_{1}={\sqrt {r^{2}-(r-1/2)^{2}}}={\sqrt {r^{2}-(r^{2}-r+1/4)}}={\sqrt {r-1/4}}}

Da bis hierhin noch kein x-Schritt stattgefunden haben soll, ist das Fehlerglied mit

{\displaystyle \sum _{y=0}^{y_{1}}(2*y+1)=y_{1}^{2}}

zu initialisieren, wobei y1² durch Runden zu r wird.

Beispiel: im Bild oben: r=11, y1=3 (abgerundet), Fehlerglied bei y=y1=3 ist 1+3+5=9, Fehlerglied bei y=4 ist 1+3+5+7=16. Wurde das Fehlerglied mit r=11 initialisiert, so findet der erste Vorzeichenwechsel und damit der erste x-Schritt tatsächlich beim Übergang von y1 zu y1+1 statt.

Zeichnen nicht-vollständiger Oktanten

Die obigen Implementierungen zeichnen immer nur komplette Oktanten bzw. Kreise. Wenn man nur einen bestimmten Kreisbogen von einem Winkel {\displaystyle \alpha } bis zu einem Winkel {\displaystyle \beta } zeichnen will, muss man das so implementieren, dass man sich die {\displaystyle x}- und {\displaystyle y}-Koordinaten dieser Endpunkte im Vorhinein berechnet, wobei man unvermeidlich auf Trigonometrie oder Wurzelrechnung zurückgreifen muss (s. a. Heron-Verfahren). Dann lässt man den Bresenham-Algorithmus über den kompletten Oktanten bzw. Kreis laufen und setzt die Pixel aber nur dann, wenn sie in den gewünschten Bereich fallen. Nach Beendigung dieses Kurvenstücks kann man den Algorithmus vorzeitig abbrechen.

Ellipsen

Auch für Ellipsen gibt es wieder mehrere mögliche Ansätze. Man kann bei achsenparallelen Ellipsen von der entsprechenden Gleichung

{\displaystyle {\frac {x^{2}}{a^{2}}}+{\frac {y^{2}}{b^{2}}}=1}

wobei {\displaystyle a} und {\displaystyle b} die beiden Halbachsenlängen angeben, ausgehen und dann ähnlich wie oben beim Kreis vorgehen.

Man kann aber auch durch Skalierung der gezeichneten {\displaystyle x}- und {\displaystyle y}-Werte (und ggf. horizontaler bzw. vertikaler Linienerweiterungen) auf Basis des Kreisalgorithmus solche achsenparallele Ellipsen erzeugen. Dabei benutzt man den Kreisalgorithmus mit der kleineren Ellipsenachse als Radius und addiert in der anderen Richtung einen Wert hinzu, den man wiederum per Bresenham-Linienalgorithmus ansteigend vom Pol zum Äquator ermitteln kann. Da die Ellipse in die längere Achsenrichtung gestreckt werden muss, setzt man dann nicht nur einzelne Pixel, sondern muss ggf. eine Linie (allerdings eine einfache, horizontale oder vertikale) vom vorherigen Punkt zum nächsten ziehen.

Eine allgemeine Ellipse Kann man Aus einer so achsenparallelen Gewinn, sterben INDEMAR Mann komplette Grafik addition Wacholder Scherung unterwirft. Wieder Benutzte man EINE addition Bresenham-Linienalgorithmus, um den Versatz in den Achsenrichtungen Eines ansteigend zu ermitteln und bei IHN- Jedem zu zeichnenden Koordinaten einzubeziehen.

Kompakte Variante

Wer Algorithmus für die Linie kennt, kann xy-symmetrisch als die Kreisvariante formuliert werden. Damit kann auch ein kontinuierlicher Viertelkreis gezeichnet werden, war Ellipse hilfreich.

Leere Ellipse ( int xm , int ym , int a , int b )
{
 int dx = 0 , dy = b ; / * im I. Quadranten von links oben nach rechts unten * /
 lang a2 = a * a , b2 = b * b ;
 langes err = b2 - ( 2 * b - 1 ) * a2 , e2; / * Fehler im 1. Schritt * /
 do {
 setPixel ( xm + dx , ym + dy ); / * I. Quadrant * /
 setPixel ( xm - dx , ym + dy ); / * II. Quadrant * /
 setPixel ( xm - dx , ym - dy ); / * III. Quadrant * /
 setPixel ( xm + dx , ym - dy ); / * IV. Quadrant * /
 e2 = 2* err ;
 if ( e2 < ( 2 * dx + 1 ) * b2 ) { dx ++ ; err + = ( 2 * dx + 1 ) * b2 ; }
 if ( e2 > - ( 2 * dy - 1 ) * a2 ) { dy - ; err - = ( 2 * dy- 1 ) * a2 ; }
 } while ( dy > = 0 );
 while ( dx ++ < a ) { / * Fehlerhafter Abbruch bei flachem Ellipsen (b = 1) * /
 setPixel ( xm + dx , ym ); / * -> Spitze der Ellipse voll * /
 setPixel ( xm - dx , ym );
 }
}

Es hat ihn immer wieder getestet und Diagonalschritt und Corrigiert diesen bei zu großem Abstand. Die Schritte werden aber immer im nächsten Quadranten und dann wird bei flachen Ellipsen (b = 1) zu früh abgebrochen. In diesen Fällen gibt es auch einiges. Die Fehlervariable muss 3-fach im Wertebereich (Stellenanzahl, Bits) vom Radius (Halbachsen) aufweisen (etwa 64-Bit oder Gleitkommazahl).

Diese Methode kann für Kreise verwöhnt werden (a = b = r). Die Vereinfachung (wird durch die Fehlervariable durch 2r 2 gekürzt wird) führt dann zu den oben gesehenen Kreisbeispielen. Aus vier nahtlosen Viertelkreisen wird so ein fortlaufender Vollkreis, wie es etwa bei Plottern erforderlich ist.

Weitere Verallgemeinerungen

BEREITS im Jahr 1968 Wird Idee publiziert sterben, den Bresenham-Algorithmus für Digitalisierung von Durch kubische Gleichungen beschriebene Kurve zu verallgemeinern sterben. [5] Wirklich ausgeführt gerechnet werden Würfel Details der erst 1993 u. A. Von Pitt Driveway [6] und unabhängig Davon in der US – Patent 5717847. [7] Eine anwendung zur Strukturierung im Submikron-Bereich von Durch rationale kubische Bezier berandeten Geometrie chen Figur fanä das Elle Verfahren in dem Lithographiewerkzeug LION-LV1. [8]

Weblinks

 Commons: Bresenham-Algorithmus – Sammlung von Bildern, Videos und Audiodateien
  • Bresenhams Algorithmus (NIST-Lexikon der Algorithmen und Datenstrukturen) – Hintergründe zum Bresenham-Algorithmus, mit Original Quellcode (Englisch)
  • Rasterung von Linien, Kreisen, Ellipsen (Uni Magdeburg, Institut für Simulation und Grafik) – Java Applet Zum Nachvollziehen des Bresenham
  • Die Schönheit von Bresenhams Algorithmus – Eine einfache Implementierung zum Zeichnen von Linien, Kreisen, Ellipsen und Bézierkurven (englisch)

Einzelnachweise

  1. Hochspringen↑ JE Bresenham: Algorithmus für die Computersteuerung eines digitalen Plotter. In: IBM System Journal , 4, 1, 1965, S. 25-30, ISSN  0018-8670 , cse.iitb.ac.in (PDF; 223 KB; englisch) bereit 1963 als Vortrag auf der ACM National Conference in Denver präsentieren .
    Die erste VERÖFFENTLICHUNGwo Grundidee für sterben Kreisgenerierung findet sich in: HB Keller, JR Swenson: Experimente auf dem Gitter Problem der Gauss . (PDF; 788 KB) In: Mathe. Comp. 17, 1963, S. 223-230, Abschnitt 3.
  2. Hochspringen↑ MLV Pitteway: Algorithmus zum Zeichnen von Ellipsen oder Hyperbolae mit einem digitalen Plotter . In: Computer J. , 10 (3) November 1967, S. 282-289 (Englisch)
  3. Hochspringen↑ JRVan Aachen: Ein effizienter Ellipsen-Zeichnungsalgorithmus . In: CG & A , 4 (9), September 1984, S. 24-35 (Englisch)
  4. Hochspringen↑ FG Stockton: XY Verschiebezeichnung . In: Mitteilungen der ACM , Vol. 4, nein. 6, April 1963, S. 161 (Englisch)
  5. Hochspringen↑ RJ Botting, MLV Pitteway: Kubische Erweiterung eines Kegelschnitt-Algorithmus. In: Computer Journal , 11, 1968, S. 120
  6. Hochspringen↑ Fiaz Hussain, Michael Pitteway: Rasterung der Konturen von Schriften. (PDF; 165 KB) In: Electronic Publishing , Band 6, 1993, Nr. 3, S. 171-181
  7. Hochspringen↑ Verfahren zur Erzeugung flacher technischer Kurven oder Konturen , eingereicht am Dez. 23. 1993
  8. Hochspringen↑ R. Plontke: LION-LV1: Ein Lithographie-System für integrierte Optik und Nanostrukturen. In: Jenaer Jahrbuch zur Technik- und Industriegeschichte , Bd. 9, 2006, S. 535-566

Schreibe einen Kommentar