随笔 - 373  文章 - 1  评论 - 771  阅读 - 137万

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

本文以使用混沌方法生成若干种谢尔宾斯基相关的分形图形。

(1)谢尔宾斯基三角形

给三角形的3个顶点,和一个当前点,然后以以下的方式进行迭代处理:

a.随机选择三角形的某一个顶点,计算出它与当前点的中点位置;

b.将计算出的中点做为当前点,再重新执行操作a

相关代码如下:

复制代码
class SierpinskiTriangle : public FractalEquation
{
public:
    SierpinskiTriangle()
    {
        m_StartX = 0.0f;
        m_StartY = 0.0f;
        m_StartZ = 0.0f;

        m_triangleX[0] = 0.0f;
        m_triangleY[0] = FRACTAL_RADIUS;

        m_triangleX[1] = FRACTAL_RADIUS*sinf(PI/3);
        m_triangleY[1] = -FRACTAL_RADIUS*sinf(PI/6);

        m_triangleX[2] = -m_triangleX[1];
        m_triangleY[2] = m_triangleY[1];
    }

    void IterateValue(float x, float y, float z, float& outX, float& outY, float& outZ) const
    {
        int r = rand()%3;
        outX = (x + m_triangleX[r])*0.5f;
        outY = (y + m_triangleY[r])*0.5f;
        outZ = z;
    }

private:
    float m_triangleX[3];
    float m_triangleY[3];
};
复制代码

关于基类FractalEquation的定义见:混沌与分形

最终生成的图形为:

通过这一算法可以生成如下图像:

(2)谢尔宾斯基矩形

既然能生成三角形的图形,那么对于矩形会如何呢?尝试下吧:

复制代码
class SierpinskiRectangle : public FractalEquation
{
public:
    SierpinskiRectangle()
    {
        m_StartX = 0.0f;
        m_StartY = 0.0f;
        m_StartZ = 0.0f;

        m_ParamA = 1.0f;
        m_ParamB = 1.0f;

        m_rectX[0] = FRACTAL_RADIUS;
        m_rectY[0] = FRACTAL_RADIUS;

        m_rectX[1] = FRACTAL_RADIUS;
        m_rectY[1] = -FRACTAL_RADIUS;

        m_rectX[2] = -FRACTAL_RADIUS;
        m_rectY[2] = -FRACTAL_RADIUS;

        m_rectX[3] = -FRACTAL_RADIUS;
        m_rectY[3] = FRACTAL_RADIUS;
    }

    void IterateValue(float x, float y, float z, float& outX, float& outY, float& outZ) const
    {
        int r = rand()%4;
        outX = (x + m_rectX[r])*0.5f;
        outY = (y + m_rectY[r])*0.5f;
        outZ = z;
    }

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

    void SetParamA(float v)
    {
        m_ParamA = v;

        m_rectX[0] = FRACTAL_RADIUS*m_ParamA;
        m_rectX[1] = FRACTAL_RADIUS*m_ParamA;
        m_rectX[2] = -FRACTAL_RADIUS*m_ParamA;
        m_rectX[3] = -FRACTAL_RADIUS*m_ParamA;
    }

    void SetParamB(float v)
    {
        m_ParamB = v;

        m_rectY[0] = FRACTAL_RADIUS*m_ParamB;
        m_rectY[1] = -FRACTAL_RADIUS*m_ParamB;
        m_rectY[2] = -FRACTAL_RADIUS*m_ParamB;
        m_rectY[3] = FRACTAL_RADIUS*m_ParamB;
    }

private:
    float m_rectX[4];
    float m_rectY[4];
};
复制代码

图形如下:

噢,SHIT,毫无规律可言。

那就变动一下吧:

复制代码
class FractalSquare : public FractalEquation
{
public:
    FractalSquare()
    {
        m_StartX = 0.0f;
        m_StartY = 0.0f;
        m_StartZ = 0.0f;

        m_rectX[0] = FRACTAL_RADIUS;
        m_rectY[0] = FRACTAL_RADIUS;

        m_rectX[1] = FRACTAL_RADIUS;
        m_rectY[1] = -FRACTAL_RADIUS;

        m_rectX[2] = -FRACTAL_RADIUS;
        m_rectY[2] = -FRACTAL_RADIUS;

        m_rectX[3] = -FRACTAL_RADIUS;
        m_rectY[3] = FRACTAL_RADIUS;
    }

