Tutoriel Lee Byron Mesh

///////////////////////////////////////////////////////////////////////
——— LIBRAIRIE MESH DE LEE BYRON ————-
///////////////////////////////////////////////////////////////////////
Alexandre Rivaux / Bonjour Interactive Lab
À la découverte du diagramme de Voronoi
et du Diagramme de Delaunnay.

Source Code :
Sketches Processing

///////////////////////////////////////////////////////////////////////

PRÉSENTATION.

Mesh est une librairie simple et rapide à implémenter permetant de réaliser diagrammes de Delaunay,
diagrammes de Voronoi et convex hull. Elle a été créée par Lee Byron (designer) qui cherchait alors
à trouver une librairie Java la plus simple possible pour ces besoins. Elle se base sur la librairie
Quick Hull 3D pour JAVA.

Le diagramme de Delaunay
triangulation

La triangulation de Delaunay d’un ensemble de points est une triangulation dont le cercle passant
par les trois sommets ne contient aucun autre point.

Le diagramme de Delaunay
voronoi

Le diagramme de Voronoi partitionne l’espace en régions, chacune d’entre elle réunissant les points
qui sont plus proches d’un object que de tous les autres.

Convex Hull
Chull

L’enveloppe convexe est un polygone réunissant l’ensemble des points présent.

///////////////////////////////////////////////////////////////////////

Premier Exemple.

Mesh & Processing

Comme dit précédement, Mesh est une librairie très simple à implémenter et très utile lorsque qu’on
l’on cherche à obtenir un résultat rapide. Cependant avant de commencer à travailler avec, il est
important d’en connaitre les limites. Ainsi il faut savoir que cette librairie ne nous permettra
que de produire des Diagrammes en 2D.

Dans un premier exemple nous verrons comment créer un Delaunay, un Voronoi et un convex hull de manière
statique. Nous partirons d’une base simple. Un sketch de 640*360 possédant une classe de particules.
À chaque clic nous ajouterons une particule sur scène et ce à une position aléatoire. Voici notre
skecth de départ :

ArrayList<Particule> myParticle;

