test_get_turns.hpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
  3. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
  4. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
  5. // This file was modified by Oracle on 2014, 2016, 2017, 2018.
  6. // Modifications copyright (c) 2014-2018 Oracle and/or its affiliates.
  7. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  8. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
  9. // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
  10. // Use, modification and distribution is subject to the Boost Software License,
  11. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  12. // http://www.boost.org/LICENSE_1_0.txt)
  13. #ifndef BOOST_GEOMETRY_TEST_ALGORITHMS_OVERLAY_TEST_GET_TURNS_HPP
  14. #define BOOST_GEOMETRY_TEST_ALGORITHMS_OVERLAY_TEST_GET_TURNS_HPP
  15. #include <iostream>
  16. #include <iomanip>
  17. #include <geometry_test_common.hpp>
  18. #include <boost/geometry/strategies/strategies.hpp>
  19. #include <boost/geometry/algorithms/detail/overlay/get_turns.hpp>
  20. #include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
  21. #include <boost/geometry/io/wkt/read.hpp>
  22. #include <boost/geometry/io/wkt/write.hpp>
  23. struct expected_pusher
  24. : std::vector<std::string>
  25. {
  26. expected_pusher & operator()(std::string const& ex)
  27. {
  28. std::vector<std::string>::push_back(ex);
  29. return *this;
  30. }
  31. };
  32. inline expected_pusher expected(std::string const& ex)
  33. {
  34. expected_pusher res;
  35. return res(ex);
  36. }
  37. struct equal_turn
  38. {
  39. equal_turn(std::string const& s) : turn_ptr(&s) {}
  40. template <typename T>
  41. bool operator()(T const& t) const
  42. {
  43. std::string const& s = (*turn_ptr);
  44. std::string::size_type const count = s.size();
  45. return (count > 0
  46. ? bg::method_char(t.method) == s[0]
  47. : true)
  48. && (count > 1
  49. ? bg::operation_char(t.operations[0].operation) == s[1]
  50. : true)
  51. && (count > 2
  52. ? bg::operation_char(t.operations[1].operation) == s[2]
  53. : true)
  54. && equal_operations_ex(t.operations[0], t.operations[1], s);
  55. }
  56. template <typename P, typename R>
  57. static bool equal_operations_ex(bg::detail::overlay::turn_operation<P, R> const& /*op0*/,
  58. bg::detail::overlay::turn_operation<P, R> const& /*op1*/,
  59. std::string const& /*s*/)
  60. {
  61. return true;
  62. }
  63. template <typename P, typename R>
  64. static bool equal_operations_ex(bg::detail::overlay::turn_operation_linear<P, R> const& op0,
  65. bg::detail::overlay::turn_operation_linear<P, R> const& op1,
  66. std::string const& s)
  67. {
  68. std::string::size_type const count = s.size();
  69. return (count > 3
  70. ? is_colinear_char(op0.is_collinear) == s[3]
  71. : true)
  72. && (count > 4
  73. ? is_colinear_char(op1.is_collinear) == s[4]
  74. : true);
  75. }
  76. static char is_colinear_char(bool is_collinear)
  77. {
  78. return is_collinear ? '=' : '+';
  79. }
  80. const std::string * turn_ptr;
  81. };
  82. template <typename Turns>
  83. struct turns_printer
  84. {
  85. turns_printer(Turns const& t) : turns(t) {}
  86. friend std::ostream & operator<<(std::ostream & os, turns_printer const& tp)
  87. {
  88. std::vector<std::string> vec(tp.turns.size());
  89. std::transform(tp.turns.begin(), tp.turns.end(), vec.begin(), to_string());
  90. std::sort(vec.begin(), vec.end());
  91. std::copy(vec.begin(), vec.end(), std::ostream_iterator<std::string>(os, " "));
  92. return os;
  93. }
  94. struct to_string
  95. {
  96. template <typename P, typename R>
  97. std::string operator()(bg::detail::overlay::turn_info<P, R, bg::detail::overlay::turn_operation<P, R> > const& t) const
  98. {
  99. std::string res(3, ' ');
  100. res[0] = bg::method_char(t.method);
  101. res[1] = bg::operation_char(t.operations[0].operation);
  102. res[2] = bg::operation_char(t.operations[1].operation);
  103. return res;
  104. }
  105. template <typename P, typename R>
  106. std::string operator()(bg::detail::overlay::turn_info<P, R, bg::detail::overlay::turn_operation_linear<P, R> > const& t) const
  107. {
  108. std::string res(5, ' ');
  109. res[0] = bg::method_char(t.method);
  110. res[1] = bg::operation_char(t.operations[0].operation);
  111. res[2] = bg::operation_char(t.operations[1].operation);
  112. res[3] = equal_turn::is_colinear_char(t.operations[0].is_collinear);
  113. res[4] = equal_turn::is_colinear_char(t.operations[1].is_collinear);
  114. return res;
  115. }
  116. };
  117. Turns const& turns;
  118. };
  119. template <>
  120. struct turns_printer<expected_pusher>
  121. {
  122. turns_printer(expected_pusher const& t) : turns(t) {}
  123. friend std::ostream & operator<<(std::ostream & os, turns_printer const& tp)
  124. {
  125. std::vector<std::string> vec(tp.turns.size());
  126. std::copy(tp.turns.begin(), tp.turns.end(), vec.begin());
  127. std::sort(vec.begin(), vec.end());
  128. std::copy(vec.begin(), vec.end(), std::ostream_iterator<std::string>(os, " "));
  129. return os;
  130. }
  131. expected_pusher const& turns;
  132. };
  133. template <typename Geometry1, typename Geometry2, typename Expected, typename Strategy>
  134. void check_geometry_range(Geometry1 const& g1,
  135. Geometry2 const& g2,
  136. std::string const& wkt1,
  137. std::string const& wkt2,
  138. Expected const& expected,
  139. Strategy const& strategy)
  140. {
  141. typedef bg::detail::no_rescale_policy robust_policy_type;
  142. typedef typename bg::point_type<Geometry2>::type point_type;
  143. typedef typename bg::detail::segment_ratio_type
  144. <
  145. point_type, robust_policy_type
  146. >::type segment_ratio_type;
  147. typedef bg::detail::overlay::turn_info
  148. <
  149. typename bg::point_type<Geometry2>::type,
  150. segment_ratio_type,
  151. typename bg::detail::get_turns::turn_operation_type
  152. <
  153. Geometry1,
  154. Geometry2,
  155. segment_ratio_type
  156. >::type
  157. > turn_info;
  158. typedef bg::detail::overlay::assign_null_policy assign_policy_t;
  159. typedef bg::detail::get_turns::no_interrupt_policy interrupt_policy_t;
  160. std::vector<turn_info> detected;
  161. interrupt_policy_t interrupt_policy;
  162. robust_policy_type robust_policy;
  163. // Don't switch the geometries
  164. typedef bg::detail::get_turns::get_turn_info_type
  165. <
  166. Geometry1, Geometry2, assign_policy_t
  167. > turn_policy_t;
  168. bg::dispatch::get_turns
  169. <
  170. typename bg::tag<Geometry1>::type, typename bg::tag<Geometry2>::type,
  171. Geometry1, Geometry2, false, false,
  172. turn_policy_t
  173. >::apply(0, g1, 1, g2, strategy, robust_policy, detected, interrupt_policy);
  174. bool ok = boost::size(expected) == detected.size();
  175. BOOST_CHECK_MESSAGE(ok,
  176. "get_turns: " << wkt1 << " and " << wkt2
  177. << " -> Expected turns #: " << boost::size(expected) << " detected turns #: " << detected.size());
  178. if (ok)
  179. {
  180. std::vector<turn_info> turns = detected;
  181. for ( typename boost::range_iterator<Expected const>::type sit = boost::begin(expected) ;
  182. sit != boost::end(expected) ; ++sit)
  183. {
  184. typename std::vector<turn_info>::iterator
  185. it = std::find_if(turns.begin(), turns.end(), equal_turn(*sit));
  186. if ( it != turns.end() )
  187. {
  188. turns.erase(it);
  189. }
  190. else
  191. {
  192. ok = false;
  193. break;
  194. }
  195. }
  196. }
  197. if ( !ok )
  198. {
  199. BOOST_CHECK_MESSAGE(false,
  200. "get_turns: " << wkt1 << " and " << wkt2
  201. << " -> Expected turns: " << turns_printer<Expected>(expected)
  202. << "Detected turns: " << turns_printer<std::vector<turn_info> >(detected));
  203. #ifdef BOOST_GEOMETRY_TEST_DEBUG
  204. std::cout << "Coordinates: "
  205. << typeid(typename bg::coordinate_type<Geometry1>::type).name()
  206. << ", "
  207. << typeid(typename bg::coordinate_type<Geometry2>::type).name()
  208. << std::endl;
  209. #endif
  210. }
  211. }
  212. template <typename Geometry1, typename Geometry2, typename Expected>
  213. void check_geometry_range(Geometry1 const& g1,
  214. Geometry2 const& g2,
  215. std::string const& wkt1,
  216. std::string const& wkt2,
  217. Expected const& expected)
  218. {
  219. typename bg::strategy::intersection::services::default_strategy
  220. <
  221. typename bg::cs_tag<Geometry1>::type
  222. >::type strategy;
  223. check_geometry_range(g1, g2, wkt1, wkt2, expected, strategy);
  224. }
  225. template <typename Geometry1, typename Geometry2, typename Expected, typename Strategy>
  226. void test_geometry_range(std::string const& wkt1, std::string const& wkt2,
  227. Expected const& expected, Strategy const& strategy)
  228. {
  229. Geometry1 geometry1;
  230. Geometry2 geometry2;
  231. bg::read_wkt(wkt1, geometry1);
  232. bg::read_wkt(wkt2, geometry2);
  233. check_geometry_range(geometry1, geometry2, wkt1, wkt2, expected, strategy);
  234. }
  235. template <typename Geometry1, typename Geometry2, typename Expected>
  236. void test_geometry_range(std::string const& wkt1, std::string const& wkt2,
  237. Expected const& expected)
  238. {
  239. Geometry1 geometry1;
  240. Geometry2 geometry2;
  241. bg::read_wkt(wkt1, geometry1);
  242. bg::read_wkt(wkt2, geometry2);
  243. check_geometry_range(geometry1, geometry2, wkt1, wkt2, expected);
  244. }
  245. template <typename G1, typename G2>
  246. void test_geometry(std::string const& wkt1, std::string const& wkt2,
  247. std::string const& ex0)
  248. {
  249. test_geometry_range<G1, G2>(wkt1, wkt2, expected(ex0));
  250. }
  251. template <typename G1, typename G2>
  252. void test_geometry(std::string const& wkt1, std::string const& wkt2,
  253. std::string const& ex0, std::string const& ex1)
  254. {
  255. test_geometry_range<G1, G2>(wkt1, wkt2, expected(ex0)(ex1));
  256. }
  257. template <typename G1, typename G2>
  258. void test_geometry(std::string const& wkt1, std::string const& wkt2,
  259. std::string const& ex0, std::string const& ex1, std::string const& ex2)
  260. {
  261. test_geometry_range<G1, G2>(wkt1, wkt2, expected(ex0)(ex1)(ex2));
  262. }
  263. template <typename G1, typename G2>
  264. void test_geometry(std::string const& wkt1, std::string const& wkt2,
  265. expected_pusher const& expected)
  266. {
  267. test_geometry_range<G1, G2>(wkt1, wkt2, expected);
  268. }
  269. template <typename G1, typename G2, typename Strategy>
  270. void test_geometry(std::string const& wkt1, std::string const& wkt2,
  271. expected_pusher const& expected,
  272. Strategy const& strategy)
  273. {
  274. test_geometry_range<G1, G2>(wkt1, wkt2, expected, strategy);
  275. }
  276. #endif // BOOST_GEOMETRY_TEST_ALGORITHMS_OVERLAY_TEST_GET_TURNS_HPP