Trois afficheurs :
Classe principale de l'application de remplissage d'un triangle 2D : TraceTriangle2D.java
/**
* La classe <code>TraceTriangle2D</code> implante un programme d'affichage
* de triangles rasterises pour l'affichage.
*
* @author Nicolas Janey
* @author nicolas.janey@univ-fcomte.fr
* @version 1.0, 16/11/08
*/
public class TraceTriangle2D {
public static void main(String [] args) {
ApplicationFrame f;
f = new ApplicationFrame("Tracé de triangle par algorithme de Bresenham");
f.add("Bords triangle 2D en 8 connexité",
(Afficheur) new AfficheurBords());
f.add("Remplissage triangle 2D",
(Afficheur) new AfficheurTriangle());
f.add("Remplissage triangle 2D avec bords marqués",
(Afficheur) new AfficheurTriangle2());
f.setSize(480,420);
f.setLocation(50,250);
f.setVisible(true);
}
}
Afficheur qui utilise l'algorithme générique de Bresenham pour dessiner les bords de la facette en tant que segments de droite : AfficheurBords.java
import java.awt.*;
/**
* La classe <code>AfficheurBords</code> implante l'interface {@link Afficheur Afficheur}
* pour developper une methode d'affichage d'un triangle 2D par affichage en 8-connexite
* des pixels de ses bords au moyen de l'algorithme de Bresenham.
*
* @author Nicolas Janey
* @author nicolas.janey@univ-fcomte.fr
* @version 1.0, 12/11/08
*/
public class AfficheurBords implements Afficheur {
private int tx;
private int ty;
private int zoom = 20;
private Graphics g;
/**
* Methode d'affichage executee en boucle infinie pour realiser l'affichage
* d'un objet en projection parallele orthographique.
*
* @param g l'objet <code>Graphics</code> d'affichage.
* @param numeroImage le nombre de fois ou cette methode a deja ete appelee.
* @param tx la largeur (en pixels) de la zone de dessin.
* @param ty la hauteur (en pixels) de la zone de dessin.
*/
public void paint(Graphics g,int numeroImage,int tx,int ty) {
g.drawString("Remplissage triangle",10,20);
this.tx = tx;
this.ty = ty;
this.g = g;
int x1 = 2;
int y1 = 2;
int x2 = 21;
int y2 = 13;
int x3 = 5;
int y3 = 17;
ligne(x1,y1,x2,y2);
ligne(x2,y2,x3,y3);
ligne(x3,y3,x1,y1);
g.setColor(Color.yellow);
drawLine(x1,y1,x2,y2);
drawLine(x2,y2,x3,y3);
drawLine(x3,y3,x1,y1);
}
private void drawLine(int xi,int yi,int xf,int yf) {
g.drawLine((int) ((xi+0.5)*zoom),(int) (ty-(yi-0.5)*zoom),
(int) ((xf+0.5)*zoom),(int) (ty-(yf-0.5)*zoom));
}
private void tracePixel(int x,int y,Color c) {
// System.out.format("%3d %3d\n",x,y);
g.setColor(c);
g.fillRect(x*zoom,ty-y*zoom,zoom,zoom);
g.setColor(Color.black);
g.drawRect(x*zoom,ty-y*zoom,zoom,zoom);
}
private void ligne(int xi,int yi,int xf,int yf) {
int dx,dy,i,xinc,yinc,cumul,x,y ;
x = xi ;
y = yi ;
dx = xf - xi ;
dy = yf - yi ;
xinc = ( dx > 0 ) ? 1 : -1 ;
yinc = ( dy > 0 ) ? 1 : -1 ;
dx = Math.abs(dx) ;
dy = Math.abs(dy) ;
tracePixel(x,y,Color.red);
if ( dx > dy ) {
cumul = dx / 2 ;
for ( i = 1 ; i <= dx ; i++ ) {
x += xinc ;
cumul += dy ;
if (cumul >= dx) {
cumul -= dx ;
y += yinc ; }
tracePixel(x,y,Color.red); } }
else {
cumul = dy / 2 ;
for ( i = 1 ; i <= dy ; i++ ) {
y += yinc ;
cumul += dx ;
if ( cumul >= dy ) {
cumul -= dy ;
x += xinc ; }
tracePixel(x,y,Color.red); } }
}
}
Afficheur de remplissage d'une facette triangulaire 2D : AfficheurTriangle.java
Les bords à gauche (tableau minx[y]) et à droite (tableau maxx[y]) sont calculés au moyen de l'algorithme de Bresenham. Puis ces tableaux sont utilisés pour tracer les trames horizontales de pixels de remplissage.
import java.awt.*;
/**
* La classe <code>AfficheurTriangle</code> implante l'interface {@link Afficheur Afficheur}
* pour developper une methode d'affichage d'un triangle 2D par remplissage
* au moyen de variantes de l'algorithme de Bresenham.
*
* @author Nicolas Janey
* @author nicolas.janey@univ-fcomte.fr
* @version 1.0, 12/11/08
*/
public class AfficheurTriangle implements Afficheur {
private int tx;
private int ty;
private int zoom = 20;
private Graphics g;
/**
* Methode d'affichage executee en boucle infinie pour realiser l'affichage
* d'un objet en projection parallele orthographique.
*
* @param g l'objet <code>Graphics</code> d'affichage.
* @param numeroImage le nombre de fois ou cette methode a deja ete appelee.
* @param tx la largeur (en pixels) de la zone de dessin.
* @param ty la hauteur (en pixels) de la zone de dessin.
*/
public void paint(Graphics g,int numeroImage,int tx,int ty) {
g.drawString("Remplissage triangle",10,20);
this.tx = tx;
this.ty = ty;
this.g = g;
int x1 = 2;
int y1 = 2;
int x2 = 21;
int y2 = 13;
int x3 = 5;
int y3 = 17;
int xmin = Math.min(x1,Math.min(x2,x3));
int xmax = Math.max(x1,Math.max(x2,x3));
int ymin = Math.min(y1,Math.min(y2,y3));
int ymax = Math.max(y1,Math.max(y2,y3));
int minx[] = new int[ymax-ymin+1];
int maxx[] = new int[ymax-ymin+1];
for ( int i = 0 ; i < minx.length ; i++ ) {
minx[i] = xmax;
maxx[i] = xmin; }
ligne(x1,y1,x2,y2,minx,maxx,ymin);
ligne(x2,y2,x3,y3,minx,maxx,ymin);
ligne(x3,y3,x1,y1,minx,maxx,ymin);
for ( int y = ymin ; y <= ymax ; y++ )
for ( int x = minx[y-ymin] ; x <= maxx[y-ymin] ; x++ )
tracePixel(x,y,Color.red);
g.setColor(Color.yellow);
drawLine(x1,y1,x2,y2);
drawLine(x2,y2,x3,y3);
drawLine(x3,y3,x1,y1);
}
private void drawLine(int xi,int yi,int xf,int yf) {
g.drawLine((int) ((xi+0.5)*zoom),(int) (ty-(yi-0.5)*zoom),
(int) ((xf+0.5)*zoom),(int) (ty-(yf-0.5)*zoom));
}
private void tracePixel(int x,int y,Color c) {
// System.out.format("%3d %3d\n",x,y);
g.setColor(c);
g.fillRect(x*zoom,ty-y*zoom,zoom,zoom);
g.setColor(Color.black);
g.drawRect(x*zoom,ty-y*zoom,zoom,zoom);
}
private void tracePixel(int x,int y,int [] minx,int [] maxx,int ymin) {
if ( x < minx[y-ymin] )
minx[y-ymin] = x;
if ( x > maxx[y-ymin] )
maxx[y-ymin] = x;
}
private void ligne(int xi,int yi,int xf,int yf,int [] minx,int [] maxx,int ymin) {
int dx,dy,i,xinc,yinc,cumul,x,y ;
x = xi ;
y = yi ;
dx = xf - xi ;
dy = yf - yi ;
xinc = ( dx > 0 ) ? 1 : -1 ;
yinc = ( dy > 0 ) ? 1 : -1 ;
dx = Math.abs(dx) ;
dy = Math.abs(dy) ;
tracePixel(x,y,minx,maxx,ymin);
if ( dx > dy ) {
cumul = dx / 2 ;
for ( i = 1 ; i <= dx ; i++ ) {
x += xinc ;
cumul += dy ;
if (cumul >= dx) {
cumul -= dx ;
y += yinc ; }
tracePixel(x,y,minx,maxx,ymin); } }
else {
cumul = dy / 2 ;
for ( i = 1 ; i <= dy ; i++ ) {
y += yinc ;
cumul += dx ;
if ( cumul >= dy ) {
cumul -= dy ;
x += xinc ; }
tracePixel(x,y,minx,maxx,ymin); } }
}
private void ligne(int xi,int yi,int xf,int yf) {
int dx,dy,i,xinc,yinc,cumul,x,y ;
x = xi ;
y = yi ;
dx = xf - xi ;
dy = yf - yi ;
xinc = ( dx > 0 ) ? 1 : -1 ;
yinc = ( dy > 0 ) ? 1 : -1 ;
dx = Math.abs(dx) ;
dy = Math.abs(dy) ;
tracePixel(x,y,Color.green);
if ( dx > dy ) {
cumul = dx / 2 ;
for ( i = 1 ; i <= dx ; i++ ) {
x += xinc ;
cumul += dy ;
if (cumul >= dx) {
cumul -= dx ;
y += yinc ; }
tracePixel(x,y,Color.green); } }
else {
cumul = dy / 2 ;
for ( i = 1 ; i <= dy ; i++ ) {
y += yinc ;
cumul += dx ;
if ( cumul >= dy ) {
cumul -= dy ;
x += xinc ; }
tracePixel(x,y,Color.green); } }
}
}
Afficheur de remplissage d'une facette triangulaire 2D puis dessin de ses bords en tant que segments de droite : AfficheurTriangle2.java
import java.awt.*;
/**
* La classe <code>AfficheurTriangle</code> implante l'interface {@link Afficheur Afficheur}
* pour developper une methode d'affichage d'un triangle 2D par remplissage
* au moyen de variantes de l'algorithme de Bresenham.
*
* @author Nicolas Janey
* @author nicolas.janey@univ-fcomte.fr
* @version 1.0, 12/11/08
*/
public class AfficheurTriangle2 implements Afficheur {
private int tx;
private int ty;
private int zoom = 20;
private Graphics g;
/**
* Methode d'affichage executee en boucle infinie pour realiser l'affichage
* d'un objet en projection parallele orthographique.
*
* @param g l'objet <code>Graphics</code> d'affichage.
* @param numeroImage le nombre de fois ou cette methode a deja ete appelee.
* @param tx la largeur (en pixels) de la zone de dessin.
* @param ty la hauteur (en pixels) de la zone de dessin.
*/
public void paint(Graphics g,int numeroImage,int tx,int ty) {
g.drawString("Remplissage triangle avec bords marqués",10,20);
this.tx = tx;
this.ty = ty;
this.g = g;
int x1 = 2;
int y1 = 2;
int x2 = 21;
int y2 = 13;
int x3 = 5;
int y3 = 17;
int xmin = Math.min(x1,Math.min(x2,x3));
int xmax = Math.max(x1,Math.max(x2,x3));
int ymin = Math.min(y1,Math.min(y2,y3));
int ymax = Math.max(y1,Math.max(y2,y3));
int minx[] = new int[ymax-ymin+1];
int maxx[] = new int[ymax-ymin+1];
for ( int i = 0 ; i < minx.length ; i++ ) {
minx[i] = xmax;
maxx[i] = xmin; }
ligne(x1,y1,x2,y2,minx,maxx,ymin);
ligne(x2,y2,x3,y3,minx,maxx,ymin);
ligne(x3,y3,x1,y1,minx,maxx,ymin);
for ( int y = ymin ; y <= ymax ; y++ )
for ( int x = minx[y-ymin] ; x <= maxx[y-ymin] ; x++ )
tracePixel(x,y,Color.red);
ligne(x1,y1,x2,y2);
ligne(x2,y2,x3,y3);
ligne(x3,y3,x1,y1);
g.setColor(Color.yellow);
drawLine(x1,y1,x2,y2);
drawLine(x2,y2,x3,y3);
drawLine(x3,y3,x1,y1);
}
private void drawLine(int xi,int yi,int xf,int yf) {
g.drawLine((int) ((xi+0.5)*zoom),(int) (ty-(yi-0.5)*zoom),
(int) ((xf+0.5)*zoom),(int) (ty-(yf-0.5)*zoom));
}
private void tracePixel(int x,int y,Color c) {
// System.out.format("%3d %3d\n",x,y);
g.setColor(c);
g.fillRect(x*zoom,ty-y*zoom,zoom,zoom);
g.setColor(Color.black);
g.drawRect(x*zoom,ty-y*zoom,zoom,zoom);
}
private void tracePixel(int x,int y,int [] minx,int [] maxx,int ymin) {
if ( x < minx[y-ymin] )
minx[y-ymin] = x;
if ( x > maxx[y-ymin] )
maxx[y-ymin] = x;
}
private void ligne(int xi,int yi,int xf,int yf,int [] minx,int [] maxx,int ymin) {
int dx,dy,i,xinc,yinc,cumul,x,y ;
x = xi ;
y = yi ;
dx = xf - xi ;
dy = yf - yi ;
xinc = ( dx > 0 ) ? 1 : -1 ;
yinc = ( dy > 0 ) ? 1 : -1 ;
dx = Math.abs(dx) ;
dy = Math.abs(dy) ;
tracePixel(x,y,minx,maxx,ymin);
if ( dx > dy ) {
cumul = dx / 2 ;
for ( i = 1 ; i <= dx ; i++ ) {
x += xinc ;
cumul += dy ;
if (cumul >= dx) {
cumul -= dx ;
y += yinc ; }
tracePixel(x,y,minx,maxx,ymin); } }
else {
cumul = dy / 2 ;
for ( i = 1 ; i <= dy ; i++ ) {
y += yinc ;
cumul += dx ;
if ( cumul >= dy ) {
cumul -= dy ;
x += xinc ; }
tracePixel(x,y,minx,maxx,ymin); } }
}
private void ligne(int xi,int yi,int xf,int yf) {
int dx,dy,i,xinc,yinc,cumul,x,y ;
x = xi ;
y = yi ;
dx = xf - xi ;
dy = yf - yi ;
xinc = ( dx > 0 ) ? 1 : -1 ;
yinc = ( dy > 0 ) ? 1 : -1 ;
dx = Math.abs(dx) ;
dy = Math.abs(dy) ;
tracePixel(x,y,Color.green);
if ( dx > dy ) {
cumul = dx / 2 ;
for ( i = 1 ; i <= dx ; i++ ) {
x += xinc ;
cumul += dy ;
if (cumul >= dx) {
cumul -= dx ;
y += yinc ; }
tracePixel(x,y,Color.green); } }
else {
cumul = dy / 2 ;
for ( i = 1 ; i <= dy ; i++ ) {
y += yinc ;
cumul += dx ;
if ( cumul >= dy ) {
cumul -= dy ;
x += xinc ; }
tracePixel(x,y,Color.green); } }
}
}