/Src/Dependencies/Boost/libs/geometry/test/strategies/pythagoras.cpp

http://hadesmem.googlecode.com/ · C++ · 320 lines · 210 code · 78 blank · 32 comment · 4 complexity · 9a8fecdb4f3be3a2e1362590003d29dd MD5 · raw file

  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Unit Test
  3. // Copyright (c) 2007-2011 Barend Gehrels, Amsterdam, the Netherlands.
  4. // Copyright (c) 2008-2011 Bruno Lalande, Paris, France.
  5. // Copyright (c) 2009-2011 Mateusz Loskot, London, UK.
  6. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
  7. // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
  8. // Use, modification and distribution is subject to the Boost Software License,
  9. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  10. // http://www.boost.org/LICENSE_1_0.txt)
  11. #include <geometry_test_common.hpp>
  12. #if defined(_MSC_VER)
  13. # pragma warning( disable : 4101 )
  14. #endif
  15. #include <boost/timer.hpp>
  16. #include <boost/concept/requires.hpp>
  17. #include <boost/concept_check.hpp>
  18. #include <boost/geometry/algorithms/assign.hpp>
  19. #include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
  20. #include <boost/geometry/strategies/concepts/distance_concept.hpp>
  21. #include <boost/geometry/geometries/point.hpp>
  22. #include <boost/geometry/geometries/adapted/c_array.hpp>
  23. #include <boost/geometry/geometries/adapted/boost_tuple.hpp>
  24. #include <test_common/test_point.hpp>
  25. #ifdef HAVE_TTMATH
  26. # include <boost/geometry/extensions/contrib/ttmath_stub.hpp>
  27. #endif
  28. BOOST_GEOMETRY_REGISTER_C_ARRAY_CS(cs::cartesian)
  29. BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian)
  30. template <typename P1, typename P2>
  31. void test_null_distance_3d()
  32. {
  33. P1 p1;
  34. bg::assign_values(p1, 1, 2, 3);
  35. P2 p2;
  36. bg::assign_values(p2, 1, 2, 3);
  37. typedef bg::strategy::distance::pythagoras<P1, P2> pythagoras_type;
  38. typedef typename bg::strategy::distance::services::return_type<pythagoras_type>::type return_type;
  39. pythagoras_type pythagoras;
  40. return_type result = pythagoras.apply(p1, p2);
  41. BOOST_CHECK_EQUAL(result, return_type(0));
  42. }
  43. template <typename P1, typename P2>
  44. void test_axis_3d()
  45. {
  46. P1 p1;
  47. bg::assign_values(p1, 0, 0, 0);
  48. P2 p2;
  49. bg::assign_values(p2, 1, 0, 0);
  50. typedef bg::strategy::distance::pythagoras<P1, P2> pythagoras_type;
  51. typedef typename bg::strategy::distance::services::return_type<pythagoras_type>::type return_type;
  52. pythagoras_type pythagoras;
  53. return_type result = pythagoras.apply(p1, p2);
  54. BOOST_CHECK_EQUAL(result, return_type(1));
  55. bg::assign_values(p2, 0, 1, 0);
  56. result = pythagoras.apply(p1, p2);
  57. BOOST_CHECK_EQUAL(result, return_type(1));
  58. bg::assign_values(p2, 0, 0, 1);
  59. result = pythagoras.apply(p1, p2);
  60. BOOST_CHECK_CLOSE(result, return_type(1), 0.001);
  61. }
  62. template <typename P1, typename P2>
  63. void test_arbitrary_3d()
  64. {
  65. P1 p1;
  66. bg::assign_values(p1, 1, 2, 3);
  67. P2 p2;
  68. bg::assign_values(p2, 9, 8, 7);
  69. {
  70. typedef bg::strategy::distance::pythagoras<P1, P2> strategy_type;
  71. typedef typename bg::strategy::distance::services::return_type<strategy_type>::type return_type;
  72. strategy_type strategy;
  73. return_type result = strategy.apply(p1, p2);
  74. BOOST_CHECK_CLOSE(result, return_type(10.77032961427), 0.001);
  75. }
  76. {
  77. // Check comparable distance
  78. typedef bg::strategy::distance::comparable::pythagoras<P1, P2> strategy_type;
  79. typedef typename bg::strategy::distance::services::return_type<strategy_type>::type return_type;
  80. strategy_type strategy;
  81. return_type result = strategy.apply(p1, p2);
  82. BOOST_CHECK_EQUAL(result, return_type(116));
  83. }
  84. }
  85. template <typename P1, typename P2, typename CalculationType>
  86. void test_services()
  87. {
  88. namespace bgsd = bg::strategy::distance;
  89. namespace services = bg::strategy::distance::services;
  90. {
  91. // Compile-check if there is a strategy for this type
  92. typedef typename services::default_strategy<bg::point_tag, P1, P2>::type pythagoras_strategy_type;
  93. }
  94. P1 p1;
  95. bg::assign_values(p1, 1, 2, 3);
  96. P2 p2;
  97. bg::assign_values(p2, 4, 5, 6);
  98. double const sqr_expected = 3*3 + 3*3 + 3*3; // 27
  99. double const expected = sqrt(sqr_expected); // sqrt(27)=5.1961524227
  100. // 1: normal, calculate distance:
  101. typedef bgsd::pythagoras<P1, P2, CalculationType> strategy_type;
  102. BOOST_CONCEPT_ASSERT( (bg::concept::PointDistanceStrategy<strategy_type>) );
  103. typedef typename bgsd::services::return_type<strategy_type>::type return_type;
  104. strategy_type strategy;
  105. return_type result = strategy.apply(p1, p2);
  106. BOOST_CHECK_CLOSE(result, return_type(expected), 0.001);
  107. // 2: "similar" to construct a similar strategy (similar but with other template-parameters) for, e.g., the reverse P2/P1
  108. // 2a: similar_type:
  109. typedef typename services::similar_type<strategy_type, P2, P1>::type similar_type;
  110. // 2b: get_similar
  111. similar_type similar = services::get_similar<strategy_type, P2, P1>::apply(strategy);
  112. //result = similar.apply(p1, p2); // should NOT compile because p1/p2 should also be reversed here
  113. result = similar.apply(p2, p1);
  114. BOOST_CHECK_CLOSE(result, return_type(expected), 0.001);
  115. // 3: "comparable" to construct a "comparable strategy" for P1/P2
  116. // a "comparable strategy" is a strategy which does not calculate the exact distance, but
  117. // which returns results which can be mutually compared (e.g. avoid sqrt)
  118. // 3a: "comparable_type"
  119. typedef typename services::comparable_type<strategy_type>::type comparable_type;
  120. // 3b: "get_comparable"
  121. comparable_type comparable = bgsd::services::get_comparable<strategy_type>::apply(strategy);
  122. return_type c_result = comparable.apply(p1, p2);
  123. BOOST_CHECK_CLOSE(c_result, return_type(sqr_expected), 0.001);
  124. // 4: the comparable_type should have a distance_strategy_constructor as well,
  125. // knowing how to compare something with a fixed distance
  126. return_type c_dist5 = services::result_from_distance<comparable_type>::apply(comparable, 5.0);
  127. return_type c_dist6 = services::result_from_distance<comparable_type>::apply(comparable, 6.0);
  128. // If this is the case:
  129. BOOST_CHECK(c_dist5 < c_result && c_result < c_dist6);
  130. // This should also be the case
  131. return_type dist5 = services::result_from_distance<strategy_type>::apply(strategy, 5.0);
  132. return_type dist6 = services::result_from_distance<strategy_type>::apply(strategy, 6.0);
  133. BOOST_CHECK(dist5 < result && result < dist6);
  134. }
  135. template <typename CoordinateType, typename CalculationType, typename AssignType>
  136. void test_big_2d_with(AssignType const& x1, AssignType const& y1,
  137. AssignType const& x2, AssignType const& y2)
  138. {
  139. typedef bg::model::point<CoordinateType, 2, bg::cs::cartesian> point_type;
  140. typedef bg::strategy::distance::pythagoras
  141. <
  142. point_type,
  143. point_type,
  144. CalculationType
  145. > pythagoras_type;
  146. pythagoras_type pythagoras;
  147. typedef typename bg::strategy::distance::services::return_type<pythagoras_type>::type return_type;
  148. point_type p1, p2;
  149. bg::assign_values(p1, x1, y1);
  150. bg::assign_values(p2, x2, y2);
  151. return_type d = pythagoras.apply(p1, p2);
  152. /***
  153. std::cout << typeid(CalculationType).name()
  154. << " " << std::fixed << std::setprecision(20) << d
  155. << std::endl << std::endl;
  156. ***/
  157. BOOST_CHECK_CLOSE(d, return_type(1076554.5485833955678294387789057), 0.001);
  158. }
  159. template <typename CoordinateType, typename CalculationType>
  160. void test_big_2d()
  161. {
  162. test_big_2d_with<CoordinateType, CalculationType>
  163. (123456.78900001, 234567.89100001,
  164. 987654.32100001, 876543.21900001);
  165. }
  166. template <typename CoordinateType, typename CalculationType>
  167. void test_big_2d_string()
  168. {
  169. test_big_2d_with<CoordinateType, CalculationType>
  170. ("123456.78900001", "234567.89100001",
  171. "987654.32100001", "876543.21900001");
  172. }
  173. template <typename P1, typename P2>
  174. void test_all_3d()
  175. {
  176. test_null_distance_3d<P1, P2>();
  177. test_axis_3d<P1, P2>();
  178. test_arbitrary_3d<P1, P2>();
  179. }
  180. template <typename P>
  181. void test_all_3d()
  182. {
  183. test_all_3d<P, int[3]>();
  184. test_all_3d<P, float[3]>();
  185. test_all_3d<P, double[3]>();
  186. test_all_3d<P, test::test_point>();
  187. test_all_3d<P, bg::model::point<int, 3, bg::cs::cartesian> >();
  188. test_all_3d<P, bg::model::point<float, 3, bg::cs::cartesian> >();
  189. test_all_3d<P, bg::model::point<double, 3, bg::cs::cartesian> >();
  190. }
  191. template <typename P, typename Strategy>
  192. void time_compare_s(int const n)
  193. {
  194. boost::timer t;
  195. P p1, p2;
  196. bg::assign_values(p1, 1, 1);
  197. bg::assign_values(p2, 2, 2);
  198. Strategy strategy;
  199. typename bg::strategy::distance::services::return_type<Strategy>::type s = 0;
  200. for (int i = 0; i < n; i++)
  201. {
  202. for (int j = 0; j < n; j++)
  203. {
  204. bg::set<0>(p2, bg::get<0>(p2) + 0.001);
  205. s += strategy.apply(p1, p2);
  206. }
  207. }
  208. std::cout << "s: " << s << " t: " << t.elapsed() << std::endl;
  209. }
  210. template <typename P>
  211. void time_compare(int const n)
  212. {
  213. time_compare_s<P, bg::strategy::distance::pythagoras<P> >(n);
  214. time_compare_s<P, bg::strategy::distance::comparable::pythagoras<P> >(n);
  215. }
  216. int test_main(int, char* [])
  217. {
  218. test_all_3d<int[3]>();
  219. test_all_3d<float[3]>();
  220. test_all_3d<double[3]>();
  221. test_all_3d<test::test_point>();
  222. test_all_3d<bg::model::point<int, 3, bg::cs::cartesian> >();
  223. test_all_3d<bg::model::point<float, 3, bg::cs::cartesian> >();
  224. test_all_3d<bg::model::point<double, 3, bg::cs::cartesian> >();
  225. test_big_2d<float, float>();
  226. test_big_2d<double, double>();
  227. test_big_2d<long double, long double>();
  228. test_big_2d<float, long double>();
  229. test_services<bg::model::point<float, 3, bg::cs::cartesian>, double[3], long double>();
  230. test_services<double[3], test::test_point, float>();
  231. time_compare<bg::model::point<double, 2, bg::cs::cartesian> >(10000);
  232. #if defined(HAVE_TTMATH)
  233. typedef ttmath::Big<1,4> tt;
  234. typedef bg::model::point<tt, 3, bg::cs::cartesian> tt_point;
  235. //test_all_3d<tt[3]>();
  236. test_all_3d<tt_point>();
  237. test_all_3d<tt_point, tt_point>();
  238. test_big_2d<tt, tt>();
  239. test_big_2d_string<tt, tt>();
  240. #endif
  241. return 0;
  242. }