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); } }
  }
}

RETOUR