Search code examples
c++boostr-tree

Build rtree with boost::geometry results in errors


I wrote this small program, following the boost documentation, but I get pages of errors when building it.

#include <boost/geometry/index/rtree.hpp>
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/point_xy.hpp>
#include <iostream>

namespace bg = boost::geometry;
namespace bgi = boost::geometry::index;

typedef bg::model::d2::point_xy<double> point_2d;

class Foo
{
public:
    point_2d position;
    Foo(double x, double y) : position(x, y) {}
    auto get() const { return position; }
};

int main()
{
    bgi::rtree<Foo, bgi::quadratic<16>> rtree;

    rtree.insert(Foo(1.0, 2.0));
    rtree.insert(Foo(3.0, 4.0));
    rtree.insert(Foo(5.0, 6.0));
    rtree.insert(Foo(7.0, 8.0));

    // Define a search box with a certain distance from a given point
    point_2d search_point(0.0, 0.0);
    double search_distance = 5.0;
    point_2d lower_left(search_point.x() - search_distance, search_point.y() - search_distance);
    point_2d upper_right(search_point.x() + search_distance, search_point.y() + search_distance);
    bg::model::box<point_2d> search_box(lower_left, upper_right);

    // Use the rtree to search for instances of Foo within the search box
    std::vector<Foo> result;
    rtree.query(bgi::intersects(search_box), std::back_inserter(result));

    // Print the results
    std::cout << "Found " << result.size() << " instances of Foo within the search box" << std::endl;
    for (const auto& foo : result)
        std::cout << "Foo at position (" << foo.position.x() << ", " << foo.position.y() << ")" << std::endl;

}

Here is the build:

