sort_by_side.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Unit Test
  3. // Copyright (c) 2016 Barend Gehrels, Amsterdam, the Netherlands.
  4. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
  5. // This file was modified by Oracle on 2017, 2019.
  6. // Modifications copyright (c) 2017, 2019, Oracle and/or its affiliates.
  7. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  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. #include <boost/geometry.hpp>
  13. #include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
  14. #include <boost/geometry/geometries/geometries.hpp>
  15. #include <boost/assign/list_of.hpp>
  16. #include <boost/foreach.hpp>
  17. #include "multi_overlay_cases.hpp"
  18. namespace
  19. {
  20. template <typename T>
  21. std::string as_string(std::vector<T> const& v)
  22. {
  23. std::stringstream out;
  24. bool first = true;
  25. BOOST_FOREACH(T const& value, v)
  26. {
  27. out << (first ? "[" : " , ") << value;
  28. first = false;
  29. }
  30. out << (first ? "" : "]");
  31. return out.str();
  32. }
  33. }
  34. // Adapted copy of handle_colocations::gather_cluster_properties
  35. template
  36. <
  37. bool Reverse1, bool Reverse2,
  38. bg::overlay_type OverlayType,
  39. typename Clusters,
  40. typename Turns,
  41. typename Geometry1,
  42. typename Geometry2,
  43. typename SideStrategy
  44. >
  45. std::vector<std::size_t> gather_cluster_properties(
  46. Clusters& clusters, Turns& turns,
  47. bg::detail::overlay::operation_type for_operation,
  48. Geometry1 const& geometry1, Geometry2 const& geometry2,
  49. SideStrategy const& strategy)
  50. {
  51. using namespace boost::geometry;
  52. using namespace boost::geometry::detail::overlay;
  53. std::vector<std::size_t> result;
  54. typedef typename boost::range_value<Turns>::type turn_type;
  55. typedef typename turn_type::point_type point_type;
  56. typedef typename turn_type::turn_operation_type turn_operation_type;
  57. // Define sorter, sorting counter-clockwise such that polygons are on the
  58. // right side
  59. typedef sort_by_side::side_sorter
  60. <
  61. Reverse1, Reverse2, OverlayType, point_type, SideStrategy, std::less<int>
  62. > sbs_type;
  63. for (typename Clusters::iterator mit = clusters.begin();
  64. mit != clusters.end(); ++mit)
  65. {
  66. cluster_info& cinfo = mit->second;
  67. std::set<signed_size_type> const& ids = cinfo.turn_indices;
  68. if (ids.empty())
  69. {
  70. return result;
  71. }
  72. sbs_type sbs(strategy);
  73. point_type turn_point; // should be all the same for all turns in cluster
  74. bool first = true;
  75. for (typename std::set<signed_size_type>::const_iterator sit = ids.begin();
  76. sit != ids.end(); ++sit)
  77. {
  78. signed_size_type turn_index = *sit;
  79. turn_type const& turn = turns[turn_index];
  80. if (first)
  81. {
  82. turn_point = turn.point;
  83. }
  84. for (int i = 0; i < 2; i++)
  85. {
  86. turn_operation_type const& op = turn.operations[i];
  87. sbs.add(op, turn_index, i, geometry1, geometry2, first);
  88. first = false;
  89. }
  90. }
  91. sbs.apply(turn_point);
  92. sbs.find_open();
  93. sbs.assign_zones(for_operation);
  94. cinfo.open_count = sbs.open_count(for_operation);
  95. result.push_back(cinfo.open_count);
  96. }
  97. return result;
  98. }
  99. // Adapted copy of overlay::apply
  100. template
  101. <
  102. bg::overlay_type OverlayType,
  103. bool Reverse1, bool Reverse2, bool ReverseOut,
  104. typename GeometryOut,
  105. typename Geometry1, typename Geometry2,
  106. typename RobustPolicy, typename Strategy
  107. >
  108. std::vector<std::size_t> apply_overlay(
  109. Geometry1 const& geometry1, Geometry2 const& geometry2,
  110. RobustPolicy const& robust_policy,
  111. Strategy const& strategy)
  112. {
  113. using namespace boost::geometry;
  114. typedef typename bg::point_type<GeometryOut>::type point_type;
  115. typedef bg::detail::overlay::traversal_turn_info
  116. <
  117. point_type,
  118. typename bg::detail::segment_ratio_type<point_type, RobustPolicy>::type
  119. > turn_info;
  120. typedef std::deque<turn_info> turn_container_type;
  121. // Define the clusters, mapping cluster_id -> turns
  122. typedef std::map
  123. <
  124. signed_size_type,
  125. bg::detail::overlay::cluster_info
  126. > cluster_type;
  127. turn_container_type turns;
  128. detail::get_turns::no_interrupt_policy policy;
  129. bg::get_turns
  130. <
  131. Reverse1, Reverse2,
  132. detail::overlay::assign_null_policy
  133. >(geometry1, geometry2, strategy, robust_policy, turns, policy);
  134. cluster_type clusters;
  135. bg::enrich_intersection_points<Reverse1, Reverse2, OverlayType>(turns,
  136. clusters, geometry1, geometry2, robust_policy, strategy);
  137. // Gather cluster properties, with test option
  138. return ::gather_cluster_properties<Reverse1, Reverse2, OverlayType>(
  139. clusters, turns, bg::detail::overlay::operation_from_overlay<OverlayType>::value,
  140. geometry1, geometry2, strategy.get_side_strategy());
  141. }
  142. template <typename Geometry, bg::overlay_type OverlayType>
  143. void test_sort_by_side(std::string const& case_id,
  144. std::string const& wkt1, std::string const& wkt2,
  145. std::vector<std::size_t> const& expected_open_count)
  146. {
  147. // std::cout << case_id << std::endl;
  148. Geometry g1;
  149. bg::read_wkt(wkt1, g1);
  150. Geometry g2;
  151. bg::read_wkt(wkt2, g2);
  152. // Reverse if necessary
  153. bg::correct(g1);
  154. bg::correct(g2);
  155. typedef typename boost::range_value<Geometry>::type geometry_out;
  156. typedef typename bg::rescale_overlay_policy_type
  157. <
  158. Geometry,
  159. Geometry
  160. >::type rescale_policy_type;
  161. rescale_policy_type robust_policy
  162. = bg::get_rescale_policy<rescale_policy_type>(g1, g2);
  163. typedef typename bg::strategy::intersection::services::default_strategy
  164. <
  165. typename bg::cs_tag<Geometry>::type
  166. >::type strategy_type;
  167. strategy_type strategy;
  168. std::vector<std::size_t> result = ::apply_overlay
  169. <
  170. OverlayType, false, false, false, geometry_out
  171. >(g1, g2, robust_policy, strategy);
  172. BOOST_CHECK_MESSAGE(result == expected_open_count,
  173. " caseid=" << case_id
  174. << " open count: expected=" << as_string(expected_open_count)
  175. << " detected=" << as_string(result));
  176. }
  177. // Define two small macro's to avoid repetitions of testcases/names etc
  178. #define TEST_INT(caseid, exp) { (test_sort_by_side<multi_polygon, bg::overlay_intersection>) \
  179. ( #caseid "_int", caseid[0], caseid[1], exp); }
  180. #define TEST_UNION(caseid, exp) { (test_sort_by_side<multi_polygon, bg::overlay_union>) \
  181. ( #caseid "_union", caseid[0], caseid[1], exp); }
  182. using boost::assign::list_of;
  183. template <typename T>
  184. void test_all()
  185. {
  186. typedef bg::model::point<T, 2, bg::cs::cartesian> point_type;
  187. typedef bg::model::polygon<point_type> polygon;
  188. typedef bg::model::multi_polygon<polygon> multi_polygon;
  189. // Selection of test cases having only one cluster
  190. TEST_INT(case_64_multi, list_of(1));
  191. TEST_INT(case_72_multi, list_of(3));
  192. TEST_INT(case_107_multi, list_of(2));
  193. TEST_INT(case_123_multi, list_of(3));
  194. TEST_INT(case_124_multi, list_of(3));
  195. TEST_INT(case_recursive_boxes_10, list_of(2));
  196. TEST_INT(case_recursive_boxes_20, list_of(2));
  197. TEST_INT(case_recursive_boxes_21, list_of(1));
  198. TEST_INT(case_recursive_boxes_22, list_of(0));
  199. TEST_UNION(case_recursive_boxes_46, list_of(2)(1)(2)(1)(1)(2)(1));
  200. TEST_UNION(case_62_multi, list_of(2));
  201. TEST_UNION(case_63_multi, list_of(2));
  202. TEST_UNION(case_64_multi, list_of(1));
  203. TEST_UNION(case_107_multi, list_of(1));
  204. TEST_UNION(case_123_multi, list_of(1));
  205. TEST_UNION(case_124_multi, list_of(1));
  206. TEST_UNION(case_recursive_boxes_10, list_of(1));
  207. TEST_UNION(case_recursive_boxes_18, list_of(3));
  208. TEST_UNION(case_recursive_boxes_19, list_of(3));
  209. TEST_UNION(case_recursive_boxes_20, list_of(2));
  210. TEST_UNION(case_recursive_boxes_21, list_of(1));
  211. TEST_UNION(case_recursive_boxes_22, list_of(1));
  212. TEST_UNION(case_recursive_boxes_23, list_of(3));
  213. }
  214. int test_main(int, char* [])
  215. {
  216. test_all<double>();
  217. return 0;
  218. }