混沌分形之迭代函数系统(IFS)

IFS是分形的重要分支。它是分形图像处理中最富生命力而且最具有广阔应用前景的领域之一。这一工作最早可以追溯到Hutchinson于1981年对自相似集的研究。美国科学家M.F.Barnsley于1985年发展了这一分形构型系统,并命名为迭代函数系统(Iterated Function System,IFS),后来又由Stephen Demko等人将其公式化,并引入到图像合成领域中。IFS将待生成的图像看做是由许多与整体相似的(自相似)或经过一定变换与整体相似的(自仿射)小块拼贴而成。
算法:
1.设定一个起始点(x0,y0)及总的迭代步数。
2.以概率P选取仿射变换W,形式为
     X1=a*x0 + b*y0 + e
     Y1=c*x0 + d*y0 + f

     X1=(a * x0*cosf(c/180)) - (b * y0*sinf(d/180)) + e
     Y1=(a * x0*sinf(c/180)) + (b * y0*cosf(d/180)) + f
3.以W作用点(x0,y0),得到新坐标(x1,y1)。
4.令x0=x1,y0=y1。
5.在屏幕上打出(x0,y0)。
6.重返第2步,进行下一次迭代,直到迭代次数大于总步数为止。

(1)三角形

class IFSTriangle : public FractalEquation
{
public:
    IFSTriangle()
    {
        m_StartX = 0.0f;
        m_StartY = 0.0f;
        m_StartZ = 0.0f;

        m_ParamA = 0.0f;
        m_ParamB = 0.5f;

        //‘IFS码赋值
        m[0][0] = 0.5f; m[0][1] = 0; m[0][2] = 0;  m[0][3] = 0.5f;  m[0][4] = 0;     m[0][5] = 0;    m[0][6] = 0.333f;
        m[1][0] = 0.5f; m[1][1] = 0; m[1][2] = 0;  m[1][3] = 0.5f;  m[1][4] = 0.5f;  m[1][5] = 0;    m[1][6] = 0.333f;
        m[2][0] = 0.5f; m[2][1] = 0; m[2][2] = 0;  m[2][3] = 0.5f;  m[2][4] = 0.25f; m[2][5] = 0.5f; m[2][6] = 0.334f;
    }

    void IterateValue(float x, float y, float z, float& outX, float& outY, float& outZ) const
    {
        float a, b, c, d, e, f;    //‘仿射变幻中的系数

        float R = (float)rand()/RAND_MAX;

        if (R <= m[0][6])
        {
            a = m[0][0]; b = m[0][1]; c = m[0][2]; d = m[0][3]; e = m[0][4]; f = m[0][5];
        }
        else if (R <= m[0][6] + m[1][6])
        {
            a = m[1][0]; b = m[1][1]; c = m[1][2]; d = m[1][3]; e = m[1][4]; f = m[1][5];
        }
        else
        {
            a = m[2][0]; b = m[2][1]; c = m[2][2]; d = m[2][3]; e = m[2][4]; f = m[2][5];
        } 

        outX = (a * x) + (b * y) + e*FRACTAL_RADIUS;
        outY = (c * x) + (d * y) + f*FRACTAL_RADIUS;
        outZ = z;
    }

    bool IsValidParamA() const {return true;}
    bool IsValidParamB() const {return true;}

    void SetParamA(float v)
    {
        m_ParamA = v;
        m[2][1] = v;
    }

    void SetParamB(float v)
    {
        m_ParamB = v;
        m[2][0] = v;
        m[0][3] = v;
    }

private:
    float m[3][7];      // ‘存放IFS码
};

这里生成的是谢尔宾斯基三角形,但可以通过参数设置对其变形

(2)皇冠

class IFSCrown : public FractalEquation
{
public:
    IFSCrown()
    {
        m_StartX = 0.0f;
        m_StartY = 0.0f;
        m_StartZ = 0.0f;

        m_ParamA = 2.0f;

        //‘IFS码赋值
        m[0][0] = 0.5f;   m[0][1] = 0.5f;   m[0][2] = 0;  m[0][3] = 0;  m[0][4] = 0;    m[0][5] = 0;   m[0][6] = 0.2f;
        m[1][0] = 0.5f;   m[1][1] = 0.5f;   m[1][2] = 0;  m[1][3] = 0;  m[1][4] = 0.5f; m[1][5] = 0;   m[1][6] = 0.2f;
        m[2][0] = 0.25f;  m[2][1] = 0.25f;  m[2][2] = 0;  m[2][3] = 0;  m[2][4] = 2.0f; m[2][5] = 2.0f;m[2][6] = 0.3f;
        m[3][0] = 0.25f;  m[3][1] = 0.25f;  m[3][2] = 0;  m[3][3] = 0;  m[3][4] = -1.0f;m[3][5] = 2.0f;m[3][6] = 0.3f;
    }

