Mandelbrot Set Julia Set -- 美丽分形 (C++, MFC + BCG + CxImage 实现)

article/2025/9/15 18:03:09

    一、分形(Fractal)

    这个概念应该很多人听过,说到这个应该就会提到最著名的Mandelbrot Set与Julia Set,最近便着手写了个能画出两者图形的一个小程序,环境为 VS2013 + BCG + CxImage。

    关于两者的概念,网上很多非常清晰的解释,这里便不再啰嗦,核心公式即

f(z) = z^2 + c

    Mandelbrot Set是在z = 0处,对复平面上每一点c进行迭代计算,若每一个 |f(z)| 小于2,则其属于集合内,当然,我们在计算机计算时只能设定一个迭代次数,超过迭代上限仍然模小于2的认为属于集合。

    Julia Set则是对于设定的一个常数c(其模假定小于2),对复平面内的每一点z进行迭代计算,若满足模小于2则属于集合,两者有差别,具体解释可以维基。

   二、 画图实现

    2.1 复数定义

class CComplex
{
public:~CComplex(){};CComplex(long double real = 0, long double imag = 0): m_real(real), m_imag(imag){}CComplex& operator +=(const CComplex &rhs){this->m_real += rhs.m_real;this->m_imag += rhs.m_imag;return *this;}CComplex& operator -=(const CComplex &rhs){this->m_real -= rhs.m_real;this->m_imag -= rhs.m_imag;return *this;}friend CComplex operator +(const CComplex &lhs, const CComplex &rhs);friend CComplex operator -(const CComplex &lhs, const CComplex &rhs);friend CComplex operator *(const CComplex &lhs, const CComplex &rhs);friend bool operator ==(const CComplex &lhs, const CComplex &rhs);inline friend double modulus_square(const CComplex & c){return c.m_real * c.m_real + c.m_imag * c.m_imag;}inline friend CComplex complex_power(const CComplex &c, unsigned int n){CComplex result(1);for (unsigned int i = 0; i < n; ++i)result = result * c;return result;}void setReal(long double real){this->m_real = real;}void setImag(long double imag){this->m_imag = imag;}private:long double m_real;long double m_imag;
};
CComplex operator +(const CComplex &lhs, const CComplex &rhs)
{CComplex result(lhs);result += rhs;return result;
}CComplex operator -(const CComplex &lhs, const CComplex &rhs)
{CComplex result(lhs);result -= rhs;return result;
}CComplex operator *(const CComplex &lhs, const CComplex &rhs)
{CComplex result(lhs.m_real * rhs.m_real - lhs.m_imag * rhs.m_imag,lhs.m_imag * rhs.m_real + lhs.m_real * rhs.m_imag);return result;
}bool operator ==(const CComplex &lhs, const CComplex &rhs)
{return lhs.m_real == rhs.m_real && lhs.m_imag == rhs.m_imag;
}

    2.2 迭代计算

    Mandelbrot 的计算代码如下(为速度考虑,使用了OpenMP多线程)

void CMandelSet::CalcImagePixel()
{if (!m_pxim) return;CxImage *pxim = m_pxim;int width = pxim->GetWidth();int height = pxim->GetHeight();#ifndef _DEBUG
#pragma omp parallel for
#endiffor (int i = 0; i < height; ++i){CComplex C(0, m_dFromY + (m_dToY - m_dFromY) * i / static_cast<long double>(height));for (int j = 0; j < width; ++j){C.setReal(m_dFromX + (m_dToX - m_dFromX) * j / static_cast<long double>(width));CComplex Z;int k = 0;for (k = 0; k < m_nIteration; ++k){if (modulus_square(Z) > 4.0) break;// f(z) = z^n + C;Z = complex_power(Z, m_nExponent) + C;}m_matImageInfo[j][i] = k;}}
}

    类似, Julia 的计算如下,

