occupation_info.hpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2012-2014 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_OCCUPATION_INFO_HPP
  10. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OCCUPATION_INFO_HPP
  11. #include <algorithm>
  12. #include <boost/range.hpp>
  13. #include <boost/geometry/core/assert.hpp>
  14. #include <boost/geometry/core/coordinate_type.hpp>
  15. #include <boost/geometry/core/point_type.hpp>
  16. #include <boost/geometry/policies/compare.hpp>
  17. #include <boost/geometry/iterators/closing_iterator.hpp>
  18. #include <boost/geometry/algorithms/detail/get_left_turns.hpp>
  19. namespace boost { namespace geometry
  20. {
  21. #ifndef DOXYGEN_NO_DETAIL
  22. namespace detail
  23. {
  24. template <typename Point, typename T>
  25. struct angle_info
  26. {
  27. typedef T angle_type;
  28. typedef Point point_type;
  29. segment_identifier seg_id;
  30. std::size_t turn_index;
  31. int operation_index;
  32. std::size_t cluster_index;
  33. Point intersection_point;
  34. Point point; // either incoming or outgoing point
  35. bool incoming;
  36. bool blocked;
  37. bool included;
  38. inline angle_info()
  39. : blocked(false)
  40. , included(false)
  41. {}
  42. };
  43. template <typename AngleInfo>
  44. class occupation_info
  45. {
  46. public :
  47. typedef std::vector<AngleInfo> collection_type;
  48. std::size_t count;
  49. inline occupation_info()
  50. : count(0)
  51. {}
  52. template <typename RobustPoint>
  53. inline void add(RobustPoint const& incoming_point,
  54. RobustPoint const& outgoing_point,
  55. RobustPoint const& intersection_point,
  56. std::size_t turn_index, int operation_index,
  57. segment_identifier const& seg_id)
  58. {
  59. geometry::equal_to<RobustPoint> comparator;
  60. if (comparator(incoming_point, intersection_point))
  61. {
  62. return;
  63. }
  64. if (comparator(outgoing_point, intersection_point))
  65. {
  66. return;
  67. }
  68. AngleInfo info;
  69. info.seg_id = seg_id;
  70. info.turn_index = turn_index;
  71. info.operation_index = operation_index;
  72. info.intersection_point = intersection_point;
  73. {
  74. info.point = incoming_point;
  75. info.incoming = true;
  76. m_angles.push_back(info);
  77. }
  78. {
  79. info.point = outgoing_point;
  80. info.incoming = false;
  81. m_angles.push_back(info);
  82. }
  83. }
  84. template <typename RobustPoint, typename Turns, typename SideStrategy>
  85. inline void get_left_turns(RobustPoint const& origin, Turns& turns,
  86. SideStrategy const& strategy)
  87. {
  88. typedef detail::left_turns::angle_less
  89. <
  90. typename AngleInfo::point_type,
  91. SideStrategy
  92. > angle_less;
  93. // Sort on angle
  94. std::sort(m_angles.begin(), m_angles.end(), angle_less(origin, strategy));
  95. // Group same-angled elements
  96. std::size_t cluster_size = detail::left_turns::assign_cluster_indices(m_angles, origin);
  97. // Block all turns on the right side of any turn
  98. detail::left_turns::block_turns(m_angles, cluster_size);
  99. detail::left_turns::get_left_turns(m_angles, turns);
  100. }
  101. #if defined(BOOST_GEOMETRY_BUFFER_ENLARGED_CLUSTERS)
  102. template <typename RobustPoint>
  103. inline bool has_rounding_issues(RobustPoint const& origin) const
  104. {
  105. return detail::left_turns::has_rounding_issues(angles, origin);
  106. }
  107. #endif
  108. private :
  109. collection_type m_angles; // each turn splitted in incoming/outgoing vectors
  110. };
  111. template<typename Pieces>
  112. inline void move_index(Pieces const& pieces, signed_size_type& index, signed_size_type& piece_index, int direction)
  113. {
  114. BOOST_GEOMETRY_ASSERT(direction == 1 || direction == -1);
  115. BOOST_GEOMETRY_ASSERT(
  116. piece_index >= 0
  117. && piece_index < static_cast<signed_size_type>(boost::size(pieces)) );
  118. BOOST_GEOMETRY_ASSERT(
  119. index >= 0
  120. && index < static_cast<signed_size_type>(boost::size(pieces[piece_index].robust_ring)));
  121. // NOTE: both index and piece_index must be in valid range
  122. // this means that then they could be of type std::size_t
  123. // if the code below was refactored
  124. index += direction;
  125. if (direction == -1 && index < 0)
  126. {
  127. piece_index--;
  128. if (piece_index < 0)
  129. {
  130. piece_index = boost::size(pieces) - 1;
  131. }
  132. index = boost::size(pieces[piece_index].robust_ring) - 1;
  133. }
  134. if (direction == 1
  135. && index >= static_cast<signed_size_type>(boost::size(pieces[piece_index].robust_ring)))
  136. {
  137. piece_index++;
  138. if (piece_index >= static_cast<signed_size_type>(boost::size(pieces)))
  139. {
  140. piece_index = 0;
  141. }
  142. index = 0;
  143. }
  144. }
  145. template
  146. <
  147. typename RobustPoint,
  148. typename Turn,
  149. typename Pieces,
  150. typename Info
  151. >
  152. inline void add_incoming_and_outgoing_angles(
  153. RobustPoint const& intersection_point, // rescaled
  154. Turn const& turn,
  155. Pieces const& pieces, // using rescaled offsets of it
  156. int operation_index,
  157. segment_identifier seg_id,
  158. Info& info)
  159. {
  160. segment_identifier real_seg_id = seg_id;
  161. geometry::equal_to<RobustPoint> comparator;
  162. // Move backward and forward
  163. RobustPoint direction_points[2];
  164. for (int i = 0; i < 2; i++)
  165. {
  166. signed_size_type index = turn.operations[operation_index].index_in_robust_ring;
  167. signed_size_type piece_index = turn.operations[operation_index].piece_index;
  168. while(comparator(pieces[piece_index].robust_ring[index], intersection_point))
  169. {
  170. move_index(pieces, index, piece_index, i == 0 ? -1 : 1);
  171. }
  172. direction_points[i] = pieces[piece_index].robust_ring[index];
  173. }
  174. info.add(direction_points[0], direction_points[1], intersection_point,
  175. turn.turn_index, operation_index, real_seg_id);
  176. }
  177. } // namespace detail
  178. #endif // DOXYGEN_NO_DETAIL
  179. }} // namespace boost::geometry
  180. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OCCUPATION_INFO_HPP