加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

Processing中绘制Voronoi(泰森多边形)和水立方

(2014-05-09 18:19:47)
标签:

processing

voronoi

水立方

设计与编程

建筑参数化

分类: Processing笔记
http://s12/bmiddle/003yPQBJzy6IKcs7ZO39b&690
http://s12/mw690/003yPQBJzy6IK5fTTrZbb&690

Voronoi最出名的例子就是北京奥运的水立方了。它在自然界中非常常见,比如长颈鹿图案,龟壳图案等。

那么,什么是Voronoi?
我能想到的通俗点的解释是这样的:
想象一个平面(就拿长方形来讲好了),该平面内散落着若干种子点(比如,10个种子),现在对组成这个平面的无数个点喊话:请大家立刻找到离自己最近的种子点认大哥,并以此划分为10个帮派!于是,10个点的voronoi图案形成了。
下图是从百度百科扒的,配色嘛.....
http://s1/bmiddle/003yPQBJzy6IK6aVGx240&690

由于“每一点都能找到离自己最近的种子点”这一特性,voronoi在城市规划,气象学,统计学,建筑和结构等方向有很多应用。另外,单纯从美学角度讲,这种先撒种子,再划势力范围的方法能生成或者配合生成很多漂亮图案。
一张桌子:
http://s2/bmiddle/003yPQBJzy6IKcPUbnz51&690

丹麦BIG的一个建筑概念:
http://s14/bmiddle/003yPQBJzy6IKdFgawled&690



Processing中画voronoi有不少方法,下面这种我把它起名叫“逐像素扫描法”,相对于中垂线法省很多代码。
主要思路:遍历窗口内的每一个像素点,求出该像素点到每个种子点的距离,对这些距离排序,得到最小距离和第二小距离,然后进行比较,如果这两个距离相等则说明该像素点在多边形的边上,对其染色标出;如果不等,则说明该像素点在多边形内,不作处理。遍历完成后就得到了一张染过色的网,表明voronoi的边界。

代码约30行,如下:
int qty=20;
PVector everyPixel;
PVector[]seed=new PVector[qty];
float[]distance=new float[qty];
float min,secmin;
float threshold=1f;

size(600,400);

for(int i=0;i
  seed[i]=new PVector(random(width),random(height));
  fill(255,255,0);
  ellipse(seed[i].x,seed[i].y,5,5);
}

for(int i=0;i
  for(int j=0;j
    everyPixel=new PVector(i,j);
    for(int k=0;k
      distance[k]=everyPixel.dist(seed[k]);
    }
    distance=sort(distance);
    min=distance[0];
    secmin=distance[1];

    if(abs(secmin-min)
      stroke(255);
      point(i,j);
    }
  }
}
 
 
20个种子点是随机生成的,下图是得到的一个结果:
http://s10/bmiddle/003yPQBJzy6IKao9awF89&690


代码注释:
int qty=20;//设20个种子点
PVector everyPixel;//将来会通过把每一像素点的值赋给everyPixel进行遍历。
PVector[]seed=new PVector[qty];//20个种子点的位置
float[]distance=new float[qty]; //像素点到20个种子点的距离
float min,secmin;//最小距离和第二小距离
float threshold=1f;//由于距离是浮点数,在实际执行中,几乎不可能出现两个距离恰好相等的情况,所以使用的是阈值法,距离差小于某个阈值的都算相等

size(600,400);

for(int i=0;i
  seed[i]=new PVector(random(width),random(height));//随机出20个点
  fill(255,255,0);
  ellipse(seed[i].x,seed[i].y,5,5);//画小圈标记这20个点的位置
}

for(int i=0;i
  for(int j=0;j
    everyPixel=new PVector(i,j);//像素点信息赋给变量
    for(int k=0;k
      distance[k]=everyPixel.dist(seed[k]);
         //该像素到20个种子的距离,形成一个数组
    distance=sort(distance);  //对该数组排序
    min=distance[0];      //得到最小距离
    secmin=distance[1];   //得到第二小距离

    if(abs(secmin-min)
      stroke(255);     //填充白色,对于point的染色,要用stroke,而不是fill
      point(i,j);       //描点
    }
  }
}
 
 
如果我们进一步把上面的代码加点颜色的变化就能得到下面这种漂亮一些图案:
http://s2/bmiddle/003yPQBJzy6IKbTbM2t91&690

如果进一步把代码打包成类,并把生成图案作为材质图贴到立方体上就能得到题图的水立方。
整个过程so easy,颤抖吧,grasshopper  :-)
http://s9/bmiddle/003yPQBJzy6IKdOibIk58&690
http://s9/bmiddle/003yPQBJzy6IKgfaIkwc8&690

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有