void CMandelSet::CalcImagePixel()
{if (!m_pxim) return;CxImage *pxim = m_pxim;int width = pxim->GetWidth();int height = pxim->GetHeight();#ifndef _DEBUG
#pragma omp parallel for
#endiffor (int i = 0; i < height; ++i){CComplex C(0, m_dFromY + (m_dToY - m_dFromY) * i / static_cast<long double>(height));for (int j = 0; j < width; ++j){C.setReal(m_dFromX + (m_dToX - m_dFromX) * j / static_cast<long double>(width));CComplex Z;int k = 0;for (k = 0; k < m_nIteration; ++k){if (modulus_square(Z) > 4.0) break;// f(z) = z^n + C;Z = complex_power(Z, m_nExponent) + C;}m_matImageInfo[j][i] = k;}}
}

    这里,为了后期调整颜色时无需重新计算,只是先把迭代次数记录进一个与图像同样大小的矩阵中,调整颜色时直接对图像的每个像素点按其迭代次数从调色板取颜色即可。


    2.3 颜色设定

    这里颜色的设定通过迭代次数来确定,借用HSL空间,保证L(Lightness)渐变,然后转到RGB空间进行着色,这里参考了网上yangw80的做法,先定义一个调色板,定义一共多少颜色数,我这里MAXCOLOR取了128,代码如下

void CFractal::InitPallette(double h1 /* = 137.0 */, double h2 /* = 30.0 */)
{for (int i = 0; i < MAXCOLOR / 2; ++i){m_crPallette[i] = HSL2RGB(h1, 1.0, i * 2.0 / double(MAXCOLOR));m_crPallette[MAXCOLOR - 1 - i] = HSL2RGB(h2, 1.0, i * 2.0 / double(MAXCOLOR));}
}
     为了后期能自己调整图形的颜色,我预留了接口用来调整色相 h1、h2 . HSL2RGB的转换,我在网上并没找到合理的函数,大多是HSV2RGB的,于是根据维基对 HSL Space -> RGB Space的转换条件,动手写了一个,如下

COLORREF CFractal::HSL2RGB(double h, double s, double l)
{const double C = (1 - fabs(2 * l - 1)) * s; // chromaconst double H = h / 60;const double X = C * (1 - fabs(fmod(H, 2) - 1));double rgb1[3] = { 0 };if (H > 0 && H < 1)  rgb1[0] = C, rgb1[1] = X, rgb1[2] = 0;else if (H >= 1 && H < 2) rgb1[0] = X, rgb1[1] = C, rgb1[2] = 0;else if (H >= 2 && H < 3) rgb1[0] = 0, rgb1[1] = C, rgb1[2] = X;else if (H >= 3 && H < 4) rgb1[0] = 0, rgb1[1] = X, rgb1[2] = C;else if (H >= 4 && H < 5) rgb1[0] = X, rgb1[1] = 0, rgb1[2] = C;else if (H >= 5 && H < 6) rgb1[0] = C, rgb1[1] = 0, rgb1[2] = X;else                      rgb1[0] = 0, rgb1[1] = 0, rgb1[2] = 0;const double m = l - 0.5 * C;return RGB((rgb1[0] + m) * 255, (rgb1[1] + m) * 255, (rgb1[2] + m) * 255);
}

    然后整幅图形的着色便是根据每一个像素点的迭代次数从调色板里的颜色取值,比如迭代次为1000次,则取 1000 % MAXCOLOR 相应调色板位置的颜色。


    2.4 结果

    下面为 Mandelbrot Set 的原图与一张局部放大图效果:


Julia 下面为 Julia Set 在C = 0.4 + 0.3i 时的原图及局部放大图




随便局部放大一下就是一张绝美的壁纸啊,有木有^_^。


    此外,Mandelbrot 还可以设置 F(z) = z^2 + c 的幂的大小,下面分别是 z^2、z^3、 z^4、 z^5 下的图形


    而对于 Julia 则可心通过设定不同的 C 值得到不同的图像,

    数学的美有时不得不令人惊叹!!!



http://chatgpt.dhexx.cn/article/iER3DYL5.shtml

相关文章

曼德布洛特集合 (Mandelbrot set)

如下方法,可以生成著名的曼德布洛特集合。 def Mandelbrot_set(): Y, X = np.mgrid[-1.3:1.3:0.005, -2:1:0.005] Z = X + 1j * Y c = tf.constant(Z.astype(np.complex64)) zs = tf.Variable© ns = tf.Variable(tf.zeros_like(c, tf.float32)) sess = tf.InteractiveSes…

