Вот базовая программа с двойным индексом (R-дерево и std :: map), выполняющая двунаправленную индексацию: от символа к блоку / интервалу и от блока / интервала к символу:
Включает, iostream
требуется только для вывода.
#include <boost/geometry.hpp>
#include <map>
#include <vector>
#include <iostream>
Пространства имен для удобства.
namespace bg = boost::geometry;
namespace bgi = boost::geometry::index;
Основной двунаправленный индекс, позволяющий вставлять пары box / interval-char и находить box на основе charили вектор символов на основе коробки (пересекающийся).insert()
объединяет блоки при необходимости.
template <typename Box, typename T>
class rtree_map_index
{
typedef std::map<T, Box> map_type;
typedef typename map_type::iterator map_iterator;
typedef typename map_type::const_iterator map_const_iterator;
typedef std::pair<Box, map_iterator> rtree_value;
typedef bgi::rtree<rtree_value, bgi::rstar<4> > rtree_type;
public:
void insert(Box const& box, T const& v)
{
std::pair<map_iterator, bool>
p = m_map.insert(std::make_pair(v, box));
map_iterator map_it = p.first;
T const& map_val = map_it->first;
Box & map_box = map_it->second;
// new key,value inserted into map
if (p.second)
{
// insert it to the r-tree
m_rtree.insert(rtree_value(map_box, map_it));
}
// key already exists in map and box has to be expanded
else if (! bg::covered_by(box, map_box))
{
// calculate expanded box
Box new_box = map_box;
bg::expand(new_box, box);
// update r-tree
m_rtree.remove(rtree_value(map_box, map_it));
m_rtree.insert(rtree_value(new_box, map_it));
// update map
map_box = new_box;
}
}
bool find(T const& v, Box & result) const
{
map_const_iterator it = m_map.find(v);
if (it != m_map.end())
{
result = it->second;
return true;
}
return false;
}
void find(Box const& box, std::vector<char> & result) const
{
std::vector<rtree_value> res;
m_rtree.query(bgi::intersects(box), std::back_inserter(res));
result.resize(res.size());
for (size_t i = 0; i < res.size(); ++i)
result[i] = res[i].second->first;
}
private:
rtree_type m_rtree;
map_type m_map;
};
Основная функция с базовым вариантом использования.
int main()
{
для двумерных данных, хранящихся в r-дереве (блоки).
{
typedef bg::model::point<double, 2, bg::cs::cartesian> point;
typedef bg::model::box<point> box;
rtree_map_index<box, char> index;
index.insert(box(point(0, 0), point(3, 3)), 'a');
index.insert(box(point(1, 1), point(4, 4)), 'a');
index.insert(box(point(5, 5), point(6, 6)), 'b');
box res1;
index.find('a', res1);
std::cout << bg::wkt(res1) << std::endl;
std::vector<char> res2;
index.find(box(point(4, 4), point(5, 5)), res2);
BOOST_ASSERT(res2.size() == 2);
std::cout << res2[0] << std::endl;
std::cout << res2[1] << std::endl;
}
для одномерных данных, хранящихся в r-дереве (интервалы)
{
typedef bg::model::point<double, 1, bg::cs::cartesian> point;
typedef bg::model::box<point> box;
rtree_map_index<box, char> index;
index.insert(box(point(0), point(3)), 'a');
index.insert(box(point(1), point(4)), 'a');
index.insert(box(point(5), point(6)), 'b');
box res1;
index.find('a', res1);
std::cout << "(" << bg::get<0, 0>(res1) << ", " << bg::get<1, 0>(res1) << ")" << std::endl;
std::vector<char> res2;
index.find(box(point(4), point(5)), res2);
BOOST_ASSERT(res2.size() == 2);
std::cout << res2[0] << std::endl;
std::cout << res2[1] << std::endl;
}
Конец.
return 0;
}
Обратите внимание, что вместо rtree
Вы могли бы использовать interval_map
.Вы должны быть в состоянии построить на вершине rtree_map_index
.Вы можете добавить конструктор, создающий map и rtree из контейнера элементов типа std::pair<Box, T>
, чтобы воспользоваться преимуществами алгоритма упаковки r-дерева.Вы можете реализовать любую нужную вам функцию find()
.И т.д.