##// END OF EJS Templates
Updates merge method...
Alexandre Leroux -
r646:cb05b478d08e
parent child
Show More
@@ -256,16 +256,7 public:
256 return;
256 return;
257 }
257 }
258
258
259 if (prepend) {
259 insert(other.cbegin(), other.cend(), prepend);
260 auto otherDataSize = other.m_Data.size();
261 m_Data.insert(m_Data.begin(), otherDataSize, 0.);
262 for (auto i = 0; i < otherDataSize; ++i) {
263 m_Data.replace(i, other.m_Data.at(i));
264 }
265 }
266 else {
267 m_Data.append(other.m_Data);
268 }
269 }
260 }
270
261
271 void clear()
262 void clear()
@@ -332,16 +323,16 public:
332 }
323 }
333 }
324 }
334
325
335 /// Inserts at the end of the array data the values passed as a parameter. This
326 void insert(ArrayDataIterator first, ArrayDataIterator last, bool prepend = false)
336 /// method is intended to be used in the context of generating a back insert iterator, or only
337 /// if it's ensured that the total size of the vector is consistent with the number of
338 /// components of the array data
339 /// @param values the values to insert
340 /// @sa http://en.cppreference.com/w/cpp/iterator/back_inserter
341 void push_back(const QVector<double> &values)
342 {
327 {
343 Q_ASSERT(values.size() % m_NbComponents == 0);
328 auto firstImpl = dynamic_cast<arraydata_detail::IteratorValue<Dim, true> *>(first->impl());
344 m_Data.append(values);
329 auto lastImpl = dynamic_cast<arraydata_detail::IteratorValue<Dim, true> *>(last->impl());
330
331 if (firstImpl && lastImpl) {
332 auto insertIt = prepend ? m_Data.begin() : m_Data.end();
333
334 m_Data.insert(insertIt, firstImpl->m_It, lastImpl->m_It);
335 }
345 }
336 }
346
337
347 /**
338 /**
@@ -134,10 +134,6 class SCIQLOP_CORE_EXPORT DataSeries : public IDataSeries {
134 friend class DataSeriesMergeHelper;
134 friend class DataSeriesMergeHelper;
135
135
136 public:
136 public:
137 /// Tag needed to define the push_back() method
138 /// @sa push_back()
139 using value_type = DataSeriesIteratorValue;
140
141 /// @sa IDataSeries::xAxisData()
137 /// @sa IDataSeries::xAxisData()
142 std::shared_ptr<ArrayData<1> > xAxisData() override { return m_XAxisData; }
138 std::shared_ptr<ArrayData<1> > xAxisData() override { return m_XAxisData; }
143 const std::shared_ptr<ArrayData<1> > xAxisData() const { return m_XAxisData; }
139 const std::shared_ptr<ArrayData<1> > xAxisData() const { return m_XAxisData; }
@@ -254,6 +250,17 public:
254 }
250 }
255 }
251 }
256
252
253 void insert(DataSeriesIterator first, DataSeriesIterator last, bool prepend = false)
254 {
255 auto firstImpl = dynamic_cast<dataseries_detail::IteratorValue<Dim, true> *>(first->impl());
256 auto lastImpl = dynamic_cast<dataseries_detail::IteratorValue<Dim, true> *>(last->impl());
257
258 if (firstImpl && lastImpl) {
259 m_XAxisData->insert(firstImpl->m_XIt, lastImpl->m_XIt, prepend);
260 m_ValuesData->insert(firstImpl->m_ValuesIt, lastImpl->m_ValuesIt, prepend);
261 }
262 }
263
257 /// @sa IDataSeries::minXAxisData()
264 /// @sa IDataSeries::minXAxisData()
258 DataSeriesIterator minXAxisData(double minXAxisData) const override
265 DataSeriesIterator minXAxisData(double minXAxisData) const override
259 {
266 {
@@ -287,7 +294,7 public:
287 begin, end, minXAxisData,
294 begin, end, minXAxisData,
288 [](const auto &itValue, const auto &value) { return itValue.x() < value; });
295 [](const auto &itValue, const auto &value) { return itValue.x() < value; });
289 auto upperIt = std::upper_bound(
296 auto upperIt = std::upper_bound(
290 begin, end, maxXAxisData,
297 lowerIt, end, maxXAxisData,
291 [](const auto &value, const auto &itValue) { return value < itValue.x(); });
298 [](const auto &value, const auto &itValue) { return value < itValue.x(); });
292
299
293 return std::make_pair(lowerIt, upperIt);
300 return std::make_pair(lowerIt, upperIt);
@@ -327,22 +334,6 public:
327 virtual void lockWrite() { m_Lock.lockForWrite(); }
334 virtual void lockWrite() { m_Lock.lockForWrite(); }
328 virtual void unlock() { m_Lock.unlock(); }
335 virtual void unlock() { m_Lock.unlock(); }
329
336
330 // ///// //
331 // Other //
332 // ///// //
333
334 /// Inserts at the end of the data series the value of the iterator passed as a parameter. This
335 /// method is intended to be used in the context of generating a back insert iterator
336 /// @param iteratorValue the iterator value containing the values to insert
337 /// @sa http://en.cppreference.com/w/cpp/iterator/back_inserter
338 /// @sa merge()
339 /// @sa value_type
340 void push_back(const value_type &iteratorValue)
341 {
342 m_XAxisData->push_back(QVector<double>{iteratorValue.x()});
343 m_ValuesData->push_back(iteratorValue.values());
344 }
345
346 protected:
337 protected:
347 /// Protected ctor (DataSeries is abstract). The vectors must have the same size, otherwise a
338 /// Protected ctor (DataSeries is abstract). The vectors must have the same size, otherwise a
348 /// DataSeries with no values will be created.
339 /// DataSeries with no values will be created.
@@ -27,45 +27,6 MergeScope<FEnd> scope(FEnd end)
27 return MergeScope<FEnd>{end};
27 return MergeScope<FEnd>{end};
28 }
28 }
29
29
30 /**
31 * Enum used to position a data series relative to another during a merge operation
32 */
33 enum class MergePosition { LOWER_THAN, GREATER_THAN, EQUAL, OVERLAP };
34
35 /**
36 * Computes the position of the first data series relative to the second data series
37 * @param lhs the first data series
38 * @param rhs the second data series
39 * @return the merge position computed
40 * @remarks the data series must not be empty
41 */
42 template <int Dim>
43 MergePosition mergePosition(DataSeries<Dim> &lhs, DataSeries<Dim> &rhs)
44 {
45 Q_ASSERT(!lhs.isEmpty() && !rhs.isEmpty());
46
47 // Case lhs < rhs
48 auto lhsLast = --lhs.cend();
49 auto rhsFirst = rhs.cbegin();
50 if (lhsLast->x() < rhsFirst->x()) {
51 return MergePosition::LOWER_THAN;
52 }
53
54 // Case lhs > rhs
55 auto lhsFirst = lhs.cbegin();
56 auto rhsLast = --rhs.cend();
57 if (lhsFirst->x() > rhsLast->x()) {
58 return MergePosition::GREATER_THAN;
59 }
60
61 // Other cases
62 auto equal = std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend(),
63 [](const auto &it1, const auto &it2) {
64 return it1.x() == it2.x() && it1.values() == it2.values();
65 });
66 return equal ? MergePosition::EQUAL : MergePosition::OVERLAP;
67 }
68
69 } // namespace detail
30 } // namespace detail
70
31
71
32
@@ -92,40 +53,30 struct DataSeriesMergeHelper {
92 return;
53 return;
93 }
54 }
94
55
95 // Gets the position of the source in relation to the destination
56 auto destMin = dest.cbegin()->x();
96 auto sourcePosition = detail::mergePosition(source, dest);
57 auto destMax = (--dest.cend())->x();
97
58
98 switch (sourcePosition) {
59 auto sourceBegin = source.cbegin();
99 case detail::MergePosition::LOWER_THAN:
60 auto sourceEnd = source.cend();
100 case detail::MergePosition::GREATER_THAN: {
61 auto sourceMin = sourceBegin->x();
101 auto prepend = sourcePosition == detail::MergePosition::LOWER_THAN;
62 auto sourceMax = (--source.cend())->x();
102 dest.m_XAxisData->add(*source.m_XAxisData, prepend);
63
103 dest.m_ValuesData->add(*source.m_ValuesData, prepend);
64 // Case : source bounds are inside dest bounds -> no merge is made
104 break;
65 if (sourceMin >= destMin && sourceMax <= destMax) {
105 }
66 return;
106 case detail::MergePosition::EQUAL:
107 // the data series equal each other : no merge made
108 break;
109 case detail::MergePosition::OVERLAP: {
110 // the two data series overlap : merge is made
111 auto temp = dest.clone();
112 if (auto tempSeries = dynamic_cast<DataSeries<Dim> *>(temp.get())) {
113 // Makes the merge :
114 // - Data are sorted by x-axis values
115 // - If two entries are in the source range and the other range, only one entry
116 // is retained as result
117 // - The results are stored directly in the data series
118 dest.clear();
119 std::set_union(
120 tempSeries->cbegin(), tempSeries->cend(), source.cbegin(), source.cend(),
121 std::back_inserter(dest),
122 [](const auto &it1, const auto &it2) { return it1.x() < it2.x(); });
123 }
124 break;
125 }
126 default:
127 Q_ASSERT(false);
128 }
67 }
68
69 // Default case :
70 // - prepend to dest the values of source that are lower than min value of dest
71 // - append to dest the values of source that are greater than max value of dest
72 auto lowerIt
73 = std::lower_bound(sourceBegin, sourceEnd, destMin,
74 [](const auto &it, const auto &val) { return it.x() < val; });
75 auto upperIt
76 = std::upper_bound(lowerIt, sourceEnd, destMax,
77 [](const auto &val, const auto &it) { return val < it.x(); });
78 dest.insert(sourceBegin, lowerIt, true);
79 dest.insert(upperIt, sourceEnd);
129 }
80 }
130 };
81 };
131
82
General Comments 0
You need to be logged in to leave comments. Login now