// Boost.Geometry Index // Unit Test // Copyright (c) 2011-2015 Adam Wulkiewicz, Lodz, Poland. // This file was modified by Oracle on 2019-2021. // Modifications copyright (c) 2019-2021, Oracle and/or its affiliates. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_GEOMETRY_INDEX_TEST_RTREE_HPP #define BOOST_GEOMETRY_INDEX_TEST_RTREE_HPP #include #include #include #include #include #include #include #include #include #include //#include //#include namespace generate { // Set point's coordinates template struct outside_point {}; template struct outside_point< bg::model::point > { typedef bg::model::point P; static P apply() { return P(13, 26); } }; template struct outside_point< bg::model::point > { typedef bg::model::point P; static P apply() { return P(13, 26, 13); } }; // Default value generation template struct value_default { static Value apply(){ return Value(); } }; // Values, input and rtree generation template struct value {}; template struct value< bg::model::point > { typedef bg::model::point P; static P apply(int x, int y) { return P(x, y); } }; template struct value< bg::model::box< bg::model::point > > { typedef bg::model::point P; typedef bg::model::box

B; static B apply(int x, int y) { return B(P(x, y), P(x + 2, y + 3)); } }; template struct value< bg::model::segment< bg::model::point > > { typedef bg::model::point P; typedef bg::model::segment

S; static S apply(int x, int y) { return S(P(x, y), P(x + 2, y + 3)); } }; template struct value< std::pair, int> > { typedef bg::model::point P; typedef std::pair R; static R apply(int x, int y) { return std::make_pair(P(x, y), x + y * 100); } }; template struct value< std::pair >, int> > { typedef bg::model::point P; typedef bg::model::box

B; typedef std::pair R; static R apply(int x, int y) { return std::make_pair(B(P(x, y), P(x + 2, y + 3)), x + y * 100); } }; template struct value< std::pair >, int> > { typedef bg::model::point P; typedef bg::model::segment

S; typedef std::pair R; static R apply(int x, int y) { return std::make_pair(S(P(x, y), P(x + 2, y + 3)), x + y * 100); } }; template struct value< boost::tuple, int, int> > { typedef bg::model::point P; typedef boost::tuple R; static R apply(int x, int y) { return boost::make_tuple(P(x, y), x + y * 100, 0); } }; template struct value< boost::tuple >, int, int> > { typedef bg::model::point P; typedef bg::model::box

B; typedef boost::tuple R; static R apply(int x, int y) { return boost::make_tuple(B(P(x, y), P(x + 2, y + 3)), x + y * 100, 0); } }; template struct value< boost::tuple >, int, int> > { typedef bg::model::point P; typedef bg::model::segment

S; typedef boost::tuple R; static R apply(int x, int y) { return boost::make_tuple(S(P(x, y), P(x + 2, y + 3)), x + y * 100, 0); } }; template struct value< bg::model::point > { typedef bg::model::point P; static P apply(int x, int y, int z) { return P(x, y, z); } }; template struct value< bg::model::box< bg::model::point > > { typedef bg::model::point P; typedef bg::model::box

B; static B apply(int x, int y, int z) { return B(P(x, y, z), P(x + 2, y + 3, z + 4)); } }; template struct value< std::pair, int> > { typedef bg::model::point P; typedef std::pair R; static R apply(int x, int y, int z) { return std::make_pair(P(x, y, z), x + y * 100 + z * 10000); } }; template struct value< std::pair >, int> > { typedef bg::model::point P; typedef bg::model::box

B; typedef std::pair R; static R apply(int x, int y, int z) { return std::make_pair(B(P(x, y, z), P(x + 2, y + 3, z + 4)), x + y * 100 + z * 10000); } }; template struct value< boost::tuple, int, int> > { typedef bg::model::point P; typedef boost::tuple R; static R apply(int x, int y, int z) { return boost::make_tuple(P(x, y, z), x + y * 100 + z * 10000, 0); } }; template struct value< boost::tuple >, int, int> > { typedef bg::model::point P; typedef bg::model::box

B; typedef boost::tuple R; static R apply(int x, int y, int z) { return boost::make_tuple(B(P(x, y, z), P(x + 2, y + 3, z + 4)), x + y * 100 + z * 10000, 0); } }; template struct value< std::tuple, int, int> > { typedef bg::model::point P; typedef std::tuple R; static R apply(int x, int y) { return std::make_tuple(P(x, y), x + y * 100, 0); } }; template struct value< std::tuple >, int, int> > { typedef bg::model::point P; typedef bg::model::box

B; typedef std::tuple R; static R apply(int x, int y) { return std::make_tuple(B(P(x, y), P(x + 2, y + 3)), x + y * 100, 0); } }; template struct value< std::tuple >, int, int> > { typedef bg::model::point P; typedef bg::model::segment

S; typedef std::tuple R; static R apply(int x, int y) { return std::make_tuple(S(P(x, y), P(x + 2, y + 3)), x + y * 100, 0); } }; template struct value< std::tuple, int, int> > { typedef bg::model::point P; typedef std::tuple R; static R apply(int x, int y, int z) { return std::make_tuple(P(x, y, z), x + y * 100 + z * 10000, 0); } }; template struct value< std::tuple >, int, int> > { typedef bg::model::point P; typedef bg::model::box

B; typedef std::tuple R; static R apply(int x, int y, int z) { return std::make_tuple(B(P(x, y, z), P(x + 2, y + 3, z + 4)), x + y * 100 + z * 10000, 0); } }; } // namespace generate // shared_ptr value template struct test_object { test_object(Indexable const& indexable_) : indexable(indexable_) {} Indexable indexable; }; namespace boost { namespace geometry { namespace index { template struct indexable< boost::shared_ptr< test_object > > { typedef boost::shared_ptr< test_object > value_type; typedef Indexable const& result_type; result_type operator()(value_type const& value) const { return value->indexable; } }; }}} namespace generate { template struct value< boost::shared_ptr > > > { typedef bg::model::point P; typedef test_object

