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 分形图形。
每次迭代需要掷骰子根据概率选择使用那组参数:
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 次迭代将点画在画布上。
以下计算两次为了找到边界值,好转换坐标。
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如下(图像已经过旋转处理):
如果想要方程组参数自动生成可使用如下函数:
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},