backtrack_check_si.hpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
  3. // This file was modified by Oracle on 2017.
  4. // Modifications copyright (c) 2017, Oracle and/or its affiliates.
  5. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  6. // Use, modification and distribution is subject to the Boost Software License,
  7. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  8. // http://www.boost.org/LICENSE_1_0.txt)
  9. #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_BACKTRACK_CHECK_SI_HPP
  10. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_BACKTRACK_CHECK_SI_HPP
  11. #include <cstddef>
  12. #include <string>
  13. #include <boost/range.hpp>
  14. #include <boost/geometry/core/access.hpp>
  15. #include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
  16. #include <boost/geometry/algorithms/detail/has_self_intersections.hpp>
  17. #if defined(BOOST_GEOMETRY_DEBUG_INTERSECTION) || defined(BOOST_GEOMETRY_OVERLAY_REPORT_WKT)
  18. # include <boost/geometry/algorithms/detail/overlay/debug_turn_info.hpp>
  19. # include <boost/geometry/io/wkt/wkt.hpp>
  20. #endif
  21. namespace boost { namespace geometry
  22. {
  23. #ifndef DOXYGEN_NO_DETAIL
  24. namespace detail { namespace overlay
  25. {
  26. template <typename Turns>
  27. inline void clear_visit_info(Turns& turns)
  28. {
  29. typedef typename boost::range_value<Turns>::type tp_type;
  30. for (typename boost::range_iterator<Turns>::type
  31. it = boost::begin(turns);
  32. it != boost::end(turns);
  33. ++it)
  34. {
  35. for (typename boost::range_iterator
  36. <
  37. typename tp_type::container_type
  38. >::type op_it = boost::begin(it->operations);
  39. op_it != boost::end(it->operations);
  40. ++op_it)
  41. {
  42. op_it->visited.clear();
  43. }
  44. }
  45. }
  46. struct backtrack_state
  47. {
  48. bool m_good;
  49. inline backtrack_state() : m_good(true) {}
  50. inline void reset() { m_good = true; }
  51. inline bool good() const { return m_good; }
  52. };
  53. enum traverse_error_type
  54. {
  55. traverse_error_none,
  56. traverse_error_no_next_ip_at_start,
  57. traverse_error_no_next_ip,
  58. traverse_error_dead_end_at_start,
  59. traverse_error_dead_end,
  60. traverse_error_visit_again,
  61. traverse_error_endless_loop
  62. };
  63. inline std::string traverse_error_string(traverse_error_type error)
  64. {
  65. switch (error)
  66. {
  67. case traverse_error_none : return "";
  68. case traverse_error_no_next_ip_at_start : return "No next IP at start";
  69. case traverse_error_no_next_ip : return "No next IP";
  70. case traverse_error_dead_end_at_start : return "Dead end at start";
  71. case traverse_error_dead_end : return "Dead end";
  72. case traverse_error_visit_again : return "Visit again";
  73. case traverse_error_endless_loop : return "Endless loop";
  74. default : return "";
  75. }
  76. return "";
  77. }
  78. template
  79. <
  80. typename Geometry1,
  81. typename Geometry2
  82. >
  83. class backtrack_check_self_intersections
  84. {
  85. struct state : public backtrack_state
  86. {
  87. bool m_checked;
  88. inline state()
  89. : m_checked(true)
  90. {}
  91. };
  92. public :
  93. typedef state state_type;
  94. template
  95. <
  96. typename Operation,
  97. typename Rings, typename Ring, typename Turns,
  98. typename Strategy,
  99. typename RobustPolicy,
  100. typename Visitor
  101. >
  102. static inline void apply(std::size_t size_at_start,
  103. Rings& rings,
  104. Ring& ring,
  105. Turns& turns,
  106. typename boost::range_value<Turns>::type const& turn,
  107. Operation& operation,
  108. traverse_error_type traverse_error,
  109. Geometry1 const& geometry1,
  110. Geometry2 const& geometry2,
  111. Strategy const& strategy,
  112. RobustPolicy const& robust_policy,
  113. state_type& state,
  114. Visitor& visitor)
  115. {
  116. visitor.visit_traverse_reject(turns, turn, operation, traverse_error);
  117. state.m_good = false;
  118. // Check self-intersections and throw exception if appropriate
  119. if (! state.m_checked)
  120. {
  121. state.m_checked = true;
  122. has_self_intersections(geometry1, strategy, robust_policy);
  123. has_self_intersections(geometry2, strategy, robust_policy);
  124. }
  125. // Make bad output clean
  126. rings.resize(size_at_start);
  127. geometry::traits::clear<typename boost::range_value<Rings>::type>::apply(ring);
  128. // Reject this as a starting point
  129. operation.visited.set_rejected();
  130. // And clear all visit info
  131. clear_visit_info(turns);
  132. }
  133. };
  134. #ifdef BOOST_GEOMETRY_OVERLAY_REPORT_WKT
  135. template
  136. <
  137. typename Geometry1,
  138. typename Geometry2
  139. >
  140. class backtrack_debug
  141. {
  142. public :
  143. typedef backtrack_state state_type;
  144. template <typename Operation, typename Rings, typename Turns>
  145. static inline void apply(std::size_t size_at_start,
  146. Rings& rings, typename boost::range_value<Rings>::type& ring,
  147. Turns& turns, Operation& operation,
  148. std::string const& reason,
  149. Geometry1 const& geometry1,
  150. Geometry2 const& geometry2,
  151. state_type& state
  152. )
  153. {
  154. std::cout << " REJECT " << reason << std::endl;
  155. state.m_good = false;
  156. rings.resize(size_at_start);
  157. ring.clear();
  158. operation.visited.set_rejected();
  159. clear_visit_info(turns);
  160. int c = 0;
  161. for (int i = 0; i < turns.size(); i++)
  162. {
  163. for (int j = 0; j < 2; j++)
  164. {
  165. if (turns[i].operations[j].visited.rejected())
  166. {
  167. c++;
  168. }
  169. }
  170. }
  171. std::cout << "BACKTRACK (" << reason << " )"
  172. << " " << c << " of " << turns.size() << " rejected"
  173. << std::endl;
  174. std::cout
  175. << geometry::wkt(geometry1) << std::endl
  176. << geometry::wkt(geometry2) << std::endl;
  177. }
  178. };
  179. #endif // BOOST_GEOMETRY_OVERLAY_REPORT_WKT
  180. }} // namespace detail::overlay
  181. #endif // DOXYGEN_NO_DETAIL
  182. }} // namespace boost::geometry
  183. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_BACKTRACK_CHECK_SI_HPP