Search code examples
c++boostr-tree

Storing or accessing objects in boost r-tree


I am using Boost's r-tree implementation in my code. I have a list of objects with coordinates (say cities on a map, if it matters), which I wish to index in the r-tree, to perform fast NN search, etc. I have followed their iterative query example, in which trees are storing boost::geometry::model::point objects.

My question: is there anyway to store objects (i.e. the cities themselves) instead of just their coordinates in the tree? One solution I thought about is to use indexing of my own. If this is indeed what I should do - is there anyway to find the index of the objects by the order in which they were inserted to the tree?

So, for example, when I look for the KNNs of some cities - I would like to extract not only their coordinates (or distances), like they do in the example:

for ( rtree_t::const_query_iterator
        it = rtree.qbegin(bgi::nearest(pt, N));
        it != rtree.qend() ;
        ++it ) {

    std::cout << bg::wkt(*it) << ", distance= " << bg::distance(pt, *it) << std::endl;
}

But also the order at which they were inserted into the tree, so I could access them e.g. from a vector that contains the objects by order of insertion.


Solution

  • You can store any type in a rtree, you just have to tell Boost how to get the coordinates out.

    So the first step is to make a type with both a index and point:

    struct CityRef {
        size_t index;
        point location;
    };
    

    You can specialize boost::geometry::index::indexable to give Boost a way to find the point you've put in there:

    template <>
    struct bgi::indexable<CityRef>
    {
        typedef point result_type;
        point operator()(const CityRef& c) const { return c.location; }
    };
    

    Then you can use your type in place of point when declaring your rtree:

    typedef bgi::rtree< CityRef, bgi::linear<16> > rtree_t;
    

    And when you iterate, the iterator will refer to your type instead of point:

    for ( rtree_t::const_query_iterator
          it = rtree.qbegin(bgi::nearest(pt, 100)) ;
          it != rtree.qend() ;
          ++it )
    {
        // *it is a CityRef, do whatever you want
    }
    

    Here is a demo using that example with another type: https://godbolt.org/z/zT3xcf