    void IterateValue(float x, float y, float z, float& outX, float& outY, float& outZ) const
    {
        float a, b, c, d, e, f;    //‘仿射变幻中的系数

        float R = (float)rand()/RAND_MAX;

        if (R <= m[0][6])
        {
            a = m[0][0]; b = m[0][1]; c = m[0][2]; d = m[0][3]; e = m[0][4]; f = m[0][5];
        }
        else if (R <= m[0][6] + m[1][6])
        {
            a = m[1][0]; b = m[1][1]; c = m[1][2]; d = m[1][3]; e = m[1][4]; f = m[1][5];
        }
        else if (R <= m[0][6] + m[1][6] + m[2][6])
        {
            a = m[2][0]; b = m[2][1]; c = m[2][2]; d = m[2][3]; e = m[2][4]; f = m[2][5];
        }
        else
        {
            a = m[3][0]; b = m[3][1]; c = m[3][2]; d = m[3][3]; e = m[3][4]; f = m[3][5];
        }

        outX = (a * x*cosf(c/180)) - (b * y*sinf(d/180)) + e*FRACTAL_RADIUS;
        outY = (a * x*sinf(c/180)) + (b * y*cosf(d/180)) + f*FRACTAL_RADIUS;
        outZ = z;
    }

    bool IsValidParamA() const {return true;}

    void SetParamA(float v)
    {
        m_ParamA = v;
        m[2][4] = v;
        m[2][5] = v;
        m[3][4] = 1 - v;
        m[3][5] = v;
    }

private:
    float m[4][7];      // ‘存放IFS码
};

(3)芦苇

// 芦苇
class IFSBulrush : public FractalEquation
{
public:
    IFSBulrush()
    {
        m_StartX = 0.0f;
        m_StartY = 0.0f;
        m_StartZ = 0.0f;

        m_ParamA = 10.0f;

        float k = m_ParamA*100.0f;

        //‘IFS码赋值
        m[0][0] = 0.5f;  m[0][1] = 0.5f;  m[0][2] = 0;  m[0][3] = 0;  m[0][4] = 0;    m[0][5] = 0;        m[0][6] = 0.3f;
        m[1][0] = 0.5f;  m[1][1] = 0.5f;  m[1][2] = k;  m[1][3] = k;  m[1][4] = 1;    m[1][5] = k/1600;   m[1][6] = 0.3f;
        m[2][0] = 0.5f;  m[2][1] = 0.5f;  m[2][2] = 0;  m[2][3] = 0;  m[2][4] = 0.5f; m[2][5] = 0;        m[2][6] = 0.4f;
    }

    void IterateValue(float x, float y, float z, float& outX, float& outY, float& outZ) const
    {
        float a, b, c, d, e, f;    //‘仿射变幻中的系数

        float R = (float)rand()/RAND_MAX;

        if (R <= m[0][6])
        {
            a = m[0][0]; b = m[0][1]; c = m[0][2]; d = m[0][3]; e = m[0][4]; f = m[0][5];
        }
        else if (R <= m[0][6] + m[1][6])
        {
            a = m[1][0]; b = m[1][1]; c = m[1][2]; d = m[1][3]; e = m[1][4]; f = m[1][5];
        }
        else
        {
            a = m[2][0]; b = m[2][1]; c = m[2][2]; d = m[2][3]; e = m[2][4]; f = m[2][5];
        } 

        outX = (a * x*cosf(c/180)) - (b * y*sinf(d/180)) + e*FRACTAL_RADIUS;
        outY = (a * x*sinf(c/180)) + (b * y*cosf(d/180)) + f*FRACTAL_RADIUS;
        outZ = z;
    }

    bool IsValidParamA() const {return true;}

    void SetParamA(float v)
    {
        m_ParamA = v;
        float k = m_ParamA*100.0f;
        m[1][2] = k;
        m[1][3] = k;
        m[1][5] = k/1600;
    }

private:
    float m[3][7];      // ‘存放IFS码
};

(4)万花筒

