##// END OF EJS Templates
Updates AxisRenderingUtils to use variable's type instead of dataseries
Alexandre Leroux -
r1335:89a3f92d2fbb
parent child
Show More
@@ -1,37 +1,44
1 1 #ifndef SCIQLOP_AXISRENDERINGUTILS_H
2 2 #define SCIQLOP_AXISRENDERINGUTILS_H
3 3
4 4 #include <memory>
5 5
6 6 #include <QtCore/QLoggingCategory>
7 7 #include <QtCore/QString>
8 8
9 9 Q_DECLARE_LOGGING_CATEGORY(LOG_AxisRenderingUtils)
10 10
11 11 class IDataSeries;
12 12 class QCPAxis;
13 13 class QCustomPlot;
14 14 class SqpColorScale;
15 class Variable;
15 16
16 17 /// Formats a data value according to the axis on which it is present
17 18 QString formatValue(double value, const QCPAxis &axis);
18 19
19 20 /**
20 21 * Helper used to handle axes rendering
21 22 */
22 23 struct IAxisHelper {
23 24 virtual ~IAxisHelper() noexcept = default;
24 25
25 26 /// Set properties of the plot's axes and the color scale associated to plot passed as
26 27 /// parameters
27 28 /// @param plot the plot for which to set axe properties
28 29 /// @param colorScale the color scale for which to set properties
29 30 virtual void setProperties(QCustomPlot &plot, SqpColorScale &colorScale) = 0;
31
32 /// Set the units of the plot's axes and the color scale associated to plot passed as
33 /// parameters
34 /// @param plot the plot for which to set axe units
35 /// @param colorScale the color scale for which to set unit
36 virtual void setUnits(QCustomPlot &plot, SqpColorScale &colorScale) = 0;
30 37 };
31 38
32 39 struct IAxisHelperFactory {
33 /// Creates IAxisHelper according to a data series
34 static std::unique_ptr<IAxisHelper> create(std::shared_ptr<IDataSeries> dataSeries) noexcept;
40 /// Creates IPlottablesHelper according to the type of data series a variable holds
41 static std::unique_ptr<IAxisHelper> create(const Variable &variable) noexcept;
35 42 };
36 43
37 44 #endif // SCIQLOP_AXISRENDERINGUTILS_H
@@ -1,177 +1,207
1 1 #include "Visualization/AxisRenderingUtils.h"
2 2
3 3 #include <Data/ScalarSeries.h>
4 4 #include <Data/SpectrogramSeries.h>
5 5 #include <Data/VectorSeries.h>
6 6
7 #include <Variable/Variable.h>
8
7 9 #include <Visualization/SqpColorScale.h>
8 10 #include <Visualization/qcustomplot.h>
9 11
10 12 Q_LOGGING_CATEGORY(LOG_AxisRenderingUtils, "AxisRenderingUtils")
11 13
12 14 namespace {
13 15
14 16 const auto DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd hh:mm:ss:zzz");
15 17
16 18 /// Format for datetimes on a axis
17 19 const auto DATETIME_TICKER_FORMAT = QStringLiteral("yyyy/MM/dd \nhh:mm:ss");
18 20
19 21 const auto NUMBER_FORMAT = 'g';
20 22 const auto NUMBER_PRECISION = 9;
21 23
22 24 /// Generates the appropriate ticker for an axis, depending on whether the axis displays time or
23 25 /// non-time data
24 26 QSharedPointer<QCPAxisTicker> axisTicker(bool isTimeAxis, QCPAxis::ScaleType scaleType)
25 27 {
26 28 if (isTimeAxis) {
27 29 auto dateTicker = QSharedPointer<QCPAxisTickerDateTime>::create();
28 30 dateTicker->setDateTimeFormat(DATETIME_TICKER_FORMAT);
29 31 dateTicker->setDateTimeSpec(Qt::UTC);
30 32
31 33 return dateTicker;
32 34 }
33 35 else if (scaleType == QCPAxis::stLogarithmic) {
34 36 return QSharedPointer<QCPAxisTickerLog>::create();
35 37 }
36 38 else {
37 39 // default ticker
38 40 return QSharedPointer<QCPAxisTicker>::create();
39 41 }
40 42 }
41 43
42 44 /**
43 45 * Sets properties of the axis passed as parameter
44 46 * @param axis the axis to set
45 47 * @param unit the unit to set for the axis
46 48 * @param scaleType the scale type to set for the axis
47 49 */
48 50 void setAxisProperties(QCPAxis &axis, const Unit &unit,
49 51 QCPAxis::ScaleType scaleType = QCPAxis::stLinear)
50 52 {
51 53 // label (unit name)
52 54 axis.setLabel(unit.m_Name);
53 55
54 56 // scale type
55 57 axis.setScaleType(scaleType);
56 58 if (scaleType == QCPAxis::stLogarithmic) {
57 59 // Scientific notation
58 60 axis.setNumberPrecision(0);
59 61 axis.setNumberFormat("eb");
60 62 }
61 63
62 64 // ticker (depending on the type of unit)
63 65 axis.setTicker(axisTicker(unit.m_TimeUnit, scaleType));
64 66 }
65 67
66 68 /**
67 69 * Delegate used to set axes properties
68 70 */
69 71 template <typename T, typename Enabled = void>
70 72 struct AxisSetter {
71 static void setProperties(T &, QCustomPlot &, SqpColorScale &)
73 static void setProperties(QCustomPlot &, SqpColorScale &)
72 74 {
73 75 // Default implementation does nothing
74 76 qCCritical(LOG_AxisRenderingUtils()) << "Can't set axis properties: unmanaged type of data";
75 77 }
78
79 static void setUnits(T &, QCustomPlot &, SqpColorScale &)
80 {
81 // Default implementation does nothing
82 qCCritical(LOG_AxisRenderingUtils()) << "Can't set axis units: unmanaged type of data";
83 }
76 84 };
77 85
78 86 /**
79 87 * Specialization of AxisSetter for scalars and vectors
80 88 * @sa ScalarSeries
81 89 * @sa VectorSeries
82 90 */
83 91 template <typename T>
84 92 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
85 93 or std::is_base_of<VectorSeries, T>::value> > {
86 static void setProperties(T &dataSeries, QCustomPlot &plot, SqpColorScale &)
94 static void setProperties(QCustomPlot &, SqpColorScale &)
95 {
96 // Nothing to do
97 }
98
99 static void setUnits(T &dataSeries, QCustomPlot &plot, SqpColorScale &)
87 100 {
88 101 dataSeries.lockRead();
89 102 auto xAxisUnit = dataSeries.xAxisUnit();
90 103 auto valuesUnit = dataSeries.valuesUnit();
91 104 dataSeries.unlock();
92 105
93 106 setAxisProperties(*plot.xAxis, xAxisUnit);
94 107 setAxisProperties(*plot.yAxis, valuesUnit);
95 108 }
96 109 };
97 110
98 111 /**
99 112 * Specialization of AxisSetter for spectrograms
100 113 * @sa SpectrogramSeries
101 114 */
102 115 template <typename T>
103 116 struct AxisSetter<T, typename std::enable_if_t<std::is_base_of<SpectrogramSeries, T>::value> > {
104 static void setProperties(T &dataSeries, QCustomPlot &plot, SqpColorScale &colorScale)
117 static void setProperties(QCustomPlot &plot, SqpColorScale &colorScale)
105 118 {
106 dataSeries.lockRead();
107 auto xAxisUnit = dataSeries.xAxisUnit();
108 auto yAxisUnit = dataSeries.yAxisUnit();
109 auto valuesUnit = dataSeries.valuesUnit();
110 dataSeries.unlock();
111
112 setAxisProperties(*plot.xAxis, xAxisUnit);
113 setAxisProperties(*plot.yAxis, yAxisUnit, QCPAxis::stLogarithmic);
114
115 119 // Displays color scale in plot
116 120 plot.plotLayout()->insertRow(0);
117 121 plot.plotLayout()->addElement(0, 0, colorScale.m_Scale);
118 122 colorScale.m_Scale->setType(QCPAxis::atTop);
119 123 colorScale.m_Scale->setMinimumMargins(QMargins{0, 0, 0, 0});
120 124
121 125 // Aligns color scale with axes
122 126 auto marginGroups = plot.axisRect()->marginGroups();
123 127 for (auto it = marginGroups.begin(), end = marginGroups.end(); it != end; ++it) {
124 128 colorScale.m_Scale->setMarginGroup(it.key(), it.value());
125 129 }
126 130
127 131 // Set color scale properties
128 setAxisProperties(*colorScale.m_Scale->axis(), valuesUnit, QCPAxis::stLogarithmic);
129 132 colorScale.m_AutomaticThreshold = true;
130 133 }
134
135 static void setUnits(T &dataSeries, QCustomPlot &plot, SqpColorScale &colorScale)
136 {
137 dataSeries.lockRead();
138 auto xAxisUnit = dataSeries.xAxisUnit();
139 auto yAxisUnit = dataSeries.yAxisUnit();
140 auto valuesUnit = dataSeries.valuesUnit();
141 dataSeries.unlock();
142
143 setAxisProperties(*plot.xAxis, xAxisUnit);
144 setAxisProperties(*plot.yAxis, yAxisUnit, QCPAxis::stLogarithmic);
145 setAxisProperties(*colorScale.m_Scale->axis(), valuesUnit, QCPAxis::stLogarithmic);
146 }
131 147 };
132 148
133 149 /**
134 150 * Default implementation of IAxisHelper, which takes data series to set axes properties
135 151 * @tparam T the data series' type
136 152 */
137 153 template <typename T>
138 154 struct AxisHelper : public IAxisHelper {
139 explicit AxisHelper(T &dataSeries) : m_DataSeries{dataSeries} {}
155 explicit AxisHelper(std::shared_ptr<T> dataSeries) : m_DataSeries{dataSeries} {}
140 156
141 157 void setProperties(QCustomPlot &plot, SqpColorScale &colorScale) override
142 158 {
143 AxisSetter<T>::setProperties(m_DataSeries, plot, colorScale);
159 AxisSetter<T>::setProperties(plot, colorScale);
144 160 }
145 161
146 T &m_DataSeries;
162 void setUnits(QCustomPlot &plot, SqpColorScale &colorScale) override
163 {
164 if (m_DataSeries) {
165 AxisSetter<T>::setUnits(*m_DataSeries, plot, colorScale);
166 }
167 else {
168 qCCritical(LOG_AxisRenderingUtils()) << "Can't set units: inconsistency between the "
169 "type of data series and the type supposed";
170 }
171 }
172
173 std::shared_ptr<T> m_DataSeries;
147 174 };
148 175
149 176 } // namespace
150 177
151 178 QString formatValue(double value, const QCPAxis &axis)
152 179 {
153 180 // If the axis is a time axis, formats the value as a date
154 181 if (auto axisTicker = qSharedPointerDynamicCast<QCPAxisTickerDateTime>(axis.ticker())) {
155 182 return DateUtils::dateTime(value, axisTicker->dateTimeSpec()).toString(DATETIME_FORMAT);
156 183 }
157 184 else {
158 185 return QString::number(value, NUMBER_FORMAT, NUMBER_PRECISION);
159 186 }
160 187 }
161 188
162 std::unique_ptr<IAxisHelper>
163 IAxisHelperFactory::create(std::shared_ptr<IDataSeries> dataSeries) noexcept
189 std::unique_ptr<IAxisHelper> IAxisHelperFactory::create(const Variable &variable) noexcept
164 190 {
165 if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(dataSeries)) {
166 return std::make_unique<AxisHelper<ScalarSeries> >(*scalarSeries);
167 }
168 else if (auto spectrogramSeries = std::dynamic_pointer_cast<SpectrogramSeries>(dataSeries)) {
169 return std::make_unique<AxisHelper<SpectrogramSeries> >(*spectrogramSeries);
170 }
171 else if (auto vectorSeries = std::dynamic_pointer_cast<VectorSeries>(dataSeries)) {
172 return std::make_unique<AxisHelper<VectorSeries> >(*vectorSeries);
173 }
174 else {
175 return std::make_unique<AxisHelper<IDataSeries> >(*dataSeries);
191 switch (variable.type()) {
192 case DataSeriesType::SCALAR:
193 return std::make_unique<AxisHelper<ScalarSeries> >(
194 std::dynamic_pointer_cast<ScalarSeries>(variable.dataSeries()));
195 case DataSeriesType::SPECTROGRAM:
196 return std::make_unique<AxisHelper<SpectrogramSeries> >(
197 std::dynamic_pointer_cast<SpectrogramSeries>(variable.dataSeries()));
198 case DataSeriesType::VECTOR:
199 return std::make_unique<AxisHelper<VectorSeries> >(
200 std::dynamic_pointer_cast<VectorSeries>(variable.dataSeries()));
201 default:
202 // Creates default helper
203 break;
176 204 }
205
206 return std::make_unique<AxisHelper<IDataSeries> >(nullptr);
177 207 }
General Comments 0
You need to be logged in to leave comments. Login now