clang++ --std=c++17 tree.cpp -lboost-geometry 2>&1 | head -n50 
In file included from tree.cpp:1:
In file included from /usr/include/boost/geometry/index/rtree.hpp:49:
/usr/include/boost/geometry/index/indexable.hpp:64:5: error: no matching function for call to 'assertion_failed'
    BOOST_MPL_ASSERT_MSG(
    ^~~~~~~~~~~~~~~~~~~~~
/usr/include/boost/mpl/assert.hpp:454:51: note: expanded from macro 'BOOST_MPL_ASSERT_MSG'
#   define BOOST_MPL_ASSERT_MSG( c, msg, types_ ) \
                                                  ^
/usr/include/boost/mpl/assert.hpp:440:9: note: expanded from macro '\
BOOST_MPL_ASSERT_MSG_IMPL'
        boost::mpl::assertion_failed<(c)>( BOOST_PP_CAT(mpl_assert_arg,counter)::assert_arg() ) \
        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/boost/mpl/assert.hpp:60:58: note: expanded from macro '\
BOOST_MPL_AUX_ASSERT_CONSTANT'
#   define BOOST_MPL_AUX_ASSERT_CONSTANT(T, expr) enum { expr }
                                                         ^~~~
/usr/include/boost/geometry/index/indexable.hpp:351:7: note: in instantiation of template class 'boost::geometry::index::detail::indexable<Foo, false>' requested here
    : detail::indexable<Value>
      ^
/usr/include/boost/geometry/index/detail/translator.hpp:46:14: note: in instantiation of template class 'boost::geometry::index::indexable<Foo>' requested here
    : public IndexableGetter
             ^
/usr/include/boost/geometry/index/detail/translator.hpp:74:22: note: in instantiation of template class 'boost::geometry::index::detail::translator<boost::geometry::index::indexable<Foo>, boost::geometry::index::equal_to<Foo> >' requested here
    typedef typename IndexableGetter::result_type type;
                     ^
/usr/include/boost/geometry/index/detail/translator.hpp:82:22: note: in instantiation of template class 'boost::geometry::index::detail::result_type<boost::geometry::index::detail::translator<boost::geometry::index::indexable<Foo>, boost::geometry::index::equal_to<Foo> > >' requested here
            typename result_type<IndexableGetter>::type
                     ^
/usr/include/boost/geometry/index/rtree.hpp:177:37: note: in instantiation of template class 'boost::geometry::index::detail::indexable_type<boost::geometry::index::detail::translator<boost::geometry::index::indexable<Foo>, boost::geometry::index::equal_to<Foo> > >' requested here
    typedef typename index::detail::indexable_type<
                                    ^
tree.cpp:27:41: note: in instantiation of template class 'boost::geometry::index::rtree<Foo, boost::geometry::index::quadratic<16, 4>, boost::geometry::index::indexable<Foo>, boost::geometry::index::equal_to<Foo>, boost::container::new_allocator<Foo> >' requested here
    bgi::rtree<Foo, bgi::quadratic<16>> rtree;
                                        ^
/usr/include/boost/mpl/assert.hpp:83:5: note: candidate function template not viable: no known conversion from 'boost::mpl::failed ************(boost::geometry::index::detail::indexable<Foo, false>::NOT_VALID_INDEXABLE_TYPE::************)(Foo)' to 'typename assert<false>::type' (aka 'mpl_::assert<false>') for 1st argument
int assertion_failed( typename assert<C>::type );
    ^
In file included from tree.cpp:1:
In file included from /usr/include/boost/geometry/index/rtree.hpp:28:
In file included from /usr/include/boost/geometry/algorithms/detail/comparable_distance/interface.hpp:23:
In file included from /usr/include/boost/geometry/geometries/concepts/check.hpp:28:
In file included from /usr/include/boost/geometry/geometries/concepts/box_concept.hpp:23:
In file included from /usr/include/boost/geometry/core/access.hpp:25:
In file included from /usr/include/boost/geometry/core/coordinate_type.hpp:20:
/usr/include/boost/geometry/core/point_type.hpp:45:5: error: no matching function for call to 'assertion_failed'
    BOOST_MPL_ASSERT_MSG
    ^~~~~~~~~~~~~~~~~~~~
/usr/include/boost/mpl/assert.hpp:454:51: note: expanded from macro 'BOOST_MPL_ASSERT_MSG'
#   define BOOST_MPL_ASSERT_MSG( c, msg, types_ ) \

Solution

  • Foo is not an indexable type. Meaning, mainly, that rtree doesn't know what geometry to index it by.

    Let's make an IndexableGetter:

    struct ByPos {
        using result_type = point_2d;
        result_type const& operator()(Foo const& f) const { return f.position; }
    };
    

    Now you can use it:

    Live On Coliru

    #include <boost/geometry/index/rtree.hpp>
    #include <boost/geometry.hpp>
    #include <boost/geometry/geometries/point_xy.hpp>
    #include <iostream>
    
    namespace bg = boost::geometry;
    namespace bgi = boost::geometry::index;
    
    using point_2d = bg::model::d2::point_xy<double> ;
    using box      = bg::model::box<point_2d>;
    
    struct Foo {
        point_2d position;
        Foo(double x, double y) : position(x, y) {}
        auto get() const { return position; }
    
        struct ByPos {
            using result_type = point_2d;
            result_type const& operator()(Foo const& f) const { return f.position; }
        };
    };
    
    auto intersecting(auto const& search, auto const& tree) {
        std::vector<std::reference_wrapper<Foo const>> result;
        tree.query(bgi::intersects(search), back_inserter(result));
        return result;
    }
    
    int main() {
        bgi::rtree<Foo, bgi::quadratic<16>, Foo::ByPos> rtree;
    
        rtree.insert({1.0, 2.0});
        rtree.insert({3.0, 4.0});
        rtree.insert({5.0, 6.0});
        rtree.insert({7.0, 8.0});
    
        // box with given distance from center
        auto makebox = [&](double d, point_2d c = {}) {
            return box{{c.x() - d, c.y() - d}, {c.x() + d, c.y() + d}};
        };
    
        auto key = makebox(5.0);
        std::cout << "Within " << bg::dsv(key) << ":\n";
    
        for (Foo const& foo : intersecting(key, rtree))
            std::cout << " - at " << bg::dsv(foo.position) << "\n";
    }
    

    Prints

    Within ((-5, -5), (5, 5)):
     - at (1, 2)
     - at (3, 4)