// 万花筒
class IFSPhantoscope : public FractalEquation
{
public:
    IFSPhantoscope()
    {
        m_StartX = 0.0f;
        m_StartY = 0.0f;
        m_StartZ = 0.0f;

        m_ParamA = 2.0f;

        float k = m_ParamA*100.0f;

        //‘IFS码赋值
        m[0][0] = 0.2f;  m[0][1] = 0.2f;  m[0][2] = 0;  m[0][3] = 0;  m[0][4] = 0.7f; m[0][5] = 0;     m[0][6] = 0.2f;
        m[1][0] = 0.2f;  m[1][1] = 0.2f;  m[1][2] = 0;  m[1][3] = 0;  m[1][4] =-0.7f; m[1][5] = 0;     m[1][6] = 0.2f;
        m[2][0] = 0.2f;  m[2][1] = 0.2f;  m[2][2] = 0;  m[2][3] = 0;  m[2][4] = 0;    m[2][5] = 0.7f;  m[2][6] = 0.2f;
        m[3][0] = 0.2f;  m[3][1] = 0.2f;  m[3][2] = 0;  m[3][3] = 0;  m[3][4] = 0;    m[3][5] = -0.7f; m[3][6] = 0.2f;
        m[4][0] = 0.85f; m[4][1] = 0.85f; m[4][2] = k;  m[4][3] = k;  m[4][4] = 0;    m[4][5] = 0;     m[4][6] = 0.2f;
    }

    void IterateValue(float x, float y, float z, float& outX, float& outY, float& outZ) const
    {
        float a, b, c, d, e, f;    //‘仿射变幻中的系数

        float R = (float)rand()/RAND_MAX;

        if (R <= m[0][6])
        {
            a = m[0][0]; b = m[0][1]; c = m[0][2]; d = m[0][3]; e = m[0][4]; f = m[0][5];
        }
        else if (R <= m[0][6] + m[1][6])
        {
            a = m[1][0]; b = m[1][1]; c = m[1][2]; d = m[1][3]; e = m[1][4]; f = m[1][5];
        }
        else if (R <= m[0][6] + m[1][6] + m[2][6])
        {
            a = m[2][0]; b = m[2][1]; c = m[2][2]; d = m[2][3]; e = m[2][4]; f = m[2][5];
        }
        else if (R <= m[0][6] + m[1][6] + m[2][6] + m[3][6])
        {
            a = m[3][0]; b = m[3][1]; c = m[3][2]; d = m[3][3]; e = m[3][4]; f = m[3][5];
        }
        else
        {
            a = m[4][0]; b = m[4][1]; c = m[4][2]; d = m[4][3]; e = m[4][4]; f = m[4][5];
        }

        outX = (a * x*cosf(c/180)) - (b * y*sinf(d/180)) + e*FRACTAL_RADIUS;
        outY = (a * x*sinf(c/180)) + (b * y*cosf(d/180)) + f*FRACTAL_RADIUS;
        outZ = z;
    }

    bool IsValidParamA() const {return true;}

    void SetParamA(float v)
    {
        m_ParamA = v;
        float k = m_ParamA*100.0f;
        m[4][2] = k;
        m[4][3] = k;
    }

private:
    float m[5][7];      // ‘存放IFS码
};

(5)Tree

class IFSTree : public FractalEquation
{
public:
    IFSTree()
    {
        m_StartX = 0.0f;
        m_StartY = 0.0f;
        m_StartZ = 0.0f;

        //‘IFS码赋值
        m[0][0] = 0.195f;  m[0][1] =-0.488f; m[0][2] = 0.344f; m[0][3] = 0.433f; m[0][4] = 0.4431f; m[0][5] = 0.2452f; m[0][6] = 0.25f;
        m[1][0] = 0.462f;  m[1][1] = 0.414f; m[1][2] =-0.252f; m[1][3] = 0.361f; m[1][4] = 0.2511f; m[1][5] = 0.5692f; m[1][6] = 0.25f;
        m[2][0] =-0.058f;  m[2][1] =-0.07f;  m[2][2] = 0.453f; m[2][3] =-0.111f; m[2][4] = 0.5976f; m[2][5] = 0.0969f; m[2][6] = 0.25f;
        m[3][0] =-0.035f;  m[3][1] = 0.07f;  m[3][2] =-0.469f; m[3][3] =-0.022f; m[3][4] = 0.4884f; m[3][5] = 0.5069f; m[3][6] = 0.2f;
        m[4][0] =-0.637f;  m[4][1] = 0.0f;   m[4][2] = 0.0f;   m[4][3] = 0.501f; m[4][4] = 0.8562f; m[4][5] = 0.2513f; m[4][6] = 0.05f;
    }

