当前位置:   article > 正文

QT多线程渲染Mandelbrot集_qt 多线程渲染

qt 多线程渲染

QT多线程渲染 Mandelbrot集

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

  • 式中 Z n + 1 Z_{n+1} Zn+1 是复数 Z = a + bi 的第n+1次迭代,
  • C是确定该点在复平面中位置的复数值.
  • z的初始值为0.迭代将一直进行下去,直到z的幅值大于2或者迭代次数已经达到某种任意规定的限度.

分析 :

MandelbrotWidget

主线程,负责绘制Mandelbrot图像(渲染线程RenderThread传递过来的Mandelbrot图像引用)

RenderThread

渲染线程,负责迭代计算生成Mandelbrot图像,完成时传递参数给主线程绘制

  • 外部调用,启动渲染render:
/*!
 * \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();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 线程函数run:

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();
    }
}
  • 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
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/648948
推荐阅读
相关标签
  

闽ICP备14008679号