曼德勃罗特集是人类有史以来做出的最奇异,最瑰丽的几何图形.曾被称为“上帝的指纹”。 这个点集均出自公式:Zn+1=(Zn)^2+C。(此处Z、C均为复数)所有使得该公式无限迭代后的结果能保持有限数值的复数C的集合,构成曼德勃罗集。

曼德勃罗集:



看起来十分美丽和神秘,接下来就让我们用程序来绘制它。


在编写代码之前,我们先要了解这个图片中不同颜色所代表的含义。

首先注意到的自然是占面积最大的中央黑色。黑色代表在迭代次数达到上限后其模仍小于某固定值(这里为2)的所有点。

周围的渐变色则是由点的发散速度决定的,即经过了多少次迭代,其模值开始大于2。

程序主体分为以下四个方面

1. 计算迭代次数,也就是它的发散速度。迭代次数越少,其发散速度越快。

int k=0;
for (; k < 1000; k++)
{
if (z.get_mod2() > 4.0) break;
z = z * z + c;
}

2. 对坐标系统进行一定的缩放来与显示区域的坐标系统相匹配.

假设显示高度为disp_height,宽度为disp_width.而点在显示区域中的位置为(x, y).如果显

示复数平面的这个窗口具有最小值(real_min, imag_min)和最大值(real_max, imag_max),则每

个点需用以下系数加以缩放.

c.real = real_min + x * (real_max - real_min) / disp_width;
c.imag = imag_min + y * (imag_max - imag_min) / disp_height;

3. 配色

为了使得绘制出的图形更漂亮,一个好的配色方案是少不了的。这里我使用的是以下函数生成的配色:

void InitColor()
{
// 使用 HSL 颜色模式产生角度 h1 到 h2 的渐变色
int h1 = 240, h2 = 30;
for (int i = 0; i<MAXCOLOR / 2; i++)
{
Color[i] = HSLtoRGB((float)h1, 1.0f, i * 2.0f / MAXCOLOR);
Color[MAXCOLOR - 1 - i] = HSLtoRGB((float)h2, 1.0f, i * 2.0f / MAXCOLOR);
}
}

4. ppm文件的格式

文件头部分

image << "P6\n"  //PPM magic number
<< width << ' ' //width, in ASCII decimal
<< height << '\n' //height, in ASCII decimal
<< 255<<'\n'; //maximum color value, in ASCII decimal

第一行是P2/P3/P6

第二行是图像的大小,先是行像素数,后是列像素数,中间有一个空格

第三行是一个介于1和65535之间的整数,而且必须是文本的,用来表示每一个像素的一个分量用几个比特表示。

图象数据部分

P6格式,图象数据以字节格式存储,每个色彩成分(R,G,B)一个字节,3个字节为一个像素点。

参考代码:

#include<iostream>
#include<string>
#include<fstream>
using namespace std; struct pixel //单个像素
{
char r, g, b;
}; class Complex
{
public:
Complex(double real = 0, double imag = 0) :real(real), imag(imag){}
Complex(Complex& com) :real(com.real), imag(com.imag){}
double& operator[](int i){ return i == 0 ? real : imag; }
double get_mod2(){ return pow(real, 2) + pow(imag, 2); }
Complex& operator=(Complex& com){ real = com.real; imag = com.imag; return *this; }
Complex operator+(Complex& com){ return Complex(real + com.real, imag + com.imag); }
Complex operator*(Complex& com){ return Complex(real*com.real - imag*com.imag, real*com.imag + imag*com.real); } private:
double real, imag;
}; class Mandelbrot
{
public:
Mandelbrot(int _width=640, int _height=480)
:path(path), width(_width), height(_height){}
~Mandelbrot(){}
public:
void set_path(string path)
{
this->path = path;
}
void draw(double from_x,double to_x,double from_y,double to_y) //图片保存路径
{
create_image();
write_head(); for (int y = 0; y < height; y++)
{
Complex c(0, from_y + (to_y - from_y) * y / (double)height);
for (int x = 0; x < width; x++)
{
c[0] = from_x + (to_x - from_x) * x / (double)width;
Complex z(0, 0);
int k;
for (k = 0; k < 1000; k++)
{
if (z.get_mod2() > 4.0) break;
z = z * z + c;
}
pixel p = { Color[k % 64].b, Color[k % 64].g,
Color[k % 64].r
};
pixel q = { 0, 0, 0 };
if (k == 1000) //收敛
{
image.write((char*)&q,sizeof(q));
}
else //发散
{
image.write((char*)&p,sizeof(p));
}
}
}
image.close();
}
void get_color(string path)
{
color.open(path,ios::binary);
for (int i = 0; i < 64; ++i)
{
color.read((char*)&Color[i], sizeof(pixel));
}
color.close();
}
int get_fileSize(){ return height*width*sizeof(pixel) / 1024; } //KB
private:
ofstream image;
ifstream color;
void create_image()
{
image.open(path,ios::binary);
}
void write_head() //文件头
{
image << "P6\n"
<< "#Mandelbrot Set\n"
<< width << ' '
<< height << '\n'
<< 255<<'\n';
} int width, height; //图片尺寸
pixel Color[64];
string path;
}; int main()
{ Mandelbrot test;
test.set_path("Mandelbrot.ppm");
test.get_color("color.dat"); //从文件中读取颜色数据
cout << test.get_fileSize()<<"KB";
test.draw(-2.1, 1.1, -1.2, 1.2); return 0;
}

