##// END OF EJS Templates
Implements method to get min/max values of a dataseries giving a range (2)
Alexandre Leroux -
r609:3d5120e0d250
parent child
Show More
@@ -1,320 +1,333
1 #ifndef SCIQLOP_DATASERIES_H
1 #ifndef SCIQLOP_DATASERIES_H
2 #define SCIQLOP_DATASERIES_H
2 #define SCIQLOP_DATASERIES_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <Common/SortUtils.h>
6 #include <Common/SortUtils.h>
7
7
8 #include <Data/ArrayData.h>
8 #include <Data/ArrayData.h>
9 #include <Data/IDataSeries.h>
9 #include <Data/IDataSeries.h>
10
10
11 #include <QLoggingCategory>
11 #include <QLoggingCategory>
12 #include <QReadLocker>
12 #include <QReadLocker>
13 #include <QReadWriteLock>
13 #include <QReadWriteLock>
14 #include <memory>
14 #include <memory>
15
15
16 // We don't use the Qt macro since the log is used in the header file, which causes multiple log
16 // We don't use the Qt macro since the log is used in the header file, which causes multiple log
17 // definitions with inheritance. Inline method is used instead
17 // definitions with inheritance. Inline method is used instead
18 inline const QLoggingCategory &LOG_DataSeries()
18 inline const QLoggingCategory &LOG_DataSeries()
19 {
19 {
20 static const QLoggingCategory category{"DataSeries"};
20 static const QLoggingCategory category{"DataSeries"};
21 return category;
21 return category;
22 }
22 }
23
23
24 template <int Dim>
24 template <int Dim>
25 class DataSeries;
25 class DataSeries;
26
26
27 namespace dataseries_detail {
27 namespace dataseries_detail {
28
28
29 template <int Dim>
29 template <int Dim>
30 class IteratorValue : public DataSeriesIteratorValue::Impl {
30 class IteratorValue : public DataSeriesIteratorValue::Impl {
31 public:
31 public:
32 explicit IteratorValue(const DataSeries<Dim> &dataSeries, bool begin)
32 explicit IteratorValue(const DataSeries<Dim> &dataSeries, bool begin)
33 : m_XIt(begin ? dataSeries.xAxisData()->cbegin() : dataSeries.xAxisData()->cend()),
33 : m_XIt(begin ? dataSeries.xAxisData()->cbegin() : dataSeries.xAxisData()->cend()),
34 m_ValuesIt(begin ? dataSeries.valuesData()->cbegin()
34 m_ValuesIt(begin ? dataSeries.valuesData()->cbegin()
35 : dataSeries.valuesData()->cend())
35 : dataSeries.valuesData()->cend())
36 {
36 {
37 }
37 }
38 IteratorValue(const IteratorValue &other) = default;
38 IteratorValue(const IteratorValue &other) = default;
39
39
40 std::unique_ptr<DataSeriesIteratorValue::Impl> clone() const override
40 std::unique_ptr<DataSeriesIteratorValue::Impl> clone() const override
41 {
41 {
42 return std::make_unique<IteratorValue<Dim> >(*this);
42 return std::make_unique<IteratorValue<Dim> >(*this);
43 }
43 }
44
44
45 bool equals(const DataSeriesIteratorValue::Impl &other) const override try {
45 bool equals(const DataSeriesIteratorValue::Impl &other) const override try {
46 const auto &otherImpl = dynamic_cast<const IteratorValue &>(other);
46 const auto &otherImpl = dynamic_cast<const IteratorValue &>(other);
47 return std::tie(m_XIt, m_ValuesIt) == std::tie(otherImpl.m_XIt, otherImpl.m_ValuesIt);
47 return std::tie(m_XIt, m_ValuesIt) == std::tie(otherImpl.m_XIt, otherImpl.m_ValuesIt);
48 }
48 }
49 catch (const std::bad_cast &) {
49 catch (const std::bad_cast &) {
50 return false;
50 return false;
51 }
51 }
52
52
53 void next() override
53 void next() override
54 {
54 {
55 ++m_XIt;
55 ++m_XIt;
56 ++m_ValuesIt;
56 ++m_ValuesIt;
57 }
57 }
58
58
59 void prev() override
59 void prev() override
60 {
60 {
61 --m_XIt;
61 --m_XIt;
62 --m_ValuesIt;
62 --m_ValuesIt;
63 }
63 }
64
64
65 double x() const override { return m_XIt->at(0); }
65 double x() const override { return m_XIt->at(0); }
66 double value() const override { return m_ValuesIt->at(0); }
66 double value() const override { return m_ValuesIt->at(0); }
67 double value(int componentIndex) const override { return m_ValuesIt->at(componentIndex); }
67 double value(int componentIndex) const override { return m_ValuesIt->at(componentIndex); }
68 double minValue() const override { return m_ValuesIt->min(); }
69 double maxValue() const override { return m_ValuesIt->max(); }
68
70
69 private:
71 private:
70 ArrayData<1>::Iterator m_XIt;
72 ArrayData<1>::Iterator m_XIt;
71 typename ArrayData<Dim>::Iterator m_ValuesIt;
73 typename ArrayData<Dim>::Iterator m_ValuesIt;
72 };
74 };
73 } // namespace dataseries_detail
75 } // namespace dataseries_detail
74
76
75 /**
77 /**
76 * @brief The DataSeries class is the base (abstract) implementation of IDataSeries.
78 * @brief The DataSeries class is the base (abstract) implementation of IDataSeries.
77 *
79 *
78 * It proposes to set a dimension for the values ​​data.
80 * It proposes to set a dimension for the values ​​data.
79 *
81 *
80 * A DataSeries is always sorted on its x-axis data.
82 * A DataSeries is always sorted on its x-axis data.
81 *
83 *
82 * @tparam Dim The dimension of the values data
84 * @tparam Dim The dimension of the values data
83 *
85 *
84 */
86 */
85 template <int Dim>
87 template <int Dim>
86 class SCIQLOP_CORE_EXPORT DataSeries : public IDataSeries {
88 class SCIQLOP_CORE_EXPORT DataSeries : public IDataSeries {
87 public:
89 public:
88 /// @sa IDataSeries::xAxisData()
90 /// @sa IDataSeries::xAxisData()
89 std::shared_ptr<ArrayData<1> > xAxisData() override { return m_XAxisData; }
91 std::shared_ptr<ArrayData<1> > xAxisData() override { return m_XAxisData; }
90 const std::shared_ptr<ArrayData<1> > xAxisData() const { return m_XAxisData; }
92 const std::shared_ptr<ArrayData<1> > xAxisData() const { return m_XAxisData; }
91
93
92 /// @sa IDataSeries::xAxisUnit()
94 /// @sa IDataSeries::xAxisUnit()
93 Unit xAxisUnit() const override { return m_XAxisUnit; }
95 Unit xAxisUnit() const override { return m_XAxisUnit; }
94
96
95 /// @return the values dataset
97 /// @return the values dataset
96 std::shared_ptr<ArrayData<Dim> > valuesData() { return m_ValuesData; }
98 std::shared_ptr<ArrayData<Dim> > valuesData() { return m_ValuesData; }
97 const std::shared_ptr<ArrayData<Dim> > valuesData() const { return m_ValuesData; }
99 const std::shared_ptr<ArrayData<Dim> > valuesData() const { return m_ValuesData; }
98
100
99 /// @sa IDataSeries::valuesUnit()
101 /// @sa IDataSeries::valuesUnit()
100 Unit valuesUnit() const override { return m_ValuesUnit; }
102 Unit valuesUnit() const override { return m_ValuesUnit; }
101
103
102
104
103 SqpRange range() const override
105 SqpRange range() const override
104 {
106 {
105 if (!m_XAxisData->cdata().isEmpty()) {
107 if (!m_XAxisData->cdata().isEmpty()) {
106 return SqpRange{m_XAxisData->cdata().first(), m_XAxisData->cdata().last()};
108 return SqpRange{m_XAxisData->cdata().first(), m_XAxisData->cdata().last()};
107 }
109 }
108
110
109 return SqpRange{};
111 return SqpRange{};
110 }
112 }
111
113
112 void clear()
114 void clear()
113 {
115 {
114 m_XAxisData->clear();
116 m_XAxisData->clear();
115 m_ValuesData->clear();
117 m_ValuesData->clear();
116 }
118 }
117
119
118 /// Merges into the data series an other data series
120 /// Merges into the data series an other data series
119 /// @remarks the data series to merge with is cleared after the operation
121 /// @remarks the data series to merge with is cleared after the operation
120 void merge(IDataSeries *dataSeries) override
122 void merge(IDataSeries *dataSeries) override
121 {
123 {
122 dataSeries->lockWrite();
124 dataSeries->lockWrite();
123 lockWrite();
125 lockWrite();
124
126
125 if (auto other = dynamic_cast<DataSeries<Dim> *>(dataSeries)) {
127 if (auto other = dynamic_cast<DataSeries<Dim> *>(dataSeries)) {
126 const auto &otherXAxisData = other->xAxisData()->cdata();
128 const auto &otherXAxisData = other->xAxisData()->cdata();
127 const auto &xAxisData = m_XAxisData->cdata();
129 const auto &xAxisData = m_XAxisData->cdata();
128
130
129 // As data series are sorted, we can improve performances of merge, by call the sort
131 // As data series are sorted, we can improve performances of merge, by call the sort
130 // method only if the two data series overlap.
132 // method only if the two data series overlap.
131 if (!otherXAxisData.empty()) {
133 if (!otherXAxisData.empty()) {
132 auto firstValue = otherXAxisData.front();
134 auto firstValue = otherXAxisData.front();
133 auto lastValue = otherXAxisData.back();
135 auto lastValue = otherXAxisData.back();
134
136
135 auto xAxisDataBegin = xAxisData.cbegin();
137 auto xAxisDataBegin = xAxisData.cbegin();
136 auto xAxisDataEnd = xAxisData.cend();
138 auto xAxisDataEnd = xAxisData.cend();
137
139
138 bool prepend;
140 bool prepend;
139 bool sortNeeded;
141 bool sortNeeded;
140
142
141 if (std::lower_bound(xAxisDataBegin, xAxisDataEnd, firstValue) == xAxisDataEnd) {
143 if (std::lower_bound(xAxisDataBegin, xAxisDataEnd, firstValue) == xAxisDataEnd) {
142 // Other data series if after data series
144 // Other data series if after data series
143 prepend = false;
145 prepend = false;
144 sortNeeded = false;
146 sortNeeded = false;
145 }
147 }
146 else if (std::upper_bound(xAxisDataBegin, xAxisDataEnd, lastValue)
148 else if (std::upper_bound(xAxisDataBegin, xAxisDataEnd, lastValue)
147 == xAxisDataBegin) {
149 == xAxisDataBegin) {
148 // Other data series if before data series
150 // Other data series if before data series
149 prepend = true;
151 prepend = true;
150 sortNeeded = false;
152 sortNeeded = false;
151 }
153 }
152 else {
154 else {
153 // The two data series overlap
155 // The two data series overlap
154 prepend = false;
156 prepend = false;
155 sortNeeded = true;
157 sortNeeded = true;
156 }
158 }
157
159
158 // Makes the merge
160 // Makes the merge
159 m_XAxisData->add(*other->xAxisData(), prepend);
161 m_XAxisData->add(*other->xAxisData(), prepend);
160 m_ValuesData->add(*other->valuesData(), prepend);
162 m_ValuesData->add(*other->valuesData(), prepend);
161
163
162 if (sortNeeded) {
164 if (sortNeeded) {
163 sort();
165 sort();
164 }
166 }
165 }
167 }
166
168
167 // Clears the other data series
169 // Clears the other data series
168 other->clear();
170 other->clear();
169 }
171 }
170 else {
172 else {
171 qCWarning(LOG_DataSeries())
173 qCWarning(LOG_DataSeries())
172 << QObject::tr("Detection of a type of IDataSeries we cannot merge with !");
174 << QObject::tr("Detection of a type of IDataSeries we cannot merge with !");
173 }
175 }
174 unlock();
176 unlock();
175 dataSeries->unlock();
177 dataSeries->unlock();
176 }
178 }
177
179
178 // ///////// //
180 // ///////// //
179 // Iterators //
181 // Iterators //
180 // ///////// //
182 // ///////// //
181
183
182 DataSeriesIterator cbegin() const override
184 DataSeriesIterator cbegin() const override
183 {
185 {
184 return DataSeriesIterator{DataSeriesIteratorValue{
186 return DataSeriesIterator{DataSeriesIteratorValue{
185 std::make_unique<dataseries_detail::IteratorValue<Dim> >(*this, true)}};
187 std::make_unique<dataseries_detail::IteratorValue<Dim> >(*this, true)}};
186 }
188 }
187
189
188 DataSeriesIterator cend() const override
190 DataSeriesIterator cend() const override
189 {
191 {
190 return DataSeriesIterator{DataSeriesIteratorValue{
192 return DataSeriesIterator{DataSeriesIteratorValue{
191 std::make_unique<dataseries_detail::IteratorValue<Dim> >(*this, false)}};
193 std::make_unique<dataseries_detail::IteratorValue<Dim> >(*this, false)}};
192 }
194 }
193
195
194 /// @sa IDataSeries::minXAxisData()
196 /// @sa IDataSeries::minXAxisData()
195 DataSeriesIterator minXAxisData(double minXAxisData) const override
197 DataSeriesIterator minXAxisData(double minXAxisData) const override
196 {
198 {
197 return std::lower_bound(
199 return std::lower_bound(
198 cbegin(), cend(), minXAxisData,
200 cbegin(), cend(), minXAxisData,
199 [](const auto &itValue, const auto &value) { return itValue.x() < value; });
201 [](const auto &itValue, const auto &value) { return itValue.x() < value; });
200 }
202 }
201
203
202 /// @sa IDataSeries::maxXAxisData()
204 /// @sa IDataSeries::maxXAxisData()
203 DataSeriesIterator maxXAxisData(double maxXAxisData) const override
205 DataSeriesIterator maxXAxisData(double maxXAxisData) const override
204 {
206 {
205 // Gets the first element that greater than max value
207 // Gets the first element that greater than max value
206 auto it = std::upper_bound(
208 auto it = std::upper_bound(
207 cbegin(), cend(), maxXAxisData,
209 cbegin(), cend(), maxXAxisData,
208 [](const auto &value, const auto &itValue) { return value < itValue.x(); });
210 [](const auto &value, const auto &itValue) { return value < itValue.x(); });
209
211
210 return it == cbegin() ? cend() : --it;
212 return it == cbegin() ? cend() : --it;
211 }
213 }
212
214
213 std::pair<DataSeriesIterator, DataSeriesIterator> xAxisRange(double minXAxisData,
215 std::pair<DataSeriesIterator, DataSeriesIterator> xAxisRange(double minXAxisData,
214 double maxXAxisData) const override
216 double maxXAxisData) const override
215 {
217 {
216 if (minXAxisData > maxXAxisData) {
218 if (minXAxisData > maxXAxisData) {
217 std::swap(minXAxisData, maxXAxisData);
219 std::swap(minXAxisData, maxXAxisData);
218 }
220 }
219
221
220 auto begin = cbegin();
222 auto begin = cbegin();
221 auto end = cend();
223 auto end = cend();
222
224
223 auto lowerIt = std::lower_bound(
225 auto lowerIt = std::lower_bound(
224 begin, end, minXAxisData,
226 begin, end, minXAxisData,
225 [](const auto &itValue, const auto &value) { return itValue.x() < value; });
227 [](const auto &itValue, const auto &value) { return itValue.x() < value; });
226 auto upperIt = std::upper_bound(
228 auto upperIt = std::upper_bound(
227 begin, end, maxXAxisData,
229 begin, end, maxXAxisData,
228 [](const auto &value, const auto &itValue) { return value < itValue.x(); });
230 [](const auto &value, const auto &itValue) { return value < itValue.x(); });
229
231
230 return std::make_pair(lowerIt, upperIt);
232 return std::make_pair(lowerIt, upperIt);
231 }
233 }
232
234
233 std::pair<DataSeriesIterator, DataSeriesIterator>
235 std::pair<DataSeriesIterator, DataSeriesIterator>
234 valuesBounds(double minXAxisData, double maxXAxisData) const override
236 valuesBounds(double minXAxisData, double maxXAxisData) const override
235 {
237 {
236 // Places iterators to the correct x-axis range
238 // Places iterators to the correct x-axis range
237 auto xAxisRangeIts = xAxisRange(minXAxisData, maxXAxisData);
239 auto xAxisRangeIts = xAxisRange(minXAxisData, maxXAxisData);
238
240
239 // Returns end iterators if the range is empty
241 // Returns end iterators if the range is empty
240 if (xAxisRangeIts.first == xAxisRangeIts.second) {
242 if (xAxisRangeIts.first == xAxisRangeIts.second) {
241 return std::make_pair(cend(), cend());
243 return std::make_pair(cend(), cend());
242 }
244 }
243
245
244 /// @todo ALX: complete
246 // Gets the iterator on the min of all values data
247 auto minIt = std::min_element(
248 xAxisRangeIts.first, xAxisRangeIts.second, [](const auto &it1, const auto &it2) {
249 return SortUtils::minCompareWithNaN(it1.minValue(), it2.minValue());
250 });
245
251
252 // Gets the iterator on the max of all values data
253 auto maxIt = std::max_element(
254 xAxisRangeIts.first, xAxisRangeIts.second, [](const auto &it1, const auto &it2) {
255 return SortUtils::maxCompareWithNaN(it1.maxValue(), it2.maxValue());
256 });
257
258 return std::make_pair(minIt, maxIt);
246 }
259 }
247
260
248 // /////// //
261 // /////// //
249 // Mutexes //
262 // Mutexes //
250 // /////// //
263 // /////// //
251
264
252 virtual void lockRead() { m_Lock.lockForRead(); }
265 virtual void lockRead() { m_Lock.lockForRead(); }
253 virtual void lockWrite() { m_Lock.lockForWrite(); }
266 virtual void lockWrite() { m_Lock.lockForWrite(); }
254 virtual void unlock() { m_Lock.unlock(); }
267 virtual void unlock() { m_Lock.unlock(); }
255
268
256 protected:
269 protected:
257 /// Protected ctor (DataSeries is abstract). The vectors must have the same size, otherwise a
270 /// Protected ctor (DataSeries is abstract). The vectors must have the same size, otherwise a
258 /// DataSeries with no values will be created.
271 /// DataSeries with no values will be created.
259 /// @remarks data series is automatically sorted on its x-axis data
272 /// @remarks data series is automatically sorted on its x-axis data
260 explicit DataSeries(std::shared_ptr<ArrayData<1> > xAxisData, const Unit &xAxisUnit,
273 explicit DataSeries(std::shared_ptr<ArrayData<1> > xAxisData, const Unit &xAxisUnit,
261 std::shared_ptr<ArrayData<Dim> > valuesData, const Unit &valuesUnit)
274 std::shared_ptr<ArrayData<Dim> > valuesData, const Unit &valuesUnit)
262 : m_XAxisData{xAxisData},
275 : m_XAxisData{xAxisData},
263 m_XAxisUnit{xAxisUnit},
276 m_XAxisUnit{xAxisUnit},
264 m_ValuesData{valuesData},
277 m_ValuesData{valuesData},
265 m_ValuesUnit{valuesUnit}
278 m_ValuesUnit{valuesUnit}
266 {
279 {
267 if (m_XAxisData->size() != m_ValuesData->size()) {
280 if (m_XAxisData->size() != m_ValuesData->size()) {
268 clear();
281 clear();
269 }
282 }
270
283
271 // Sorts data if it's not the case
284 // Sorts data if it's not the case
272 const auto &xAxisCData = m_XAxisData->cdata();
285 const auto &xAxisCData = m_XAxisData->cdata();
273 if (!std::is_sorted(xAxisCData.cbegin(), xAxisCData.cend())) {
286 if (!std::is_sorted(xAxisCData.cbegin(), xAxisCData.cend())) {
274 sort();
287 sort();
275 }
288 }
276 }
289 }
277
290
278 /// Copy ctor
291 /// Copy ctor
279 explicit DataSeries(const DataSeries<Dim> &other)
292 explicit DataSeries(const DataSeries<Dim> &other)
280 : m_XAxisData{std::make_shared<ArrayData<1> >(*other.m_XAxisData)},
293 : m_XAxisData{std::make_shared<ArrayData<1> >(*other.m_XAxisData)},
281 m_XAxisUnit{other.m_XAxisUnit},
294 m_XAxisUnit{other.m_XAxisUnit},
282 m_ValuesData{std::make_shared<ArrayData<Dim> >(*other.m_ValuesData)},
295 m_ValuesData{std::make_shared<ArrayData<Dim> >(*other.m_ValuesData)},
283 m_ValuesUnit{other.m_ValuesUnit}
296 m_ValuesUnit{other.m_ValuesUnit}
284 {
297 {
285 // Since a series is ordered from its construction and is always ordered, it is not
298 // Since a series is ordered from its construction and is always ordered, it is not
286 // necessary to call the sort method here ('other' is sorted)
299 // necessary to call the sort method here ('other' is sorted)
287 }
300 }
288
301
289 /// Assignment operator
302 /// Assignment operator
290 template <int D>
303 template <int D>
291 DataSeries &operator=(DataSeries<D> other)
304 DataSeries &operator=(DataSeries<D> other)
292 {
305 {
293 std::swap(m_XAxisData, other.m_XAxisData);
306 std::swap(m_XAxisData, other.m_XAxisData);
294 std::swap(m_XAxisUnit, other.m_XAxisUnit);
307 std::swap(m_XAxisUnit, other.m_XAxisUnit);
295 std::swap(m_ValuesData, other.m_ValuesData);
308 std::swap(m_ValuesData, other.m_ValuesData);
296 std::swap(m_ValuesUnit, other.m_ValuesUnit);
309 std::swap(m_ValuesUnit, other.m_ValuesUnit);
297
310
298 return *this;
311 return *this;
299 }
312 }
300
313
301 private:
314 private:
302 /**
315 /**
303 * Sorts data series on its x-axis data
316 * Sorts data series on its x-axis data
304 */
317 */
305 void sort() noexcept
318 void sort() noexcept
306 {
319 {
307 auto permutation = SortUtils::sortPermutation(*m_XAxisData, std::less<double>());
320 auto permutation = SortUtils::sortPermutation(*m_XAxisData, std::less<double>());
308 m_XAxisData = m_XAxisData->sort(permutation);
321 m_XAxisData = m_XAxisData->sort(permutation);
309 m_ValuesData = m_ValuesData->sort(permutation);
322 m_ValuesData = m_ValuesData->sort(permutation);
310 }
323 }
311
324
312 std::shared_ptr<ArrayData<1> > m_XAxisData;
325 std::shared_ptr<ArrayData<1> > m_XAxisData;
313 Unit m_XAxisUnit;
326 Unit m_XAxisUnit;
314 std::shared_ptr<ArrayData<Dim> > m_ValuesData;
327 std::shared_ptr<ArrayData<Dim> > m_ValuesData;
315 Unit m_ValuesUnit;
328 Unit m_ValuesUnit;
316
329
317 QReadWriteLock m_Lock;
330 QReadWriteLock m_Lock;
318 };
331 };
319
332
320 #endif // SCIQLOP_DATASERIES_H
333 #endif // SCIQLOP_DATASERIES_H
@@ -1,82 +1,88
1 #ifndef SCIQLOP_DATASERIESITERATOR_H
1 #ifndef SCIQLOP_DATASERIESITERATOR_H
2 #define SCIQLOP_DATASERIESITERATOR_H
2 #define SCIQLOP_DATASERIESITERATOR_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <memory>
6 #include <memory>
7
7
8 /**
8 /**
9 * @brief The DataSeriesIteratorValue class represents the current value of a data series iterator.
9 * @brief The DataSeriesIteratorValue class represents the current value of a data series iterator.
10 * It offers standard access methods for the data in the series (x-axis, values), but it is up to
10 * It offers standard access methods for the data in the series (x-axis, values), but it is up to
11 * each series to define its own implementation of how to retrieve this data, by implementing the
11 * each series to define its own implementation of how to retrieve this data, by implementing the
12 * DataSeriesIteratorValue::Impl interface
12 * DataSeriesIteratorValue::Impl interface
13 *
13 *
14 * @sa DataSeriesIterator
14 * @sa DataSeriesIterator
15 */
15 */
16 class SCIQLOP_CORE_EXPORT DataSeriesIteratorValue {
16 class SCIQLOP_CORE_EXPORT DataSeriesIteratorValue {
17 public:
17 public:
18 struct Impl {
18 struct Impl {
19 virtual ~Impl() noexcept = default;
19 virtual ~Impl() noexcept = default;
20 virtual std::unique_ptr<Impl> clone() const = 0;
20 virtual std::unique_ptr<Impl> clone() const = 0;
21 virtual bool equals(const Impl &other) const = 0;
21 virtual bool equals(const Impl &other) const = 0;
22 virtual void next() = 0;
22 virtual void next() = 0;
23 virtual void prev() = 0;
23 virtual void prev() = 0;
24 virtual double x() const = 0;
24 virtual double x() const = 0;
25 virtual double value() const = 0;
25 virtual double value() const = 0;
26 virtual double value(int componentIndex) const = 0;
26 virtual double value(int componentIndex) const = 0;
27 virtual double minValue() const = 0;
28 virtual double maxValue() const = 0;
27 };
29 };
28
30
29 explicit DataSeriesIteratorValue(std::unique_ptr<Impl> impl);
31 explicit DataSeriesIteratorValue(std::unique_ptr<Impl> impl);
30 DataSeriesIteratorValue(const DataSeriesIteratorValue &other);
32 DataSeriesIteratorValue(const DataSeriesIteratorValue &other);
31 DataSeriesIteratorValue(DataSeriesIteratorValue &&other) = default;
33 DataSeriesIteratorValue(DataSeriesIteratorValue &&other) = default;
32 DataSeriesIteratorValue &operator=(DataSeriesIteratorValue other);
34 DataSeriesIteratorValue &operator=(DataSeriesIteratorValue other);
33
35
34 bool equals(const DataSeriesIteratorValue &other) const;
36 bool equals(const DataSeriesIteratorValue &other) const;
35
37
36 /// Advances to the next value
38 /// Advances to the next value
37 void next();
39 void next();
38 /// Moves back to the previous value
40 /// Moves back to the previous value
39 void prev();
41 void prev();
40 /// Gets x-axis data
42 /// Gets x-axis data
41 double x() const;
43 double x() const;
42 /// Gets value data
44 /// Gets value data
43 double value() const;
45 double value() const;
44 /// Gets value data depending on an index
46 /// Gets value data depending on an index
45 double value(int componentIndex) const;
47 double value(int componentIndex) const;
48 /// Gets min of all values data
49 double minValue() const;
50 /// Gets max of all values data
51 double maxValue() const;
46
52
47 private:
53 private:
48 std::unique_ptr<Impl> m_Impl;
54 std::unique_ptr<Impl> m_Impl;
49 };
55 };
50
56
51 /**
57 /**
52 * @brief The DataSeriesIterator class represents an iterator used for data series. It defines all
58 * @brief The DataSeriesIterator class represents an iterator used for data series. It defines all
53 * operators needed for a standard forward iterator
59 * operators needed for a standard forward iterator
54 * @sa http://www.cplusplus.com/reference/iterator/
60 * @sa http://www.cplusplus.com/reference/iterator/
55 */
61 */
56 class SCIQLOP_CORE_EXPORT DataSeriesIterator {
62 class SCIQLOP_CORE_EXPORT DataSeriesIterator {
57 public:
63 public:
58 using iterator_category = std::forward_iterator_tag;
64 using iterator_category = std::forward_iterator_tag;
59 using value_type = const DataSeriesIteratorValue;
65 using value_type = const DataSeriesIteratorValue;
60 using difference_type = std::ptrdiff_t;
66 using difference_type = std::ptrdiff_t;
61 using pointer = value_type *;
67 using pointer = value_type *;
62 using reference = value_type &;
68 using reference = value_type &;
63
69
64 explicit DataSeriesIterator(DataSeriesIteratorValue value);
70 explicit DataSeriesIterator(DataSeriesIteratorValue value);
65 virtual ~DataSeriesIterator() noexcept = default;
71 virtual ~DataSeriesIterator() noexcept = default;
66 DataSeriesIterator(const DataSeriesIterator &) = default;
72 DataSeriesIterator(const DataSeriesIterator &) = default;
67 DataSeriesIterator(DataSeriesIterator &&) = default;
73 DataSeriesIterator(DataSeriesIterator &&) = default;
68 DataSeriesIterator &operator=(const DataSeriesIterator &) = default;
74 DataSeriesIterator &operator=(const DataSeriesIterator &) = default;
69 DataSeriesIterator &operator=(DataSeriesIterator &&) = default;
75 DataSeriesIterator &operator=(DataSeriesIterator &&) = default;
70
76
71 DataSeriesIterator &operator++();
77 DataSeriesIterator &operator++();
72 DataSeriesIterator &operator--();
78 DataSeriesIterator &operator--();
73 pointer operator->() const { return &m_CurrentValue; }
79 pointer operator->() const { return &m_CurrentValue; }
74 reference operator*() const { return m_CurrentValue; }
80 reference operator*() const { return m_CurrentValue; }
75 bool operator==(const DataSeriesIterator &other) const;
81 bool operator==(const DataSeriesIterator &other) const;
76 bool operator!=(const DataSeriesIterator &other) const;
82 bool operator!=(const DataSeriesIterator &other) const;
77
83
78 private:
84 private:
79 DataSeriesIteratorValue m_CurrentValue;
85 DataSeriesIteratorValue m_CurrentValue;
80 };
86 };
81
87
82 #endif // SCIQLOP_DATASERIESITERATOR_H
88 #endif // SCIQLOP_DATASERIESITERATOR_H
@@ -1,75 +1,85
1 #include "Data/DataSeriesIterator.h"
1 #include "Data/DataSeriesIterator.h"
2
2
3 DataSeriesIteratorValue::DataSeriesIteratorValue(
3 DataSeriesIteratorValue::DataSeriesIteratorValue(
4 std::unique_ptr<DataSeriesIteratorValue::Impl> impl)
4 std::unique_ptr<DataSeriesIteratorValue::Impl> impl)
5 : m_Impl{std::move(impl)}
5 : m_Impl{std::move(impl)}
6 {
6 {
7 }
7 }
8
8
9 DataSeriesIteratorValue::DataSeriesIteratorValue(const DataSeriesIteratorValue &other)
9 DataSeriesIteratorValue::DataSeriesIteratorValue(const DataSeriesIteratorValue &other)
10 : m_Impl{other.m_Impl->clone()}
10 : m_Impl{other.m_Impl->clone()}
11 {
11 {
12 }
12 }
13
13
14 DataSeriesIteratorValue &DataSeriesIteratorValue::operator=(DataSeriesIteratorValue other)
14 DataSeriesIteratorValue &DataSeriesIteratorValue::operator=(DataSeriesIteratorValue other)
15 {
15 {
16 std::swap(m_Impl, other.m_Impl);
16 std::swap(m_Impl, other.m_Impl);
17 return *this;
17 return *this;
18 }
18 }
19
19
20 bool DataSeriesIteratorValue::equals(const DataSeriesIteratorValue &other) const
20 bool DataSeriesIteratorValue::equals(const DataSeriesIteratorValue &other) const
21 {
21 {
22 return m_Impl->equals(*other.m_Impl);
22 return m_Impl->equals(*other.m_Impl);
23 }
23 }
24
24
25 void DataSeriesIteratorValue::next()
25 void DataSeriesIteratorValue::next()
26 {
26 {
27 m_Impl->next();
27 m_Impl->next();
28 }
28 }
29
29
30 void DataSeriesIteratorValue::prev()
30 void DataSeriesIteratorValue::prev()
31 {
31 {
32 m_Impl->prev();
32 m_Impl->prev();
33 }
33 }
34
34
35 double DataSeriesIteratorValue::x() const
35 double DataSeriesIteratorValue::x() const
36 {
36 {
37 return m_Impl->x();
37 return m_Impl->x();
38 }
38 }
39
39
40 double DataSeriesIteratorValue::value() const
40 double DataSeriesIteratorValue::value() const
41 {
41 {
42 return m_Impl->value();
42 return m_Impl->value();
43 }
43 }
44
44
45 double DataSeriesIteratorValue::value(int componentIndex) const
45 double DataSeriesIteratorValue::value(int componentIndex) const
46 {
46 {
47 return m_Impl->value(componentIndex);
47 return m_Impl->value(componentIndex);
48 }
48 }
49
49
50 double DataSeriesIteratorValue::minValue() const
51 {
52 return m_Impl->minValue();
53 }
54
55 double DataSeriesIteratorValue::maxValue() const
56 {
57 return m_Impl->maxValue();
58 }
59
50 DataSeriesIterator::DataSeriesIterator(DataSeriesIteratorValue value)
60 DataSeriesIterator::DataSeriesIterator(DataSeriesIteratorValue value)
51 : m_CurrentValue{std::move(value)}
61 : m_CurrentValue{std::move(value)}
52 {
62 {
53 }
63 }
54
64
55 DataSeriesIterator &DataSeriesIterator::operator++()
65 DataSeriesIterator &DataSeriesIterator::operator++()
56 {
66 {
57 m_CurrentValue.next();
67 m_CurrentValue.next();
58 return *this;
68 return *this;
59 }
69 }
60
70
61 DataSeriesIterator &DataSeriesIterator::operator--()
71 DataSeriesIterator &DataSeriesIterator::operator--()
62 {
72 {
63 m_CurrentValue.prev();
73 m_CurrentValue.prev();
64 return *this;
74 return *this;
65 }
75 }
66
76
67 bool DataSeriesIterator::operator==(const DataSeriesIterator &other) const
77 bool DataSeriesIterator::operator==(const DataSeriesIterator &other) const
68 {
78 {
69 return m_CurrentValue.equals(other.m_CurrentValue);
79 return m_CurrentValue.equals(other.m_CurrentValue);
70 }
80 }
71
81
72 bool DataSeriesIterator::operator!=(const DataSeriesIterator &other) const
82 bool DataSeriesIterator::operator!=(const DataSeriesIterator &other) const
73 {
83 {
74 return !(*this == other);
84 return !(*this == other);
75 }
85 }
General Comments 0
You need to be logged in to leave comments. Login now