81 QPainter painter(
this);
82 painter.setRenderHint(QPainter::Antialiasing,
true);
83 painter.setRenderHint(QPainter::TextAntialiasing,
true);
84 painter.fillRect(rect(), QColor(14, 17, 22));
86 const double marginLeft = 62.0;
87 const double marginRight = 24.0;
88 const double top = 30.0;
89 const double bottom = 38.0;
90 const double gap = 36.0;
91 const double available = std::max(120.0, height() - top - bottom - gap);
92 const double mapHeight = available * 0.63;
93 const QRectF mapRect(marginLeft, top,
94 std::max(40.0, width() - marginLeft - marginRight), mapHeight);
95 const QRectF curveRect(marginLeft, mapRect.bottom() + gap,
96 mapRect.width(), available - mapHeight);
98 drawFrame(painter, mapRect);
99 drawFrame(painter, curveRect);
101 painter.setPen(QColor(214, 220, 228));
102 painter.drawText(QRectF(mapRect.left(), 4.0, mapRect.width(), 20.0), Qt::AlignCenter,
103 QStringLiteral(
"Time-averaged probability density inside the billiard"));
104 painter.drawText(QRectF(curveRect.left(), mapRect.bottom() + 8.0,
105 curveRect.width(), 20.0), Qt::AlignCenter,
106 QStringLiteral(
"Spatial filling / recurrence / scatterer encounter"));
110 painter.setPen(QColor(220, 228, 238));
111 painter.drawText(mapRect, Qt::AlignCenter,
112 QStringLiteral(
"Run a Quantum Billiard preset to accumulate the occupation map"));
113 painter.drawText(curveRect, Qt::AlignCenter,
114 QStringLiteral(
"Four box walls are required; Sinai adds one circular scatterer"));
127 const double gxCentre = 0.5 *
static_cast<double>(gw - 1u);
128 const double gyCentre = 0.5 *
static_cast<double>(gh - 1u);
129 int ix0 =
static_cast<int>(std::ceil(x0 / dx + gxCentre));
130 int ix1 =
static_cast<int>(std::floor(x1 / dx + gxCentre));
131 int iy0 =
static_cast<int>(std::ceil(y0 / dy + gyCentre));
132 int iy1 =
static_cast<int>(std::floor(y1 / dy + gyCentre));
133 ix0 = std::max(0, std::min(ix0,
static_cast<int>(gw) - 1));
134 ix1 = std::max(ix0, std::min(ix1,
static_cast<int>(gw) - 1));
135 iy0 = std::max(0, std::min(iy0,
static_cast<int>(gh) - 1));
136 iy1 = std::max(iy0, std::min(iy1,
static_cast<int>(gh) - 1));
138 const int columns = ix1 - ix0 + 1;
139 const int rows = iy1 - iy0 + 1;
140 double maxDensity = 0.0;
141 for (
int y = iy0; y <= iy1; ++y) {
142 for (
int x = ix0; x <= ix1; ++x) {
143 const std::size_t index =
static_cast<std::size_t
>(y) * gw +
static_cast<std::size_t
>(x);
144 if (index < mean.size()) maxDensity = std::max(maxDensity,
static_cast<double>(mean[index]));
147 maxDensity = std::max(maxDensity, 1.0e-30);
149 if (columns > 0 && rows > 0 && mean.size() == gw * gh) {
150 QImage image(columns, rows, QImage::Format_RGB32);
151 for (
int yy = 0; yy < rows; ++yy) {
152 const int gy = iy1 - yy;
153 for (
int xx = 0; xx < columns; ++xx) {
154 const int gx = ix0 + xx;
155 const std::size_t index =
static_cast<std::size_t
>(gy) * gw +
static_cast<std::size_t
>(gx);
156 const double normalized =
static_cast<double>(mean[index]) / maxDensity;
157 image.setPixel(xx, yy, densityColour(std::sqrt(std::max(0.0, normalized))));
160 painter.setRenderHint(QPainter::SmoothPixmapTransform,
false);
161 painter.drawImage(mapRect, image, QRectF(image.rect()));
162 painter.setRenderHint(QPainter::Antialiasing,
true);
166 const double cx = mapRect.left() +
168 const double cy = mapRect.bottom() -
172 painter.setBrush(QColor(15, 18, 22, 230));
173 painter.setPen(QPen(QColor(235, 238, 242), 1.3));
174 painter.drawEllipse(QPointF(cx, cy), rx, ry);
175 painter.setBrush(Qt::NoBrush);
178 const std::vector<qpe::QuantumBilliardSample2D> &samples =
history_->
samples();
179 const double tMin = samples.front().time;
180 const double tMax = samples.back().time;
181 const double span = std::max(1.0e-12, tMax - tMin);
182 const auto mapX = [curveRect, tMin, span](
double t) {
183 return curveRect.left() + (t - tMin) / span * curveRect.width();
185 const auto mapY = [curveRect](
double v) {
186 const double clamped = std::max(0.0, std::min(1.0, v));
187 return curveRect.bottom() - clamped * curveRect.height();
190 painter.setPen(QPen(QColor(72, 80, 90), 1.0));
191 for (
int i = 1; i < 4; ++i) {
192 const double y = curveRect.top() + i * curveRect.height() / 4.0;
193 painter.drawLine(QPointF(curveRect.left(), y), QPointF(curveRect.right(), y));
196 QPainterPath occupiedPath;
197 QPainterPath fidelityPath;
198 QPainterPath obstaclePath;
199 bool started =
false;
201 const double x = mapX(sample.time);
202 const QPointF pOccupied(x, mapY(sample.occupiedFraction));
203 const QPointF pFidelity(x, mapY(sample.fidelity));
204 const QPointF pObstacle(x, mapY(std::min(1.0, 4.0 * sample.obstacleShellProbability)));
206 occupiedPath.moveTo(pOccupied);
207 fidelityPath.moveTo(pFidelity);
208 obstaclePath.moveTo(pObstacle);
211 occupiedPath.lineTo(pOccupied);
212 fidelityPath.lineTo(pFidelity);
213 obstaclePath.lineTo(pObstacle);
217 painter.setPen(QPen(QColor(80, 220, 255), 2.2));
218 painter.drawPath(occupiedPath);
219 painter.setPen(QPen(QColor(255, 205, 92), 1.7));
220 painter.drawPath(fidelityPath);
222 painter.setPen(QPen(QColor(255, 112, 160), 1.5));
223 painter.drawPath(obstaclePath);
226 painter.setPen(QColor(215, 224, 234));
227 painter.drawText(QRectF(5.0, curveRect.top() - 9.0, 50.0, 18.0),
228 Qt::AlignRight | Qt::AlignVCenter, QStringLiteral(
"1.0"));
229 painter.drawText(QRectF(5.0, curveRect.bottom() - 10.0, 50.0, 18.0),
230 Qt::AlignRight | Qt::AlignVCenter, QStringLiteral(
"0.0"));
231 painter.drawText(QRectF(curveRect.left(), curveRect.bottom() + 5.0, 90.0, 20.0),
232 Qt::AlignLeft, QString::number(tMin,
'f', 1));
233 painter.drawText(QRectF(curveRect.right() - 90.0, curveRect.bottom() + 5.0, 90.0, 20.0),
234 Qt::AlignRight, QString::number(tMax,
'f', 1));
235 painter.drawText(QRectF(curveRect.left(), curveRect.bottom() + 4.0,
236 curveRect.width(), 24.0), Qt::AlignCenter,
237 QStringLiteral(
"simulation time"));
239 const double legendY = mapRect.bottom() + 7.0;
240 painter.setPen(QColor(80, 220, 255));
241 painter.drawText(QRectF(mapRect.left(), legendY, 160.0, 20.0), Qt::AlignLeft,
242 QStringLiteral(
"cyan: occupied fraction"));
243 painter.setPen(QColor(255, 205, 92));
244 painter.drawText(QRectF(mapRect.left() + 165.0, legendY, 150.0, 20.0), Qt::AlignLeft,
245 QStringLiteral(
"yellow: fidelity"));
247 painter.setPen(QColor(255, 112, 160));
248 painter.drawText(QRectF(mapRect.left() + 315.0, legendY, 240.0, 20.0), Qt::AlignLeft,
249 QStringLiteral(
"pink: 4x obstacle-shell probability"));