6773f9b29e
三段式对比直击 Day4 slides「主线程耗时=冻结」痛点:主线程渲染冻结 / 后台单线程不卡但慢 / 后台多线程不卡且快。 - QThreadPool + QRunnable 分水平条带并行,排队信号槽回传,epoch 版本号防过期覆盖 - wheelEvent 缩放(鼠标为锚)+ mouseEvent 拖拽平移 + paintEvent 画 QImage - 子目录自带独立 CMakeLists.txt,可单独构建/共享(双模式约定同 lineedit_eye_toggle) - 配套 README(概念/走读/双构建/5 踩坑点/练习)+ 设计规格 - 已验证:独立工程 offscreen 运行 exit=0;主工程构建 exit=0(w64devkit g++16 + mingw73 Qt5.14.2) 注:主工程 examples/CMakeLists.txt 的接入(mandelbrot + lineedit_eye_toggle + qdialog + themes 原子接入)与顶层 CMakeLists 本地调试改动未一并提交,待整体确认后单独提交。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
55 lines
2.2 KiB
C++
55 lines
2.2 KiB
C++
// ============================================================================
|
||
// mandelbrot_strip_task.cpp —— 调色板构造 + renderStrip 纯计算实现
|
||
// MandelbrotStripTask 的成员全部内联在头文件,本 .cpp 只需让 AUTOMOC 扫到
|
||
// strip_task.h 的 Q_OBJECT(#include 它即可),并实现非内联的 MandelPalette
|
||
// 与 renderStrip。
|
||
// ============================================================================
|
||
#include "mandelbrot_strip_task.h"
|
||
|
||
#include <QColor>
|
||
#include <QtGlobal>
|
||
|
||
// 迭代次数 → HSV 色相循环(彩虹环),集合内部点统一黑色。
|
||
MandelPalette::MandelPalette(int maxIter) {
|
||
const int n = qMax(1, maxIter);
|
||
table_.resize(n);
|
||
for (int i = 0; i < n; ++i) {
|
||
if (i == n - 1) { table_[i] = qRgb(0, 0, 0); continue; } // 集合内 → 黑
|
||
const int hue = static_cast<int>((360.0 * 4.0 * i / n));
|
||
table_[i] = QColor::fromHsv(hue % 360, 255, 255).rgb();
|
||
}
|
||
}
|
||
|
||
// 标准 Mandelbrot 迭代 z = z² + c,逃逸半径 2。逐像素写入 RGB32。
|
||
QImage renderStrip(const MandelViewport& vp, const MandelPalette& pal, int y0, int y1) {
|
||
const int w = vp.width;
|
||
const int top = qBound(0, y0, vp.height);
|
||
const int bot = qBound(0, y1, vp.height);
|
||
if (w <= 0 || bot <= top) return {};
|
||
|
||
QImage img(w, bot - top, QImage::Format_RGB32);
|
||
const double x0 = vp.centerX - vp.scale * vp.width / 2.0;
|
||
const double y0c = vp.centerY - vp.scale * vp.height / 2.0;
|
||
const int maxIter = vp.maxIter;
|
||
|
||
for (int py = top; py < bot; ++py) {
|
||
const double cy = y0c + vp.scale * py;
|
||
auto* line = reinterpret_cast<QRgb*>(img.scanLine(py - top)); // RGB32 = 每像素 1 个 QRgb
|
||
for (int px = 0; px < w; ++px) {
|
||
const double cx = x0 + vp.scale * px;
|
||
double zx = 0.0, zy = 0.0;
|
||
int iter = 0;
|
||
while (iter < maxIter) {
|
||
const double zx2 = zx * zx;
|
||
const double zy2 = zy * zy;
|
||
if (zx2 + zy2 > 4.0) break; // 逃逸
|
||
zy = 2.0 * zx * zy + cy;
|
||
zx = zx2 - zy2 + cx;
|
||
++iter;
|
||
}
|
||
line[px] = pal.color(iter >= maxIter ? maxIter - 1 : iter);
|
||
}
|
||
}
|
||
return img;
|
||
}
|