DataSeriesMergeHelper.h
83 lines
| 2.6 KiB
| text/x-c
|
CLexer
r0 | #ifndef SCIQLOP_DATASERIESMERGEHELPER_H | |||
#define SCIQLOP_DATASERIESMERGEHELPER_H | ||||
template <int Dim> | ||||
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 <typename FEnd> | ||||
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 <typename FEnd> | ||||
MergeScope<FEnd> scope(FEnd end) | ||||
{ | ||||
return MergeScope<FEnd>{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 <int Dim> | ||||
static void merge(DataSeries<Dim> &source, DataSeries<Dim> &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 | ||||