backtrack_check_si.hpp 5.9 KB

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