分形树

藏宝库编辑 2024-9-3 05:37:57 75 0 来自 中国
书名:代码本色:用编程模仿天然系统
作者:Daniel Shiffman
译者:周晗彬
ISBN:978-7-115-36947-5
第8章目次
8.5 树



  • 到现在为止,我们接触的分形都是确定性的,也就是说,这类分形没有任何随机因
    素,每次运行都会构建出雷同的效果。
  • 对于传统分形和可视化编程技能的演示,它们黑白常不错的素材;
  • 但在模仿方面,它们过于精确,不敷贴近天然。
  • 接下来讨论随机(非确定性)分形的构建技能。
1、确定性分形技能构建


  • 本节要模仿的是带有分支的树。
  • 起首,让我们用确定性分形技能构建一棵分形树。构建规则如下:


  • 再一次,我们用递归方式构建了一个分形:树枝是一个线段,线段末端有两根小树枝。


2、实现的思绪


  • 这个分形的难点在于它的分形规则用到了旋转,每个新的树枝必须在原树枝上旋转一定的角度,而原树枝也是云云。幸运的是:Processing专门有一个机制用于管理旋转角度,即变更矩阵。
  • 让我们从主干开始。由于要涉及rotate()函数,我们必须在绘制过程中不绝地沿着树枝平移。主干是从屏幕底部开始的(如上图所示),因此我们要做的第一件事就是平移到主干所在的位置。
    translate(width/2,height);
  • 紧接着我们要画一根向上延伸的线段
    line(0,0,0,-100);
  • 树干绘制完成后,为了画出它的树枝,我们必要平移到树干的末端,然后举行旋转。
    (末了,我们必要把这些利用实现为递归函数,但在此之前要先梳理出具体步调。)
  • 记着,在Processing中,旋转始终都是绕着原点举行的。因此,我们必须把原点平移到当前树枝的末端。
translate(0,-100);rotate(PI/6);line(0,0,0,-100);

  • 如今我们已经画好了右边的树枝,下面要添加左边的树枝。在向右旋转之前,我们可以调用pushMatrix()函数生存转换矩阵的当前状态,旋转完成后再调用popMatrix()函数规复状态,接着在树干左边画树枝。以下是全部代码。
translate(width/2, height);line(0,0,0,-100); 树干translate(0,-100);pushMatrix();rotate(PI/6);line(0,0,0,-100); 右边的树枝popMatrix();rotate(-PI/6);line(0,0,0,-100); 左边的树枝3、递归树的实现


  • 如果把每个line()函数调用都当成一根“树枝”,你会发现,树枝实在是一条线段,线段的末端还毗连着两条线段。
    我们可以直接调用line()函数产生更多树枝,但雷同于康托尔集和科赫曲线,这么做会让代码变得复杂而粗笨。
    相反地,我们可以把上述逻辑作为递归函数的实现思绪,把此中的line()函数调用更换为递归的branch()函数。
    下面来看看这种实现。
void branch() {    line(0, 0, 0, -100); 绘制树枝    translate(0, -100); 平移到末端    pushMatrix();    rotate(PI/6); 向右旋转,再画新的树枝    branch();    popMatrix();    pushMatrix();    rotate(-PI/6); 向左旋转,再画新的树枝    branch();    popMatrix();}

  • 在上面的代码中,每个branch()函数调用的附近都有成对的pushMatrix()函数和popMatrix()函数调用。
    这种实现方式非常神奇。每次调用branch()函数之前,pushMatrix()函数都会事先记着当前树枝的位置。
    请把本身当作Processing,实行着用笔和纸跟踪递归函数的实行,你会发现:步伐起首画全部右边的树枝,当它达到尽头时,popMatrix()函数会逐个规复之前每个树枝的状态,然后再开始画左边的树枝。
  • 以上递归函数并不会画出一棵树,因为它没有退出条件,终极只是陷入无穷的递归调用。你大概还会发现,图中树枝随着层数的增长而收缩。以下代码让树枝的长度不绝收缩,一旦树枝长度小于某个值,就制止递归。
void branch(float len) { branch()函数继承一个长度参数    line(0, 0, 0, -len);    translate(0, -len);    len *= 0.66; 每个树枝的长度以2/3的倍数收缩    if (len > 2) {        pushMatrix();        rotate(theta);        branch(len); 后续的branch()调用必须传入长度参数        popMatrix()        pushMatrix();        rotate(-theta);        branch(len);        popMatrix();        }}4、随机分形树


  • 在分形树中加入一点点随机性就可以使它的形状更贴近天然。
    查察一棵树的形状,你会发现每根树枝的角度和长度都不雷同,别的,每根树枝的分支数目也不雷同。
    简朴地改变树枝的角度和长度能带来什么样的效果?这很容易实现,只要在绘制时获取一个随机数即可。
void branch(float len) {    float theta = random(0, PI/3); 选择一个随机数作为树枝的角度    line(0, 0, 0, -len);    translate(0, -len);    len *= 0.66;    if (len > 2) {        pushMatrix();        rotate(theta);        branch(len);        popMatrix();        pushMatrix();        rotate(-theta);        branch(len);        popMatrix();        }}
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-10-19 06:26, Processed in 0.173393 second(s), 32 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表