// Boost.Geometry Index // Additional tests // Copyright (c) 2011-2012 Adam Wulkiewicz, Lodz, Poland. // 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 TESTS_RTREE_FUNCTION_HPP #define TESTS_RTREE_FUNCTION_HPP #include #include #include #include #include #include #include #include namespace helpers { template struct value_randomizer_impl_set {}; template struct value_randomizer_impl_set { inline static void apply( Box & b, typename boost::geometry::index::traits::coordinate_type::type m, typename boost::geometry::index::traits::coordinate_type::type w) { namespace bg = boost::geometry; typedef typename bg::index::traits::coordinate_type::type coord_t; coord_t c1 = ::rand() / coord_t(RAND_MAX / m); coord_t c2 = ::rand() / coord_t(RAND_MAX / w); bg::set(b, c1 - c2); bg::set(b, c1 + c2); } }; template struct value_randomizer_impl_set { inline static void apply( Point & p, typename boost::geometry::index::traits::coordinate_type::type m, typename boost::geometry::index::traits::coordinate_type::type) { namespace bg = boost::geometry; typedef typename bg::index::traits::coordinate_type::type coord_t; coord_t c = ::rand() / coord_t(RAND_MAX / m); bg::set(p, c); } }; template struct value_randomizer_impl { inline static void apply( Indexable & i, typename boost::geometry::index::traits::coordinate_type::type m, typename boost::geometry::index::traits::coordinate_type::type w) { value_randomizer_impl::apply(i, m, w); value_randomizer_impl_set< Indexable, D - 1, typename boost::geometry::index::traits::tag::type >::apply(i, m, w); } }; template struct value_randomizer_impl { inline static void apply( Indexable & i, typename boost::geometry::index::traits::coordinate_type::type m, typename boost::geometry::index::traits::coordinate_type::type w) { value_randomizer_impl_set< Indexable, 0, typename boost::geometry::index::traits::tag::type >::apply(i, m, w); } }; template struct value_randomizer { typedef Indexable value_type; typedef typename boost::geometry::index::traits::coordinate_type::type coord_t; inline value_randomizer(coord_t mm, coord_t ww) : m(mm), w(ww) {} inline Indexable operator()() const { namespace bg = boost::geometry; namespace bgi = bg::index; Indexable i; value_randomizer_impl::value>::apply(i, m, w); return i; } coord_t m, w; }; template void random_insert(Rtree & t, Cont & c, size_t n, Randomizer r) { namespace bg = boost::geometry; namespace bgi = bg::index; bgi::insert_iterator ii = bgi::inserter(t); for ( size_t i = 0 ; i < n ; ++i ) { typename Randomizer::value_type v = r(); //bgi::insert(t, v); *ii++ = v; c.push_back(v); } } template bool results_compare(Cont const& c1, Cont const& c2, Translator const& tr) { if ( c1.size() != c2.size() ) return false; for ( typename Cont::const_iterator it = c1.begin() ; it != c1.end() ; ++it ) { bool found = false; for ( typename Cont::const_iterator it2 = c2.begin() ; it2 != c2.end() ; ++it2 ) if ( tr.equals(*it, *it2) ) { found = true; break; } if ( !found ) return false; } return true; } template bool nearest_results_compare(Point const& p, Cont const& c1, Cont const& c2, Translator const& tr) { namespace bg = boost::geometry; namespace bgi = boost::geometry::index; typedef typename bgi::translator::indexable_type::type indexable_type; typedef bg::default_distance_result::type distance_type; if ( c1.size() != c2.size() ) return false; if ( c1.size() == 0 && c2.size() == 0 ) return true; distance_type biggest_distance1 = 0; for ( typename Cont::const_iterator it = c1.begin() ; it != c1.end() ; ++it ) { distance_type curr_distance = bgi::comparable_distance_near(p, tr(*it)); if ( biggest_distance1 < curr_distance ) biggest_distance1 = curr_distance; } distance_type biggest_distance2 = 0; for ( typename Cont::const_iterator it = c2.begin() ; it != c2.end() ; ++it ) { distance_type curr_distance = bgi::comparable_distance_near(p, tr(*it)); if ( biggest_distance2 < curr_distance ) biggest_distance2 = curr_distance; } return biggest_distance1 == biggest_distance2; } template struct val_mindist_cmp { val_mindist_cmp(Point const& p, Translator const& t) : pt(p), tr(t) {} template bool operator()(Value const& v1, Value const& v2) { return boost::geometry::index::comparable_distance_near(pt, tr(v1)) < boost::geometry::index::comparable_distance_near(pt, tr(v2)); } Point const& pt; Translator const& tr; }; template Box values_box(Iter first, Iter last, Translator const& tr) { namespace bg = boost::geometry; namespace bgi = bg::index; Box b; bg::assign_inverse(b); for ( ; first != last ; ++first ) { bg::expand(b, tr(*first)); } return b; } } // namespace helpers template void random_query_check(Rtree const& t, Cont const& c, size_t n, Randomizer r) { namespace bg = boost::geometry; namespace bgi = bg::index; for ( size_t i = 0 ; i < n ; ++i ) { Predicate pred = Predicate(r()); std::vector res1, res2; bgi::query(t, pred, std::back_inserter(res1)); for ( typename Cont::const_iterator it = c.begin() ; it != c.end() ; ++it ) { if ( bgi::predicates_check(pred, *it, t.translator()(*it)) ) res2.push_back(*it); } std::stringstream ss; ss << "\nPredicate: " << typeid(Predicate).name() << "\n" << "res1: " << res1.size() << ", res2: " << res2.size()<< '\n'; BOOST_CHECK_MESSAGE( helpers::results_compare(res1, res2, t.translator()), ss.str()); } } template void random_nearest_check( Rtree const& t, Cont const& c, size_t n, PointRandomizer const& pr, size_t k, PredicateRandomizer const& r) { namespace bg = boost::geometry; namespace bgi = bg::index; for ( size_t i = 0 ; i < n ; ++i ) { typename PointRandomizer::value_type pt = pr(); Predicate pred = Predicate(r()); std::vector res1, res2; bgi::nearest(t, pt, k, pred, std::back_inserter(res1)); for ( typename Cont::const_iterator it = c.begin() ; it != c.end() ; ++it ) { if ( bgi::predicates_check(pred, *it, t.translator()(*it)) ) res2.push_back(*it); } std::sort( res2.begin(), res2.end(), helpers::val_mindist_cmp< typename PointRandomizer::value_type, typename Rtree::translator_type >(pt, t.translator()) ); if ( k < res2.size() ) res2.resize(k); std::stringstream ss; ss << "\nPredicate: " << typeid(Predicate).name() << "\n" << "res1: " << res1.size() << ", res2: " << res2.size() << '\n'; BOOST_CHECK_MESSAGE(helpers::nearest_results_compare(pt, res1, res2, t.translator()), ss.str()); } } template struct tests_rtree_function_queries {}; template struct tests_rtree_function_queries { template inline static void apply(Rtree const& t, Cont const& v) { namespace bgi = boost::geometry::index; random_query_check(t, v, 5, helpers::value_randomizer(10, 5)); random_query_check >(t, v, 5, helpers::value_randomizer(10, 5)); random_query_check >(t, v, 5, helpers::value_randomizer(10, 5)); random_query_check >(t, v, 5, helpers::value_randomizer(10, 5)); random_query_check >(t, v, 5, helpers::value_randomizer(10, 5)); random_query_check >(t, v, 5, helpers::value_randomizer(10, 5)); random_query_check >(t, v, 5, helpers::value_randomizer(10, 5)); random_query_check >(t, v, 5, helpers::value_randomizer(10, 5)); random_query_check >(t, v, 5, helpers::value_randomizer(10, 5)); random_nearest_check(t, v, 5, helpers::value_randomizer