O; typedef boost::shared_ptr R; static R apply(int x, int y) { return R(new O(P(x, y))); } }; template struct value< boost::shared_ptr > > > { typedef bg::model::point P; typedef test_object

O; typedef boost::shared_ptr R; static R apply(int x, int y, int z) { return R(new O(P(x, y, z))); } }; template struct value< boost::shared_ptr > > > > { typedef bg::model::point P; typedef bg::model::box

B; typedef test_object O; typedef boost::shared_ptr R; static R apply(int x, int y) { return R(new O(B(P(x, y), P(x + 2, y + 3)))); } }; template struct value< boost::shared_ptr > > > > { typedef bg::model::point P; typedef bg::model::box

B; typedef test_object O; typedef boost::shared_ptr R; static R apply(int x, int y, int z) { return R(new O(B(P(x, y, z), P(x + 2, y + 3, z + 4)))); } }; template struct value< boost::shared_ptr > > > > { typedef bg::model::point P; typedef bg::model::segment

S; typedef test_object O; typedef boost::shared_ptr R; static R apply(int x, int y) { return R(new O(S(P(x, y), P(x + 2, y + 3)))); } }; } //namespace generate // counting value template struct counting_value { counting_value() { counter()++; } counting_value(Indexable const& i) : indexable(i) { counter()++; } counting_value(counting_value const& c) : indexable(c.indexable) { counter()++; } ~counting_value() { counter()--; } counting_value& operator=(counting_value const& c) = default; static size_t & counter() { static size_t c = 0; return c; } Indexable indexable; }; namespace boost { namespace geometry { namespace index { template struct indexable< counting_value > { typedef counting_value value_type; typedef Indexable const& result_type; result_type operator()(value_type const& value) const { return value.indexable; } }; template struct equal_to< counting_value > { typedef counting_value value_type; typedef bool result_type; bool operator()(value_type const& v1, value_type const& v2) const { return boost::geometry::equals(v1.indexable, v2.indexable); } }; }}} namespace generate { template struct value< counting_value > > { typedef bg::model::point P; typedef counting_value

R; static R apply(int x, int y) { return R(P(x, y)); } }; template struct value< counting_value > > { typedef bg::model::point P; typedef counting_value

R; static R apply(int x, int y, int z) { return R(P(x, y, z)); } }; template struct value< counting_value > > > { typedef bg::model::point P; typedef bg::model::box

B; typedef counting_value R; static R apply(int x, int y) { return R(B(P(x, y), P(x+2, y+3))); } }; template struct value< counting_value > > > { typedef bg::model::point P; typedef bg::model::box

B; typedef counting_value R; static R apply(int x, int y, int z) { return R(B(P(x, y, z), P(x+2, y+3, z+4))); } }; template struct value< counting_value > > > { typedef bg::model::point P; typedef bg::model::segment

S; typedef counting_value R; static R apply(int x, int y) { return R(S(P(x, y), P(x+2, y+3))); } }; } // namespace generate // value without default constructor template struct value_no_dctor { value_no_dctor(Indexable const& i) : indexable(i) {} Indexable indexable; }; namespace boost { namespace geometry { namespace index { template struct indexable< value_no_dctor > { typedef value_no_dctor value_type; typedef Indexable const& result_type; result_type operator()(value_type const& value) const { return value.indexable; } }; template struct equal_to< value_no_dctor > { typedef value_no_dctor value_type; typedef bool result_type; bool operator()(value_type const& v1, value_type const& v2) const { return boost::geometry::equals(v1.indexable, v2.indexable); } }; }}} namespace generate { template struct value_default< value_no_dctor > { static value_no_dctor apply() { return value_no_dctor(Indexable()); } }; template struct value< value_no_dctor > > { typedef bg::model::point P; typedef value_no_dctor

