赞
踩
Mandelbrot集
是人类有史以来做出的最奇异,最瑰丽的几何图形,曾被称为“上帝的指纹”。
这个点集均出自公式: Z n + 1 = Z n 2 + C Z_{n+1} = Z_n^2 +C Zn+1=Zn2+C,对于非线性迭代公式 Z n + 1 = Z n 2 + C Z_{n+1} = Z_n^2 +C Zn+1=Zn2+C,
所有使得无限迭代后的结果能保持有限数值的复数C的集合,构成Mandelbrot集
.
公式: Z n + 1 = Z n 2 + C Z_{n+1} = Z_n^2 +C Zn+1=Zn2+C
复数 Z = a + bi
分析 :
主线程,负责绘制Mandelbrot图像(渲染线程RenderThread传递过来的Mandelbrot图像引用)
渲染线程,负责迭代计算生成Mandelbrot图像,完成时传递参数给主线程绘制
/*! * \brief 外部调用,启动渲染,传入渲染参数(QMutexLocker保护) * \param centerX 中心x * \param centerY 中心y * \param scaleFactor 缩放比例 * \param resultSize 结果大小 */ void RenderThread::render(double centerX, double centerY, double scaleFactor,QSize resultSize) { QMutexLocker locker(&mutex); this->centerX = centerX; this->centerY = centerY; this->scaleFactor = scaleFactor; this->resultSize = resultSize; if (!isRunning()) {//--启动 start(LowPriority); } else {//--重启唤醒休眠的渲染线程 restart = true; condition.wakeOne(); } }
void RenderThread::run() { forever { //--mutex保护访问临界区资源 //--传入参数 mutex.lock(); QSize resultSize = this->resultSize; double scaleFactor = this->scaleFactor; double centerX = this->centerX; double centerY = this->centerY; mutex.unlock(); int halfWidth = resultSize.width() / 2; int halfHeight = resultSize.height() / 2; //--QImage::Format_RGB32 存储使用32位RGB格式的图像(0xffrrggbb)透明度a最大 QImage image(resultSize, QImage::Format_RGB32); ///-此数越大 图像精细度越高 const int NumPasses = 8; int pass = 0; while (pass < NumPasses) { /// \brief 最大迭代 const int MaxIterations = (1 << (2 * pass + 6)) + 32; /// \brief 幅值 Limit = 2^2 = 4 const int Limit = 4; bool allBlack = true; //--逐行扫描,生成图像 for (int y = -halfHeight; y < halfHeight; ++y) { //--重启 if (restart) break; //--终止 if (abort) return; //--读取当前行第一个像素 uint *scanLine = reinterpret_cast<uint *>(image.scanLine(y + halfHeight)); ///--虚部 double ay = centerY + (y * scaleFactor); //--每行逐个扫描像素 //--单个像素满足复平面函数关系Mandelbrot 集 for (int x = -halfWidth; x < halfWidth; ++x) { ///--实部 double ax = centerX + (x * scaleFactor); double a1 = ax; double b1 = ay; /// \brief 当前迭代次数 int numIterations = 0; //--单个像素点处,迭代计算 //--Mandelbrot 集: // Z(n+1)=(Zn)^2+C // 复数Z = a + bi // 连续计算MaxIterations次 //--求得满足Mandelbrot集合的 第MaxIterations 个点(直到z的幅值大于2) do { //--增加迭代次数 ++numIterations; //-- Z(n+1)=(Zn)^2+C //-- 复数Z = a + bi //---迭代一次----- //--实部 double a2 = (a1 * a1) - (b1 * b1) + ax; //--虚部 double b2 = (2 * a1 * b1) + ay; //--直到z的幅值大于2, Limit = 2^2,退出 if ((a2 * a2) + (b2 * b2) > Limit) break; //---继续迭代一次,记录上一次结果,用于下一次迭代----- ++numIterations; a1 = (a2 * a2) - (b2 * b2) + ax; b1 = (2 * a2 * b2) + ay; //--直到z的幅值大于2, Limit = 2^2,退出 if ((a1 * a1) + (b1 * b1) > Limit) break; } while (numIterations < MaxIterations);//--循环迭代直到次数大于限制或者z的幅值大于2 //--退出循环时,幅值大于2,颜色取值 //--轮廓外部彩色 if (numIterations < MaxIterations) { //--设置此行当前位(x位置) 像素颜色,取颜色空间的值 *scanLine++ = colormap[numIterations % ColormapSize]; allBlack = false; } //--退出循环时,迭代到最大次数,颜色取值 //--轮廓内部黑色 else { //--设置此行当前位(x位置) 像素颜色 *scanLine++ = qRgb(0, 0, 0); } }//--for每行逐个扫描 }//--for逐行扫描 //--第一轮,并且当前图像全黑,从第5(pass=4)轮开始 //--因为这种情况下pass = 0 1 2 3 是全黑 //--在轮廓内部 if (allBlack && pass == 0) { pass = 4; } else {//--包含轮廓,触发GUI线程绘制图像 if (!restart) emit renderedImage(image, scaleFactor); ++pass; } }//--while //--渲染完毕休眠等待condition.wakeOne()唤醒 mutex.lock(); if (!restart) condition.wait(&mutex); restart = false; mutex.unlock(); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。