Program Listing for File rtree.hpp
↰ Return to documentation for file (rcppsw/ds/rtree.hpp
)
#pragma once
/*******************************************************************************
* Includes
******************************************************************************/
#include <algorithm>
#include <boost/geometry.hpp>
#include <boost/geometry/index/rtree.hpp>
#include <utility>
#include <vector>
#include "rcppsw/math/vector2.hpp"
#include "rcppsw/math/vector3.hpp"
#include "rcppsw/patterns/decorator/decorator.hpp"
/*******************************************************************************
* Namespaces/Decls
******************************************************************************/
namespace rcppsw::ds {
namespace bg = boost::geometry;
namespace bgi = bg::index;
template <typename TCoordType>
using rtree_point = bg::model::point<typename TCoordType::value_type,
TCoordType::kDIMENSIONALITY,
bg::cs::cartesian>;
template <typename TCoordType>
using rtree_box = bg::model::box<rtree_point<TCoordType>>;
template<typename TCoordType,
typename TGeometryType,
typename TValueType,
size_t MAXELTS = 16>
struct rtree_spec {
static constexpr const size_t kMAXELTS = 16;
using coord_type = TCoordType;
using geometry_type = TGeometryType;
using value_type = TValueType;
using element_type = std::pair<geometry_type, value_type>;
using tree_type = bgi::rtree<element_type, bgi::rstar<MAXELTS>>;
};
/*******************************************************************************
* Class Definitions
******************************************************************************/
template <typename TSpecType>
class rtree : rpdecorator::decorator<typename TSpecType::tree_type> {
public:
using spec_type = TSpecType;
using value_type = typename spec_type::value_type;
using element_type = typename spec_type::element_type;
using geometry_type = typename spec_type::geometry_type;
using coord_type = typename spec_type::coord_type;
using rpdecorator::decorator<typename spec_type::tree_type>::decoratee;
rtree(void) = default;
/* Not move/copy constructable/assignable by default */
rtree(const rtree&) = delete;
const rtree& operator=(const rtree&) = delete;
rtree(rtree&&) = delete;
rtree& operator=(rtree&&) = delete;
std::vector<value_type> intersections(const rtree_box<coord_type>& query) const {
std::vector<element_type> res1;
res1.reserve(spec_type::kMAXELTS); /* good a guess as any */
decoratee().query(bgi::intersects(query), std::back_inserter(res1));
std::vector<value_type> res2;
res2.reserve(res1.size());
std::transform(res1.begin(),
res1.end(),
std::back_inserter(res2),
[res2](const auto& pair) { return pair.second; });
return res2;
}
std::vector<value_type> nearest(const rtree_point<coord_type>& query,
size_t k) const {
std::vector<element_type> res1;
res1.reserve(spec_type::kMAXELTS); /* good a guess as any */
decoratee().query(bgi::nearest(query, k), std::back_inserter(res1));
std::vector<value_type> res2;
res2.reserve(res1.size());
std::transform(res1.begin(),
res1.end(),
std::back_inserter(res2),
[res2](const auto& pair) { return pair.second; });
return res2;
}
bool contains(const value_type& key) const {
auto it =
std::find_if(decoratee().begin(), decoratee().end(), [key](const auto& pair) {
return key == pair.second;
});
return decoratee().end() != it;
}
void insert(const value_type& value, const geometry_type& key) {
decoratee().insert(element_type(key, value));
}
size_t remove(const value_type& value) {
std::vector<element_type> victims;
std::copy_if(decoratee().begin(),
decoratee().end(),
std::back_inserter(victims),
[value](const auto& pair) { return value == pair.second; });
return decoratee().remove(victims.begin(), victims.end());
}
size_t remove(const value_type& value, const geometry_type& key) {
return decoratee().remove(element_type(key, value));
}
RCPPSW_DECORATE_DECLDEF(insert);
RCPPSW_DECORATE_DECLDEF(begin, const);
RCPPSW_DECORATE_DECLDEF(end, const);
RCPPSW_DECORATE_DECLDEF(size, const);
};
/*******************************************************************************
* Free Functions
******************************************************************************/
template <typename TCoordType,
RCPPSW_SFINAE_DECLDEF(rmpl::is_specialization<TCoordType,
rmath::vector2>::value)>
rtree_point<TCoordType> make_rtree_point(const TCoordType& c) {
return rtree_point<TCoordType>(c.x(), c.y());
}
template <typename TCoordType,
RCPPSW_SFINAE_DECLDEF(rmpl::is_specialization<TCoordType,
rmath::vector3>::value)>
rtree_point<TCoordType> make_rtree_point(const TCoordType& c) {
return rtree_point<TCoordType>(c.x(), c.y(), c.z());
}
template <typename TCoordType,
RCPPSW_SFINAE_DECLDEF(rmpl::is_specialization<TCoordType,
rmath::vector2>::value)>
rtree_box<TCoordType> make_rtree_box(const TCoordType& ll,
const TCoordType& ur) {
return rtree_box<TCoordType>(rtree_point<TCoordType>(ll.x(),
ll.y()),
rtree_point<TCoordType>(ur.x(),
ur.y()));
}
template <typename TCoordType,
RCPPSW_SFINAE_DECLDEF(rmpl::is_specialization<TCoordType,
rmath::vector3>::value)>
rtree_box<TCoordType> make_rtree_box(const TCoordType& ll,
const TCoordType& ur) {
return rtree_box<TCoordType>(rtree_point<TCoordType>(ll.x(),
ll.y(),
ll.z()),
rtree_point<TCoordType>(ur.x(),
ur.y(),
ur.z()));
}
} /* namespace rcppsw::ds */