(10, 0), 3, bgi::empty); random_nearest_check(t, v, 5, helpers::value_randomizer

(10, 0), 3, helpers::value_randomizer(10, 5)); random_nearest_check >(t, v, 5, helpers::value_randomizer

(10, 0), 3, helpers::value_randomizer(10, 5)); random_nearest_check >(t, v, 5, helpers::value_randomizer

(10, 0), 3, helpers::value_randomizer(10, 5)); random_nearest_check >(t, v, 5, helpers::value_randomizer

(10, 0), 3, helpers::value_randomizer(10, 5)); random_nearest_check >(t, v, 5, helpers::value_randomizer

(10, 0), 3, helpers::value_randomizer(10, 5)); } }; template struct tests_rtree_function_queries { template inline static void apply(Rtree const& t, Cont const& v) { namespace bgi = boost::geometry::index; random_query_check(t, v, 5, helpers::value_randomizer(10, 5)); random_query_check >(t, v, 5, helpers::value_randomizer(10, 5)); random_query_check >(t, v, 5, helpers::value_randomizer(10, 5)); random_query_check >(t, v, 5, helpers::value_randomizer(10, 5)); random_query_check >(t, v, 5, helpers::value_randomizer(10, 5)); random_query_check >(t, v, 5, helpers::value_randomizer(10, 5)); random_query_check >(t, v, 5, helpers::value_randomizer(10, 5)); random_query_check >(t, v, 5, helpers::value_randomizer(10, 5)); random_query_check >(t, v, 5, helpers::value_randomizer(10, 5)); random_query_check >(t, v, 5, helpers::value_randomizer(10, 5)); random_query_check >(t, v, 5, helpers::value_randomizer(10, 5)); random_nearest_check(t, v, 5, helpers::value_randomizer

(10, 0), 3, bgi::empty); random_nearest_check(t, v, 5, helpers::value_randomizer

(10, 0), 3, helpers::value_randomizer(10, 5)); random_nearest_check >(t, v, 5, helpers::value_randomizer

(10, 0), 3, helpers::value_randomizer(10, 5)); random_nearest_check >(t, v, 5, helpers::value_randomizer

(10, 0), 3, helpers::value_randomizer(10, 5)); random_nearest_check >(t, v, 5, helpers::value_randomizer

(10, 0), 3, helpers::value_randomizer(10, 5)); random_nearest_check >(t, v, 5, helpers::value_randomizer

(10, 0), 3, helpers::value_randomizer(10, 5)); random_nearest_check >(t, v, 5, helpers::value_randomizer

(10, 0), 3, helpers::value_randomizer(10, 5)); } }; template void tests_rtree_function(Translator const& tr = Translator()) { namespace bg = boost::geometry; namespace bgi = bg::index; bgi::rtree t(tr); std::vector v; typedef typename bgi::rtree::indexable_type I; typedef typename bgi::rtree::box_type B; typedef typename bgi::traits::point_type::type P ; helpers::random_insert(t, v, 10, helpers::value_randomizer(10, 1)); bgi::rtree t_copy(t); BOOST_CHECK(bgi::size(t) == 10); BOOST_CHECK(bgi::size(t) == bgi::size(t_copy)); BOOST_CHECK(bg::equals(bgi::box(t), bgi::box(t_copy))); B bt = bgi::box(t); B bv = helpers::values_box(v.begin(), v.end(), tr); BOOST_CHECK(bg::equals(bt, bv)); tests_rtree_function_queries::type>::apply(t, v); bgi::clear(t); BOOST_CHECK(bgi::empty(t)); bt = bgi::box(t); B be; bg::assign_inverse(be); BOOST_CHECK(bg::equals(be, bt)); for ( size_t i = 3 ; i < 10 ; ++i ) bgi::remove(t_copy, v[i]); v.erase(v.begin() + 3, v.end()); tests_rtree_function_queries::type>::apply(t_copy, v); } BOOST_AUTO_TEST_CASE(tests_rtree_function_box3f) { #ifdef TEST_PRINT_INFO std::cout << "tests/rtree_function_box3f\n"; #endif namespace bg = boost::geometry; namespace bgi = bg::index; typedef bg::model::point P; typedef bg::model::box

B; typedef B V; tests_rtree_function< V, bgi::linear<4, 2>, bgi::translator::def >(); tests_rtree_function< V, bgi::quadratic<4, 2>, bgi::translator::def >(); tests_rtree_function< V, bgi::rstar<4, 2>, bgi::translator::def >(); } BOOST_AUTO_TEST_CASE(tests_rtree_function_box2f) { #ifdef TEST_PRINT_INFO std::cout << "tests/rtree_function_box2f\n"; #endif namespace bg = boost::geometry; namespace bgi = bg::index; typedef bg::model::point P; typedef bg::model::box

B; typedef B V; tests_rtree_function< V, bgi::linear<4, 2>, bgi::translator::def >(); tests_rtree_function< V, bgi::quadratic<4, 2>, bgi::translator::def >(); tests_rtree_function< V, bgi::rstar<4, 2>, bgi::translator::def >(); } BOOST_AUTO_TEST_CASE(tests_rtree_function_point2f) { #ifdef TEST_PRINT_INFO std::cout << "tests/rtree_function_point2f\n"; #endif namespace bg = boost::geometry; namespace bgi = bg::index; typedef bg::model::point P; typedef P V; tests_rtree_function< V, bgi::linear<4, 2>, bgi::translator::def >(); tests_rtree_function< V, bgi::quadratic<4, 2>, bgi::translator::def >(); tests_rtree_function< V, bgi::rstar<4, 2>, bgi::translator::def >(); } namespace helpers { template struct value_randomizer< std::pair > { typedef std::pair value_type; typedef typename boost::geometry::index::traits::coordinate_type::type coord_t; inline value_randomizer(coord_t mm, coord_t ww) : r(mm, ww) {} inline value_type operator()() const { return std::make_pair(r(), ::rand()); } value_randomizer r; }; } // namespace helpers BOOST_AUTO_TEST_CASE(tests_rtree_function_pair_box2f_int) { #ifdef TEST_PRINT_INFO std::cout << "tests/rtree_function_pair_box2f_int\n"; #endif namespace bg = boost::geometry; namespace bgi = bg::index; typedef bg::model::point P; typedef bg::model::box

B; typedef std::pair V; tests_rtree_function< V, bgi::linear<4, 2>, bgi::translator::def >(); tests_rtree_function< V, bgi::quadratic<4, 2>, bgi::translator::def >(); tests_rtree_function< V, bgi::rstar<4, 2>, bgi::translator::def >(); } namespace helpers { template struct value_randomizer< boost::shared_ptr< std::pair > > { typedef boost::shared_ptr< std::pair > value_type; typedef typename boost::geometry::index::traits::coordinate_type::type coord_t; inline value_randomizer(coord_t mm, coord_t ww) : r(mm, ww) {} inline value_type operator()() const { return value_type(new std::pair(r(), ::rand())); } value_randomizer r; }; } // namespace helpers BOOST_AUTO_TEST_CASE(tests_rtree_function_shared_ptr_pair_box2f_int) { #ifdef TEST_PRINT_INFO std::cout << "tests/rtree_function_shared_ptr_pair_box2f_int\n"; #endif namespace bg = boost::geometry; namespace bgi = bg::index; typedef bg::model::point P; typedef bg::model::box

B; typedef boost::shared_ptr< std::pair > V; tests_rtree_function< V, bgi::linear<4, 2>, bgi::translator::def >(); tests_rtree_function< V, bgi::quadratic<4, 2>, bgi::translator::def >(); tests_rtree_function< V, bgi::rstar<4, 2>, bgi::translator::def >(); } #endif // TESTS_RTREE_FUNCTION_HPP