is_acceptable_turn.hpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2014-2015, Oracle and/or its affiliates.
  3. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
  4. // Licensed under the Boost Software License version 1.0.
  5. // http://www.boost.org/users/license.html
  6. #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_IS_ACCEPTABLE_TURN_HPP
  7. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_IS_ACCEPTABLE_TURN_HPP
  8. #include <boost/range.hpp>
  9. #include <boost/geometry/core/point_order.hpp>
  10. #include <boost/geometry/core/tag.hpp>
  11. #include <boost/geometry/core/tags.hpp>
  12. #include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
  13. namespace boost { namespace geometry
  14. {
  15. #ifndef DOXYGEN_NO_DETAIL
  16. namespace detail { namespace is_valid
  17. {
  18. template
  19. <
  20. typename Geometry,
  21. order_selector Order = geometry::point_order<Geometry>::value,
  22. typename Tag = typename tag<Geometry>::type
  23. >
  24. struct acceptable_operation
  25. {};
  26. template <typename Polygon>
  27. struct acceptable_operation<Polygon, counterclockwise, polygon_tag>
  28. {
  29. static const detail::overlay::operation_type value =
  30. detail::overlay::operation_union;
  31. };
  32. template <typename Polygon>
  33. struct acceptable_operation<Polygon, clockwise, polygon_tag>
  34. {
  35. static const detail::overlay::operation_type value =
  36. detail::overlay::operation_intersection;
  37. };
  38. template <typename MultiPolygon>
  39. struct acceptable_operation<MultiPolygon, counterclockwise, multi_polygon_tag>
  40. {
  41. static const detail::overlay::operation_type value =
  42. detail::overlay::operation_intersection;
  43. };
  44. template <typename MultiPolygon>
  45. struct acceptable_operation<MultiPolygon, clockwise, multi_polygon_tag>
  46. {
  47. static const detail::overlay::operation_type value =
  48. detail::overlay::operation_union;
  49. };
  50. template <typename Geometry, typename Tag = typename tag<Geometry>::type>
  51. struct is_acceptable_turn
  52. {};
  53. template <typename Ring>
  54. struct is_acceptable_turn<Ring, ring_tag>
  55. {
  56. template <typename Turn>
  57. static inline bool apply(Turn const&)
  58. {
  59. return false;
  60. }
  61. };
  62. template <typename Polygon>
  63. class is_acceptable_turn<Polygon, polygon_tag>
  64. {
  65. protected:
  66. template <typename Turn, typename Method, typename Operation>
  67. static inline bool check_turn(Turn const& turn,
  68. Method method,
  69. Operation operation)
  70. {
  71. return turn.method == method
  72. && turn.operations[0].operation == operation
  73. && turn.operations[1].operation == operation;
  74. }
  75. public:
  76. template <typename Turn>
  77. static inline bool apply(Turn const& turn)
  78. {
  79. using namespace detail::overlay;
  80. if ( turn.operations[0].seg_id.ring_index
  81. == turn.operations[1].seg_id.ring_index )
  82. {
  83. return false;
  84. }
  85. operation_type const op = acceptable_operation<Polygon>::value;
  86. return check_turn(turn, method_touch_interior, op)
  87. || check_turn(turn, method_touch, op)
  88. ;
  89. }
  90. };
  91. template <typename MultiPolygon>
  92. class is_acceptable_turn<MultiPolygon, multi_polygon_tag>
  93. : is_acceptable_turn<typename boost::range_value<MultiPolygon>::type>
  94. {
  95. private:
  96. typedef typename boost::range_value<MultiPolygon>::type polygon;
  97. typedef is_acceptable_turn<polygon> base;
  98. public:
  99. template <typename Turn>
  100. static inline bool apply(Turn const& turn)
  101. {
  102. using namespace detail::overlay;
  103. if ( turn.operations[0].seg_id.multi_index
  104. == turn.operations[1].seg_id.multi_index )
  105. {
  106. return base::apply(turn);
  107. }
  108. operation_type const op = acceptable_operation<MultiPolygon>::value;
  109. if ( base::check_turn(turn, method_touch_interior, op)
  110. || base::check_turn(turn, method_touch, op))
  111. {
  112. return true;
  113. }
  114. // Turn is acceptable only in case of a touch(interior) and both lines
  115. // (polygons) do not cross
  116. return (turn.method == method_touch
  117. || turn.method == method_touch_interior)
  118. && turn.touch_only;
  119. }
  120. };
  121. }} // namespace detail::is_valid
  122. #endif // DOXYGEN_NO_DETAIL
  123. }} // namespace boost::geometry
  124. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_IS_VALID_IS_ACCEPTABLE_TURN_HPP