Step 8:Processing分形之三——Diffusion-Limited Aggregation
来源:互联网 发布:简历管理系统知乎 编辑:程序博客网 时间:2024/06/08 05:32
人类一思考,上帝就发笑。
——米兰·昆德拉 《生命中不能承受之轻》
大自然创造出瑰丽奇特的珊瑚,Witten和Sander共同提出了DLA。唐代冯延巳有诗云:“年少王孙有俊才,登高欢醉夜忘回。歌阑赏尽珊瑚树,情厚重斟琥珀杯。但愿千千岁,金菊年年秋解开。”可世人皆知珊瑚美,哪知DLA也奇妙。
Tree Corals
They look fabulous, like underwater bonsai trees that have been painted by Salvador Dali.
3D DLA
For many years now the ultimate inspiration in DLA for me has been Andy Lomas.
More Works: http://www.andylomas.com/aggregationImages.html
8.1 Diffusion-Limited Aggregation
8.1.1 Basic Idea
时光易逝,容颜易老?且看度娘怎么说:
首先置一初始粒子作为种子,在远离种子的任意位置随机产生一个粒子使其做无规行走,直至与种子接触,成为集团的一部分;然后再随机产生一个粒子,重复上述过程,这样就可以得到足够大的DLA团簇(cluster)。
君未尝与吾相知,亦无所怨。你该怎么看:
故事发生在一个被小酒馆包围的城市广场上。醉鬼们离开酒馆,开始在广场上游荡。直到他们终于遇到了一个没有任何意义的同伴,而在那时候,他们躺下睡着了,传来平静的打鼾声。你是否想亲眼看看第二天早晨睡觉人群的鸟瞰图?
Learn More: 我的博客 DLA - Diffusion Limited Aggregation
In a word, DLA即颗粒通过随机移动接触并粘附到现有固定颗粒而产生支化和珊瑚状的结构。
8.1.2 Real Life Experiments
在电沉积池中加入硫酸铜溶液, you can get results like the following images:
8.1.3 You Should Know
创始人之一Sander曾经总结过DLA 的研究意义:
- 模型用极其简单的算法抓住了广泛的自然现象的关键成分却没有明确的物理机制;
- 通过简单的运动学和动力学过程就可以产生具有标度不变性的自相似的分形结构,从而建立分形理论和实验观察之间的桥梁,在一定程度上揭示出实际体系中分形生长的机理;
- 界面具有复杂的形状和不稳定性的性质,生长过程是一个远离平衡的动力学过程,但集团的结构却有稳定且确定的分形维数。
8.2 The Story of the Drunkards
Story Outlines:
① 夜黑风高,在一个被小酒馆包围的城市广场上;
size(800, 800);//地点 background(0);//时间
② “半斤不是酒,一斤扶墙走,斤半墙走我不走。”不知何时,冒出来一个醉鬼,躺卧在广场的中央;
sleepers.add(new Drunkard(width/2, height/2)); //广场中央的醉鬼
③ 接着,四周纷纷又走出许多醉鬼;
//四周随机冒出醉鬼PVector randomDrunkard() { float i = random(4); //4种可能性 PVector p = new PVector(); float x = random(width); float y = random(height); if (i <= 1) { //顶部 p = new PVector(x, 0); } else if (i <= 2) { //底部 p = new PVector(x, height); } else if (i <= 3) { //右边缘 p = new PVector(0, y); } else if (i <= 4) { //左边缘 p = new PVector(width, y); } return p; }
④ 他们在广场四周游荡,毫无目的可言;
void walk() { vel = PVector.random2D(); //毫无目的地游荡 pos.add(vel); //只在广场上活动 pos.x = constrain(pos.x, 0, width); pos.y = constrain(pos.y, 0, height); }
⑤ 可一旦他们瞧见脚下有睡觉的人,他们自己也会情不自禁地倒下睡觉;
//是否倒下睡觉boolean checkStuck(Drunkard dr) { float d = dist(pos.x, pos.y, dr.pos.x, dr.pos.y); if (d < sqrt(radius * dr.radius * 2 * 2)) { if (random(1) < 0.1) { return true; } } return false; }
⑥ 第二天清晨,自广场上空飞过的无人机就拍下了这戏剧性的一幕。
//显示操作void draw() { background(0); //显示移动的醉鬼和睡觉的醉鬼 for (Drunkard m : movers) { m.show(); } for (Drunkard s : sleepers) { s.show(); //限制醉鬼在广场内 if (s.pos.y >= height || s.pos.y <= 0 || s.pos.x >= width || s.pos.x <= 0) { limit = true; } } for (int n = 0; n < iterations; n++) { for (int i = movers.size() - 1; i > 0; i--) { Drunkard m = movers.get(i); m.walk(); for (Drunkard s : sleepers) { if (s.checkStuck(m)) { m.stuck = true; sleepers.add(m); break; } } } } //醉鬼人数的增长 while (movers.size() < maxDrunkards && limit == false) { movers.add(new Drunkard()); }}
Source Code:
Let’s make up this story——
/** * The Story of the Drunkards * @微信公众号:维度模态 * @author:Hewes * @date 2017/08/26 *///存储移动的醉鬼和睡觉的醉鬼们ArrayList<Drunkard> movers = new ArrayList<Drunkard>(); ArrayList<Drunkard> sleepers = new ArrayList<Drunkard>();int maxDrunkards = 500; //醉鬼的数目int iterations = 500; //决定图形生长速度boolean limit = false;void setup() { size(800, 800); sleepers.add(new Drunkard(width/2, height/2)); //中央的醉鬼 //初始其余的醉鬼 for (int i = 0; i < maxDrunkards; i++) { movers.add(new Drunkard()); }}//显示操作void draw() { background(0); for (Drunkard m : movers) { m.show(); } for (Drunkard s : sleepers) { s.show(); //限制静止醉鬼在广场内 if (s.pos.y >= height || s.pos.y <= 0 || s.pos.x >= width || s.pos.x <= 0) { limit = true; } } for (int n = 0; n < iterations; n++) { for (int i = movers.size() - 1; i > 0; i--) { Drunkard m = movers.get(i); m.walk(); for (Drunkard s : sleepers) { if (s.checkStuck(m)) { m.stuck = true; sleepers.add(m); movers.remove(i); break; } } } } //醉鬼人数的增长 while (movers.size() < maxDrunkards && limit == false) { movers.add(new Drunkard()); }}//醉鬼类class Drunkard { PVector pos; PVector vel; boolean stuck; int radius; //移动的醉鬼 Drunkard() { pos = randomDrunkard(); //随机初始位置 stuck = false; //初始状态 radius = 6; //粒子半径 } //睡觉的醉鬼 Drunkard(int x, int y) { pos = new PVector(x, y); stuck = true; radius = 6; } //四周随机出现的醉鬼 PVector randomDrunkard() { float i = random(4); //4种可能性 PVector p = new PVector(); float x = random(width); float y = random(height); if (i <= 1) { //顶部 p = new PVector(x, 0); } else if (i <= 2) { //底部 p = new PVector(x, height); } else if (i <= 3) { //右边缘 p = new PVector(0, y); } else if (i <= 4) { //左边缘 p = new PVector(width, y); } return p; } //醉鬼的移动 void walk() { vel = PVector.random2D(); //随机移动速度 pos.add(vel); pos.x = constrain(pos.x, 0, width); pos.y = constrain(pos.y, 0, height); } //以圆代表醉鬼 void show() { noStroke(); if (stuck) { fill(0, 200, 0); } else { fill(300, 100, 100); } ellipse(pos.x, pos.y, radius * 2, radius * 2); } //是否睡觉 boolean checkStuck(Drunkard dr) { float d = dist(pos.x, pos.y, dr.pos.x, dr.pos.y); if (d < sqrt(radius * dr.radius * 2 * 2)) { if (random(1) < 0.1) { return true; } } return false; }}
8.3 Processing与DLA
以黑色像素点作为醉鬼形象:
将屏幕边缘设置为睡觉的醉鬼:
以圆周作为目标区域,从广场中央走出醉鬼:
嫌像素点太小?试试这个吧:
太单调?加点颜色:
导入Box2d:
See more, try more:
8.4 3D DLA
分享几个DLA神级作品:
Karsten Schmidt’s Works:
Jason’s Works:
五花马,千金裘,呼儿将出换美酒,与尔同消万古愁。The story of the drunkards
is over, I will definitely come back!
- Step 8:Processing分形之三——Diffusion-Limited Aggregation
- Step 6:Processing分形之一——Wallpaper
- Step 7:Processing分形之二——Peter de Jong Attractor
- Data-Intensive Text Processing with MapReduce 第三章(1)——local aggregation
- Step 10:二虎尽食之 Processing 添加库、模式、工具
- Step 2:Processing入门
- Step 5:Processing色彩
- 分形生活之三:分形抽屉
- 论文笔记之Diffusion-Convolutional Neural Networks
- 计算机视觉中的变分方法-扩散(Diffusion)
- Enterprise Library Step By Step系列(三):数据访问程序块——入门篇
- Enterprise Library Step By Step系列(三):数据访问程序块——入门篇
- 在VMWare中配置SQLServer2005集群 Step by Step(三)——配置域服务器
- 【MongoDB】Aggregation Pipeline——聚合管道
- 数据库设计 Step by Step (8)——视图集成
- 数据库设计 Step by Step (8)——视图集成
- 数据库设计 Step by Step (8)——视图集成
- 数据库设计 Step by Step (8)——视图集成
- Elevators UVALive
- linux磁盘管理
- 使用Java VisualVM监控JVM
- php 通过ssh2协议用sftp实现文件上传、下载
- 算法序列——最长公共子序列
- Step 8:Processing分形之三——Diffusion-Limited Aggregation
- 剑指Offer—33—丑数
- C++ 字节对齐(class 与struct)
- 好用的 CURL 类
- commonjs和ES6及requirejs模块循环引用
- 为啥出现个段错误 求解决方法 在线等哦
- this--浅析
- 金山C++开发笔试
- HTML入门的淘宝注册网页制作