JavaScript实现曼德勃罗(Mandelbrot)集合

运用知识: js线程、Mandelbrot 1. js线程 js线程简介: 在HTML5中的线程是这样一种机制&#xff0c;它允许在Web程序中并发执行多个JS脚本&#xff0c; 每一个脚本执行流都称为一个线程&#xff0c;彼此间相互独立&#xff0c;并且有浏览器中JS引擎 负责管理。 HTML5中的Web wo…

神奇的分形图像(一)-Fractal Image-Mandelbrot And Julia

分析学原理不做过多阐述&#xff1a;这里以举例子的方式加以阐述&#xff0c;更能通俗的理解其概念。 分形几何学是一门以不规则几何形态为研究对象的几何学 从上图&#xff0c;你能很清晰的回答出它们是直线、矩形、长方体、维度分别是1、2、3维 但是如下图形呢我们通常引入…

先睹为快_Mandelbrot集

本文引用自作者编写的下述图书; 本文允许以个人学习、教学等目的引用、讲授或转载&#xff0c;但需要注明原作者"海洋饼干叔 叔"&#xff1b;本文不允许以纸质及电子出版为目的进行抄摘或改编。 1.《Python编程基础及应用》&#xff0c;陈波&#xff0c;刘慧君&#…

用Python画Mandelbrot集

Mandelbrot Set&#xff08;曼德勃罗集&#xff09;可能是分形 图形中最有名的图形&#xff0c;关于它的介绍我就不多写了&#xff0c;有兴趣的可以参考这个链接 。下面是关于如何使用Python来画这个图形的尝试。 由于Python标准库中还没有对图形处理的支持&#xff0c;在此我使…

Mandelbrot Set (曼德布洛特集) VC 源代码

关于 Mandelbrot Set (曼德布洛特集) 的介绍什么的我就不多说了&#xff0c;网上一大堆。唯独清晰的代码不好找&#xff0c;所以我就贴代码吧&#xff1a; // 需要安装 EasyX 库&#xff0c;Visual C 6.0 下编译通过 #include <graphics.h> #include <conio.h> / /…

Bellman-ford算法详解

什么是Bellman-ford算法 贝尔曼-福特算法&#xff08;Bellman-Ford&#xff09;是由理查德贝尔曼&#xff08;Richard Bellman&#xff09;和莱斯特福特创立的&#xff0c;求解单源最短路径问题的一种算法。其优于Dijkstra的方面是边的权值可以为负数、实现简单&#xff0c;缺…

分形(Fractal)及分形维数(Fractal dimension)

文章目录 1. 分形介绍2. 分形的定义3. 分形维数介绍4. 历史5. 缩放的作用&#xff08;Role of scaling&#xff09;6. D 不是唯一描述符7. 分形表面结构8. 例子8.8 Hausdorff dimension8.8.1 直观概念8.8.2 正式定义8.8.2.1 Hausdorff dimension8.8.2.2 Hausdorff content 8.8.…

Mandelbrot集的最新变化形态一览——MandelBox,Mandelbulb,Burning Ship,NebulaBrot

二维Mandelbrot集——Burning Ship 采用以下迭代公式 (x4-6*x2*y2y4, 4*|x|3*|y|-4*|y|3*|x|) 看不懂的&#xff0c;可以去学习深造了。。。 Mandelbulb 这个3D的Mandelbrot集采用的是以下公式&#xff0c;这应该算是超复数的一种&#xff0c;人称“triplex”&#xff0c;三…

Mandelbrot集Julia集分形的MATLAB实现(分形艺术)

Mandelbrot集Julia集分形的MATLAB实现&#xff08;分形艺术&#xff09; 1 简单Julia集的实现1.1 如何实现更光滑的展示效果&#xff1f; 2 Mandelbrot集的实现3 永恒的细节 本文首发于 matlab爱好者 微信公众号&#xff0c;欢迎关注。 惯例声明&#xff1a;本人没有相关的工程…

神奇的分形艺术: Mandelbrot集和Julia集

前言 这段时间看了一个关于维度的视频介绍&#xff0c;叹于其惊艳的多维几何体和分形的视觉动画效果。其实关于分形&#xff0c;已经有很成熟的分形软件和应用场景&#xff0c;可以参看目前流行的分形软件一览&#xff0c;不过没有及时更新&#xff0c;有些链接已经进不了&…

