Skip to main content
标签ad报错:该广告ID(9)不存在。
  主页 > Qt入门

一个qt/c++ demo,用于显示 Mandelbulb(曼德博派) 分形图

2023-04-24 浏览:
标签ad报错:该广告ID(7)不存在。

#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsPixmapItem>
#include <QImage>

// 计算 Mandelbulb 的像素值
int mandelbulbPixel(qreal x0, qreal y0, qreal z0)
{
    const int maxIterations = 256;
    const qreal bailOut = 2.0;
    qreal x = x0;
    qreal y = y0;
    qreal z = z0;
    qreal r = 0.0;
    qreal theta = 0.0;
    qreal phi = 0.0;

    for (int i = 0; i < maxIterations; ++i) {
        // 3D Mandelbulb 的迭代公式
        r = std::sqrt(x*x + y*y + z*z);
        theta = std::atan2(std::sqrt(x*x + y*y), z);
        phi = std::atan2(y, x);
        x = std::pow(r, 8.0/3.0) * std::sin(8.0*theta) * std::cos(8.0*phi) + x0;
        y = std::pow(r, 8.0/3.0) * std::sin(8.0*theta) * std::sin(8.0*phi) + y0;
        z = std::pow(r, 8.0/3.0) * std::cos(8.0*theta) + z0;

        // 检查是否逃逸
        if (x*x + y*y + z*z > bailOut*bailOut) {
            return i;
        }
    }

    return maxIterations;
}

// 绘制 Mandelbulb
void drawMandelbulb(QGraphicsScene *scene, int width, int height)
{
    QImage image(width, height, QImage::Format_RGB32);
    const qreal scale = 2.0;
    const qreal offsetX = -0.5 * scale;
    const qreal offsetY = -0.5 * scale;
    const qreal offsetZ = -1.0;
    const qreal delta = scale / std::min(width, height) * 2.0;
    const int maxThreadCount = std::max(1, QThread::idealThreadCount());
    QVector<QFuture<void>> futures(maxThreadCount);

    for (int i = 0; i < maxThreadCount; ++i) {
        futures[i] = QtConcurrent::run([&image, width, height, scale, offsetX, offsetY, offsetZ, delta, maxThreadCount, i] {
            for (int y = i; y < height; y += maxThreadCount) {
                qreal y0 = (y + 0.5) / height * scale + offsetY;
                for (int x = 0; x < width; ++x) {
                    qreal x0 = (x + 0.5) / width * scale + offsetX;

                    // 计算像素值
                    int n = mandelbulbPixel(x0, y0, offsetZ);
                    qreal t = (qreal)n / 256.0;

                    // 将像素颜色映射为 RGB 值
                    QRgb color = QColor::fromHsvF(t, 1.0, t).rgb();
                    image.setPixel(x, height - 1 - y, color);
                }
            }
        });
    }
    for (int i = 0; i < maxThreadCount; ++i) {
        futures[i].waitForFinished();
    }

    // 显示图像
    QGraphicsPixmapItem *item = new QGraphicsPixmapItem(QPixmap::fromImage(image));
    item->setOffset(-scale/2.0, -scale/2.0);
    scene->addItem(item);
}

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    QGraphicsScene scene;
    QGraphicsView view(&scene);

    const int width = 640;
    const int height = 480;
    drawMandelbulb(&scene, width, height);

    view.show();
    return app.exec();
}