    void IterateValue(float x, float y, float z, float& outX, float& outY, float& outZ) const
    {
        int r = rand()%10;
        if (r < 4)
        {
            outX = (x + m_rectX[r])*0.5f;
            outY = (y + m_rectY[r])*0.5f;
        }
        else
        {
            outX = x*0.5f;
            outY = y*0.5f;
        }
        outZ = z;
    }

private:
    float m_rectX[4];
    float m_rectY[4];
};
复制代码

看上去还有点样。

(3)谢尔宾斯基五边形

四边形是不行的,那再试下五边:

复制代码
// 五边形
class SierpinskiPentagon : public FractalEquation
{
public:
    SierpinskiPentagon()
    {
        m_StartX = 0.0f;
        m_StartY = 0.0f;
        m_StartZ = 0.0f;

        for (int i = 0; i < 5; i++)
        {
            m_pentagonX[i] = sinf(i*PI*2/5);
            m_pentagonY[i] = cosf(i*PI*2/5);
        }
    }

    void IterateValue(float x, float y, float z, float& outX, float& outY, float& outZ) const
    {
        int r = rand()%5;
        outX = (x + m_pentagonX[r])*0.5f;
        outY = (y + m_pentagonY[r])*0.5f;
        outZ = z;
    }

private:
    float m_pentagonX[5];
    float m_pentagonY[5];
};
复制代码

有点样子,那就以此算法为基础,生成幅图像看看:

有人称谢尔宾斯基三角形为谢尔宾斯基坟垛,当我看到这幅图时,有一种恐怖的感觉。邪恶的五角形,总感觉里面有数不清的骷髅。

看来二维空间中谢尔宾斯基的单数可以生成分形图形,而双数则为无序的混沌。

(4)谢尔宾斯基四面体

再由二维扩展到三维看看:

复制代码
class SierpinskiTetrahedron : public FractalEquation
{
public:
    SierpinskiTetrahedron()
    {
        m_StartX = 0.0f;
        m_StartY = 0.0f;
        m_StartZ = 0.0f;

        m_vTetrahedron[0] = YsVector(0.0f, 0.0f, 0.0f);
        m_vTetrahedron[1] = YsVector(0.0f, 1.0f, 0.0f);
        m_vTetrahedron[2] = YsVector(YD_REAL_SQRT_3/2, 0.5f, 0.0f);
        m_vTetrahedron[3] = YsVector(YD_REAL_SQRT_3/6, 0.5f, YD_REAL_SQRT_3*YD_REAL_SQRT_2/3);

        YsVector vCenter = m_vTetrahedron[0] + m_vTetrahedron[1] + m_vTetrahedron[2] + m_vTetrahedron[3];
        vCenter *= 0.25f;

        m_vTetrahedron[0] -= vCenter;
        m_vTetrahedron[1] -= vCenter;
        m_vTetrahedron[2] -= vCenter;
        m_vTetrahedron[3] -= vCenter;

        m_vTetrahedron[0] *= FRACTAL_RADIUS;
        m_vTetrahedron[1] *= FRACTAL_RADIUS;
        m_vTetrahedron[2] *= FRACTAL_RADIUS;
        m_vTetrahedron[3] *= FRACTAL_RADIUS;
    }

    void IterateValue(float x, float y, float z, float& outX, float& outY, float& outZ) const
    {
        int r = rand()%4;
        outX = (x + m_vTetrahedron[r].x)*0.5f;
        outY = (y + m_vTetrahedron[r].y)*0.5f;
        outZ = (z + m_vTetrahedron[r].z)*0.5f;
    }

    bool Is3D() const {return true;}

private:
    YsVector m_vTetrahedron[4];
};
复制代码

(5)其他

谢尔宾斯基三角形是一种很神的东西,我写过一些生成图像的算法,常常不知不觉中就出现了谢尔宾斯基三角形。如细胞生长机

再如:

之前我写过几篇与谢尔宾斯基分形相关的文章

分形之谢尔宾斯基(Sierpinski)三角形

分形之谢尔宾斯基(Sierpinski)地毯

分形之谢尔宾斯基(Sierpinski)四面体

 

posted on   叶飞影  阅读(5114)  评论(2编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
< 2025年3月 >
23 24 25 26 27 28 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 1 2 3 4 5

点击右上角即可分享
微信分享提示