The poor man's DLA (Diffusion Limited Aggregation)
How and why I made this program?
Creative coding with DLA in the beginning.
I tried to write a code about DLA(Diffusion-limited aggregation).
DLA、拡散律速凝集(かくさんりっそくぎょうしゅう)— deconbatch (@deconbatch) September 16, 2019
舌噛みそうですね。#processing #creativecoding #generative pic.twitter.com/ufDsEViy6U
As you know, DLA needs Brownian motion. This time, I did not implement Brownian motion but a simple random walk.
Reference. 知識のサラダボウル | 拡散律速凝集
A random walk through top to bottom.
— deconbatch (@deconbatch) September 16, 2019
I drew the path of the random walk. It looks like thunder.
落雷で成長していく DLA。— deconbatch (@deconbatch) September 17, 2019
私はこれを CLA:Chain Lightning Aggregation と名付けようとは思っていない。#processing #creativecoding #generative pic.twitter.com/okOBLwWHRd
Flash of inspiration.
Then, I thought suddenly 'It probably does not need a random walk?'. So, I tried to shoot a cell on a straight line from a random angle.
ミサイルコマンドで育ててみる。— deconbatch (@deconbatch) September 17, 2019
以外とそれっぽい結果になるし、難しいブラウン運動いらないかも?#processing #creativecoding #generative pic.twitter.com/eE79qckbp4
Still more, I can drop a cell straight down from a random position.
まさかなと思いつつやってみたら…— deconbatch (@deconbatch) September 18, 2019
単純にまっすぐ落とすだけでもいいんじゃん!#processing #creativecoding #generative pic.twitter.com/HO8JxXMbsL
What I need is randomness.
In the same way, I can shoot a cell on a straight line from a random angle to the center of the canvas.
複雑なブラウン運動とか無しで、単純にランダムな方向から中心に向かって真っすぐ打ち込むとこう。#processing #creativecoding #generative pic.twitter.com/LuVN4FCwzq— deconbatch (@deconbatch) September 22, 2019
I can shoot a cell slightly shift from the center on the way.
渦巻銀河って、回転してるから渦になってると思ってるでしょう?#processing #creativecoding #generative #DLA pic.twitter.com/eBTr0qqRfR— deconbatch (@deconbatch) September 20, 2019
These look like a real DLA result. But I do not use Brownian motion, so I think they'll not call it a DLA.
Complete regularity?
Then, what happens when I shoot a cell regularity not randomly?
When I do it ordinarily.
— deconbatch (@deconbatch) September 22, 2019
When I tune the rhythm.
— deconbatch (@deconbatch) September 22, 2019
Here is the economical DLA code made with 'Processing' (Java).
And furthermore, I can draw with a complex rhythm like this.
— deconbatch (@deconbatch) September 21, 2019
Finally, I made such a complex shape with regularly rhythm shooting, with no random.
— deconbatch (@deconbatch) September 23, 2019
Here is the example code of the poor man's DLA.
This code does not display any images on the screen but generates image files in frames directory. You can make an animation with these files.
Please feel free to use this code under the terms of the GPL.
To see other works based on my code is my pleasure. And my honor.
/**
* Poor man's DLA
*
* @author @deconbatch
* @version 0.1
* Processing 3.2.1
* created 2019.10.01
*
*/
/**
* Point : Hold a point information.
*/
private class Point {
public float x, y, h; // informations are writable purposely
/**
* @param _x : x-coordinate value of the point.
* @param _y : y-coordinate value of the point.
* @param _hue : hue value of the point.
*/
Point(float _x, float _y, float _hue) {
x = _x;
y = _y;
h = _hue % 360.0;
}
}
void setup(){
size(720, 720);
colorMode(HSB, 360.0, 100.0, 100.0, 100.0);
smooth();
noLoop();
}
void draw(){
int plotMax = 7200;
int frmMax = 24 * 1;
int walkMax = height * 2;
float pSize = 4.0;
float pHue = random(360.0);
float initDiv = random(0.1, 0.4);
ArrayList<Point> cluster = new ArrayList<Point>();
for (float i = 0.0; i < 1.0; i += initDiv) {
cluster.add(new Point(
0.2 * width * cos(TWO_PI * i),
0.2 * height * sin(TWO_PI * i),
pHue));
}
translate(width * 0.5, height * 0.5);
rotate(random(TWO_PI));
float entryR = 1.0; // entryRadius
for (int plotCnt = 0; plotCnt < plotMax; plotCnt++) {
// complex rhythm
entryR += entryR;
entryR = entryR % TWO_PI;
Point p = new Point(
width * cos(entryR),
height * sin(entryR),
pHue);
for (int walkCnt = 0; walkCnt < walkMax; walkCnt++) {
// walk to the center
p.x -= cos(entryR);
p.y -= sin(entryR);
if (checkCollision(cluster, p, pSize)) {
cluster.add(p);
pHue += 0.015;
break;
}
}
if (plotCnt % floor(plotMax / frmMax) == 0) {
background(0.0, 0.0, 90.0, 100.0);
drawCluster(cluster, pSize);
saveFrame("frames/0." + String.format("%05d", plotCnt) + ".png");
}
}
// draw the final frame
background(0.0, 0.0, 90.0, 100.0);
drawCluster(cluster, pSize);
saveFrame("frames/1.00000.png");
exit();
}
/**
* drawCluster : draw the points cluster
* @param _cluster : ArrayList of the Point class.
* @param _size : draw point size.
*/
private void drawCluster(ArrayList<Point> _cluster, float _size) {
float eSat = 40.0;
float eBri = 60.0;
noStroke();
for (Point p : _cluster) {
eSat += 0.009;
eBri -= 0.003;
fill(p.h, eSat, eBri, 100.0);
ellipse(p.x, p.y, _size, _size);
}
}
/**
* checkCollision : check collision between a point and the cluster.
* @return boolean : true = detect collision.
* @param _cluster : ArrayList of the Point class.
* @param _p : a point
* @param _size : size of the point.
*/
private boolean checkCollision(ArrayList<Point> _cluster, Point _p, float _size) {
for (Point p : _cluster) {
if (dist(p.x, p.y, _p.x, _p.y) < _size * 1.0) {
return false;
}
}
for (Point p : _cluster) {
if (dist(p.x, p.y, _p.x, _p.y) < _size * 1.2) {
return true;
}
}
return false;
}
/*
Copyright (C) 2019- deconbatch
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>
*/
Example results.
I'm absolutely blown away by this! I intend to use this very soon, and I'll be sure to tag you when I do. I'm always so grateful for people like yourself that share your knowledge in an accessible way.
One note: when I copied this into Processing, I had to slightly modify the argument declarations. Everywhere that you have `ArrayList _cluster`, I had to change to `ArrayList<Point> _cluster` for it to compile. I'm using Processing 3.5.4, so slightly different version, just wanted to let you (and any future readers) know
Thank you for pointing out! I appreciate it!🙂
It was my mistake and I fixed it now. This time I copied code from this article and ran it for confirmation.👍