目录

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如下(图像已经过旋转处理):

/article/2017/04/01/ifs/ifs_tree.png
IFS-Tree

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

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

/article/2017/04/01/ifs/ifs_sprial.png
IFS-Spiral

/article/2017/04/01/ifs/ifs_flourish.png
IFS-Flourish

下面是随机生成的:

这张有些像宇宙星系!

{-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},

/article/2017/04/01/ifs/ifs_nebula.png
IFS-Nebula

这张有些抽象。

{-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},

/article/2017/04/01/ifs/ifs_ball.png
IFS-Ball