分形

目录

一,常见分形

1,Julia集

fundamental dichotomy theorem for Julia sets

2,Mandelbrot(曼德勃罗)集

Julia集和Mandelbrot集的关系

3,Koch(科赫)雪花

4,Hilbert(希尔伯特)曲线

OJ练习

5,Sierpinski(谢尔宾斯基)三角形

(1)等边三角形外形

(2)直角三角形外形

(3)任意三角形外形

6,Sierpinski地毯

二,其他分形

1,分形+镶嵌画

2,三维图形

3,Kögra分形字体

4,分形+不可能图形

5,迭代与分形

三,分形维数

1,分维

2,Hausdorff 维数

3,变步长法

四,实际应用

1,分形虎钳

五,待更新


本文部分内容来自matrix67的博客 Matrix67.com - Home

一,常见分形

1,Julia集

用复变函数Z_{k+1}=Z_k^2+C作为迭代方程,如果一个点在不断迭代之后是模值收敛的,那么就称之为收敛点。

所有收敛点组成的合集叫Julia集,每个不同的C对应的Julia集(如果存在的话)都不一样。

绘制Julia集的代码:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm

def genZ(axis, nx, ny):
    x0, x1, y0, y1 = axis
    x = np.linspace(x0, x1, nx)
    y = np.linspace(y0, y1, ny)
    real, img = np.meshgrid(x, y)
    z = real + img * 1j
    return z


# 用于生成Julia集
def getJulia(z, c, n, n0=0, m=2):
    out = abs(z)
    print(out)
    for i in range(n0, n0 + n): #n是迭代次数
        absz = abs(z)
        z[absz > m] = 0
        out[absz > m] = i
        z = z * z + c
    return out


n = 1000
axis = [-2, 2, -2, 2] # 规定矩形范围,即绘图范围
z = genZ(axis, n, n)  # 生成axis范围内的n*n个点
c = 0.5-0.4j
mBrot = getJulia(z, c, 50)
plt.imshow(mBrot, cmap=cm.jet, extent=axis)
plt.show()
c = 0.5-0.4j的结果:


c = 0.75j的结果: 

 c = 0.998 + 0.401j的结果:

c = -0.75的结果:

c = 0.285的结果:

c = -0.8+0.156j的结果:

c = -0.835 -0.2321j 的结果:

c = -0.70176-0.3842j的结果:

fundamental dichotomy theorem for Julia sets

一个 Julia 集要么是完全连通的,任意两点间都有一条通路;要么是完全不连通的,整个图形全是一个个孤立的点。

参考:点击打开链接

 

 

总结:

 

即如果0是收敛点,那么就是完全连通的,否则就是完全不连通的。

这其实就得到曼德勃罗集的定义。

2,Mandelbrot(曼德勃罗)集

曼德勃罗集是使得迭代方程Z_{k+1}=Z_k^2+C有收敛点的C的集合。

如果有收敛点,那么Z=0就是一个收敛点,经过一次迭代之后z=c

依据这个原理得到绘制代码:

import matplotlib.pyplot as plt
import numpy as np
from matplotlib import cm

def genZ(axis, nx, ny):
    x0, x1, y0, y1 = axis
    x = np.linspace(x0, x1, nx)
    y = np.linspace(y0, y1, ny)
    real, img = np.meshgrid(x, y)
    z = real + img * 1j
    return z


# 用于生成Julia集
def getJulia(z, c, n, n0=0, m=2):
    out = abs(z)
    print(out)
    for i in range(n0, n0 + n): #n是迭代次数
        absz = abs(z)
        z[absz > m] = 0
        out[absz > m] = i
        z = z * z + c
    return out


n = 1000
axis = [-2, 2, -2, 2] # 规定矩形范围,即绘图范围
z = genZ(axis, n, n)  # 生成axis范围内的n*n个点
c = z
mBrot = getJulia(z, c, 50)
plt.imshow(mBrot, cmap=cm.jet, extent=axis)
plt.show()

Julia集和Mandelbrot集的关系

定义四元布尔函数g(x1,y1,x2,y2):取起点为x1 + i y1,C=x2 + i y2,根据迭代方程Z_{k+1}=Z_k^2+C 进行无限迭代,如果收敛则函数值为1,否则函数值为0

所有使得g=1的点构成的集合,就是四维Julia-Mandelbrot集合。

这个四维集合是唯一确定的一个集合,Julia集是它的二维切片,切的位置取决于C,Mandelbrot集也是它的切片,切的位置是x1=y1=0

更多资料:

https://www.skytopia.com/project/fractal/mandelbulb.html

https://christopherolah.wordpress.com/2011/08/08/the-real-3d-mandelbrot-set/

3,Koch(科赫)雪花

雪花是三个Koch曲线组成,严格来讲Koch曲线才是分形。

Koch曲线:

4,Hilbert(希尔伯特)曲线

用递归的方式铺满2^n * 2^n的方格,起点和终点是同一侧的2个角落格子。

当n趋于正无穷就得到一条铺满整个正方形的连续曲线,叫Hilbert曲线,它的近似示例:

起点和终点是正方形同一侧的2个顶点。

三维Hilbert曲线:

OJ练习

Fractal Streets

5,Sierpinski(谢尔宾斯基)三角形

(1)等边三角形外形

 Sierpinski三角形其实是一条曲线,内部面积为0。

(2)直角三角形外形

用DFS来构造的代码:

void dfs(Mat& img, int w, int h, int s)
{
	if (s == 1) {
		img.at<char>(w, h) = 1;
		return;
	}
	dfs(img, w, h, s / 2);
	dfs(img, w + s / 2, h, s / 2);
	dfs(img, w, h + s / 2, s / 2);
}
int main()
{
	int size = 512;
	Mat img = Mat::zeros(size, size, CV_8U) + 255;
	dfs(img, 0, 0, size);
	imshow("img", img);
	cv::waitKey(0);
	return 0;
}

