##// END OF EJS Templates
Add mofif for clang format
perrinel -
r591:7644bba62054
parent child
Show More
@@ -1,240 +1,243
1 1 #include "Visualization/VisualizationGraphHelper.h"
2 2 #include "Visualization/qcustomplot.h"
3 3
4 4 #include <Common/ColorUtils.h>
5 5
6 6 #include <Data/ScalarSeries.h>
7 7 #include <Data/VectorSeries.h>
8 8
9 9 #include <Variable/Variable.h>
10 10
11 11 Q_LOGGING_CATEGORY(LOG_VisualizationGraphHelper, "VisualizationGraphHelper")
12 12
13 13 namespace {
14 14
15 15 class SqpDataContainer : public QCPGraphDataContainer {
16 16 public:
17 17 void appendGraphData(const QCPGraphData &data) { mData.append(data); }
18 18 };
19 19
20 20
21 21 /// Format for datetimes on a axis
22 22 const auto DATETIME_TICKER_FORMAT = QStringLiteral("yyyy/MM/dd \nhh:mm:ss");
23 23
24 24 /// Generates the appropriate ticker for an axis, depending on whether the axis displays time or
25 25 /// non-time data
26 26 QSharedPointer<QCPAxisTicker> axisTicker(bool isTimeAxis)
27 27 {
28 28 if (isTimeAxis) {
29 29 auto dateTicker = QSharedPointer<QCPAxisTickerDateTime>::create();
30 30 dateTicker->setDateTimeFormat(DATETIME_TICKER_FORMAT);
31 31 dateTicker->setDateTimeSpec(Qt::UTC);
32 32
33 33 return dateTicker;
34 34 }
35 35 else {
36 36 // default ticker
37 37 return QSharedPointer<QCPAxisTicker>::create();
38 38 }
39 39 }
40 40
41 41 /// Sets axes properties according to the properties of a data series
42 42 template <int Dim>
43 43 void setAxesProperties(const DataSeries<Dim> &dataSeries, QCustomPlot &plot) noexcept
44 44 {
45 45 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
46 46 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
47 47 auto setAxisProperties = [](auto axis, const auto &unit) {
48 48 // label (unit name)
49 49 axis->setLabel(unit.m_Name);
50 50
51 51 // ticker (depending on the type of unit)
52 52 axis->setTicker(axisTicker(unit.m_TimeUnit));
53 53 };
54 54 setAxisProperties(plot.xAxis, dataSeries.xAxisUnit());
55 55 setAxisProperties(plot.yAxis, dataSeries.valuesUnit());
56 56 }
57 57
58 58 /**
59 * Struct used to create plottables, depending on the type of the data series from which to create them
59 * Struct used to create plottables, depending on the type of the data series from which to create
60 * them
60 61 * @tparam T the data series' type
61 62 * @remarks Default implementation can't create plottables
62 63 */
63 64 template <typename T, typename Enabled = void>
64 65 struct PlottablesCreator {
65 66 static PlottablesMap createPlottables(T &, QCustomPlot &)
66 67 {
67 68 qCCritical(LOG_DataSeries())
68 69 << QObject::tr("Can't create plottables: unmanaged data series type");
69 70 return {};
70 71 }
71 72 };
72 73
73 74 /**
74 75 * Specialization of PlottablesCreator for scalars and vectors
75 76 * @sa ScalarSeries
76 77 * @sa VectorSeries
77 78 */
78 79 template <typename T>
79 80 struct PlottablesCreator<T,
80 81 typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
81 82 or std::is_base_of<VectorSeries, T>::value> > {
82 83 static PlottablesMap createPlottables(T &dataSeries, QCustomPlot &plot)
83 84 {
84 85 PlottablesMap result{};
85 86
86 87 // Gets the number of components of the data series
87 88 auto componentCount = dataSeries.valuesData()->componentCount();
88 89
89 90 auto colors = ColorUtils::colors(Qt::blue, Qt::red, componentCount);
90 91
91 92 // For each component of the data series, creates a QCPGraph to add to the plot
92 93 for (auto i = 0; i < componentCount; ++i) {
93 94 auto graph = plot.addGraph();
94 95 graph->setPen(QPen{colors.at(i)});
95 96
96 97 result.insert({i, graph});
97 98 }
98 99
99 100 // Axes properties
100 101 setAxesProperties(dataSeries, plot);
101 102
102 103 plot.replot();
103 104
104 105 return result;
105 106 }
106 107 };
107 108
108 109 /**
109 * Struct used to update plottables, depending on the type of the data series from which to update them
110 * Struct used to update plottables, depending on the type of the data series from which to update
111 * them
110 112 * @tparam T the data series' type
111 113 * @remarks Default implementation can't update plottables
112 114 */
113 115 template <typename T, typename Enabled = void>
114 116 struct PlottablesUpdater {
115 117 static void updatePlottables(T &, PlottablesMap &, const SqpRange &, bool)
116 118 {
117 119 qCCritical(LOG_DataSeries())
118 120 << QObject::tr("Can't update plottables: unmanaged data series type");
119 121 }
120 122 };
121 123
122 124 /**
123 125 * Specialization of PlottablesUpdater for scalars and vectors
124 126 * @sa ScalarSeries
125 127 * @sa VectorSeries
126 128 */
127 129 template <typename T>
128 130 struct PlottablesUpdater<T,
129 131 typename std::enable_if_t<std::is_base_of<ScalarSeries, T>::value
130 132 or std::is_base_of<VectorSeries, T>::value> > {
131 133 static void updatePlottables(T &dataSeries, PlottablesMap &plottables, const SqpRange &range,
132 134 bool rescaleAxes)
133 135 {
134 136 dataSeries.lockRead();
135 137
136 138 // For each plottable to update, resets its data
137 139 std::map<int, QSharedPointer<SqpDataContainer> > dataContainers{};
138 140 for (const auto &plottable : plottables) {
139 141 if (auto graph = dynamic_cast<QCPGraph *>(plottable.second)) {
140 142 auto dataContainer = QSharedPointer<SqpDataContainer>::create();
141 143 graph->setData(dataContainer);
142 144
143 145 dataContainers.insert({plottable.first, dataContainer});
144 146 }
145 147 }
146 148
147 149 // - Gets the data of the series included in the current range
148 // - Updates each plottable by adding, for each data item, a point that takes x-axis data and value data. The correct value is retrieved according to the index of the component
150 // - Updates each plottable by adding, for each data item, a point that takes x-axis data
151 // and value data. The correct value is retrieved according to the index of the component
149 152 auto subDataIts = dataSeries.subData(range.m_TStart, range.m_TEnd);
150 153 for (auto it = subDataIts.first; it != subDataIts.second; ++it) {
151 154 for (const auto &dataContainer : dataContainers) {
152 155 auto componentIndex = dataContainer.first;
153 156 dataContainer.second->appendGraphData(
154 157 QCPGraphData(it->x(), it->value(componentIndex)));
155 158 }
156 159 }
157 160
158 161 dataSeries.unlock();
159 162
160 163 if (!plottables.empty()) {
161 164 auto plot = plottables.begin()->second->parentPlot();
162 165
163 166 if (rescaleAxes) {
164 167 plot->rescaleAxes();
165 168 }
166 169
167 170 plot->replot();
168 171 }
169 172 }
170 173 };
171 174
172 175 /**
173 176 * Helper used to create/update plottables
174 177 */
175 178 struct IPlottablesHelper {
176 179 virtual ~IPlottablesHelper() noexcept = default;
177 180 virtual PlottablesMap create(QCustomPlot &plot) const = 0;
178 181 virtual void update(PlottablesMap &plottables, const SqpRange &range,
179 182 bool rescaleAxes = false) const = 0;
180 183 };
181 184
182 185 /**
183 186 * Default implementation of IPlottablesHelper, which takes data series to create/update plottables
184 187 * @tparam T the data series' type
185 188 */
186 189 template <typename T>
187 190 struct PlottablesHelper : public IPlottablesHelper {
188 191 explicit PlottablesHelper(T &dataSeries) : m_DataSeries{dataSeries} {}
189 192
190 193 PlottablesMap create(QCustomPlot &plot) const override
191 194 {
192 195 return PlottablesCreator<T>::createPlottables(m_DataSeries, plot);
193 196 }
194 197
195 198 void update(PlottablesMap &plottables, const SqpRange &range, bool rescaleAxes) const override
196 199 {
197 200 PlottablesUpdater<T>::updatePlottables(m_DataSeries, plottables, range, rescaleAxes);
198 201 }
199 202
200 203 T &m_DataSeries;
201 204 };
202 205
203 206 /// Creates IPlottablesHelper according to a data series
204 207 std::unique_ptr<IPlottablesHelper> createHelper(std::shared_ptr<IDataSeries> dataSeries) noexcept
205 208 {
206 209 if (auto scalarSeries = std::dynamic_pointer_cast<ScalarSeries>(dataSeries)) {
207 210 return std::make_unique<PlottablesHelper<ScalarSeries> >(*scalarSeries);
208 211 }
209 212 else if (auto vectorSeries = std::dynamic_pointer_cast<VectorSeries>(dataSeries)) {
210 213 return std::make_unique<PlottablesHelper<VectorSeries> >(*vectorSeries);
211 214 }
212 215 else {
213 216 return std::make_unique<PlottablesHelper<IDataSeries> >(*dataSeries);
214 217 }
215 218 }
216 219
217 220 } // namespace
218 221
219 222 PlottablesMap VisualizationGraphHelper::create(std::shared_ptr<Variable> variable,
220 223 QCustomPlot &plot) noexcept
221 224 {
222 225 if (variable) {
223 226 auto helper = createHelper(variable->dataSeries());
224 227 auto plottables = helper->create(plot);
225 228 return plottables;
226 229 }
227 230 else {
228 231 qCDebug(LOG_VisualizationGraphHelper())
229 232 << QObject::tr("Can't create graph plottables : the variable is null");
230 233 return PlottablesMap{};
231 234 }
232 235 }
233 236
234 237 void VisualizationGraphHelper::updateData(PlottablesMap &plottables,
235 238 std::shared_ptr<IDataSeries> dataSeries,
236 239 const SqpRange &dateTime)
237 240 {
238 241 auto helper = createHelper(dataSeries);
239 242 helper->update(plottables, dateTime);
240 243 }
General Comments 0
You need to be logged in to leave comments. Login now