Constantes pour les remplissages

Ces constantes sont les valeurs conseillées pour le choix du mode de remplissage.

Voici deux dessins pour lesquels je veux faire un remplissage:

Dans le dessin de gauche, une coccinelle, je veux changer la couleur rouge par du vert. Dans le dessin de droite, je veux remplir avec du blanc l'intérieur de l'étoile blanche.

Pour la coccinelle, il faut remplir en pointant là ou il y a du rouge et changer tous les points rouges en points verts. L'algorithme utilisé est "changer dans la nouvelle couleur de proche en proche tous les points qui ont la couleur pointée au départ". On s'arrêtera donc sur le noir (tête, points) et sur le blanc (cadre). Ce mode de remplissage ne fonctionne pas avec l'étoile, car en pointant au milieu, on ne changerait que les points oranges et pas les bleus, les violets... J'ai appelé ce mode de remplissage le mode COCCINELLE.

Pour l'étoile, il faut utiliser l'algorithme "changer dans la nouvelle couleur de proche en proche tous les points qui ne sont pas de la nouvelle couleur". Si on remplit avec du blanc, on ne s'arrêtera que si la couleur est blanche. Ainsi, on ira bien remplir toute l'étoile jusqu'à son bord qui est blanc. Ce mode de remplissage ne fonctionne pas avec la coccinelle, en remplissant ainsi avec du vert, jusqu'au bord vert (qui n'existe pas), on remplirait tout l'écran. J'ai appelé ce mode de remplissage le mode STAR (étoile en anglais).

 

Exemples d'utilisation

setFillMode(COCCINELLE); // Remplira en mode Coccinelle.
fillMode=COCCINELLE; // Identique à la ligne du dessus.
setFillMode(STAR); // Remplira en mode Star.

 

Référence

#define COCCINELLE true
#define STAR false

 

Voir aussi

- fill(); Remplit avec la couleur demandée
- setFillMode(); Choisit le type de remplissage
- getFillMode(); Retourne le type de remplissage
- fillMode Contient le type de remplissage
- setLimites(); Limite la zone de dessin
- setDrawInverse(); Choix du mode dessin ou inversion
- RGBcolor(); Transforme un triplet RGB en un code couleur
- BLACK, WHITE, ... Constantes couleurs
- rect(); Trace les bords d'un cadre
- fillRect(); Trace une boîte pleine
- circle(); Trace un cercle

 

Notes

Le remplissage se limite à la partie qui tient dans l'écran et qui tient dans les limites données par la fonction setLimites()

 

Exemples

PecheuxGraph_ILI9341_8bits.zip\PecheuxGraph_ILI9341_8bits\examples\Documentation\Exemple-202-fillCoccinelle\Exemple-202-fillCoccinelle.ino (dans votre fichier téléchargé):

// Ce programme montre le remplissage par une couleur avec arrêt sur une
// couleur différente couleur du point de départ
// Ici, on dessine une coccinelle et la boucle lui change la couleur de son dos.
// Si on remplit en blanc (ce qui est possible un jour) il n'y a plus de dos et les remplissages
// suivants rempliront aussi l'espace autour de la bête. 

#include <PecheuxGraph_ILI9341_8bits.h>

void setup() 
{
  setGraphMode(PAYSAGE);
  fill(0,0,WHITE); // = clrscr(WHITE); mais lent de chez lent. Ici c'est pour l'exemeple!

  // Dessin d'une coccinelle
  arc(DEMI_LARGEUR-20, DEMI_HAUTEUR, 80, DEPART_SUD+ARRIVEE_NORD, RED); // Corps
       hLine(DEMI_LARGEUR-20, DEMI_LARGEUR+20, DEMI_HAUTEUR-80, RED);
       hLine(DEMI_LARGEUR-20, DEMI_LARGEUR+20, DEMI_HAUTEUR+80, RED);
       vLine(DEMI_LARGEUR+20, DEMI_HAUTEUR-80, DEMI_HAUTEUR+80, RED); 
       fill(DEMI_LARGEUR, DEMI_HAUTEUR, RED); // Ici le mode de remplissage importe peu
  arc(DEMI_LARGEUR+20, DEMI_HAUTEUR, 80, DEPART_NORD+ARRIVEE_SUD, BLACK); // Tête
       vLine(DEMI_LARGEUR+20, DEMI_HAUTEUR-80, DEMI_HAUTEUR+80, BLACK);
       fill(DEMI_LARGEUR+30, DEMI_HAUTEUR, BLACK); // Ici le mode de remplissage importe peu
  for (int nb=6; nb>0; nb--)                           // six points noirs
  {      
    int x=DEMI_LARGEUR-60+random(65),
        y=DEMI_HAUTEUR-70+20*nb; // int fonctionne toujours car l'instruction précédente finit par  ","
    circle(x, y, 10, BLACK);  fill(x, y, BLACK); // Ici le mode de remplissage importe peu
  }
}

void loop()
{
  setFillMode(COCCINELLE); // L'autre mode ne fonctionnerait pas
  fill(DEMI_LARGEUR-99, DEMI_HAUTEUR, RANDOM_COLOR | GREY); // Remplissage du corps (perdu si on a du noir ou du blanc!)
  delay(1000);
}

Résultat:

 

PecheuxGraph_ILI9341_8bits.zip\PecheuxGraph_ILI9341_8bits\examples\Documentation\Exemple-203-fillStar\Exemple-203-fillStar.ino (dans votre fichier téléchargé):

// Ce programme montre le remplissage par une couleur avec arrêt sur une
// frontière de la couleur de remplissage. On trace une étoile et on la remplit. Il
// faut mémoriser la position de l'étoile (sinon on remplirait le ciel) ainsi que
// sa couleur pour s'arrêter sur le bord de l'étoile.

#include <PecheuxGraph_ILI9341_8bits.h>

void star(int x, int y, int couleur) // Dessine une étoile
{
  line(10+x,3+y,24+x,-8+y,couleur); lineTo(6+x,-8+y);
  lineTo(0+x,-25+y);        lineTo(-6+x,-8+y);
  lineTo(-24+x,-8+y);       lineTo(-10+x,3+y);
  lineTo(-15+x,20+y);       lineTo(0+x,10+y);
  lineTo(15+x,20+y);        lineTo(10+x,3+y);
}

void setup() 
{
  setGraphMode(PAYSAGE); // Obligatoire pour utiliser l'écran
  setFillMode(STAR); // L'autre mode ne fonctionnerait pas si le fond n'est plus noir
}

int x,y,couleur; // Paramètres d'une étoile
void loop()
{
  // On place une étoile pleine sur l'écran
  star(x=random(LARGEUR-20)+10, y=random(HAUTEUR-20)+10, RANDOM_COLOR); // Dessin de l'étoile creuse
  delay(300);
  fill(x, y, getDrawColor()) // Remplissage de l'étoile

  // Petite attente
  delay(200);
}

Résultat:

 

Côté technique

Pour faire des remplissages par diffusion, on met le premier point dans une pile. Le remplissage proprement dit consiste à:
- prendre un point dans la pile, et si il doit être rempli:
      - le remplir
      - mettre les 4 points adjacents dans une pile.

Cela consomme beaucoup d'espace de stockage interne. On peut diminuer la taille du stockage interne par différents moyens. Ceux que j'ai utilisés sont:
- avant de remplir un point, je vais le plus à gauche possible
- je remplis toute la ligne possible vers la droite, ainsi je ne mets pas dans la pile les points à droite et à gauche.
- si plusieurs points consécutifs se suivent au dessus ou en dessous, je n'empile que le premier

Par défaut la pile est de 32 points mémorisés, cela doit suffire grandement à la plupart des cas. En gros pour remplir un rectangle ou un cercle, il suffit de 2 points. Pour changer le fond d'écran, si il y a N objets, il faut environ N points à mémoriser.

Si le dessin est trop complexe, il n'y a pas la possibilité de stocker tous les points dans la pile. Certains sont "oubliés" et le remplissage sera partiel, il y aura des parties intactes. Pour palier à ce défaut, on peut augmenter la taille de la pile. Dans le fichier PecheuxGraph_ILI9341_8bits.h de la bibliothèque, dans les premières lignes, changez la taille de la pile. Par défaut il y a:
#define FILL_MAX (1<<5) // 2 puissance 5 soit 32 départs maximum
Pour augmenter la taille de la pile:
#define FILL_MAX (1<<6) // 2 puissance 6 soit 64 départs maximum
Le programme suivant permet de tester les limites de fill().

 

PecheuxGraph_ILI9341_8bits.zip\PecheuxGraph_ILI9341_8bits\examples\Documentation\Exemple-204-fillCrash\Exemple-204-fillCrash.ino (dans votre fichier téléchargé):

// Ce programme montre que si on a trop d'obstacles, fill() ne peut plus tout
// mémoriser et certaines zones ne sont pas remplies. On trace des lignes verticales
// qui ne vont pas jusqu'au bord, puis on remplit l'écran. Pour avoir quelque chose
// de différent à chaque fois, on initialise le générateur aléatoire avec un temps de
// réaction humain 

#include <PecheuxGraph_ILI9341_8bits.h>

void setup() 
{
  setGraphMode(PAYSAGE); // Obligatoire pour utiliser l'afficheur

  // Initialisation d'un vrai générateur pseudo-aléatoire
  text("Appuyez sur l'écran"); // Information pour ne pas mettre un écran noir
  while(!isTouch()); // On attend un temps variable
  randomSeed(micros()); // Initialisation avec une valeur qui ne sera jamais la même
  clrscr(); // Suppression du message
  
  for (int Nb=0; Nb<50; Nb++) // 50 lignes, à changer pour faire le test
     // Obstacles n'allant pas jusquau bord:
     vLine(random(LARGEUR-2)+1, random(HAUTEUR-2)+1, random(HAUTEUR-2)+1, GREEN);
  fill(0, 0, GREEN); // Remplit l'écran, complètement si la pile est suffisante
}

void loop()
{
}

 

Avec 40 lignes verticales cela passe souvent. Voici le dessin avant le remplissage:

Et après:

Avec 50 lignes verticales, voici le dessin avant le remplissage:

Et après! Cela ne passe plus, on a perdu des point de départ parce qu'il y en avait trop, et certaines zones ont été oubliées. Il y a des "trous":

Si l'on veut mette plus d'objets, il faut donc augmenter la taille de la pile.

 

 

fillCircle()   <<     >>   fill()