    void IterateValue(float x, float y, float z, float& outX, float& outY, float& outZ) const
    {
        float a, b, c, d, e, f;    //‘仿射变幻中的系数

        float R = (float)rand()/RAND_MAX;

        if (R <= m[0][6])
        {
            a = m[0][0]; b = m[0][1]; c = m[0][2]; d = m[0][3]; e = m[0][4]; f = m[0][5];
        }
        else if (R <= m[0][6] + m[1][6])
        {
            a = m[1][0]; b = m[1][1]; c = m[1][2]; d = m[1][3]; e = m[1][4]; f = m[1][5];
        }
        else if (R <= m[0][6] + m[1][6] + m[2][6])
        {
            a = m[2][0]; b = m[2][1]; c = m[2][2]; d = m[2][3]; e = m[2][4]; f = m[2][5];
        }
        else if (R <= m[0][6] + m[1][6] + m[2][6] + m[3][6])
        {
            a = m[3][0]; b = m[3][1]; c = m[3][2]; d = m[3][3]; e = m[3][4]; f = m[3][5];
        }
        else
        {
            a = m[4][0]; b = m[4][1]; c = m[4][2]; d = m[4][3]; e = m[4][4]; f = m[4][5];
        }

        outX = a*x + b*y + e;
        outY = c*x + d*y + f;
        outZ = z;
    }

private:
    float m[5][7];      // ‘存放IFS码
};

这个图形我很喜欢,所以还专门将其生成图像:

(6)大脑

class IFSBrain : public FractalEquation
{
public:
    IFSBrain()
    {
        m_StartX = 0.0f;
        m_StartY = 0.0f;
        m_StartZ = 0.0f;

        //‘IFS码赋值
        //0.03  0       0       0.45    0   0     0.05;
        //-0.03 0       0       -0.45   0   0.4   0.15;
        //0.56  -0.56   0.56    0.56    0   0.4   0.4;
        //0.56  0.56    -0.56   0.56    0   0.4   0.4;
        m[0][0] = 0.03f;  m[0][1] = 0.0f;   m[0][2] = 0.0f;  m[0][3] = 0.45f; m[0][4] = 0.0f; m[0][5] = 0.0f; m[0][6] = 0.05f;
        m[1][0] =-0.03f;  m[1][1] = 0.0f;   m[1][2] = 0.0f;  m[1][3] =-0.45f; m[1][4] = 0.0f; m[1][5] = 0.4f; m[1][6] = 0.15f;
        m[2][0] = 0.56f;  m[2][1] =-0.56f;  m[2][2] = 0.56f; m[2][3] = 0.56f; m[2][4] = 0.0f; m[2][5] = 0.4f; m[2][6] = 0.4f;
        m[3][0] = 0.56f;  m[3][1] = 0.56f;  m[3][2] =-0.56f; m[3][3] = 0.56f; m[3][4] = 0.0f; m[3][5] = 0.4f; m[3][6] = 0.4f;
    }

    void IterateValue(float x, float y, float z, float& outX, float& outY, float& outZ) const
    {
        float a, b, c, d, e, f;    //‘仿射变幻中的系数

        float R = (float)rand()/RAND_MAX;

        if (R <= m[0][6])
        {
            a = m[0][0]; b = m[0][1]; c = m[0][2]; d = m[0][3]; e = m[0][4]; f = m[0][5];
        }
        else if (R <= m[0][6] + m[1][6])
        {
            a = m[1][0]; b = m[1][1]; c = m[1][2]; d = m[1][3]; e = m[1][4]; f = m[1][5];
        }
        else if (R <= m[0][6] + m[1][6] + m[2][6])
        {
            a = m[2][0]; b = m[2][1]; c = m[2][2]; d = m[2][3]; e = m[2][4]; f = m[2][5];
        }
        else
        {
            a = m[3][0]; b = m[3][1]; c = m[3][2]; d = m[3][3]; e = m[3][4]; f = m[3][5];
        } 

        outX = a*x + b*y + e;
        outY = c*x + d*y + f;
        outZ = z;
    }

private:
    float m[4][7];      // ‘存放IFS码
};

------------------------------------

关于基类FractalEquation的定义及相关软件见:混沌与分形

时间: 2024-07-29 00:33:08

混沌分形之迭代函数系统(IFS)的相关文章

混沌分形之逻辑斯蒂(Logistic)映射系统

