#ifndef SCIQLOP_DATASERIESMERGEHELPER_H #define SCIQLOP_DATASERIESMERGEHELPER_H template class DataSeries; namespace detail { /** * Scope that can be used for a merge operation * @tparam FEnd the type of function that will be executed at the end of the scope */ template struct MergeScope { explicit MergeScope(FEnd end) : m_End{end} {} virtual ~MergeScope() noexcept { m_End(); } FEnd m_End; }; /** * Creates a scope for merge operation * @tparam end the function executed at the end of the scope */ template MergeScope scope(FEnd end) { return MergeScope{end}; } } // namespace detail /// Helper used to merge two DataSeries /// @sa DataSeries struct DataSeriesMergeHelper { /// Merges the source data series into the dest data series. Data of the source data series are /// consumed template static void merge(DataSeries &source, DataSeries &dest) { // Creates a scope to clear source data series at the end of the merge auto _ = detail::scope([&source]() { source.clear(); }); // Case : source data series is empty -> no merge is made if (source.isEmpty()) { return; } // Case : dest data series is empty -> we simply swap the data if (dest.isEmpty()) { std::swap(dest.m_XAxisData, source.m_XAxisData); std::swap(dest.m_ValuesData, source.m_ValuesData); return; } auto destMin = dest.cbegin()->x(); auto destMax = (--dest.cend())->x(); auto sourceBegin = source.cbegin(); auto sourceEnd = source.cend(); auto sourceMin = sourceBegin->x(); auto sourceMax = (--source.cend())->x(); // Case : source bounds are inside dest bounds -> no merge is made if (sourceMin >= destMin && sourceMax <= destMax) { return; } // Default case : // - prepend to dest the values of source that are lower than min value of dest // - append to dest the values of source that are greater than max value of dest auto lowerIt = std::lower_bound(sourceBegin, sourceEnd, destMin, [](const auto &it, const auto &val) { return it.x() < val; }); auto upperIt = std::upper_bound(lowerIt, sourceEnd, destMax, [](const auto &val, const auto &it) { return val < it.x(); }); dest.insert(sourceBegin, lowerIt, true); dest.insert(upperIt, sourceEnd); } }; #endif // SCIQLOP_DATASERIESMERGEHELPER_H