====== Figures de Lichtenberg ======
Définition sur [[https://en.wikipedia.org/wiki/Lichtenberg_figure|Wikipedia]]
En mode analogique :
[[https://youtu.be/1jhqZg8UBJU?t=145|Dangerous! Electrifying Woodworking!]]
Sinon d’autres renseignements :
[[http://capturedlightning.com/frames/lichtenbergs.html|What are Lichtenberg figures, and how do we make them?]]
[[https://images.wur.nl/digital/collection/coll13/search/page/1|Système racinaire]]
==== Illustration ====
{{media_07:hydrographie_france.jpg?400|}}
==== Théorie ====
[[http://paulbourke.net/fractals/dla/|DLA - Diffusion Limited Aggregation]]
===== Simulation =====
==== Résultat ====
{{media_03:dla-002986.png?400|}}
==== Processing ====
ArrayList arbre;
ArrayList marcheurs;
int nombreMarcheurs = 2000;
int rangMax = 0;
void setup() {
size(1600, 1000);
arbre = new ArrayList();
arbre.add(new Marcheur(width / 2, height));
marcheurs = new ArrayList();
for (int i = 0; i < nombreMarcheurs; i++) {
marcheurs.add(new Marcheur());
}
}
void draw() {
background(0);
for (int i = marcheurs.size() - 1; i >= 0; i--) {
Marcheur m = marcheurs.get(i);
m.rafraichir();
//m.afficher(rangMax);
for (int j = 0; j < arbre.size(); j++) {
Marcheur ma = arbre.get(j);
if (m.position.dist(ma.position) < (2 * ma.rayon - 4)) {
if (m.position.y < ma.position.y) {
marcheurs.remove(m);
m.rayon = ma.rayon * 0.97;
m.rang = ma.rang + 1;
m.parent = ma;
if (m.rang > rangMax) {
rangMax = m.rang;
}
arbre.add(m);
break;
} else {
m.position = haut();
}
}
}
}
for (int i = arbre.size() - 1; i >= 0; i--) {
Marcheur ma = arbre.get(i);
ma.afficher(rangMax);
}
if (marcheurs.size() == 0) {
affichageArbre();
println(rangMax);
saveFrame("images/DLA-######.png");
noLoop();
}
}
void affichageArbre() {
background(0);
for (int j = 1; j < arbre.size(); j++) {
Marcheur ma1 = arbre.get(j);
Marcheur ma2 = ma1.parent;
stroke(255);
strokeWeight(ma2.rayon / 3.5);
line(ma1.position.x, ma1.position.y, ma2.position.x, ma2.position.y);
}
}
class Marcheur {
PVector position;
Marcheur parent;
float rayon;
int rang;
Marcheur() {
position = haut();
rayon = 15;
rang = 0;
}
Marcheur(int x, int y) {
position = new PVector(x, y);
rayon = 30;
rang = 0;
}
void rafraichir() {
PVector vitesse = PVector.random2D().setMag(30);
position.add(vitesse);
position.x = constrain(position.x, 0, width);
position.y = constrain(position.y, 0, height);
}
void afficher(int r) {
noStroke();
int teinte = (int)map(rang, 0, r, 255, 10);
fill(teinte);
ellipse(position.x, position.y, 2 * rayon, 2 * rayon);
}
}
PVector pourtour() {
int a = (int)random(3);
if (a == 0) {
float r = random(width);
return new PVector(r, 0);
} else if (a == 1) {
float t = random(height);
return new PVector(0, t);
} else {
float u = random(width);
return new PVector(width, u);
}
}
PVector haut() {
float r = random(width);
return new PVector(r, 0);
}
float distSq(PVector a, PVector b) {
float dx = b.x - a.x;
float dy = b.y - a.y;
return dx * dx + dy * dy;
}
==== Processing 3D ====
Voici le code avec exportation .png et .stl :
import java.io.*;
import peasy.PeasyCam;
PeasyCam cam;
File repertoire;
ArrayList arbre;
ArrayList marcheurs;
int nombreMarcheurs = 1000;
int limite = 800;
int rangMax = 0;
public void settings() {
size(1000, 1000, P3D);
arbre = new ArrayList();
arbre.add(new Marcheur(0, 0, 0, limite));
marcheurs = new ArrayList();
for (int i = 0; i < nombreMarcheurs; i++) {
marcheurs.add(new Marcheur(limite));
}
}
public void setup() {
cam = new PeasyCam(this, 400);
repertoire = new File(sketchPath());
}
public void draw() {
lights();
scale(1);
rotateX(PI/2);
background(0);
for (int i = marcheurs.size() - 1; i >= 0; i--) {
Marcheur m = marcheurs.get(i);
m.rafraichir();
//m.afficher(1);
for (int j = 0; j < arbre.size(); j++) {
Marcheur ma = arbre.get(j);
if (dist3DSq(m.position, ma.position) < (4 * ma.rayon * ma.rayon)) {
if (m.position.z > ma.position.z) {
marcheurs.remove(m);
m.rayon = ma.rayon * 0.97;
m.rang = ma.rang + 1;
m.parent = ma;
if (m.rang > rangMax) {
rangMax = m.rang;
}
arbre.add(m);
break;
} else {
m.position = pourtour(limite);
}
}
}
}
affichageArbre(arbre);
if (marcheurs.size() == 0) {
println(rangMax);
}
}
void affichageArbre(ArrayList a) {
background(0);
for (int j = 1; j < a.size(); j++) {
Marcheur ma1 = a.get(j);
Marcheur ma2 = ma1.parent;
stroke(255);
strokeWeight(ma2.rayon / 3.5);
line(ma1.position.x, ma1.position.y, ma1.position.z, ma2.position.x, ma2.position.y, ma2.position.z);
}
}
void keyPressed() {
if (key == ' ') {
saveFrame("images/DLA3D-######.png");
}
if (key == 'e') {
exporterSTL(arbre);
}
}
void exporterSTL(ArrayList a) {
String ligne = "[";
for (int j = 1; j < a.size(); j++) {
if (j != 1) {
ligne += ",";
}
Marcheur ma1 = a.get(j);
Marcheur ma2 = ma1.parent;
String p1 = "[" + ma1.position.x + "," + ma1.position.y + "," + ma1.position.z + "]";
String p2 = "[" + ma2.position.x + "," + ma2.position.y + "," + ma2.position.z + "]";
ligne += "[[" + p1 + "," + ma1.rayon / 3.5 + "]," + "[" + p2 + "," + ma2.rayon / 3.5 + "]]";
}
ligne += "]";
println(ligne);
String[] cmd = {"/Applications/OpenSCAD.app/Contents/MacOS/OpenSCAD",
"-o",
"Arbre.stl",
"-D",
"u = " + ligne,
"Arbre.scad"};
Process p;
try {
p = Runtime.getRuntime().exec(cmd, new String[0], repertoire);
p.waitFor();
float error = p.exitValue();
println("Erreur = " + error);
}
catch (InterruptedException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
class Marcheur {
PVector position;
Marcheur parent;
float rayon;
int rang;
int limite;
Marcheur(int l) {
limite = l;
position = pourtour(limite);
rayon = 15;
rang = 0;
}
Marcheur(int x, int y, int z, int l) {
limite = l;
position = new PVector(x, y, z);
rayon = 30;
rang = 1;
}
void rafraichir() {
PVector vitesse = PVector.random3D().setMag(30);
position.add(vitesse);
position.setMag(constrain(position.mag(), 0, limite));
}
void afficher(int r) {
noStroke();
int teinte = (int)map(rang, 0, r, 255, 10);
fill(teinte);
pushMatrix();
translate(position.x, position.y, position.z);
sphere( 2 * rayon);
popMatrix();
}
}
PVector pourtour(int l) {
PVector v = PVector.random3D().setMag(l);
v.z = abs(v.z);
return v;
}
float dist3DSq(PVector a, PVector b) {
float dx = b.x - a.x;
float dy = b.y - a.y;
float dz = b.z - a.z;
return dx * dx + dy * dy + dz * dz;
}
Pour la partie OpenSACD de l'exportation .stl :
$fn = 15;
u = [[[[10, 10, 10], 30], [[30, 20, 40], 20]], [[[30, 20, 40], 20], [[60, 30, 45], 10]]];
for (i = [0:len(u) - 1]) {
element(u[i]);
}
module element(e) {
a = e[0];
b = e[1];
hull() {
translate(a[0]) sphere(d = a[1]);
translate(b[0]) sphere(d = b[1]);
}
}
==== Code ====
=== Heightmap ===
[[https://forum.processing.org/two/discussion/25167/fly-over-a-heightmap-generated-landscape|v]]
=== Agrégation limitée par la diffusion (DLA) ===
[[https://medium.com/@jason.webb/simulating-dla-in-js-f1914eb04b1d|Simulating 2D diffusion-limited aggregation (DLA) with JavaScript]]
[[https://thecodingtrain.com/CodingChallenges/034-dla.html|Diffusion-Limited Aggregation]]
[[https://www.openprocessing.org/sketch/460864|Challenge #34: Diffusion-Limited Aggregation]]
{{tag> processing sylvain}}