R; static R apply(int x, int y) { return R(P(x, y)); } }; template struct value< value_no_dctor > > { typedef bg::model::point P; typedef value_no_dctor

R; static R apply(int x, int y, int z) { return R(P(x, y, z)); } }; template struct value< value_no_dctor > > > { typedef bg::model::point P; typedef bg::model::box

B; typedef value_no_dctor R; static R apply(int x, int y) { return R(B(P(x, y), P(x+2, y+3))); } }; template struct value< value_no_dctor > > > { typedef bg::model::point P; typedef bg::model::box

B; typedef value_no_dctor R; static R apply(int x, int y, int z) { return R(B(P(x, y, z), P(x+2, y+3, z+4))); } }; template struct value< value_no_dctor > > > { typedef bg::model::point P; typedef bg::model::segment

S; typedef value_no_dctor R; static R apply(int x, int y) { return R(S(P(x, y), P(x+2, y+3))); } }; // generate input template struct input {}; template <> struct input<2> { template static void apply(std::vector & input, Box & qbox, int size = 1) { BOOST_GEOMETRY_INDEX_ASSERT(0 < size, "the value must be greather than 0"); for ( int i = 0 ; i < 12 * size ; i += 3 ) { for ( int j = 1 ; j < 25 * size ; j += 4 ) { input.push_back( generate::value::apply(i, j) ); } } typedef typename bg::traits::point_type::type P; qbox = Box(P(3, 0), P(10, 9)); } }; template <> struct input<3> { template static void apply(std::vector & input, Box & qbox, int size = 1) { BOOST_GEOMETRY_INDEX_ASSERT(0 < size, "the value must be greather than 0"); for ( int i = 0 ; i < 12 * size ; i += 3 ) { for ( int j = 1 ; j < 25 * size ; j += 4 ) { for ( int k = 2 ; k < 12 * size ; k += 5 ) { input.push_back( generate::value::apply(i, j, k) ); } } } typedef typename bg::traits::point_type::type P; qbox = Box(P(3, 0, 3), P(10, 9, 11)); } }; // generate_value_outside template struct value_outside_impl {}; template struct value_outside_impl { static Value apply() { //TODO - for size > 1 in generate_input<> this won't be outside return generate::value::apply(13, 26); } }; template struct value_outside_impl { static Value apply() { //TODO - for size > 1 in generate_input<> this won't be outside return generate::value::apply(13, 26, 13); } }; template inline typename Rtree::value_type value_outside() { typedef typename Rtree::value_type V; typedef typename Rtree::indexable_type I; return value_outside_impl::value>::apply(); } template void rtree(Rtree & tree, Elements & input, Box & qbox) { typedef typename Rtree::indexable_type I; generate::input< bg::dimension::value >::apply(input, qbox); tree.insert(input.begin(), input.end()); } } // namespace generate namespace basictest { // low level test functions template Iter find(Rtree const& rtree, Iter first, Iter last, Value const& value) { for (; first != last; ++first) if (rtree.value_eq()(value, *first)) return first; return first; } template void compare_outputs(Rtree const& rtree, std::vector const& output, std::vector const& expected_output) { bool are_sizes_ok = (expected_output.size() == output.size()); BOOST_CHECK(are_sizes_ok); if (are_sizes_ok) { for (Value const& v : expected_output) { BOOST_CHECK(find(rtree, output.begin(), output.end(), v) != output.end()); } } } template void exactly_the_same_outputs(Rtree const& rtree, Range1 const& output, Range2 const& expected_output) { size_t s1 = std::distance(output.begin(), output.end()); size_t s2 = std::distance(expected_output.begin(), expected_output.end()); BOOST_CHECK(s1 == s2); if (s1 == s2) { typename Range1::const_iterator it1 = output.begin(); typename Range2::const_iterator it2 = expected_output.begin(); for (; it1 != output.end() && it2 != expected_output.end(); ++it1, ++it2) { if (!rtree.value_eq()(*it1, *it2)) { BOOST_CHECK(false && "rtree.translator().equals(*it1, *it2)"); break; } } } } // alternative version of std::copy taking iterators of differnet types template void copy_alt(First first, Last last, Out out) { for (; first != last; ++first, ++out) *out = *first; } // test query iterators template void check_fwd_iterators(QItF first, QItL last) { QItF vinit = QItF(); BOOST_CHECK(vinit == last); #ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL QItL vinit2 = QItL(); BOOST_CHECK(vinit2 == last); #endif QItF def; BOOST_CHECK(def == last); #ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL QItL def2; BOOST_CHECK(def2 == last); #endif QItF it = first; for (; it != last && first != last; ++it, ++first) { BOOST_CHECK(it == first); bg::index::equal_to::value_type> eq; BOOST_CHECK(eq(*it, *first)); } BOOST_CHECK(it == last); BOOST_CHECK(first == last); } // spatial query template void spatial_query(Rtree & rtree, Predicates const& pred, std::vector const& expected_output) { BOOST_CHECK(bgi::detail::rtree::utilities::are_levels_ok(rtree)); if (!rtree.empty()) BOOST_CHECK(bgi::detail::rtree::utilities::are_boxes_ok(rtree)); std::vector output; size_t n = rtree.query(pred, std::back_inserter(output)); BOOST_CHECK(expected_output.size() == n); compare_outputs(rtree, output, expected_output); std::vector output2; size_t n2 = query(rtree, pred, std::back_inserter(output2)); BOOST_CHECK(n == n2); exactly_the_same_outputs(rtree, output, output2); exactly_the_same_outputs(rtree, output, rtree | bgi::adaptors::queried(pred)); std::vector output3; std::copy(rtree.qbegin(pred), rtree.qend(), std::back_inserter(output3)); compare_outputs(rtree, output3, expected_output); std::vector output4; std::copy(qbegin(rtree, pred), qend(rtree), std::back_inserter(output4)); exactly_the_same_outputs(rtree, output3, output4); check_fwd_iterators(rtree.qbegin(pred), rtree.qend()); #ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL { std::vector output4; std::copy(rtree.qbegin_(pred), rtree.qend_(pred), std::back_inserter(output4)); compare_outputs(rtree, output4, expected_output); output4.clear(); copy_alt(rtree.qbegin_(pred), rtree.qend_(), std::back_inserter(output4)); compare_outputs(rtree, output4, expected_output); check_fwd_iterators(rtree.qbegin_(pred), rtree.qend_(pred)); check_fwd_iterators(rtree.qbegin_(pred), rtree.qend_()); } #endif } // rtree specific queries tests template void intersects(Rtree const& tree, std::vector const& input, Box const& qbox) { std::vector expected_output; for (Value const& v : input) { if (bg::intersects(tree.indexable_get()(v), qbox)) { expected_output.push_back(v); } } //spatial_query(tree, qbox, expected_output); spatial_query(tree, bgi::intersects(qbox), expected_output); spatial_query(tree, !bgi::disjoint(qbox), expected_output); /*typedef bg::traits::point_type::type P; bg::model::ring

qring; bg::convert(qbox, qring); spatial_query(tree, bgi::intersects(qring), expected_output); spatial_query(tree, !bgi::disjoint(qring), expected_output); bg::model::polygon

