LaTeX中绘制分形图形

背景知识

分形(Fractal)是芒德勃罗在 1973 年提出的一个数学概念。通常分形被定义为一个粗糙或零碎的集合形状,可以分成数个部分,且每一部分都是整体缩小后的形状,定义表明分形具有自相似性。在 LaTeX 中,可以通过 Lindenmayer System Drawing Library 来实现分形图形的绘制,Lindenmayer System 又称L系统,L-system是一系列不同形式的正规语法规则,多被用于植物生长过程建模,但是也被用于模拟各种生物体的形态。L-system也能用于生成自相似的分形,例如迭代函数系统,与分形图形绘制。L系统由一系列的符号、绘制动作组成如(向左转,向前移动)以及一系列的规则(如重复)组成。在 LaTeX 中的 Lindenmayer System Drawing Library 包的用法符合L系统的基本特性。因此使用 Lindenmayer 宏包绘制分形图形的关键就是了解图形的L系统的表示。

Lindenmayer System Drawing Library 简介

在上文中提到了L系统主要由符号与绘制动作以及规则组成,LaTeX 中的 L 系统也同样由这些规则组成,在 LaTeX 绘制分形主要可以分为两步

  • 定义分形的相应符号与规则。
  • 绘制分形图形。

符号与规则

在 Lindenmayer System Drawing Library 中提供了六种基本符号,辅助完成图形绘制,简要说明如下:

  • F 向前移动一段距离并绘制相应线条
  • f 向前移动一段距离不绘制线条
  • + 向左旋转相应角度
  • - 向右移动相应角度
  • [ 存储当前状态
  • ] 恢复存储状态

通过以上中符号进行组合,可以绘制出常见的一些分形图形,另外在该宏包中还定义了一些其他的绘制命令,通过这些命令可以自定义符号与规则,完成一些其他复杂图形绘制,但比较遗憾的是该宏包无法进行三维分形图形的绘制。关于这些命令的具体使用方法可以参考 tikz 的用户手册,下面是一些常见分形图形的绘制代码!

康托尔尘(Cantor Dust)

康托尔集是散落在线段上的一些点,这些点通过不断的将线段三等分,截断中间的部分形成。绘制代码如下:

1
2
3
4
5
6
7
8
9
10
11
\pgfdeclarelindenmayersystem{Cantor Dust}{
\symbol{X}{\pgflsystemmoveforward} % 定义符号
\symbol{Y}{\pgflsystemdrawforward}
\rule{X -> XYX} % 定义规则
\rule{Y -> YXY}
}

\begin{tikzpicture}
\draw[green!50!black][lindenmayer system={Cantor Dust, axiom=X, order=2}] %绘制图形,其中axiom表示起始点,order表示阶数,可以调节
lindenmayer system;
\end{tikzpicture}

绘制结果如图所示:
![Cantor Dust](/img/Cantor Dust.png)

科克曲线(Koch Curve)

设想一个边长为1的等边三角形,取每边中间的三分之一,接上去一个形状完全相似的但边长为其三分之一的三角形,结果是一个六角形。现在取六角形的每个边做同样的变换,即在中间三分之一接上更小的三角形,以此重复,直至无穷。外界的变得原来越细微曲折,形状接近理想化的雪花。他的名字叫科克曲线,因为瑞典数学家科克在1904年第一次描述了这种不论由直段还是由曲段组成的始终保持连通的线。

1
2
3
4
5
6
7
\pgfdeclarelindenmayersystem{Koch curve}{
\rule{F -> F-F++F-F}}
\begin{tikzpicture}
\shadedraw[shading=color wheel]
[l-system={Koch curve, step=2pt, angle=60, axiom=F++F++F, order=4}]
lindenmayer system -- cycle;
\end{tikzpicture}

绘制结果如图所示:
![Koch curve](/img/Koch Curve.png)

希尔伯特曲线(Hilbert curve)