前几天,有个同事看到我生成的一幅逻辑斯蒂分岔图像后,问我:“这是咪咪吗?”我回答:“淫者见淫.”好吧,这里将生成几种分岔映射图形,包括逻辑斯蒂映射系统,正弦映射系统和曼德勃罗映射系统.实际上这几种图形算不上分形,只不过它与我写的其他分形对象使用相同的基类,所以也将其列入混沌分形的范畴. 关于基类FractalEquation的定义及相关软件见:混沌与分形 (1)逻辑斯蒂映射系统 // 逻辑斯蒂映射系统 class LogisticMap : public FractalEquation { pu

混沌图像---马丁迭代【密集恐惧症患者慎入】

马丁迭代是我必需要讲的一个方程,因为之前看到一段由它生成图像的代码,我才开始研究混沌生成图像,并写了这个软件:YChaos生成混沌图像.马丁迭代图像的生成过程,如同生物的生长,一层层,一圈圈不停地变大变深变粗.虽然最终生成的图像看上去都差不多,但每一个参数下的图像的生成过程都不一样.最能体现混沌的是,马丁迭代的参数中,只要对任意一项,哪怕是极小的修改也会导致最终生成的数据完全不一样. 似乎网上关于它的资料很少,我只找到这么几句: 受Mandelbrot集产生思想的影响,Martin提出了一对公式

Excel 2016新增函数之IFS

Excel 2016新增函数之IFS 在2016年1月功能更新中,EXCEL 2016新增几个常用重要函数,主要有:ifs,switch,maxifs,minifs,concat,textjoin等. 注意,要能使用上述函数,Office的版本很重要,并不是所有的Office 2016能使用.建议 在https://products.office.com/zh-CN/try试用Office 365,安装最新版的Office 2016. 你也可以在通过Office 365安装程序进行在线安装.安装

Mathematica 迭代函数

学习Mathematica迭代函数的几个画图例子: 1.三角形沿着某一点旋转 verticse = {{0, 0}, {1, 0}, {1/2, Sqrt[3]/2}}; tri = Line[verticse /. {a_, b__}->{a, b, a}]; Graphics[tri] rotation[gr_] := Rotate[gr, Pi/13, {1, 1}]; Graphics[NestList[rotation, tri, 30]] 2.绘出迭代平移之后的三角形 transla

javascript学习笔记--迭代函数

概要 这里的迭代函数指的是对数组对象的操作方法,js数组共有五个迭代函数:every.fifter.forEach.map.some. 1.every every方法,返回值为Boolean类型,true表示数组中所有元素都满足条件,false表示数组中至少有一个不满足条件,代码如下: 1 var numbers = [1,2,3,4,5,4,3,2,1]; 2 numbers.every(function(item,index,array){ return item > 2; }) 3 输出:

python 内建迭代函数 iter()

内建迭代函数iter有两种使用方法,如下: 原文地址:https://www.cnblogs.com/bcyczhhb/p/11809838.html

混沌分形之马丁(Martin)迭代

我不记得从什么地方看到的这种分形图形生成方式,再到网上找竟然一时没查到任何相关资料.没关系,总之这种图形也很漂亮多变,并且其算法比较简单.只是我最后生成的图像有点瘆人,密集恐惧症患者慎入. 相关代码如下: class MartinIterate : public FractalEquation { public: MartinIterate() { m_StartX = 1.0f; m_StartY = 1.0f; m_StartZ = 0.0f; m_ParamA = 0.68f; m_Par

混沌分形之谢尔宾斯基(Sierpinski)

本文以使用混沌方法生成若干种谢尔宾斯基相关的分形图形. (1)谢尔宾斯基三角形 给三角形的3个顶点,和一个当前点,然后以以下的方式进行迭代处理: a.随机选择三角形的某一个顶点,计算出它与当前点的中点位置: b.将计算出的中点做为当前点,再重新执行操作a 相关代码如下: class SierpinskiTriangle : public FractalEquation { public: SierpinskiTriangle() { m_StartX = 0.0f; m_StartY = 0.0

混沌分形之填充集

通过分形来生成图像,有一个特点是:不想生成什么样的图像就写出相应的算法,而是生成出来的图像像什么,那算法就是什么.总之,当你在写这个算法时或设置相关参数时,你几乎无法猜测出你要生成的图像是什么样子.而生成图像的时间又比较久,无法实时地调整参数.所以我这使用了填充集的方式,先计算少量的顶点,以显示出图像的大致轮廓.确定好参数后再进行图像生成.所谓填充集,就是随机生成顶点位置,当满足要求时顶点保留,否则剔除.这里将填充集的方式来生成Julia集,曼德勃罗集和牛顿迭代集. (1)Julia集 // 填