Newer
Older
/******************************************************************************
* File: RangeMap.impl.h
* Date: 17.5.2018
*****************************************************************************/
#include "Grinder.h"
#include "RangeMap.h"
#include "util/StringConv.h"
template<typename ValType>
void RangeMap<ValType>::add(value_type at, const range_type& range)
template<typename ValType>
void RangeMap<ValType>::add(value_type at, const range_vector_type& ranges)
{
}
template<typename ValType>
void RangeMap<ValType>::add(const RangeMap<value_type>& other)
{
for (const auto& rangeMapEntry : other._rangeMap)
add(rangeMapEntry.first, rangeMapEntry.second);
void RangeMap<ValType>::remove(value_type at, const range_type& range)
{
if (_rangeMap.find(at) != _rangeMap.end())
{
_rangeMap[at] -= range;
if (_rangeMap[at].empty())
_rangeMap.erase(at);
}
}
template<typename ValType>
void RangeMap<ValType>::remove(value_type at, const range_vector_type& ranges)
{
}
template<typename ValType>
void RangeMap<ValType>::remove(const RangeMap<value_type>& other)
{
for (const auto& rangeMapEntry : other._rangeMap)
remove(rangeMapEntry.first, rangeMapEntry.second);
void RangeMap<ValType>::moveTo(value_type x, value_type y)
auto xOffset = x - mapBounds.first.first;
auto yOffset = y - mapBounds.second.first;
if (xOffset != 0)
{
// Offset every range in the map
for (auto& rangeRow : _rangeMap)
rangeRow.second.offsetRanges(xOffset);
}
if (yOffset != 0)
{
// Build a new map that is offset by the given amount
range_map_type newMap;
for (auto it = _rangeMap.begin(); it != _rangeMap.end(); ++it)
newMap[it->first + yOffset] = std::move(_rangeMap[it->first]);
_rangeMap = std::move(newMap);
}
}
template<typename ValType>
bool RangeMap<ValType>::contains(value_type at) const
{
return find(at) != _rangeMap.cend();
}
template<typename ValType>
bool RangeMap<ValType>::contains(value_type at, value_type value) const
{
if (_rangeMap.find(at) != _rangeMap.cend())
return _rangeMap.at(at).contains(value);
else
return false;
}
template<typename ValType>
bool RangeMap<ValType>::adjoins(value_type at, const range_type& range) const
{
// Ranges can overlap or touch, so look at the row above and below the given row as well
for (int offset = -1; offset <= 1; ++offset)
{
auto it = _rangeMap.find(static_cast<value_type>(at + offset));
if (it != _rangeMap.cend())
{
if (it->second.adjoins(range))
return true;
}
}
return false;
}
template<typename ValType>
auto RangeMap<ValType>::bounds() const
{
std::pair<value_type, value_type> boundsX{std::numeric_limits<value_type>::max(), std::numeric_limits<value_type>::min()};
std::pair<value_type, value_type> boundsY{std::numeric_limits<value_type>::max(), std::numeric_limits<value_type>::min()};
if (rangeBounds.first < boundsX.first)
boundsX.first = rangeBounds.first;
if (rangeBounds.second > boundsX.second)
boundsX.second = rangeBounds.second;
// Get bounds in y direction
if (rangeMapEntry.first < boundsY.first)
boundsY.first = rangeMapEntry.first;
if (rangeMapEntry.first > boundsY.second)
boundsY.second = rangeMapEntry.first;
}
return std::make_pair(boundsX, boundsY);
}
auto RangeMap<ValType>::regions() const
using RegionsType = std::list<RangeMap<value_type>>;
RegionsType regions;
// Iterate over all ranges in each row
for (auto rangeRow : _rangeMap)
{
std::list<typename RegionsType::iterator> adjoiningRegions;
// Find all adjoining regions of the current range
for (auto it = regions.begin(); it != regions.end(); ++it)
if (it->adjoins(rangeRow.first, range))
adjoiningRegions.push_back(it);
}
if (adjoiningRegions.size() > 1) // Merge regions
{
RangeMap<value_type> mergedRegion;
// Merge the adjoining regions and remove each one, as they will be replaced by the new region
for (auto it : adjoiningRegions)
mergedRegion.add(*it);
regions.erase(it);
}
mergedRegion.add(rangeRow.first, range);
regions.push_back(std::move(mergedRegion));
}
else if (adjoiningRegions.size() == 1) // Extend region
{
adjoiningRegions.front()->add(rangeRow.first, range);
}
else // Create a new region
{
RangeMap<value_type> newRegion;
newRegion.add(rangeRow.first, range);
regions.push_back(std::move(newRegion));
}
}
}
return regions;
}
template<typename ValType>
QString RangeMap<ValType>::toString() const
{
QStringList rangeMap;
for (const auto& rangeMapEntry : _rangeMap)
rangeMap << QString{"%1:%2"}.arg(StringConv::convertValue(rangeMapEntry.first)).arg(rangeMapEntry.second.toString());
return rangeMap.join("|");
}
template<typename ValType>
void RangeMap<ValType>::fromString(const QString& str)
{
_rangeMap.clear();
for (auto rangeVector : str.split("|", Qt::SkipEmptyParts))
{
QStringList tokens = rangeVector.split(":");
if (tokens.size() == 2)
_rangeMap[StringConv::convertString<value_type>(tokens[0])] = tokens[1];
}
}