(Traduction et remaniement de http://www.cs.helsinki.fi/group/goa/mallinnus/lines/bresenh.html)
[Introduction|Bresenham pour l'octant 1|Amélioration de l'algorithme|Les autres octants] |
Le but de l'algorithme de Bresenham est de tracer un segment de droite en utilisant uniquement les points d'une grille discrète comme dans la figure ci-dessous: Pour ce faire 8 cas sont distingués, suivant la pente de la droite et le sens dans lequel le segment est dessiné. Ces 8 cas divise le plan euclidien en 8 zone appelées octants:
Considérez le tracer d'une droite de pente m avec
0<=m<=1 sur une grille entre les points (x1,y1)
et (x2,y2) tels que x1<x2, c'est à dire le cas de
l'octant 1.
Si on considère qu'à chaque
pas de l'algorithme de traçage on incrémente x,
après avoir tracé un point en (x,y),
l'algorithme doit déterminer quel sera le prochain point
affiché et il y a pour cela 2 possibilités: il peut
tracer le point (x+1,y), ou le point (x+1,y+1).
Ainsi, travaillant dans le premier octant du plan,
tracer une droite devient un problème de décision avec
deux possibilités à chaque étape.
Nous pouvons tracer un diagramme de la situation après que
l'algorithme ait affiché le point (x,y) :
Après avoir dessiné le point (x,y),
l'algorithme doit faire un compromis entre ce que l'on veut dessiner
et ce que la résolution de la grille permet réellement
de dessiner. Habituellement le point (x,y) est
déjà une erreur, le point réel sur la droite
n'étant pas accessible sur la grille. Ainsi nous associons une
erreur d'ordonnée ε à pour chaque abscisse
x car l'ordonnée réelle devrait être y+ε. Cette
erreur se trouvera dans l'intervalle [-0.5,+0.5[.
En passant de x à x+1, on augmente la
valeur de l'ordonnée (mathématique) d'une
quantité égale à la pente de la droite:
m. Nous choisirons donc de tracer (x+1,y)
si la différence entre cette nouvelle ordonnée et
y est inférieure à 0,5, c'est à
dire si:
Autrement nous tracerons (x+1,y+1). En faisant ainsi nous
réduisons au minimum l'erreur globale entre le segment de
droite mathématique et le tracé de ce segment.
L'erreur résultant de ce nouveau point peut maintenant être
considéré comme le nouvel ε, ceci nous permettra de
répéter pour le prochain point sur la droite, celui pour
lequel l'abscisse est x+2.
La nouvelle valeur de l'erreur peut adopter une de deux valeurs
possibles, selon le choix du point tracé. Si (x+1,y)
est choisi, la nouvelle valeur de l'erreur est donnée par:
Autrement elle est:
On obtient ainsi l'algorithme suivant:
Cet algorithme utilise des variables à virgule flottante. Pour éviter cela (les tests en nombre entiers étant plus efficaces), en posant
Δx = x2-x1sachant que m=Δy/Δx, on manipule quelque peu l'expression du test en multipliant par 2 et par Δx pour obtenir:
Δy = y2-y1
2ε&Deltax+2Δy < Δx |
Toutes les quantités de cette inégalité sont maintenant entières.
En posant ε'=εΔx, le test devient:
2(ε'+Δy) < Δx |
Les règles de mise à jour pour l'erreur sur chaque étape peuvent également être adaptées à ε':
|
|
Voici une implémentation en C++ de l'algorithme de Bresenham pour des segments de droite dans le premier octant:
void octant1(Screen &s, unsigned x1, unsigned y1, unsigned x2, unsigned y2, unsigned char colour ) { int dx = x2 - x1, dy = y2 - y1, y = y1, eps = 0; for ( int x = x1; x <= x2; x++ ) { s.Plot(x,y,colour); eps += dy; if ( (eps << 1) >= dx ) { y++; eps -= dx; } } }Cette fonction n'utilise que des nombres entiers positifs, utilise le décalage à gauche pour la multiplication et élimine des opérations superflues par l'utilisation rusée du
eps
variable.
Cette implémentation est inachevée, elle ne vérifie pas que les paramètres correspondent bien au tracage d'un segment de droite dans le premier octant