Table des matières

Feu de forêt

Solution pour le TD Feu de forêt.

Utilisation de pixels

Dans ce TD, on a besoin d'exploiter une grille représentant la forêt. On pourrait créer une grille sous forme d'un tableau que l'on recopierait ensuite sur le graphique. Processing donne la possibilité d'agir directement sur le graphique par l'intermédiaire de pixels.

On commence par loadPixels(); qui initialise une variable système pixels. C'est un tableau à une dimension correspondant à la lecture des pixels de gauche à droite et de haut en bas. On atteint le pixel en ligne line et colonne col par pixels[line*width + col]. On met à jour l'affichage par upadatePixels();

pixels contient des items de type color. On peut par exemple créer la couleur color(0,250,0) pour les arbres.

Le code

/* définition des couleurs */
color tree = color(0,250,0);
color nothing = color(150,150,150);
color burnt = color(0,0,0);
color burning = color(245, 170, 66);

/* réglage des probabilités */
final float p_arbre = 1; // proba d'une init en arbre
final float p_propagation = .55; // proba de transmission du feu

void setup(){
  size(800,600);

  // initialisation de la forêt
  loadPixels();
  // d'abord création aléatoire des arbres ou vide
  for (int i=0; i<height*width; i++) {
    if (random(1) <= p_arbre) {
      pixels[i] = tree;
    } else {
      pixels[i] = nothing;
    }
  }
  // on allume un petit carré en haut à gauche
  for (int line=7; line<=11; line++){
    for (int col=7; col<=11; col++){
      pixels[line*width + col] = burning;
    }
  }
  updatePixels();
}

boolean canburn(int line, int col){
  /* on fournit une ligne et une colonne
     en utilisant la variable globale pixels
     renvoie true si la case désignée contient un arbre
     renvoie false si pas un arbre ou pas dans le cadre
  */
  if ((line < 0) || (line >= height)){
    return false;
  }
  if ((col<0) || (col>= width)) {
    return false;
  }
  return pixels[line*width + col] == tree;
}

void propagation(int line, int col, boolean[] prop){
  /* considérant une case en line et col qui est en feu,
     détermine les voisins qui s'enflamment,
     met à jour le tableau prop qui contiendra à la fin true
     pour toutes les cases à allumer
  */
  color current = pixels[line*width + col];
  if (current != burning) {
    return;
  }
  // on envisage la propagation au voisins
  if (canburn(line-1, col) && (random(1) < p_propagation)){
     prop[(line-1)*width + col] = true;
  }
  if (canburn(line+1, col) && (random(1) < p_propagation)){
     prop[(line+1)*width + col] = true;
  }
  if (canburn(line, col-1) && (random(1) < p_propagation)){
     prop[line*width + col-1] = true;
  }
  if (canburn(line, col+1) && (random(1) < p_propagation)){
     prop[line*width + col+1] = true;
  }
}

void draw(){
  loadPixels();
  // prop sert à noter les cases qu'il faudra allumer
  boolean[] prop = new boolean[height*width];
  for (int i=0; i<height*width; i++){
    prop[i] = false;
  }
  for (int line=0; line<height; line++){
    for (int col=0; col<width; col++){
      propagation(line, col, prop);
    }
  }
  /* mise à jour : allumage des cases qui s'enflamment
     et extinction des cases qui étaient déjà en feu */
  for (int line=0; line<height; line++){
    for (int col=0; col<width; col++){
      if (pixels[line*width + col] == burning){
        pixels[line*width + col] = burnt;
      } else if (prop[line*width + col]) {
        pixels[line*width + col] = burning;
      }
    }
  }
  updatePixels();
}