qpoly; bg::convert(qbox, qpoly); spatial_query(tree, bgi::intersects(qpoly), expected_output); spatial_query(tree, !bgi::disjoint(qpoly), expected_output);*/ } template void disjoint(Rtree const& tree, std::vector const& input, Box const& qbox) { std::vector expected_output; for (Value const& v : input) { if (bg::disjoint(tree.indexable_get()(v), qbox)) { expected_output.push_back(v); } } spatial_query(tree, bgi::disjoint(qbox), expected_output); spatial_query(tree, !bgi::intersects(qbox), expected_output); /*typedef bg::traits::point_type::type P; bg::model::ring

qring; bg::convert(qbox, qring); spatial_query(tree, bgi::disjoint(qring), expected_output); bg::model::polygon

qpoly; bg::convert(qbox, qpoly); spatial_query(tree, bgi::disjoint(qpoly), expected_output);*/ } template struct contains_impl { template static void apply(Rtree const& tree, std::vector const& input, Box const& qbox) { std::vector expected_output; for (Value const& v : input) { if (bg::within(qbox, tree.indexable_get()(v))) { expected_output.push_back(v); } } spatial_query(tree, bgi::contains(qbox), expected_output); /*typedef bg::traits::point_type::type P; bg::model::ring

qring; bg::convert(qbox, qring); spatial_query(tree, bgi::contains(qring), expected_output); bg::model::polygon

qpoly; bg::convert(qbox, qpoly); spatial_query(tree, bgi::contains(qpoly), expected_output);*/ } }; template <> struct contains_impl { template static void apply(Rtree const& /*tree*/, std::vector const& /*input*/, Box const& /*qbox*/) {} }; template <> struct contains_impl { template static void apply(Rtree const& /*tree*/, std::vector const& /*input*/, Box const& /*qbox*/) {} }; template void contains(Rtree const& tree, std::vector const& input, Box const& qbox) { contains_impl< typename bg::tag< typename Rtree::indexable_type >::type >::apply(tree, input, qbox); } template struct covered_by_impl { template static void apply(Rtree const& tree, std::vector const& input, Box const& qbox) { std::vector expected_output; for (Value const& v : input) { if (bgi::detail::covered_by_bounds( tree.indexable_get()(v), qbox, bgi::detail::get_strategy(tree.parameters()))) { expected_output.push_back(v); } } spatial_query(tree, bgi::covered_by(qbox), expected_output); /*typedef bg::traits::point_type::type P; bg::model::ring

qring; bg::convert(qbox, qring); spatial_query(tree, bgi::covered_by(qring), expected_output); bg::model::polygon

qpoly; bg::convert(qbox, qpoly); spatial_query(tree, bgi::covered_by(qpoly), expected_output);*/ } }; template <> struct covered_by_impl { template static void apply(Rtree const& /*tree*/, std::vector const& /*input*/, Box const& /*qbox*/) {} }; template void covered_by(Rtree const& tree, std::vector const& input, Box const& qbox) { covered_by_impl< typename bg::tag< typename Rtree::indexable_type >::type >::apply(tree, input, qbox); } template struct covers_impl { template static void apply(Rtree const& tree, std::vector const& input, Box const& qbox) { std::vector expected_output; for (Value const& v : input) { if (bg::covered_by(qbox, tree.indexable_get()(v))) { expected_output.push_back(v); } } spatial_query(tree, bgi::covers(qbox), expected_output); /*typedef bg::traits::point_type::type P; bg::model::ring

qring; bg::convert(qbox, qring); spatial_query(tree, bgi::covers(qring), expected_output); bg::model::polygon

qpoly; bg::convert(qbox, qpoly); spatial_query(tree, bgi::covers(qpoly), expected_output);*/ } }; template <> struct covers_impl { template static void apply(Rtree const& /*tree*/, std::vector const& /*input*/, Box const& /*qbox*/) {} }; template <> struct covers_impl { template static void apply(Rtree const& /*tree*/, std::vector const& /*input*/, Box const& /*qbox*/) {} }; template void covers(Rtree const& tree, std::vector const& input, Box const& qbox) { covers_impl< typename bg::tag< typename Rtree::indexable_type >::type >::apply(tree, input, qbox); } template struct overlaps_impl { template static void apply(Rtree const& tree, std::vector const& input, Box const& qbox) { std::vector expected_output; for (Value const& v : input) { if (bg::overlaps(tree.indexable_get()(v), qbox)) { expected_output.push_back(v); } } spatial_query(tree, bgi::overlaps(qbox), expected_output); /*typedef bg::traits::point_type::type P; bg::model::ring

qring; bg::convert(qbox, qring); spatial_query(tree, bgi::overlaps(qring), expected_output); bg::model::polygon

qpoly; bg::convert(qbox, qpoly); spatial_query(tree, bgi::overlaps(qpoly), expected_output);*/ } }; template <> struct overlaps_impl { template static void apply(Rtree const& /*tree*/, std::vector const& /*input*/, Box const& /*qbox*/) {} }; template <> struct overlaps_impl { template static void apply(Rtree const& /*tree*/, std::vector const& /*input*/, Box const& /*qbox*/) {} }; template void overlaps(Rtree const& tree, std::vector const& input, Box const& qbox) { overlaps_impl< typename bg::tag< typename Rtree::indexable_type >::type >::apply(tree, input, qbox); } //template //struct touches_impl //{ // template // static void apply(Rtree const& tree, std::vector const& input, Box const& qbox) // {} //}; // //template <> //struct touches_impl //{ // template // static void apply(Rtree const& tree, std::vector const& input, Box const& qbox) // { // std::vector expected_output; // // for (Value const& v : input) // { // if (bg::touches(tree.translator()(v), qbox)) // { // expected_output.push_back(v); // } // } // // spatial_query(tree, bgi::touches(qbox), expected_output); // } //}; // //template //void touches(Rtree const& tree, std::vector const& input, Box const& qbox) //{ // touches_impl< // bgi::traits::tag::type, // bgi::traits::dimension::value // >::apply(tree, input, qbox); //} template struct within_impl { template static void apply(Rtree const& tree, std::vector const& input, Box const& qbox) { std::vector expected_output; for (Value const& v : input) { if (bg::within(tree.indexable_get()(v), qbox)) { expected_output.push_back(v); } } spatial_query(tree, bgi::within(qbox), expected_output); /*typedef bg::traits::point_type::type P; bg::model::ring

qring; bg::convert(qbox, qring); spatial_query(tree, bgi::within(qring), expected_output); bg::model::polygon