MATLAB | 分形的艺术——(Mandelbrot)曼德勃罗特集合

PART.0 Mandelbrot 介绍 “无规则的碎片” “魔鬼的聚合物” “上帝的指纹” Mandelbrot集合有着多种称谓&#xff0c;那么什么是曼德勃罗特集&#xff1f;Mandelbrot集合可以用复二次多项式&#xff1a; f c ( z ) z 2 c f_c(z)z^2c fc​(z)z2c 来表示&#xff0c;其中c是…

神奇的Python-实现曼德布洛特(Mandelbrot)集合(一行代码,matplotlib numpy,tensorflow)分别实现

神奇的Python-实现曼德布洛特(Mandelbrot)集合(一行代码&#xff0c;matplotlib numpy&#xff0c;tensorflow)分别实现 Mandelbrot图实际上是由Mandelbrot集合构成的图像。 Mandelbrot集合的定义如下&#xff1a; z n 1 z n 2 c z_{n1}z^2_nc zn1​zn2​c 其中&#xff…

曼德勃罗集(Mandelbrot Set)

先来膜拜一下大神&#xff01; 曼德勃罗(Benoit B. Mandelbrot)&#xff0c;数学家、经济学家&#xff0c;分形理论的创始人。1924年生于波兰华沙&#xff1b;1936年随全家移居法国巴黎&#xff0c;在那里经历了动荡的二战时期&#xff1b;1948年在帕萨迪纳获得航空硕士学位&am…

用matlab画Mandelbrot(曼德布罗特)图

Mandelbrot图实际上是由Mandelbrot集合构成的图像。 Mandelbrot集合的定义如下&#xff1a; zn1z2nc 其中&#xff0c;c是一个复数。加入给定一个复数 z0 &#xff0c;比如 z00 &#xff0c;那么这个递推式会生成一个序列&#xff1a; [z0,z1,z2,z3,...] 。如果这个序列收敛…

Mandelbrot 并行实现

最近要交并行计算的作业了,这周终于把作业写了个大概,这期间感觉学了不少东西,总结一下。 Mandelbrot Set 背景 前几天逛维基百科的时候看到了如下的消息:著名数学家、分形之父Benot B. Mandelbrot(中文名本华曼德博)美国时间10月15日辞世,享年85岁。 “1979年,在哈…

Mastering Qt 5 学习笔记-Mandelbrot

是一个 Mandelbrot 分形的多线程计算。 用户将看到分形&#xff0c;并能够在该窗口中平移和缩放。Mandelbrot 分形是一个处理复数 (a bi) 的数值集&#xff0c;该图像中的每个黑色像素都趋向于发散到一个无限值&#xff0c;&#xff0c;而绿色像素则有界于一个有限值。绿色像素…

Mandelbrot集合及其渲染

什么是Mandelbrot集合&#xff1f; Mandelbrot集合是在复数平面上组成分形的点的集合&#xff0c;它正是以数学家Mandelbrot命名。 Mandelbrot集合可以用复二次多项式\[ f_c(z)z^2c \] 来定义 其中c是一个复数。对于每一个c&#xff0c;从\(z 0\),开始对\(f_c(z)\)进行迭代。 …

分形之父 Mandelbrot

著名数学家&#xff0c;被誉为分形之父的Mandelbrot先生&#xff0c;美国时间10月15日在马萨诸塞州剑桥辞世&#xff0c;享年85岁。他用“美丽”改变了我们的世界观&#xff0c;他被认为是20世纪后半叶少有的影响深远而且广泛的科学伟人之一&#xff0c;1993年他获得沃尔夫物理…

Ettercap系列 II:基于命令行界面(结合driftnet截获目标机器正在浏览的图片)

相信跟着这个系列走&#xff0c;一直看到这篇文章的读者已经了解了基于图形化Ettercap的操作&#xff0c;并对Arp欺骗和Ettercap相关的术语有所了解。本篇就如何在命令行界面下操作ettercap&#xff0c;以实现与图形化界面相同的效果展开讨论。可能你会不解&#xff1a;既然我已…