void setup() { 
  size(640, 360, JAVA2D);
  smooth();

void draw() { 
  background(0);
  if (mousePressed) { 
  Particule p = new Particule(random(20, width-20), random(20,height-20), myParticle.size());
} 
  myParticle.add(p);
for (Particule p : myParticle) { 
  p.display(); 
}

Voir le sketch, Voronoi Exemeple et notez bien que nous avons également une classe de Particule.

Nous allons maintenant créer nos diagrammes. Notre première étape sera donc d’importer notre librarie
et de créer nos 3 objets/diagrammes. Mesh nous propose 3 classes, une par diagramme :

– Delaunay
– Voronoi
– Hull

Nous devons aussi créer un tableau nous permettant de stocker la position de chacune de nos particules.
Nous ferons un tableau à deux dimensions que nous appelerons “points”.

//IMPORTER LA LIBRARIE MESH
import megamu.mesh.*; 

ArrayList<Particule> myParticle;

//Voronoi & Delaunay
float[][] points;
Delaunay triangleDelaunay;
Voronoi diagramVoronoi;
Hull myHull;

void setup() { 
  size(640, 360, JAVA2D);
  smooth();

  myParticle= new ArrayList<Particule>();
}

Dans notre draw() nous allons stocker les coordonnées de nos particules dans notre tableau “points”.
Nous nous servirons ensuite de ce tableau pour calculer nos diagrammes.

void draw() { 
  background(0);
if (mousePressed) { 
  Particule p = new Particule(random(20, width-20), random(20,height-20), myParticle.size());
  myParticle.add(p);

//1- Stocker les coordonnées de nos particules dans un tableau de point.
  points = new float[myParticle.size()][2];
for (int i=0; i<myParticle.size(); i++) { 
  Particule pi = myParticle.get(i);
  points[i][0] = pi.x;
  points[i][1] = pi.y;
} 
 
for (Particule p : myParticle) { 
  p.display(); 
}
}

Pour le calcul des diagrammes nous allons devoir initialiser nos objets à l’aide de notre
tableau “points”. Nous calculerons ensuite les coordonées des points d’origine et d’arrivée
à l’aide de méthode spécifique à chacun de nos objet diagrammes.

Ainsi pour le delaunay, nous obtenons :

triangleDelaunay = new Delaunay(points);
float[][] myEdges = triangleDelaunay.getEdges();

for (int i=0; i<myEdges.length;i++) { 
  float startX = myEdges[i][0]; //coordonnée x de départ
  float startY = myEdges[i][1]; //coordonnée y de départ
  float endX = myEdges[i][2];  //coordonnée x d’arrivée
  float endY = myEdges[i][3]; //coordonnée y d’arrivée
  stroke(255);
  line( startX, startY, endX, endY );
} 

Pour le voronoi nous obtenons :

diagramVoronoi = new Voronoi(points);
float[][] myEdgesVoronoi = diagramVoronoi.getEdges();

for (int i=0; i<myEdgesVoronoi.length; i++) { 
  float startX = myEdges[i][0]; //coordonnée x de départ
  float startY = myEdges[i][1]; //coordonnée y de départ
  float endX = myEdges[i][2];  //coordonnée x d’arrivée
  float endY = myEdges[i][3]; //coordonnée y d’arrivée
  stroke(255);
  line( startX, startY, endX, endY );
} 


Enfin pour le convex hull nous obtenons :

myHull = new Hull(points);
MPolygon myRegion = myHull.getRegion();
  stroke(255);
  noFill();
  myRegion.draw(this);


///////////////////////////////////////////////////////////////////////

Enfin, une autre possibilité que nous apporte Mesh est d’obtenir des polygones des régions
créées par le Voronoi à l’aide de la méthode getRegion(). Afin de rendre ces régions plus
visible nous définirons une couleur pour chacune d’entre elles. Nous avions attribué une
valeur de bleu à chacune de nos particules. Nous allons récuperer cette valeur pour
l’attribuer à nos régions.

MPolygon myRegion = myHull.getRegion();

for (int i=0; i<myRegions.length; i++) {
  Particule p = myParticle.get(i);
  // an array of points
  float[][] regionCoordinates = myRegions[i].getCoords();
  fill(p.pc);
  myRegions[i].draw(this); // draw this shape
}


Maintenant que nous savons comment créer des diagrammes de Delaunay, Voronoi ou
Convex Hull on peut facilement imaginer de nombreuses applications. Que ce soit
de rendre nos diagrammes animés, de réaliser des visuelles génératifs ou encore
de réaliser un diagramme de Voronoi à partir d’un flux vidéo les possibilités
sont immenses.

Dans les exemples suivants nous réaliserons deux visuels génératifs basés sur les
même règles. L’un à l’aide d’un diagramme de Delaunay, le second avec un diagramme
de Voronoi.

Pour cela nous allons créer un générateur de particules. Au clic nous générons un nombre
aléatoire de particules, celles-ci seront placées au centre de notre sketch. Chacune d’entre
elles aura une vitesse aléatoire. Lors de leur création nous définirons une distance maximale
pour chacune d’entres-elles. Lorsque l’une d’entre elles aura atteint son but nous stopperons
l’animation et viderons notre tableau. Enfin le dessin génératif sera produit par nos diagrammes.

Notre classe de particules sera donc définie comme ceci :

//declaration d’une classe
class Particule { 
  //Declaration des membres classe particules
  float x, y, r, or, angle;
  float vr;
  float d;
  color c;
  float colorRatio;
  
//Declaration de la fonction constructeur au variable de stockage x_et y_ permettant de 
//stocker les varaible x et y
Particule(float r_, float angle_, float colorRatio_) { 
  this.r = 0;
  this.or = r_;
  this.angle = angle_;
  this.vr = random(0.1, 0.5);
  this.d = 10;
  this.colorRatio = colorRatio_;
  //définissions de la couleur
  this.c = color(random(colorRatio, colorRatio+60),random(80, 100),random(80,100)); 
 }

void position() {
  this.x = cos(this.angle)*this.r;
  this.y = sin(this.angle)*this.r;

void motion() {
  this.r += this.vr;
}

void checkEdge() { 
if(this.r > this.or || this.r < 0) { 
  this.vr*=-1; 
 }
}
void display() { 
  stroke(255);
  fill(this.c);
  noStroke();
  ellipse(x, y, this.d, this.d);
 } 
}


Notre setup() et draw de départ();

ArrayList<Particule> myParticle; //notre tableau de particules
int nbParticles; //nombre de particules générée au clic
float rayon, colorRatio; //Distance Max et Gamme de couleur aléatoire
float angleGlobal; //angle de rotation de notre skecth
float vAngle; //sens de la rotation
boolean clear; //vider le tableau

void setup() {
  size(800, 800, JAVA2D);
  smooth();
  colorMode(HSB, 360, 100, 100, 100);
  background(0);
  myParticle= new ArrayList<Particule>();
} 

void draw() { 
  pushMatrix();
  translate(width/2, height/2); //déplacement de la Matrice
  angleGlobal += vAngle; //Rotation du sketch
  rotate(radians(angleGlobal));
 if (mousePressed == true) { //Génération des particules
  background(0); //Effacer la scène
  initateParticle(); //Créer des particules

  Particule p = new Particule(rayon, random(TWO_PI), colorRatio); 
  myParticle.add(p);
for (Particule p : myParticle) { 
  p.motion();
  p.checkEdge();
  p.position();
  p.display();
}
  popMatrix();
  clearParticules();

void initateParticle() { //fonction définissant les particules
  vAngle = random(-0.1, 0.1);
  nbParticles = int(random(200, 300));
  colorRatio = random(0, 300);
  rayon = random(400, 800);
}

void clearParticules(){ 
//Fonction vidant le tableau de particules
for (Particule p : myParticle) {  
if (p.r >= p.or) { 
  clear = true; 
 }
}


img_8685
///////////////////////////////////////////////////////////////////////

Ajoutons maintenant notre premier diagramme pour réaliser notre premier visuel.
Ici un diagramme de Delaunay.

import megamu.mesh.*;
float[][] points;
Delaunay triangleDelaunay;
  //couleurs définie par un bruit perlin
  c = noise(cOff);
  cOff+=0.01;
  c = map(c, 0, 1, colorRatio, colorRatio+60);

  //Stocker les coordonnées de nos particules dans un tableau
  points = new float[myParticle.size()][2];
for (int i=0; i<myParticle.size(); i++) { 
  Particule pi = myParticle.get(i);
  points[i][0] = pi.x;
  points[i][1] = pi.y;
} 
//delaunay
triangleDelaunay = new Delaunay(points);
float[][] myEdges = triangleDelaunay.getEdges();
for (int i=0; i<myEdges.length;i++) { 
  float startX = myEdges[i][0];
  float startY = myEdges[i][1];
  float endX = myEdges[i][2];
  float endY = myEdges[i][3];
  float d = dist(startX, startY, endX, endY);
  if (d < 50)  { //ici nous ne dessinons que si d est inferieur à 50
  stroke(c, 100, 100, 10);
line( startX, startY, endX, endY );
 } 
}
 
if(clear == true) {
  myParticle.clear();
  initateParticle();
  clear = false;
 } 
} 


Faisons de même pour le diagramme de Voronoi.

import megamu.mesh.*;
float[][] points;
Voronoi diagramVoronoi;
//couleurs définie par un bruit perlin
c = noise(cOff);
cOff+=0.01;
c = map(c, 0, 1, colorRatio, colorRatio+60);

//Stocker les coordonnées de nos particules dans un tableau
points = new float[myParticle.size()][2];
for (int i=0; iwww.arivaux.com
Licensed under GNU General Public License (GPL) version 3.

///////////////////////////////////////////////////////////////////////