// Boost.Geometry (aka GGL, Generic Geometry Library) // Unit Test // Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2008-2011 Bruno Lalande, Paris, France. // Copyright (c) 2009-2011 Mateusz Loskot, London, UK. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. // 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) #include #if defined(_MSC_VER) # pragma warning( disable : 4101 ) #endif #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_TTMATH # include #endif BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian); template void test_null_distance_3d() { P1 p1; bg::assign_values(p1, 1, 2, 3); P2 p2; bg::assign_values(p2, 1, 2, 3); typedef bg::strategy::distance::pythagoras pythagoras_type; typedef typename bg::strategy::distance::services::return_type::type return_type; pythagoras_type pythagoras; return_type result = pythagoras.apply(p1, p2); BOOST_CHECK_EQUAL(result, return_type(0)); } template void test_axis_3d() { P1 p1; bg::assign_values(p1, 0, 0, 0); P2 p2; bg::assign_values(p2, 1, 0, 0); typedef bg::strategy::distance::pythagoras pythagoras_type; typedef typename bg::strategy::distance::services::return_type::type return_type; pythagoras_type pythagoras; return_type result = pythagoras.apply(p1, p2); BOOST_CHECK_EQUAL(result, return_type(1)); bg::assign_values(p2, 0, 1, 0); result = pythagoras.apply(p1, p2); BOOST_CHECK_EQUAL(result, return_type(1)); bg::assign_values(p2, 0, 0, 1); result = pythagoras.apply(p1, p2); BOOST_CHECK_CLOSE(result, return_type(1), 0.001); } template void test_arbitrary_3d() { P1 p1; bg::assign_values(p1, 1, 2, 3); P2 p2; bg::assign_values(p2, 9, 8, 7); { typedef bg::strategy::distance::pythagoras strategy_type; typedef typename bg::strategy::distance::services::return_type::type return_type; strategy_type strategy; return_type result = strategy.apply(p1, p2); BOOST_CHECK_CLOSE(result, return_type(10.77032961427), 0.001); } { // Check comparable distance typedef bg::strategy::distance::comparable::pythagoras strategy_type; typedef typename bg::strategy::distance::services::return_type::type return_type; strategy_type strategy; return_type result = strategy.apply(p1, p2); BOOST_CHECK_EQUAL(result, return_type(116)); } } template void test_services() { namespace bgsd = bg::strategy::distance; namespace services = bg::strategy::distance::services; { // Compile-check if there is a strategy for this type typedef typename services::default_strategy::type pythagoras_strategy_type; } P1 p1; bg::assign_values(p1, 1, 2, 3); P2 p2; bg::assign_values(p2, 4, 5, 6); double const sqr_expected = 3*3 + 3*3 + 3*3; // 27 double const expected = sqrt(sqr_expected); // sqrt(27)=5.1961524227 // 1: normal, calculate distance: typedef bgsd::pythagoras strategy_type; BOOST_CONCEPT_ASSERT( (bg::concept::PointDistanceStrategy) ); typedef typename bgsd::services::return_type::type return_type; strategy_type strategy; return_type result = strategy.apply(p1, p2); BOOST_CHECK_CLOSE(result, return_type(expected), 0.001); // 2: "similar" to construct a similar strategy (similar but with other template-parameters) for, e.g., the reverse P2/P1 // 2a: similar_type: typedef typename services::similar_type::type similar_type; // 2b: get_similar similar_type similar = services::get_similar::apply(strategy); //result = similar.apply(p1, p2); // should NOT compile because p1/p2 should also be reversed here result = similar.apply(p2, p1); BOOST_CHECK_CLOSE(result, return_type(expected), 0.001); // 3: "comparable" to construct a "comparable strategy" for P1/P2 // a "comparable strategy" is a strategy which does not calculate the exact distance, but // which returns results which can be mutually compared (e.g. avoid sqrt) // 3a: "comparable_type" typedef typename services::comparable_type::type comparable_type; // 3b: "get_comparable" comparable_type comparable = bgsd::services::get_comparable::apply(strategy); return_type c_result = comparable.apply(p1, p2); BOOST_CHECK_CLOSE(c_result, return_type(sqr_expected), 0.001); // 4: the comparable_type should have a distance_strategy_constructor as well, // knowing how to compare something with a fixed distance return_type c_dist5 = services::result_from_distance::apply(comparable, 5.0); return_type c_dist6 = services::result_from_distance::apply(comparable, 6.0); // If this is the case: BOOST_CHECK(c_dist5 < c_result && c_result < c_dist6); // This should also be the case return_type dist5 = services::result_from_distance::apply(strategy, 5.0); return_type dist6 = services::result_from_distance::apply(strategy, 6.0); BOOST_CHECK(dist5 < result && result < dist6); } template void test_big_2d_with(AssignType const& x1, AssignType const& y1, AssignType const& x2, AssignType const& y2) { typedef bg::model::point point_type; typedef bg::strategy::distance::pythagoras < point_type, point_type, CalculationType > pythagoras_type; pythagoras_type pythagoras; typedef typename bg::strategy::distance::services::return_type::type return_type; point_type p1, p2; bg::assign_values(p1, x1, y1); bg::assign_values(p2, x2, y2); return_type d = pythagoras.apply(p1, p2); /*** std::cout << typeid(CalculationType).name() << " " << std::fixed << std::setprecision(20) << d << std::endl << std::endl; ***/ BOOST_CHECK_CLOSE(d, return_type(1076554.5485833955678294387789057), 0.001); } template void test_big_2d() { test_big_2d_with (123456.78900001, 234567.89100001, 987654.32100001, 876543.21900001); } template void test_big_2d_string() { test_big_2d_with ("123456.78900001", "234567.89100001", "987654.32100001", "876543.21900001"); } template void test_all_3d() { test_null_distance_3d(); test_axis_3d(); test_arbitrary_3d(); } template void test_all_3d() { test_all_3d(); test_all_3d(); test_all_3d(); test_all_3d(); test_all_3d >(); test_all_3d >(); test_all_3d >(); } template void time_compare_s(int const n) { boost::timer t; P p1, p2; bg::assign_values(p1, 1, 1); bg::assign_values(p2, 2, 2); Strategy strategy; typename bg::strategy::distance::services::return_type::type s = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { bg::set<0>(p2, bg::get<0>(p2) + 0.001); s += strategy.apply(p1, p2); } } std::cout << "s: " << s << " t: " << t.elapsed() << std::endl; } template void time_compare(int const n) { time_compare_s >(n); time_compare_s >(n); } int test_main(int, char* []) { test_all_3d(); test_all_3d(); test_all_3d(); test_all_3d(); test_all_3d >(); test_all_3d >(); test_all_3d >(); test_big_2d(); test_big_2d(); test_big_2d(); test_big_2d(); test_services, double[3], long double>(); test_services(); time_compare >(10000); #if defined(HAVE_TTMATH) typedef ttmath::Big<1,4> tt; typedef bg::model::point tt_point; //test_all_3d(); test_all_3d(); test_all_3d(); test_big_2d(); test_big_2d_string(); #endif return 0; }