---参考自:http://codebus.easyx.cn/yw80/post/zoomable-mandelbrot-set

【C++】Mandelbrot集绘制(生成ppm文件)的更多相关文章

  1. 广义mandelbrot集,使用python的matplotlib绘制,支持放大缩小

    迭代公式的指数,使用的1+5j,这是个复数.所以是广义mandelbrot集,大家能够自行改动指数,得到其它图形.各种库安装不全的,自行想办法,能够在这个站点找到差点儿全部的python库 http: ...

  2. 使用OpenGL进行Mandelbrot集的可视化

    Mandelbrot集是哪一集?? Mandelbrot集不是哪一集!! 啊不对-- Mandelbrot集是哪一集!! 好像也不对-- Mandelbrot集是数集!! 所以--他不是一集而是数集? ...

  3. 获得mysql内容,生成xml文件,另外,为了webservice发送

    <xyt> <news id> <url></url> <title></title> </news> </x ...

  4. [原创] 利用前端+php批量生成html文件,传入新文本,输出新的html文件

    本人因为要想自己写个小说网站练练手,在其中遇到的一些问题,将其解决方法总结出来,例如: 1:小说网站存储了大量的小说,每个小说主页都很相似,url不同,不是使用的history属性改写的,所以如果人工 ...

  5. java自动生成entity文件

    网上关于自动生成entity文件的代码很多,看了很多代码后,在先辈们的基础上再完善一些功能(指定多个表,全部表). 为了使用方便所以把两个类写在一个java文件中,所以大家可以直接拿这个java文件, ...

  6. Java 动态生成 PDF 文件

    每片文章前来首小诗:   今日夕阳伴薄雾,印着雪墙笑开颜.我心仿佛出窗前,浮在半腰望西天.  --泥沙砖瓦浆木匠 需求: 项目里面有需要java动态生成 PDF 文件,提供下载.今天我找了下有关了,系 ...

  7. spark中saveAsTextFile如何最终生成一个文件

    原文地址: http://www.cnblogs.com/029zz010buct/p/4685173.html 一般而言,saveAsTextFile会按照执行task的多少生成多少个文件,比如pa ...

  8. Java多线程之赛跑游戏(含生成exe文件)

    在JavaSE中,多线程是一个重要的内容. 我们要了解多线程的概念,就要先了解进程的概念:要了解进程的概念,就离不开操作系统的概念. 在一台正常运行的电脑中,计算机硬件(如CPU.内存.硬盘.网卡.显 ...

  9. Spark中如何生成Avro文件

    研究spark的目的之一就是要取代MR,目前我司MR的一个典型应用场景即为生成Avro文件,然后加载到HIVE表里,所以如何在Spark中生成Avro文件,就是必然之路了. 我本人由于对java不熟, ...

随机推荐

  1. 1.理解Numpy、pandas

    之前一直做得只是采集数据,而没有再做后期对数据的处理分析工作,自己也是有意愿去往这些方向学习的,最近就在慢慢的接触. 首先简单理解一下numpy和pandas:一.NumPy:1.NumPy是高性能计 ...

  2. 27.Docker集群部署

    对于scrapy的部署方式 1.Scrapyd 安装扩展组件,远程控制scrapy任务,包括部署源代码,启动任务,监听任务.scrapy-client .scrapyd api 协助完成部署和监听操作 ...

  3. cookie、localStorage、sessionStorage和会话控制机制

    简介 cookie cookie的内容主要包括:名字Name.值Value.域Domain.路径Path.过期时间Expires/Max-Age.大小Size.HTTP.Secure.SameSite ...

  4. ThinkPHP输入验证和I方法使用

    在Web开发过程中,我们经常需要获取系统变量或者用户提交的数据,这些变量数据错综复杂,而且一不小心就容易引起安全隐患,但是如果利用好ThinkPHP提供的变量获取功能,就可以轻松的获取和驾驭变量了. ...

  5. 【Source Insight 】之marco学习笔记1

    我们学习编程语言都是从Hello World!,现在我们学习marco也不例外 打开C:\Users\%USERPROFILE%\Documents\Source Insight 4.0\Projec ...

  6. Oracle表复杂查询

    转自:https://www.cnblogs.com/w-gao/p/7288293.html Oracle表复杂查询 聚合函数 max(字段值)  -- 求最大值 min(字段值)  -- 求最小值 ...

  7. react-native android 和ios 集成 jpush-react-native 激光推送

    安装 $ npm install jpush-react-native --save # jpush-react-native 版本以后需要同时安装 jcore-react-native $ npm ...

  8. Spring cloud(2)B Eureka 注册微服务到服务中心

    1.在provide上添加pom(必须加上web)   如果不加 启动后就会自己关闭 <dependency> <groupId>org.springframework.clo ...

  9. linux输入密码的实现

    可以使用 getpass 这个函数,无回显的密码,为什么无回显,因为Linux的开发者一般认为不回显比显示为*更安全(比如当密码只有一两位长度的时候,设置为*几乎没有一点安全性). char *get ...

  10. 机器学习进阶-案例实战-图像全景拼接-图像全景拼接(RANSCA) 1.sift.detectAndComputer(获得sift图像关键点) 2.cv2.findHomography(计算单应性矩阵H) 3.cv2.warpPerspective(获得单应性变化后的图像) 4.cv2.line(对关键点位置进行连线画图)

    1. sift.detectAndComputer(gray, None)  # 计算出图像的关键点和sift特征向量 参数说明:gray表示输入的图片 2.cv2.findHomography(kp ...