##// END OF EJS Templates
Adds method to get all variables from model...
Adds method to get all variables from model This method will be used to generate forbidden names when renaming a variable (i.e. names of existing variables)

File last commit:

r668:aaf56376a038
r684:c7028b4894dd
Show More
DataSeriesMergeHelper.h
132 lines | 4.4 KiB | text/x-c | CLexer
/ core / include / Data / DataSeriesMergeHelper.h
Alexandre Leroux
Updates merge() method (1)...
r668 #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};
}
/**
* Enum used to position a data series relative to another during a merge operation
*/
enum class MergePosition { LOWER_THAN, GREATER_THAN, EQUAL, OVERLAP };
/**
* Computes the position of the first data series relative to the second data series
* @param lhs the first data series
* @param rhs the second data series
* @return the merge position computed
* @remarks the data series must not be empty
*/
template <int Dim>
MergePosition mergePosition(DataSeries<Dim> &lhs, DataSeries<Dim> &rhs)
{
Q_ASSERT(!lhs.isEmpty() && !rhs.isEmpty());
// Case lhs < rhs
auto lhsLast = --lhs.cend();
auto rhsFirst = rhs.cbegin();
if (lhsLast->x() < rhsFirst->x()) {
return MergePosition::LOWER_THAN;
}
// Case lhs > rhs
auto lhsFirst = lhs.cbegin();
auto rhsLast = --rhs.cend();
if (lhsFirst->x() > rhsLast->x()) {
return MergePosition::GREATER_THAN;
}
// Other cases
auto equal = std::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin(), rhs.cend(),
[](const auto &it1, const auto &it2) {
return it1.x() == it2.x() && it1.values() == it2.values();
});
return equal ? MergePosition::EQUAL : MergePosition::OVERLAP;
}
} // 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;
}
// Gets the position of the source in relation to the destination
auto sourcePosition = detail::mergePosition(source, dest);
switch (sourcePosition) {
case detail::MergePosition::LOWER_THAN:
case detail::MergePosition::GREATER_THAN: {
auto prepend = sourcePosition == detail::MergePosition::LOWER_THAN;
dest.m_XAxisData->add(*source.m_XAxisData, prepend);
dest.m_ValuesData->add(*source.m_ValuesData, prepend);
break;
}
case detail::MergePosition::EQUAL:
// the data series equal each other : no merge made
break;
case detail::MergePosition::OVERLAP: {
// the two data series overlap : merge is made
auto temp = dest.clone();
if (auto tempSeries = dynamic_cast<DataSeries<Dim> *>(temp.get())) {
// Makes the merge :
// - Data are sorted by x-axis values
// - If two entries are in the source range and the other range, only one entry
// is retained as result
// - The results are stored directly in the data series
dest.clear();
std::set_union(
tempSeries->cbegin(), tempSeries->cend(), source.cbegin(), source.cend(),
std::back_inserter(dest),
[](const auto &it1, const auto &it2) { return it1.x() < it2.x(); });
}
break;
}
default:
Q_ASSERT(false);
}
}
};
#endif // SCIQLOP_DATASERIESMERGEHELPER_H