qpoly; bg::convert(qbox, qpoly); spatial_query(tree, bgi::within(qpoly), expected_output);*/ } }; template <> struct within_impl { template static void apply(Rtree const& /*tree*/, std::vector const& /*input*/, Box const& /*qbox*/) {} }; template void within(Rtree const& tree, std::vector const& input, Box const& qbox) { within_impl< typename bg::tag< typename Rtree::indexable_type >::type >::apply(tree, input, qbox); } // rtree nearest queries template struct NearestKLess { typedef typename bg::default_distance_result::type D; template bool operator()(std::pair const& p1, std::pair const& p2) const { return p1.first < p2.first; } }; template struct NearestKTransform { typedef typename bg::default_distance_result::type D; template Value const& operator()(std::pair const& p) const { return p.second; } }; template inline void compare_nearest_outputs(Rtree const& rtree, std::vector const& output, std::vector const& expected_output, Point const& pt, Distance greatest_distance) { // check output bool are_sizes_ok = (expected_output.size() == output.size()); BOOST_CHECK(are_sizes_ok); if (are_sizes_ok) { for (Value const& v : output) { // TODO - perform explicit check here? // should all objects which are closest be checked and should exactly the same be found? if (find(rtree, expected_output.begin(), expected_output.end(), v) == expected_output.end()) { Distance d = bg::comparable_distance(pt, rtree.indexable_get()(v)); BOOST_CHECK(d == greatest_distance); } } } } template inline void check_sorted_by_distance(Rtree const& rtree, std::vector const& output, Point const& pt) { typedef typename bg::default_distance_result::type D; D prev_dist = 0; for (Value const& v : output) { D d = bg::comparable_distance(pt, rtree.indexable_get()(v)); BOOST_CHECK(prev_dist <= d); prev_dist = d; } } template inline void nearest_query_k(Rtree const& rtree, std::vector const& input, Point const& pt, unsigned int k) { // TODO: Nearest object may not be the same as found by the rtree if distances are equal // All objects with the same closest distance should be picked typedef typename bg::default_distance_result::type D; std::vector< std::pair > test_output; // calculate test output - k closest values pairs for (Value const& v : input) { D d = bg::comparable_distance(pt, rtree.indexable_get()(v)); if (test_output.size() < k) { test_output.push_back(std::make_pair(d, v)); } else { std::sort(test_output.begin(), test_output.end(), NearestKLess()); if (d < test_output.back().first) { test_output.back() = std::make_pair(d, v); } } } // caluclate biggest distance std::sort(test_output.begin(), test_output.end(), NearestKLess()); D greatest_distance = 0; if (! test_output.empty()) { greatest_distance = test_output.back().first; } // transform test output to vector of values std::vector expected_output(test_output.size(), generate::value_default::apply()); std::transform(test_output.begin(), test_output.end(), expected_output.begin(), NearestKTransform()); // calculate output using rtree std::vector output; rtree.query(bgi::nearest(pt, k), std::back_inserter(output)); // check output compare_nearest_outputs(rtree, output, expected_output, pt, greatest_distance); exactly_the_same_outputs(rtree, output, rtree | bgi::adaptors::queried(bgi::nearest(pt, k))); std::vector output2(k, generate::value_default::apply()); typename Rtree::size_type found_count = rtree.query(bgi::nearest(pt, k), output2.begin()); output2.resize(found_count, generate::value_default::apply()); exactly_the_same_outputs(rtree, output, output2); std::vector output3; std::copy(rtree.qbegin(bgi::nearest(pt, k)), rtree.qend(), std::back_inserter(output3)); compare_nearest_outputs(rtree, output3, expected_output, pt, greatest_distance); check_sorted_by_distance(rtree, output3, pt); check_fwd_iterators(rtree.qbegin(bgi::nearest(pt, k)), rtree.qend()); #ifdef BOOST_GEOMETRY_INDEX_DETAIL_EXPERIMENTAL { std::vector output4; std::copy(rtree.qbegin_(bgi::nearest(pt, k)), rtree.qend_(bgi::nearest(pt, k)), std::back_inserter(output4)); exactly_the_same_outputs(rtree, output4, output3); output4.clear(); copy_alt(rtree.qbegin_(bgi::nearest(pt, k)), rtree.qend_(), std::back_inserter(output4)); exactly_the_same_outputs(rtree, output4, output3); check_fwd_iterators(rtree.qbegin_(bgi::nearest(pt, k)), rtree.qend_(bgi::nearest(pt, k))); check_fwd_iterators(rtree.qbegin_(bgi::nearest(pt, k)), rtree.qend_()); } #endif } // rtree nearest not found struct AlwaysFalse { template bool operator()(Value const& ) const { return false; } }; template void nearest_query_not_found(Rtree const& rtree, Point const& pt) { typedef typename Rtree::value_type Value; std::vector output_v; size_t n_res = rtree.query(bgi::nearest(pt, 5) && bgi::satisfies(AlwaysFalse()), std::back_inserter(output_v)); BOOST_CHECK(output_v.size() == n_res); BOOST_CHECK(n_res < 5); } template bool satisfies_fun(Value const& ) { return true; } struct satisfies_obj { template bool operator()(Value const& ) const { return true; } }; template void satisfies(Rtree const& rtree, std::vector const& input) { std::vector result; rtree.query(bgi::satisfies(satisfies_obj()), std::back_inserter(result)); BOOST_CHECK(result.size() == input.size()); result.clear(); rtree.query(!bgi::satisfies(satisfies_obj()), std::back_inserter(result)); BOOST_CHECK(result.size() == 0); result.clear(); rtree.query(bgi::satisfies(satisfies_fun), std::back_inserter(result)); BOOST_CHECK(result.size() == input.size()); result.clear(); rtree.query(!bgi::satisfies(satisfies_fun), std::back_inserter(result)); BOOST_CHECK(result.size() == 0); result.clear(); rtree.query(bgi::satisfies([](Value const&){ return true; }), std::back_inserter(result)); BOOST_CHECK(result.size() == input.size()); result.clear(); rtree.query(!bgi::satisfies([](Value const&){ return true; }), std::back_inserter(result)); BOOST_CHECK(result.size() == 0); } // rtree copying and moving template void copy_swap_move(Rtree const& tree, Box const& qbox) { typedef typename Rtree::value_type Value; typedef typename Rtree::parameters_type Params; size_t s = tree.size(); Params params = tree.parameters(); std::vector expected_output; tree.query(bgi::intersects(qbox), std::back_inserter(expected_output)); // copy constructor Rtree t1(tree); BOOST_CHECK(tree.empty() == t1.empty()); BOOST_CHECK(tree.size() == t1.size()); BOOST_CHECK(t1.parameters().get_max_elements() == params.get_max_elements()); BOOST_CHECK(t1.parameters().get_min_elements() == params.get_min_elements()); std::vector output; t1.query(bgi::intersects(qbox), std::back_inserter(output)); exactly_the_same_outputs(t1, output, expected_output); // copying assignment operator t1 = tree; BOOST_CHECK(tree.empty() == t1.empty()); BOOST_CHECK(tree.size() == t1.size()); BOOST_CHECK(t1.parameters().get_max_elements() == params.get_max_elements()); BOOST_CHECK(t1.parameters().get_min_elements() == params.get_min_elements()); output.clear(); t1.query(bgi::intersects(qbox), std::back_inserter(output)); exactly_the_same_outputs(t1, output, expected_output); Rtree t2(tree.parameters(), tree.indexable_get(), tree.value_eq(), tree.get_allocator()); t2.swap(t1); BOOST_CHECK(tree.empty() == t2.empty()); BOOST_CHECK(tree.size() == t2.size()); BOOST_CHECK(true == t1.empty()); BOOST_CHECK(0 == t1.size()); // those fails e.g. on darwin 4.2.1 because it can't copy base obejcts properly BOOST_CHECK(t1.parameters().get_max_elements() == params.get_max_elements()); BOOST_CHECK(t1.parameters().get_min_elements() == params.get_min_elements()); BOOST_CHECK(t2.parameters().get_max_elements() == params.get_max_elements()); BOOST_CHECK(t2.parameters().get_min_elements() == params.get_min_elements()); output.clear(); t1.query(bgi::intersects(qbox), std::back_inserter(output)); BOOST_CHECK(output.empty()); output.clear(); t2.query(bgi::intersects(qbox), std::back_inserter(output)); exactly_the_same_outputs(t2, output, expected_output); t2.swap(t1); // those fails e.g. on darwin 4.2.1 because it can't copy base obejcts properly BOOST_CHECK(t1.parameters().get_max_elements() == params.get_max_elements()); BOOST_CHECK(t1.parameters().get_min_elements() == params.get_min_elements()); BOOST_CHECK(t2.parameters().get_max_elements() == params.get_max_elements()); BOOST_CHECK(t2.parameters().get_min_elements() == params.get_min_elements()); // moving constructor Rtree t3(boost::move(t1), tree.get_allocator()); BOOST_CHECK(t3.size() == s); BOOST_CHECK(t1.size() == 0); BOOST_CHECK(t3.parameters().get_max_elements() == params.get_max_elements()); BOOST_CHECK(t3.parameters().get_min_elements() == params.get_min_elements()); output.clear(); t3.query(bgi::intersects(qbox), std::back_inserter(output)); exactly_the_same_outputs(t3, output, expected_output); // moving assignment operator t1 = boost::move(t3); BOOST_CHECK(t1.size() == s); BOOST_CHECK(t3.size() == 0); BOOST_CHECK(t1.parameters().get_max_elements() == params.get_max_elements()); BOOST_CHECK(t1.parameters().get_min_elements() == params.get_min_elements()); output.clear(); t1.query(bgi::intersects(qbox), std::back_inserter(output)); exactly_the_same_outputs(t1, output, expected_output); //TODO - test SWAP ::boost::ignore_unused(params); } template inline void my_copy(I first, I last, O out) { for ( ; first != last ; ++first, ++out ) *out = *first; } // rtree creation and insertion template void create_insert(Rtree const& tree, std::vector const& input, Box const& qbox) { std::vector expected_output; tree.query(bgi::intersects(qbox), std::back_inserter(expected_output)); { Rtree t(tree.parameters(), tree.indexable_get(), tree.value_eq(), tree.get_allocator()); for (Value const& v : input) { t.insert(v); } BOOST_CHECK(tree.size() == t.size()); std::vector output; t.query(bgi::intersects(qbox), std::back_inserter(output)); exactly_the_same_outputs(t, output, expected_output); } { Rtree t(tree.parameters(), tree.indexable_get(), tree.value_eq(), tree.get_allocator()); //std::copy(input.begin(), input.end(), bgi::inserter(t)); my_copy(input.begin(), input.end(), bgi::inserter(t)); // to suppress MSVC warnings BOOST_CHECK(tree.size() == t.size()); std::vector output; t.query(bgi::intersects(qbox), std::back_inserter(output)); exactly_the_same_outputs(t, output, expected_output); } { Rtree t(input.begin(), input.end(), tree.parameters(), tree.indexable_get(), tree.value_eq(), tree.get_allocator()); BOOST_CHECK(tree.size() == t.size()); std::vector output; t.query(bgi::intersects(qbox), std::back_inserter(output)); compare_outputs(t, output, expected_output); } { Rtree t(input, tree.parameters(), tree.indexable_get(), tree.value_eq(), tree.get_allocator()); BOOST_CHECK(tree.size() == t.size()); std::vector output; t.query(bgi::intersects(qbox), std::back_inserter(output)); compare_outputs(t, output, expected_output); } { Rtree t(tree.parameters(), tree.indexable_get(), tree.value_eq(), tree.get_allocator()); t.insert(input.begin(), input.end()); BOOST_CHECK(tree.size() == t.size()); std::vector output; t.query(bgi::intersects(qbox), std::back_inserter(output)); exactly_the_same_outputs(t, output, expected_output); } { Rtree t(tree.parameters(), tree.indexable_get(), tree.value_eq(), tree.get_allocator()); t.insert(input); BOOST_CHECK(tree.size() == t.size()); std::vector output; t.query(bgi::intersects(qbox), std::back_inserter(output)); exactly_the_same_outputs(t, output, expected_output); } { Rtree t(tree.parameters(), tree.indexable_get(), tree.value_eq(), tree.get_allocator()); for (Value const& v : input) { bgi::insert(t, v); } BOOST_CHECK(tree.size() == t.size()); std::vector output; bgi::query(t, bgi::intersects(qbox), std::back_inserter(output)); exactly_the_same_outputs(t, output, expected_output); } { Rtree t(tree.parameters(), tree.indexable_get(), tree.value_eq(), tree.get_allocator()); bgi::insert(t, input.begin(), input.end()); BOOST_CHECK(tree.size() == t.size()); std::vector output; bgi::query(t, bgi::intersects(qbox), std::back_inserter(output)); exactly_the_same_outputs(t, output, expected_output); } { Rtree t(tree.parameters(), tree.indexable_get(), tree.value_eq(), tree.get_allocator()); bgi::insert(t, input); BOOST_CHECK(tree.size() == t.size()); std::vector output; bgi::query(t, bgi::intersects(qbox), std::back_inserter(output)); exactly_the_same_outputs(t, output, expected_output); } } // rtree removing template void remove(Rtree const& tree, Box const& qbox) { typedef typename Rtree::value_type Value; std::vector values_to_remove; tree.query(bgi::intersects(qbox), std::back_inserter(values_to_remove)); BOOST_CHECK(0 < values_to_remove.size()); std::vector expected_output; tree.query(bgi::disjoint(qbox), std::back_inserter(expected_output)); size_t expected_removed_count = values_to_remove.size(); size_t expected_size_after_remove = tree.size() - values_to_remove.size(); // Add value which is not stored in the Rtree Value outsider = generate::value_outside(); values_to_remove.push_back(outsider); { Rtree t(tree); size_t r = 0; for (Value const& v : values_to_remove) { r += t.remove(v); } BOOST_CHECK( r == expected_removed_count ); std::vector output; t.query(bgi::disjoint(qbox), std::back_inserter(output)); BOOST_CHECK( t.size() == expected_size_after_remove ); BOOST_CHECK( output.size() == tree.size() - expected_removed_count ); compare_outputs(t, output, expected_output); } { Rtree t(tree); size_t r = t.remove(values_to_remove.begin(), values_to_remove.end()); BOOST_CHECK( r == expected_removed_count ); std::vector output; t.query(bgi::disjoint(qbox), std::back_inserter(output)); BOOST_CHECK( t.size() == expected_size_after_remove ); BOOST_CHECK( output.size() == tree.size() - expected_removed_count ); compare_outputs(t, output, expected_output); } { Rtree t(tree); size_t r = t.remove(values_to_remove); BOOST_CHECK( r == expected_removed_count ); std::vector output; t.query(bgi::disjoint(qbox), std::back_inserter(output)); BOOST_CHECK( t.size() == expected_size_after_remove ); BOOST_CHECK( output.size() == tree.size() - expected_removed_count ); compare_outputs(t, output, expected_output); } { Rtree t(tree); size_t r = 0; for (Value const& v : values_to_remove) { r += bgi::remove(t, v); } BOOST_CHECK( r == expected_removed_count ); std::vector output; bgi::query(t, bgi::disjoint(qbox), std::back_inserter(output)); BOOST_CHECK( t.size() == expected_size_after_remove ); BOOST_CHECK( output.size() == tree.size() - expected_removed_count ); compare_outputs(t, output, expected_output); } { Rtree t(tree); size_t r = bgi::remove(t, values_to_remove.begin(), values_to_remove.end()); BOOST_CHECK( r == expected_removed_count ); std::vector output; bgi::query(t, bgi::disjoint(qbox), std::back_inserter(output)); BOOST_CHECK( t.size() == expected_size_after_remove ); BOOST_CHECK( output.size() == tree.size() - expected_removed_count ); compare_outputs(t, output, expected_output); } { Rtree t(tree); size_t r = bgi::remove(t, values_to_remove); BOOST_CHECK( r == expected_removed_count ); std::vector output; bgi::query(t, bgi::disjoint(qbox), std::back_inserter(output)); BOOST_CHECK( t.size() == expected_size_after_remove ); BOOST_CHECK( output.size() == tree.size() - expected_removed_count ); compare_outputs(t, output, expected_output); } } template void clear(Rtree const& tree, std::vector const& input, Box const& qbox) { std::vector values_to_remove; tree.query(bgi::intersects(qbox), std::back_inserter(values_to_remove)); BOOST_CHECK(0 < values_to_remove.size()); //clear { Rtree t(tree); std::vector expected_output; t.query(bgi::intersects(qbox), std::back_inserter(expected_output)); size_t s = t.size(); t.clear(); BOOST_CHECK(t.empty()); BOOST_CHECK(t.size() == 0); t.insert(input); BOOST_CHECK(t.size() == s); std::vector output; t.query(bgi::intersects(qbox), std::back_inserter(output)); exactly_the_same_outputs(t, output, expected_output); } } template void range(Rtree & tree, std::vector const& input) { check_fwd_iterators(tree.begin(), tree.end()); size_t count = std::distance(tree.begin(), tree.end()); BOOST_CHECK(count == tree.size()); BOOST_CHECK(count == input.size()); count = std::distance(boost::begin(tree), boost::end(tree)); BOOST_CHECK(count == tree.size()); count = boost::size(tree); BOOST_CHECK(count == tree.size()); count = 0; for (Value const& v : tree) { boost::ignore_unused(v); ++count; } BOOST_CHECK(count == tree.size()); } // rtree queries template void queries(Rtree const& tree, std::vector const& input, Box const& qbox) { basictest::intersects(tree, input, qbox); basictest::disjoint(tree, input, qbox); basictest::covered_by(tree, input, qbox); basictest::overlaps(tree, input, qbox); //basictest::touches(tree, input, qbox); basictest::within(tree, input, qbox); basictest::contains(tree, input, qbox); basictest::covers(tree, input, qbox); typedef typename bg::point_type::type P; P pt; bg::centroid(qbox, pt); basictest::nearest_query_k(tree, input, pt, 10); basictest::nearest_query_not_found(tree, generate::outside_point

