test_distance_se_common.hpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Unit Test
  3. // Copyright (c) 2014-2017, Oracle and/or its affiliates.
  4. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
  5. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  6. // Licensed under the Boost Software License version 1.0.
  7. // http://www.boost.org/users/license.html
  8. #ifndef BOOST_GEOMETRY_TEST_DISTANCE_SE_COMMON_HPP
  9. #define BOOST_GEOMETRY_TEST_DISTANCE_SE_COMMON_HPP
  10. #include <iostream>
  11. #include <string>
  12. #include <boost/mpl/assert.hpp>
  13. #include <boost/type_traits/is_integral.hpp>
  14. #include <boost/type_traits/is_same.hpp>
  15. #include <boost/geometry/geometries/point.hpp>
  16. #include <boost/geometry/geometries/point_xy.hpp>
  17. #include <boost/geometry/geometries/segment.hpp>
  18. #include <boost/geometry/geometries/linestring.hpp>
  19. #include <boost/geometry/geometries/polygon.hpp>
  20. #include <boost/geometry/geometries/ring.hpp>
  21. #include <boost/geometry/geometries/box.hpp>
  22. #include <boost/geometry/geometries/multi_point.hpp>
  23. #include <boost/geometry/geometries/multi_linestring.hpp>
  24. #include <boost/geometry/geometries/multi_polygon.hpp>
  25. #include <boost/geometry/io/wkt/write.hpp>
  26. #include <boost/geometry/io/dsv/write.hpp>
  27. #include <boost/geometry/algorithms/num_interior_rings.hpp>
  28. #include <boost/geometry/algorithms/distance.hpp>
  29. #include <boost/geometry/algorithms/comparable_distance.hpp>
  30. #include <boost/geometry/strategies/strategies.hpp>
  31. #include <from_wkt.hpp>
  32. #include <string_from_type.hpp>
  33. #include "distance_brute_force.hpp"
  34. namespace bg = ::boost::geometry;
  35. static const double earth_radius_km = 6371.0;
  36. static const double earth_radius_miles = 3959.0;
  37. //========================================================================
  38. template <typename T>
  39. struct check_equal
  40. {
  41. template <typename Value, typename = void>
  42. struct equal_to
  43. {
  44. static inline void apply(Value const& x, Value const& y)
  45. {
  46. BOOST_CHECK(x == y);
  47. }
  48. };
  49. template <typename Dummy>
  50. struct equal_to<double, Dummy>
  51. {
  52. static inline void apply(double x, double y)
  53. {
  54. BOOST_CHECK_CLOSE(x, y, 0.001);
  55. }
  56. };
  57. template <typename Geometry1, typename Geometry2>
  58. static inline void apply(std::string const& /*case_id*/,
  59. std::string const& /*subcase_id*/,
  60. Geometry1 const& /*geometry1*/,
  61. Geometry2 const& /*geometry2*/,
  62. T const& detected,
  63. T const& expected)
  64. {
  65. equal_to<T>::apply(expected, detected);
  66. /*
  67. TODO:
  68. Ideally we would want the following, but it does not work well
  69. approximate equality test.
  70. BOOST_CHECK_MESSAGE(equal_to<T>::apply(expected, detected),
  71. "case ID: " << case_id << "-" << subcase_id << "; "
  72. << "G1: " << bg::wkt(geometry1)
  73. << " - "
  74. << "G2: " << bg::wkt(geometry2)
  75. << " -> Detected: " << detected
  76. << "; Expected: " << expected);
  77. */
  78. }
  79. };
  80. //========================================================================
  81. template
  82. <
  83. typename Geometry1, typename Geometry2,
  84. int id1 = bg::geometry_id<Geometry1>::value,
  85. int id2 = bg::geometry_id<Geometry2>::value
  86. >
  87. struct test_distance_of_geometries
  88. : public test_distance_of_geometries<Geometry1, Geometry2, 0, 0>
  89. {};
  90. template <typename Geometry1, typename Geometry2>
  91. struct test_distance_of_geometries<Geometry1, Geometry2, 0, 0>
  92. {
  93. template
  94. <
  95. typename DistanceType,
  96. typename ComparableDistanceType,
  97. typename Strategy
  98. >
  99. static inline
  100. void apply(std::string const& case_id,
  101. std::string const& wkt1,
  102. std::string const& wkt2,
  103. DistanceType const& expected_distance,
  104. ComparableDistanceType const& expected_comparable_distance,
  105. Strategy const& strategy,
  106. bool test_reversed = true)
  107. {
  108. Geometry1 geometry1 = from_wkt<Geometry1>(wkt1);
  109. Geometry2 geometry2 = from_wkt<Geometry2>(wkt2);
  110. apply(case_id, geometry1, geometry2,
  111. expected_distance, expected_comparable_distance,
  112. strategy, test_reversed);
  113. }
  114. template <typename DistanceType, typename Strategy>
  115. static inline
  116. void apply(std::string const& case_id,
  117. std::string const& wkt1,
  118. std::string const& wkt2,
  119. DistanceType const& expected_distance,
  120. Strategy const& strategy,
  121. bool test_reversed = true)
  122. {
  123. Geometry1 geometry1 = from_wkt<Geometry1>(wkt1);
  124. Geometry2 geometry2 = from_wkt<Geometry2>(wkt2);
  125. apply(case_id, geometry1, geometry2,
  126. expected_distance, expected_distance,
  127. strategy, test_reversed);
  128. }
  129. template
  130. <
  131. typename DistanceType,
  132. typename ComparableDistanceType,
  133. typename Strategy
  134. >
  135. static inline
  136. void apply(std::string const& case_id,
  137. Geometry1 const& geometry1,
  138. Geometry2 const& geometry2,
  139. DistanceType const& expected_distance,
  140. ComparableDistanceType const& expected_comparable_distance,
  141. Strategy const& strategy,
  142. bool test_reversed = true)
  143. {
  144. #ifdef BOOST_GEOMETRY_TEST_DEBUG
  145. std::cout << "case ID: " << case_id << "; "
  146. << "G1: " << bg::wkt(geometry1)
  147. << " - "
  148. << "G2: " << bg::wkt(geometry2)
  149. << std::endl;
  150. #endif
  151. namespace services = bg::strategy::distance::services;
  152. using bg::unit_test::distance_brute_force;
  153. typedef typename bg::default_distance_result
  154. <
  155. Geometry1, Geometry2
  156. >::type default_distance_result;
  157. typedef typename services::return_type
  158. <
  159. Strategy, Geometry1, Geometry2
  160. >::type distance_result_from_strategy;
  161. static const bool same_regular = boost::is_same
  162. <
  163. default_distance_result,
  164. distance_result_from_strategy
  165. >::type::value;
  166. BOOST_CHECK(same_regular);
  167. typedef typename bg::default_comparable_distance_result
  168. <
  169. Geometry1, Geometry2
  170. >::type default_comparable_distance_result;
  171. typedef typename services::return_type
  172. <
  173. typename services::comparable_type<Strategy>::type,
  174. Geometry1,
  175. Geometry2
  176. >::type comparable_distance_result_from_strategy;
  177. static const bool same_comparable = boost::is_same
  178. <
  179. default_comparable_distance_result,
  180. comparable_distance_result_from_strategy
  181. >::type::value;
  182. BOOST_CHECK( same_comparable );
  183. // check distance with passed strategy
  184. distance_result_from_strategy dist =
  185. bg::distance(geometry1, geometry2, strategy);
  186. check_equal
  187. <
  188. distance_result_from_strategy
  189. >::apply(case_id, "a", geometry1, geometry2,
  190. dist, expected_distance);
  191. // check against the comparable distance computed in a
  192. // brute-force manner
  193. default_distance_result dist_brute_force
  194. = distance_brute_force(geometry1, geometry2, strategy);
  195. check_equal
  196. <
  197. default_distance_result
  198. >::apply(case_id, "b", geometry1, geometry2,
  199. dist_brute_force, expected_distance);
  200. // check comparable distance with passed strategy
  201. comparable_distance_result_from_strategy cdist =
  202. bg::comparable_distance(geometry1, geometry2, strategy);
  203. check_equal
  204. <
  205. default_comparable_distance_result
  206. >::apply(case_id, "c", geometry1, geometry2,
  207. cdist, expected_comparable_distance);
  208. // check against the comparable distance computed in a
  209. // brute-force manner
  210. default_comparable_distance_result cdist_brute_force
  211. = distance_brute_force(geometry1,
  212. geometry2,
  213. services::get_comparable
  214. <
  215. Strategy
  216. >::apply(strategy));
  217. check_equal
  218. <
  219. default_comparable_distance_result
  220. >::apply(case_id, "d", geometry1, geometry2,
  221. cdist_brute_force, expected_comparable_distance);
  222. #ifdef BOOST_GEOMETRY_TEST_DEBUG
  223. std::cout << string_from_type<typename bg::coordinate_type<Geometry1>::type>::name()
  224. << string_from_type<typename bg::coordinate_type<Geometry2>::type>::name()
  225. << " -> "
  226. << string_from_type<default_distance_result>::name()
  227. << string_from_type<default_comparable_distance_result>::name()
  228. << std::endl;
  229. std::cout << "strategy radius: " << strategy.radius() << std::endl;
  230. std::cout << "expected distance = "
  231. << expected_distance << " ; "
  232. << "expected comp. distance = "
  233. << expected_comparable_distance
  234. << std::endl;
  235. std::cout << "distance = "
  236. << dist << " ; "
  237. << "comp. distance = "
  238. << cdist
  239. << std::endl;
  240. if ( !test_reversed )
  241. {
  242. std::cout << std::endl;
  243. }
  244. #endif
  245. if ( test_reversed )
  246. {
  247. // check distance with given strategy
  248. dist = bg::distance(geometry2, geometry1, strategy);
  249. check_equal
  250. <
  251. default_distance_result
  252. >::apply(case_id, "ra", geometry2, geometry1,
  253. dist, expected_distance);
  254. // check comparable distance with given strategy
  255. cdist = bg::comparable_distance(geometry2, geometry1, strategy);
  256. check_equal
  257. <
  258. default_comparable_distance_result
  259. >::apply(case_id, "rc", geometry2, geometry1,
  260. cdist, expected_comparable_distance);
  261. #ifdef BOOST_GEOMETRY_TEST_DEBUG
  262. std::cout << "distance[reversed args] = "
  263. << dist << " ; "
  264. << "comp. distance[reversed args] = "
  265. << cdist
  266. << std::endl;
  267. std::cout << std::endl;
  268. #endif
  269. }
  270. }
  271. };
  272. //========================================================================
  273. template <typename Geometry1, typename Geometry2, typename Strategy>
  274. void test_empty_input(Geometry1 const& geometry1,
  275. Geometry2 const& geometry2,
  276. Strategy const& strategy)
  277. {
  278. try
  279. {
  280. bg::distance(geometry1, geometry2);
  281. }
  282. catch(bg::empty_input_exception const& )
  283. {
  284. return;
  285. }
  286. BOOST_CHECK_MESSAGE(false,
  287. "A empty_input_exception should have been thrown");
  288. try
  289. {
  290. bg::distance(geometry2, geometry1);
  291. }
  292. catch(bg::empty_input_exception const& )
  293. {
  294. return;
  295. }
  296. BOOST_CHECK_MESSAGE(false,
  297. "A empty_input_exception should have been thrown");
  298. try
  299. {
  300. bg::distance(geometry1, geometry2, strategy);
  301. }
  302. catch(bg::empty_input_exception const& )
  303. {
  304. return;
  305. }
  306. BOOST_CHECK_MESSAGE(false,
  307. "A empty_input_exception should have been thrown");
  308. try
  309. {
  310. bg::distance(geometry2, geometry1, strategy);
  311. }
  312. catch(bg::empty_input_exception const& )
  313. {
  314. return;
  315. }
  316. BOOST_CHECK_MESSAGE(false,
  317. "A empty_input_exception should have been thrown");
  318. }
  319. #endif // BOOST_GEOMETRY_TEST_DISTANCE_SE_COMMON_HPP