希尔伯特曲线是一种能填充满一个平面正方形的分形曲线(空间填充曲线)由皮亚诺在1890年发现,由大卫·希尔伯特在1891年绘制出,

1
2
3
4
5
6
7
8
\pgfdeclarelindenmayersystem{Hilbert curve}{
\rule{L -> +RF-LFL-FR+}
\rule{R -> -LF+RFR+FL-}}
\begin{tikzpicture}
\draw [green!50!black, rotate=90]
[l-system={Fractal plant, axiom=X, order=6, step=2pt, angle=25}]
lindenmayer system;
\end{tikzpicture}

示例绘图结果:
![Koch curve](/img/Hilbert Curve.png)

龙形曲线(Dragon Curve)

Heighway dragon curve
龙形曲线是由美国科学家 John Heighway, Bruce Banks, and William Harter 提出,因此又称为 Harter–Heighway dragon。龙形曲线着色后形状与中国龙图腾中的蟠龙类似,但在本文的例子中并没有对其着色,绘制的阶数也偏低,因此,并不美丽!后续改进。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
\pgfdeclarelindenmayersystem{Dragon Curve}{
\symbol{X}{}
\symbol{Y}{}
\symbol{F}{\pgflsystemdrawforward}
\symbol{+}{\pgflsystemturnleft}
\symbol{-}{\pgflsystemturnright}
\rule{X -> X+YF+}
\rule{Y -> -FX−Y}
}

\begin{tikzpicture}
\draw[lindenmayer system={Dragon Curve, axiom=FX, order=8, angle=90}]
lindenmayer system;
\end{tikzpicture}

示例代码绘制结果:
![Dragon Curve](/img/Dragon Curve.png)

谢尔宾斯基三角形(Sierpinski triangle)

谢尔宾斯基三角形是也是一种分形,它由波兰数学家谢尔宾斯基在 1915 年提出,它可以通过以下三步形成:

  • 绘制一个等边三角形
  • 连接每条边的中点,将其分为四个全等的等边三角形,并移除位于正中间的三角形
  • 对剩余的三角形重复上一步骤
1
2
3
4
5
6
7
8
\pgfdeclarelindenmayersystem{Sierpinski triangle}{
\rule{F -> G-F-G}
\rule{G -> F+G+F}}
\begin{tikzpicture}
\shadedraw [top color=white, bottom color=blue!80, draw=blue!80!black]
[l-system={Sierpinski triangle, step=2pt, angle=60, axiom=F, order=8}]
lindenmayer system -- cycle;
\end{tikzpicture}

示例绘制结果如下:
![Sierpinski triangle](/img/Sierpinski triangle.png)

分形植物(Fractal Plants)

最后再来绘制一个漂亮的分形植物作为结束吧!

1
2
3
4
5
6
7
8
\pgfdeclarelindenmayersystem{Fractal plant}{
\rule{X -> F-[[X]+X]+F[+FX]-X}
\rule{F -> FF}}
\begin{tikzpicture}
\draw [green!50!black, rotate=90]
[l-system={Fractal plant, axiom=X, order=6, step=2pt, angle=25}]
lindenmayer system;
\end{tikzpicture}

绘制结果如图:
Plants

总结

在 LaTeX 中系统中绘制分形图形最为重要的一点是了解图像的在L-System中的表达,好在在参考链接中L-System的维基百科中已经给出了大部分平面图形的L表达。最后 tikz的三维绘制能力相对较弱,三维分形绘制一般采用Mathematica绘制,在 Matrix67的博文中有一些采用 Mathematica 绘制的分形图形的示例。本文图形的着色参考了 tikz 用户手册的例子。最后需要注意的是由于在绘制时的递归需要不停的入栈,绘制程序非常耗内存,我在绘制order=20的龙形曲线就遇到过,可以手动调大 LaTeX 命令所占的内存来解决。

参考链接

[1] L - System
[2] How to create a Sierpinski triangle in LaTeX?
[3] Example: Lindenmayer systems