用位运算来构造的代码:

int main()
{
	int size = 512;
	Mat img = Mat::zeros(size, size, CV_8U) + 255;
	for (int w = 0; w < size; w++) {
		for (int h = 0; h < size; h++) {
			if ((w | h) == size-1)img.at<char>(w, h) = 0;
		}
	}
	imshow("img", img);
	cv::waitKey(0);
	return 0;
}

(3)任意三角形外形

Sierpinski三角形有一个神奇的性质:如果某一个位置上有点(没被挖去),那么它与原三角形顶点的连线上的中点处也有点。利用这个性质,也可以用于构造曲线,从起点开始,每次根据已有的点产生新的点,不断累积即可形成曲线。

int main()
{
	int size = 512;
	Mat img = Mat::zeros(size, size, CV_8U) + 255;
	int w = 0, h = 0;
	int ws[] = { 0,0,size };
	int hs[] = { 0,size,0 };
	for (int i = 0; i < 20000; i++) {
		int r = rand() % 3;
		w = (w + ws[r]) / 2;
		h = (h + hs[r]) / 2;
		img.at<char>(w, h) = 0;
	}
	imshow("img", img);
	cv::waitKey(0);
	return 0;
}

更神奇的是,其实无论从哪个点(理论上是整个平面内任意一点)开始迭代,得到的分形三角形都是一样的。

而且,只要修改顶点坐标,就能得到任意外形的分形三角形:

	int ws[] = { 100,200,300 };
	int hs[] = { 400,500,100 };

6,Sierpinski地毯

和Sierpinski三角形差不多。

void dfs(Mat& img, int r, int c, int s)
{
	if (s == 1) return;
	s /= 3;
	for (int i = 0; i < 3; i++)for (int j = 0; j < 3; j++) {
		int r2 = r + s * i, c2 = c + s * j;
		if (i == 1 && j == 1) {
			for(int r=r2;r<r2+s;r++)for(int c=c2;c<c2+s;c++)img.at<char>(r, c) = 1;
		}
		else dfs(img, r2, c2, s);
	}
}

int main()
{
	int size = 9*9*9;
	Mat img = Mat::zeros(size, size, CV_8U) + 255;
	dfs(img, 0, 0, size);
	imshow("img", img);
	cv::waitKey(0);
	return 0;
}

二,其他分形

1,分形+镶嵌画

埃舍尔的画:圆形极限

2,三维图形

Menger海绵体,把Sierpinski地毯拓展到了三维

它的斜截面:

分形抽屉

3,Kögra分形字体

4,分形+不可能图形

Koch(科赫)雪花 + 彭罗斯三角

 Sierpinski(谢尔宾斯基)三角形 + 彭罗斯三角

Cantor(康托)集 + 恶魔的音叉

Hilbert(希尔伯特)曲线 + 恶魔的音叉

勾股树 + 彭罗斯三角

5,迭代与分形

迭代和分形可以说是差不多对应的概念, 从某种意义上来说,分形其实就是不停地迭代,

只不过,分形的对象一般是经过无穷迭代之后趋于有限的一个现象,从视觉上来看,很有艺术性,从数学上来看,开辟了分数维度等新领域。

包括无穷皇后的构造,我觉得也是分形。

三,分形维数

1,分维

分形图形的复杂程度可以用分维(分形维数)来进行定量的描述。

随着分形理论的发展 ,现在已经有多种测定和计算分形维数的方法 ,有通过改变观察尺度、根据测度关系、根据相关函数、根据分布函数和频谱求维数这 5 类方法。
例如变步长法就属于通过改变观察尺度求维数的方法。

2,Hausdorff 维数

现在用得较多的Hausdorff(豪斯多夫)维数 ,其定义是 :
把一个 D维的几何对象的每一维放大L 倍 ,则该对象就会相应放大 ,若放大倍数为 K ,则三者有以下的关系 : L^D = K,即 D= In K / InL
理论上有无穷种分维。

如果一个自相似形包含自身N份,每一份的一维大小都是原来的1/s,则这个相似形的Hausdorff维度为log(N)/log(s)

一个Koch曲线包含四个小Koch曲线,大小两个Koch曲线的相似比为1/3,因此Koch曲线的Hausdorff维度为log(4)/log(3)=1.26

一个Hilbert曲线包含自身4份,每一份的一维大小都是原来的一半,因此维度等于log(4)/log(2)=2

一个Sierpinski三角形包含自身3份,每一份的一维大小都是原来的一半,因此维度等于log(3)/log(2)=1.58

3,变步长法

变步长法是用具有一定特征长度 r 的线段所构成的折线来近似地代替曲线 ,改变 r 的值 , 从而求出分维的方法。

从曲线上的任一点出发 ,以 其为圆心 ,适当的步长 r 为半径作圆 ,圆与曲线交于二 点;再以一交点为圆心 , r 为半径 ,沿曲线的一个方向 (顺时针或逆时针) 作圆 ,如此重复下去 ,直到交点与出 发点的距离小于 r 为止。这样就可以得到步长 r 和步 数 N ( r) (即圆的个数) 这一组数据。改变步长 r,如图 1 中的 a1到 a2 ,重复上述过程 ,即可得到若干组 r 和 N ( r) 的数据。

根据N(r)*r^D是常数,可以求出D

四,实际应用

1,分形虎钳

几乎可以把任意形状的物体给紧紧的夹住。

五,待更新

分形几何  https://zhuanlan.zhihu.com/p/107069796 

分形相关puzzle 如分形芯片

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值