/Src/Dependencies/Boost/libs/geometry/test/algorithms/distance.cpp

http://hadesmem.googlecode.com/ · C++ · 250 lines · 153 code · 60 blank · 37 comment · 0 complexity · 1aa79a3798abd710a7371af95feea589 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. #define TEST_ARRAY
  12. #include <sstream>
  13. #include <algorithms/test_distance.hpp>
  14. #include <boost/mpl/if.hpp>
  15. #include <boost/array.hpp>
  16. #include <boost/geometry/geometries/geometries.hpp>
  17. #include <boost/geometry/geometries/point_xy.hpp>
  18. #include <boost/geometry/geometries/adapted/c_array.hpp>
  19. #include <boost/geometry/geometries/adapted/boost_tuple.hpp>
  20. #include <test_common/test_point.hpp>
  21. #include <test_geometries/custom_segment.hpp>
  22. #include <test_geometries/wrapped_boost_array.hpp>
  23. BOOST_GEOMETRY_REGISTER_C_ARRAY_CS(cs::cartesian)
  24. BOOST_GEOMETRY_REGISTER_BOOST_TUPLE_CS(cs::cartesian)
  25. // Register boost array as a linestring
  26. namespace boost { namespace geometry { namespace traits
  27. {
  28. template <typename Point, std::size_t PointCount>
  29. struct tag< boost::array<Point, PointCount> >
  30. {
  31. typedef linestring_tag type;
  32. };
  33. }}}
  34. template <typename P>
  35. void test_distance_point()
  36. {
  37. namespace services = bg::strategy::distance::services;
  38. typedef typename bg::default_distance_result<P>::type return_type;
  39. // Basic, trivial test
  40. P p1;
  41. bg::set<0>(p1, 1);
  42. bg::set<1>(p1, 1);
  43. P p2;
  44. bg::set<0>(p2, 2);
  45. bg::set<1>(p2, 2);
  46. return_type d = bg::distance(p1, p2);
  47. BOOST_CHECK_CLOSE(d, return_type(1.4142135), 0.001);
  48. // Test specifying strategy manually
  49. typename services::default_strategy<bg::point_tag, P>::type strategy;
  50. d = bg::distance(p1, p2, strategy);
  51. BOOST_CHECK_CLOSE(d, return_type(1.4142135), 0.001);
  52. {
  53. // Test custom strategy
  54. BOOST_CONCEPT_ASSERT( (bg::concept::PointDistanceStrategy<taxicab_distance<P> >) );
  55. typedef typename services::return_type<taxicab_distance<P> >::type cab_return_type;
  56. BOOST_MPL_ASSERT((boost::is_same<cab_return_type, typename bg::coordinate_type<P>::type>));
  57. taxicab_distance<P> tcd;
  58. cab_return_type d = bg::distance(p1, p2, tcd);
  59. BOOST_CHECK( bg::math::abs(d - cab_return_type(2)) <= cab_return_type(0.01) );
  60. }
  61. {
  62. // test comparability
  63. typedef typename services::default_strategy<bg::point_tag, P>::type strategy_type;
  64. typedef typename services::comparable_type<strategy_type>::type comparable_strategy_type;
  65. strategy_type strategy;
  66. comparable_strategy_type comparable_strategy = services::get_comparable<strategy_type>::apply(strategy);
  67. return_type comparable = services::result_from_distance<comparable_strategy_type>::apply(comparable_strategy, 3);
  68. BOOST_CHECK_CLOSE(comparable, return_type(9), 0.001);
  69. }
  70. }
  71. template <typename P>
  72. void test_distance_segment()
  73. {
  74. typedef typename bg::default_distance_result<P>::type return_type;
  75. typedef typename bg::coordinate_type<P>::type coordinate_type;
  76. P s1; bg::set<0>(s1, 1); bg::set<1>(s1, 1);
  77. P s2; bg::set<0>(s2, 4); bg::set<1>(s2, 4);
  78. // Check points left, right, projected-left, projected-right, on segment
  79. P p1; bg::set<0>(p1, 0); bg::set<1>(p1, 1);
  80. P p2; bg::set<0>(p2, 1); bg::set<1>(p2, 0);
  81. P p3; bg::set<0>(p3, 3); bg::set<1>(p3, 1);
  82. P p4; bg::set<0>(p4, 1); bg::set<1>(p4, 3);
  83. P p5; bg::set<0>(p5, 3); bg::set<1>(p5, 3);
  84. bg::model::referring_segment<P const> const seg(s1, s2);
  85. return_type d1 = bg::distance(p1, seg);
  86. return_type d2 = bg::distance(p2, seg);
  87. return_type d3 = bg::distance(p3, seg);
  88. return_type d4 = bg::distance(p4, seg);
  89. return_type d5 = bg::distance(p5, seg);
  90. BOOST_CHECK_CLOSE(d1, return_type(1), 0.001);
  91. BOOST_CHECK_CLOSE(d2, return_type(1), 0.001);
  92. BOOST_CHECK_CLOSE(d3, return_type(1.4142135), 0.001);
  93. BOOST_CHECK_CLOSE(d4, return_type(1.4142135), 0.001);
  94. BOOST_CHECK_CLOSE(d5, return_type(0), 0.001);
  95. // Reverse case: segment/point instead of point/segment
  96. return_type dr1 = bg::distance(seg, p1);
  97. return_type dr2 = bg::distance(seg, p2);
  98. BOOST_CHECK_CLOSE(dr1, d1, 0.001);
  99. BOOST_CHECK_CLOSE(dr2, d2, 0.001);
  100. // Test specifying strategy manually:
  101. // 1) point-point-distance
  102. typename bg::strategy::distance::services::default_strategy<bg::point_tag, P>::type pp_strategy;
  103. d1 = bg::distance(p1, seg, pp_strategy);
  104. BOOST_CHECK_CLOSE(d1, return_type(1), 0.001);
  105. // 2) point-segment-distance
  106. typename bg::strategy::distance::services::default_strategy<bg::segment_tag, P>::type ps_strategy;
  107. d1 = bg::distance(p1, seg, ps_strategy);
  108. BOOST_CHECK_CLOSE(d1, return_type(1), 0.001);
  109. // 3) custom point strategy
  110. taxicab_distance<P> tcd;
  111. d1 = bg::distance(p1, seg, tcd);
  112. BOOST_CHECK_CLOSE(d1, return_type(1), 0.001);
  113. }
  114. template <typename P>
  115. void test_distance_array_as_linestring()
  116. {
  117. typedef typename bg::default_distance_result<P>::type return_type;
  118. // Normal array does not have
  119. boost::array<P, 2> points;
  120. bg::set<0>(points[0], 1);
  121. bg::set<1>(points[0], 1);
  122. bg::set<0>(points[1], 3);
  123. bg::set<1>(points[1], 3);
  124. P p;
  125. bg::set<0>(p, 2);
  126. bg::set<1>(p, 1);
  127. return_type d = bg::distance(p, points);
  128. BOOST_CHECK_CLOSE(d, return_type(0.70710678), 0.001);
  129. bg::set<0>(p, 5); bg::set<1>(p, 5);
  130. d = bg::distance(p, points);
  131. BOOST_CHECK_CLOSE(d, return_type(2.828427), 0.001);
  132. }
  133. template <typename P>
  134. void test_all()
  135. {
  136. test_distance_point<P>();
  137. test_distance_segment<P>();
  138. test_distance_array_as_linestring<P>();
  139. test_geometry<P, bg::model::segment<P> >("POINT(1 3)", "LINESTRING(1 1,4 4)", sqrt(2.0));
  140. test_geometry<P, bg::model::segment<P> >("POINT(3 1)", "LINESTRING(1 1,4 4)", sqrt(2.0));
  141. test_geometry<P, P>("POINT(1 1)", "POINT(2 2)", sqrt(2.0));
  142. test_geometry<P, P>("POINT(0 0)", "POINT(0 3)", 3.0);
  143. test_geometry<P, P>("POINT(0 0)", "POINT(4 0)", 4.0);
  144. test_geometry<P, P>("POINT(0 3)", "POINT(4 0)", 5.0);
  145. test_geometry<P, bg::model::linestring<P> >("POINT(1 3)", "LINESTRING(1 1,4 4)", sqrt(2.0));
  146. test_geometry<P, bg::model::linestring<P> >("POINT(3 1)", "LINESTRING(1 1,4 4)", sqrt(2.0));
  147. test_geometry<bg::model::linestring<P>, P>("LINESTRING(1 1,4 4)", "POINT(1 3)", sqrt(2.0));
  148. // Rings
  149. test_geometry<P, bg::model::ring<P> >("POINT(1 3)", "POLYGON((1 1,4 4,5 0,1 1))", sqrt(2.0));
  150. test_geometry<P, bg::model::ring<P> >("POINT(3 1)", "POLYGON((1 1,4 4,5 0,1 1))", 0.0);
  151. // other way round
  152. test_geometry<bg::model::ring<P>, P>("POLYGON((1 1,4 4,5 0,1 1))", "POINT(3 1)", 0.0);
  153. // open ring
  154. test_geometry<P, bg::model::ring<P, true, false> >("POINT(1 3)", "POLYGON((4 4,5 0,1 1))", sqrt(2.0));
  155. // Polygons
  156. test_geometry<P, bg::model::polygon<P> >("POINT(1 3)", "POLYGON((1 1,4 4,5 0,1 1))", sqrt(2.0));
  157. test_geometry<P, bg::model::polygon<P> >("POINT(3 1)", "POLYGON((1 1,4 4,5 0,1 1))", 0.0);
  158. // other way round
  159. test_geometry<bg::model::polygon<P>, P>("POLYGON((1 1,4 4,5 0,1 1))", "POINT(3 1)", 0.0);
  160. // open polygon
  161. test_geometry<P, bg::model::polygon<P, true, false> >("POINT(1 3)", "POLYGON((4 4,5 0,1 1))", sqrt(2.0));
  162. // Polygons with holes
  163. std::string donut = "POLYGON ((0 0,1 9,8 1,0 0),(1 1,4 1,1 4,1 1))";
  164. test_geometry<P, bg::model::polygon<P> >("POINT(2 2)", donut, 0.5 * sqrt(2.0));
  165. test_geometry<P, bg::model::polygon<P> >("POINT(3 3)", donut, 0.0);
  166. // other way round
  167. test_geometry<bg::model::polygon<P>, P>(donut, "POINT(2 2)", 0.5 * sqrt(2.0));
  168. // open
  169. test_geometry<P, bg::model::polygon<P, true, false> >("POINT(2 2)", "POLYGON ((0 0,1 9,8 1),(1 1,4 1,1 4))", 0.5 * sqrt(2.0));
  170. // DOES NOT COMPILE - cannot do read_wkt (because boost::array is not variably sized)
  171. // test_geometry<P, boost::array<P, 2> >("POINT(3 1)", "LINESTRING(1 1,4 4)", sqrt(2.0));
  172. test_geometry<P, test::wrapped_boost_array<P, 2> >("POINT(3 1)", "LINESTRING(1 1,4 4)", sqrt(2.0));
  173. }
  174. int test_main(int, char* [])
  175. {
  176. #ifdef TEST_ARRAY
  177. //test_all<int[2]>();
  178. //test_all<float[2]>();
  179. //test_all<double[2]>();
  180. //test_all<test::test_point>(); // located here because of 3D
  181. #endif
  182. test_all<bg::model::d2::point_xy<int> >();
  183. test_all<boost::tuple<float, float> >();
  184. test_all<bg::model::d2::point_xy<float> >();
  185. test_all<bg::model::d2::point_xy<double> >();
  186. #ifdef HAVE_TTMATH
  187. test_all<bg::model::d2::point_xy<ttmath_big> >();
  188. #endif
  189. return 0;
  190. }