Quantum Phenomena Explorer 7.9.8
Interactive quantum-phenomena Explorer Tutor — source documentation
Loading...
Searching...
No Matches
quantumcrosssectionplotwidget.cpp
Go to the documentation of this file.
1/**
2 * @file quantumcrosssectionplotwidget.cpp
3 * @brief Implements the quantumcrosssectionplotwidget visualization component used by QPE.
4 * @ingroup qpe_graphics
5 *
6 * Source: @c graphics/renderer/quantumcrosssectionplotwidget.cpp. This file is part of Quantum Phenomena Explorer (QPE),
7 * maintained by Officina Turini. See LICENSE_IT.txt / LICENSE.txt for the
8 * QPE freeware source-available terms and THIRD_PARTY_NOTICES.txt for
9 * third-party components.
10 */
11
13
14#include <QPainter>
15#include <QPainterPath>
16#include <QPaintEvent>
17
18#include <algorithm>
19#include <cmath>
20
21namespace {
22const double kPi = 3.14159265358979323846;
23}
24
26 : QWidget(parent)
27{
28 setMinimumHeight(180);
29 setAutoFillBackground(false);
30}
31
38
44
46{
47 curve_ = curve;
48 update();
49}
50
52{
55 update();
56 }
57}
58
60{
61 return QSize(420, 180);
62}
63
64const std::vector<double> &QuantumCrossSectionPlotWidget::selectedValues() const
65{
66 switch (curve_) {
67 case Curve::Real:
68 return data_.realPart;
70 return data_.imaginaryPart;
71 case Curve::Phase:
72 return data_.phase;
74 default:
75 return data_.probability;
76 }
77}
78
80{
81 switch (curve_) {
82 case Curve::Real: return QStringLiteral("Re(psi)");
83 case Curve::Imaginary: return QStringLiteral("Im(psi)");
84 case Curve::Phase: return QStringLiteral("phase / rad");
86 default:
87 return momentumSpace_
88 ? QStringLiteral("|psi_tilde|^2")
89 : QStringLiteral("|psi|^2");
90 }
91}
92
93void QuantumCrossSectionPlotWidget::valueRange(double &minimum, double &maximum) const
94{
95 const std::vector<double> &values = selectedValues();
96 if (values.empty()) {
97 minimum = 0.0;
98 maximum = 1.0;
99 return;
100 }
101
102 if (curve_ == Curve::Phase) {
103 minimum = -kPi;
104 maximum = kPi;
105 return;
106 }
107
108 const std::pair<std::vector<double>::const_iterator,
109 std::vector<double>::const_iterator> mm =
110 std::minmax_element(values.begin(), values.end());
111 minimum = *mm.first;
112 maximum = *mm.second;
113
114 if (curve_ == Curve::Probability) {
115 minimum = 0.0;
116 } else {
117 minimum = std::min(minimum, 0.0);
118 maximum = std::max(maximum, 0.0);
119 }
120
121 if (!(maximum > minimum)) {
122 const double pad = std::max(1.0, std::fabs(maximum)) * 0.5;
123 minimum -= pad;
124 maximum += pad;
125 }
126}
127
129{
130 Q_UNUSED(event);
131
132 QPainter painter(this);
133 painter.setRenderHint(QPainter::Antialiasing, true);
134 painter.setRenderHint(QPainter::TextAntialiasing, true);
135 painter.fillRect(rect(), QColor(15, 18, 23));
136
137 const QRectF plotRect(58.0, 24.0,
138 std::max(10.0, width() - 78.0),
139 std::max(10.0, height() - 62.0));
140
141 painter.setPen(QPen(QColor(78, 86, 96), 1.0));
142 for (int i = 0; i <= 4; ++i) {
143 const double tx = static_cast<double>(i) / 4.0;
144 const double x = plotRect.left() + tx * plotRect.width();
145 painter.drawLine(QPointF(x, plotRect.top()), QPointF(x, plotRect.bottom()));
146 const double y = plotRect.top() + tx * plotRect.height();
147 painter.drawLine(QPointF(plotRect.left(), y), QPointF(plotRect.right(), y));
148 }
149
150 painter.setPen(QPen(QColor(170, 180, 190), 1.0));
151 painter.drawRect(plotRect);
152
153 if (data_.empty()) {
154 painter.setPen(QColor(190, 195, 205));
155 painter.drawText(plotRect, Qt::AlignCenter, QStringLiteral("No cross-section data"));
156 return;
157 }
158
159 const std::vector<double> &values = selectedValues();
160 if (values.size() != data_.coordinate.size() || values.size() < 2u) {
161 return;
162 }
163
164 const double xMin = data_.coordinate.front();
165 const double xMax = data_.coordinate.back();
166 double yMin = 0.0;
167 double yMax = 1.0;
168 valueRange(yMin, yMax);
169
170 const auto mapX = [plotRect, xMin, xMax](double x) {
171 const double t = (x - xMin) / std::max(1.0e-30, xMax - xMin);
172 return plotRect.left() + t * plotRect.width();
173 };
174 const auto mapY = [plotRect, yMin, yMax](double y) {
175 const double t = (y - yMin) / std::max(1.0e-30, yMax - yMin);
176 return plotRect.bottom() - t * plotRect.height();
177 };
178
179 if (yMin < 0.0 && yMax > 0.0) {
180 painter.setPen(QPen(QColor(125, 130, 138), 1.0, Qt::DashLine));
181 const double y0 = mapY(0.0);
182 painter.drawLine(QPointF(plotRect.left(), y0), QPointF(plotRect.right(), y0));
183 }
184
185 QPainterPath path;
186 path.moveTo(mapX(data_.coordinate[0]), mapY(values[0]));
187 for (std::size_t i = 1u; i < values.size(); ++i) {
188 path.lineTo(mapX(data_.coordinate[i]), mapY(values[i]));
189 }
190 painter.setPen(QPen(QColor(255, 200, 70), 2.0));
191 painter.drawPath(path);
192
193 painter.setPen(QColor(210, 215, 222));
194 painter.drawText(QRectF(plotRect.left(), 2.0, plotRect.width(), 20.0),
195 Qt::AlignCenter,
196 QStringLiteral("%1 section=%2")
197 .arg(curveTitle())
198 .arg(data_.actualPosition, 0, 'f', 3));
199
200 painter.setPen(QColor(160, 168, 178));
201 painter.drawText(QRectF(2.0, plotRect.top() - 8.0, 52.0, 18.0),
202 Qt::AlignRight | Qt::AlignVCenter,
203 QString::number(yMax, 'g', 4));
204 painter.drawText(QRectF(2.0, plotRect.bottom() - 10.0, 52.0, 18.0),
205 Qt::AlignRight | Qt::AlignVCenter,
206 QString::number(yMin, 'g', 4));
207 painter.drawText(QRectF(plotRect.left(), plotRect.bottom() + 6.0, 80.0, 20.0),
208 Qt::AlignLeft,
209 QString::number(xMin, 'f', 2));
210 painter.drawText(QRectF(plotRect.right() - 80.0, plotRect.bottom() + 6.0, 80.0, 20.0),
211 Qt::AlignRight,
212 QString::number(xMax, 'f', 2));
213
214 QString axisName;
215 if (momentumSpace_) {
217 ? QStringLiteral("p_x") : QStringLiteral("p_y");
218 } else {
220 ? QStringLiteral("x") : QStringLiteral("y");
221 }
222 painter.drawText(QRectF(plotRect.left(), plotRect.bottom() + 4.0,
223 plotRect.width(), 24.0),
224 Qt::AlignCenter,
225 axisName);
226}
const std::vector< double > & selectedValues() const
Returns selected values.
void clearCrossSection()
Clears cross section.
void setMomentumSpace(bool momentumSpace)
Sets momentum space.
void paintEvent(QPaintEvent *event) override
Paints event.
qpe::WaveFunctionCrossSection2DData data_
void valueRange(double &minimum, double &maximum) const
Returns value range.
bool momentumSpace() const
Carries out momentum space.
void setCrossSection(const qpe::WaveFunctionCrossSection2DData &data)
Sets cross section.
QSize minimumSizeHint() const override
Carries out minimum size hint.
QuantumCrossSectionPlotWidget(QWidget *parent=nullptr)
Constructs a Quantum Cross Section Plot Widget instance.
Curve curve() const
Carries out curve.
Curve
Enumerates the supported Curve values.
QString curveTitle() const
Carries out curve title.
Declares the quantumcrosssectionplotwidget visualization component used by QPE.
Data structure used by the Wave Function Cross Section2D Data component.
bool empty() const noexcept
Returns whether the object contains no data.