IFS

迭代函数系统 IFS(Iterated Function System),真的是简单即复杂。

IFS-System

几组二元一次方程组:
$$
x_{n+1}=ax_n+by_n+e\\
y_{n+1}=cx_n+by_n+f
$$
不同概率下迭代生成所有点的集合。

必要参数:

  • $n$ 组 $a,b,c,d,e,f$ 的参数
  • $n$ 个概率值 $p$,$\sum_0^np=1$
  • 一组起始点 $x_0,y_0$

一句话总结就是1

IFS = 二元一次方程组 + 参数表 + 概率

实现

使用 golang 生成 IFS 分形图形。
每次迭代需要掷骰子根据概率选择使用那组参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
const (
_IFS_PARAM_NUM = 7
)

func ifs_f(a, b, e, c, d, f float64, x, y float64) (float64, float64) {
x1 := a*x + b*y + e
y1 := c*x + d*y + f
return x1, y1
}

func ifs_cal(a [][]float64, x, y float64, r *rand.Rand) (float64, float64) {
if len(a) <= 0 || len(a[0]) != _IFS_PARAM_NUM {
return x, y
}
p := r.Float64()
c := 0.0
for i := 0; i < len(a); i++ {
c += a[i][_IFS_PARAM_NUM-1]
if p <= c {
x1, y1 := ifs_f(
a[i][0], a[i][1], a[i][4],
a[i][2], a[i][3], a[i][5],
x, y)
return x1, y1
}
}
return x, y
}

经过 n 次迭代将点画在画布上。
以下计算两次为了找到边界值,好转换坐标。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
func ifs(img *image.RGBA, limit_x, limit_y int) {
a := [][]float64{
// tree
{0.195, -0.488, 0.344, 0.433, 0.4431, 0.2452, 0.25},
{0.462, 0.414, -0.252, 0.361, 0.2511, 0.5692, 0.25},
{-0.058, -0.07, 0.453, -0.111, 0.5976, 0.0969, 0.25},
{-0.035, 0.07, -0.469, -0.022, 0.4884, 0.5069, 0.2},
{-0.637, 0, 0, 0.501, 0.8562, 0.2513, 0.05},
}

s := rand.NewSource(time.Now().Unix())
r := rand.New(s)

x0 := r.Float64()
y0 := r.Float64()

x, y := x0, y0
x_min, x_max := x, x
y_min, y_max := y, y

loop := limit_x * limit_y / 2
for i := 0; i < loop; i++ {
x, y = ifs_cal(a, x, y, r)
if x < x_min {
x_min = x
}
if x > x_max {
x_max = x
}
if y < y_min {
y_min = y
}
if y > y_max {
y_max = y
}
}
x, y = x0, y0
for i := 0; i < loop; i++ {
x, y = ifs_cal(a, x, y, r)
ix := (x - x_min) * float64(limit_x) / (x_max - x_min)
iy := (y - y_min) * float64(limit_y) / (y_max - y_min)
point(img, int(ix), int(iy), color.Gray{0})
}
}

生成树形图2如下(图像已经过旋转处理):

如果想要方程组参数自动生成可使用如下函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
func ifs_array_generate(r *rand.Rand) [][]float64 {
a := [][]float64{}
p := 0.0
for p < 1 {
tp := r.Float64()
if p+tp <= 1 {
p += tp
} else {
tp = 1 - p
p = 1
}
arr := [_IFS_PARAM_NUM]float64{}
arr[_IFS_PARAM_NUM-1] = tp
for i := 0; i < _IFS_PARAM_NUM-1; i++ {
arr[i] = 2*r.Float64() - 1
}
a = append(a, arr[:])
}
return a
}

欣赏

根据不同的参数可以生成不同的图像,以下为比较典型的一些3



下面是随机生成的:

这张有些像宇宙星系!

{-0.889272, 0.656922, -0.927109, -0.322378, 0.856565, 0.478706, 0.937723},
{0.411268, -0.581772, 0.998787, -0.631693, -0.731553, 0.226007, 0.0622774},

这张有些抽象。

{-0.872001, 0.0808141, 0.205013, 0.726129, -0.133041, -0.287383, 0.790841},
{0.148498, -0.880393, 0.901023, 0.567552, 0.99911, 0.760125, 0.209159},


IFS
https://wishlily.github.io/article/code/2017/04/01/undefined/
作者
Wishlily
发布于
2017年4月1日
许可协议