::apply()); basictest::satisfies(tree, input); } // rtree creation and modification template void modifiers(Rtree const& tree, std::vector const& input, Box const& qbox) { basictest::copy_swap_move(tree, qbox); basictest::create_insert(tree, input, qbox); basictest::remove(tree, qbox); basictest::clear(tree, input, qbox); } } // namespace basictest template void test_rtree_queries(Parameters const& parameters, Allocator const& allocator) { typedef bgi::indexable I; typedef bgi::equal_to E; typedef typename boost::container::allocator_traits::template rebind_alloc A; typedef bgi::rtree Tree; typedef typename Tree::bounds_type B; Tree tree(parameters, I(), E(), allocator); std::vector input; B qbox; generate::rtree(tree, input, qbox); basictest::queries(tree, input, qbox); Tree empty_tree(parameters, I(), E(), allocator); std::vector empty_input; basictest::queries(empty_tree, empty_input, qbox); } template void test_rtree_modifiers(Parameters const& parameters, Allocator const& allocator) { typedef bgi::indexable I; typedef bgi::equal_to E; typedef typename boost::container::allocator_traits::template rebind_alloc A; typedef bgi::rtree Tree; typedef typename Tree::bounds_type B; Tree tree(parameters, I(), E(), allocator); std::vector input; B qbox; generate::rtree(tree, input, qbox); basictest::modifiers(tree, input, qbox); Tree empty_tree(parameters, I(), E(), allocator); std::vector empty_input; basictest::copy_swap_move(empty_tree, qbox); } // run all tests for a single Algorithm and single rtree // defined by Value template void test_rtree_by_value(Parameters const& parameters, Allocator const& allocator) { test_rtree_queries(parameters, allocator); test_rtree_modifiers(parameters, allocator); } // rtree inserting and removing of counting_value template void test_count_rtree_values(Parameters const& parameters, Allocator const& allocator) { typedef counting_value Value; typedef bgi::indexable I; typedef bgi::equal_to E; typedef typename boost::container::allocator_traits::template rebind_alloc A; typedef bgi::rtree Tree; typedef typename Tree::bounds_type B; Tree t(parameters, I(), E(), allocator); std::vector input; B qbox; generate::rtree(t, input, qbox); size_t rest_count = input.size(); BOOST_CHECK(t.size() + rest_count == Value::counter()); std::vector values_to_remove; t.query(bgi::intersects(qbox), std::back_inserter(values_to_remove)); rest_count += values_to_remove.size(); BOOST_CHECK(t.size() + rest_count == Value::counter()); size_t values_count = Value::counter(); for (Value const& v : values_to_remove) { size_t r = t.remove(v); --values_count; BOOST_CHECK(1 == r); BOOST_CHECK(Value::counter() == values_count); BOOST_CHECK(t.size() + rest_count == values_count); } } // rtree count template void test_rtree_count(Parameters const& parameters, Allocator const& allocator) { typedef std::pair Value; typedef bgi::indexable I; typedef bgi::equal_to E; typedef typename boost::container::allocator_traits::template rebind_alloc A; typedef bgi::rtree Tree; typedef typename Tree::bounds_type B; Tree t(parameters, I(), E(), allocator); std::vector input; B qbox; generate::rtree(t, input, qbox); BOOST_CHECK(t.count(input[0]) == 1); BOOST_CHECK(t.count(input[0].first) == 1); t.insert(input[0]); BOOST_CHECK(t.count(input[0]) == 2); BOOST_CHECK(t.count(input[0].first) == 2); t.insert(std::make_pair(input[0].first, -1)); BOOST_CHECK(t.count(input[0]) == 2); BOOST_CHECK(t.count(input[0].first) == 3); } // test rtree box template void test_rtree_bounds(Parameters const& parameters, Allocator const& allocator) { typedef bgi::indexable I; typedef bgi::equal_to E; typedef typename boost::container::allocator_traits::template rebind_alloc A; typedef bgi::rtree Tree; typedef typename Tree::bounds_type B; //typedef typename bg::traits::point_type::type P; Tree t(parameters, I(), E(), allocator); std::vector input; B qbox; B b; bg::assign_inverse(b); BOOST_CHECK(bg::equals(t.bounds(), b)); generate::rtree(t, input, qbox); b = bgi::detail::rtree::values_box(input.begin(), input.end(), t.indexable_get(), bgi::detail::get_strategy(parameters)); BOOST_CHECK(bg::equals(t.bounds(), b)); BOOST_CHECK(bg::equals(t.bounds(), bgi::bounds(t))); size_t s = input.size(); while ( s/2 < input.size() && !input.empty() ) { t.remove(input.back()); input.pop_back(); } b = bgi::detail::rtree::values_box(input.begin(), input.end(), t.indexable_get(), bgi::detail::get_strategy(parameters)); BOOST_CHECK(bg::equals(t.bounds(), b)); Tree t2(t); BOOST_CHECK(bg::equals(t2.bounds(), b)); t2.clear(); t2 = t; BOOST_CHECK(bg::equals(t2.bounds(), b)); t2.clear(); t2 = boost::move(t); BOOST_CHECK(bg::equals(t2.bounds(), b)); t.clear(); bg::assign_inverse(b); BOOST_CHECK(bg::equals(t.bounds(), b)); } // test rtree iterator template void test_rtree_range(Parameters const& parameters, Allocator const& allocator) { typedef std::pair Value; typedef bgi::indexable I; typedef bgi::equal_to E; typedef typename boost::container::allocator_traits::template rebind_alloc A; typedef bgi::rtree Tree; typedef typename Tree::bounds_type B; Tree t(parameters, I(), E(), allocator); std::vector input; B qbox; generate::rtree(t, input, qbox); basictest::range(t, input); basictest::range((Tree const&)t, input); } template void test_rtree_additional(Parameters const& parameters, Allocator const& allocator) { test_count_rtree_values(parameters, allocator); test_rtree_count(parameters, allocator); test_rtree_bounds(parameters, allocator); test_rtree_range(parameters, allocator); } // run all tests for one Algorithm for some number of rtrees // defined by some number of Values constructed from given Point template void test_rtree_for_point(Parameters const& parameters, Allocator const& allocator) { typedef std::pair PairP; typedef boost::tuple TupleP; typedef boost::shared_ptr< test_object > SharedPtrP; typedef value_no_dctor VNoDCtor; test_rtree_by_value(parameters, allocator); test_rtree_by_value(parameters, allocator); test_rtree_by_value(parameters, allocator); test_rtree_by_value(parameters, allocator); test_rtree_by_value(parameters, allocator); test_rtree_additional(parameters, allocator); typedef std::tuple StdTupleP; test_rtree_by_value(parameters, allocator); } template void test_rtree_for_box(Parameters const& parameters, Allocator const& allocator) { typedef bg::model::box Box; typedef std::pair PairB; typedef boost::tuple TupleB; typedef value_no_dctor VNoDCtor; test_rtree_by_value(parameters, allocator); test_rtree_by_value(parameters, allocator); test_rtree_by_value(parameters, allocator); test_rtree_by_value(parameters, allocator); test_rtree_additional(parameters, allocator); typedef std::tuple StdTupleB; test_rtree_by_value(parameters, allocator); } template void test_rtree_for_point(Parameters const& parameters) { test_rtree_for_point(parameters, std::allocator()); } template void test_rtree_for_box(Parameters const& parameters) { test_rtree_for_box(parameters, std::allocator()); } namespace testset { template void modifiers(Parameters const& parameters, Allocator const& allocator) { typedef std::pair Pair; typedef boost::tuple Tuple; typedef boost::shared_ptr< test_object > SharedPtr; typedef value_no_dctor VNoDCtor; test_rtree_modifiers(parameters, allocator); test_rtree_modifiers(parameters, allocator); test_rtree_modifiers(parameters, allocator); test_rtree_modifiers(parameters, allocator); test_rtree_modifiers(parameters, allocator); typedef std::tuple StdTuple; test_rtree_modifiers(parameters, allocator); } template void queries(Parameters const& parameters, Allocator const& allocator) { typedef std::pair Pair; typedef boost::tuple Tuple; typedef boost::shared_ptr< test_object > SharedPtr; typedef value_no_dctor VNoDCtor; test_rtree_queries(parameters, allocator); test_rtree_queries(parameters, allocator); test_rtree_queries(parameters, allocator); test_rtree_queries(parameters, allocator); test_rtree_queries(parameters, allocator); typedef std::tuple StdTuple; test_rtree_queries(parameters, allocator); } template void additional(Parameters const& parameters, Allocator const& allocator) { test_rtree_additional(parameters, allocator); } } // namespace testset #endif // BOOST_GEOMETRY_INDEX_TEST_RTREE_HPP