max_interval_gap.hpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2015-2020, Oracle and/or its affiliates.
  3. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
  4. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  5. // Licensed under the Boost Software License version 1.0.
  6. // http://www.boost.org/users/license.html
  7. #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_MAX_INTERVAL_GAP_HPP
  8. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_MAX_INTERVAL_GAP_HPP
  9. #include <cstddef>
  10. #include <functional>
  11. #include <queue>
  12. #include <utility>
  13. #include <vector>
  14. #include <boost/range/begin.hpp>
  15. #include <boost/range/end.hpp>
  16. #include <boost/range/value_type.hpp>
  17. #include <boost/geometry/core/assert.hpp>
  18. #include <boost/geometry/util/math.hpp>
  19. #include <boost/geometry/algorithms/detail/sweep.hpp>
  20. namespace boost { namespace geometry
  21. {
  22. #ifndef DOXYGEN_NO_DETAIL
  23. namespace detail { namespace max_interval_gap
  24. {
  25. // the class Interval must provide the following:
  26. // * must define the type value_type
  27. // * must define the type difference_type
  28. // * must have the methods:
  29. // value_type get<Index>() const
  30. // difference_type length() const
  31. // where an Index value of 0 (resp., 1) refers to the left (resp.,
  32. // right) endpoint of the interval
  33. template <typename Interval>
  34. class sweep_event
  35. {
  36. public:
  37. typedef Interval interval_type;
  38. typedef typename Interval::value_type time_type;
  39. sweep_event(Interval const& interval, bool start_event = true)
  40. : m_interval(std::cref(interval))
  41. , m_start_event(start_event)
  42. {}
  43. inline bool is_start_event() const
  44. {
  45. return m_start_event;
  46. }
  47. inline interval_type const& interval() const
  48. {
  49. return m_interval;
  50. }
  51. inline time_type time() const
  52. {
  53. return (m_start_event)
  54. ? interval().template get<0>()
  55. : interval().template get<1>();
  56. }
  57. inline bool operator<(sweep_event const& other) const
  58. {
  59. if (! math::equals(time(), other.time()))
  60. {
  61. return time() < other.time();
  62. }
  63. // a start-event is before an end-event with the same event time
  64. return is_start_event() && ! other.is_start_event();
  65. }
  66. private:
  67. std::reference_wrapper<Interval const> m_interval;
  68. bool m_start_event;
  69. };
  70. template <typename Event>
  71. struct event_greater
  72. {
  73. inline bool operator()(Event const& event1, Event const& event2) const
  74. {
  75. return event2 < event1;
  76. }
  77. };
  78. struct initialization_visitor
  79. {
  80. template <typename Range, typename PriorityQueue, typename EventVisitor>
  81. static inline void apply(Range const& range,
  82. PriorityQueue& queue,
  83. EventVisitor&)
  84. {
  85. BOOST_GEOMETRY_ASSERT(queue.empty());
  86. // it is faster to build the queue directly from the entire
  87. // range, rather than insert elements one after the other
  88. PriorityQueue pq(boost::begin(range), boost::end(range));
  89. std::swap(pq, queue);
  90. }
  91. };
  92. template <typename Event>
  93. class event_visitor
  94. {
  95. typedef typename Event::time_type event_time_type;
  96. typedef typename Event::interval_type::difference_type difference_type;
  97. public:
  98. event_visitor()
  99. : m_overlap_count(0)
  100. , m_max_gap_left(0)
  101. , m_max_gap_right(0)
  102. {}
  103. template <typename PriorityQueue>
  104. inline void apply(Event const& event, PriorityQueue& queue)
  105. {
  106. if (event.is_start_event())
  107. {
  108. ++m_overlap_count;
  109. queue.push(Event(event.interval(), false));
  110. }
  111. else
  112. {
  113. --m_overlap_count;
  114. if (m_overlap_count == 0 && ! queue.empty())
  115. {
  116. // we may have a gap
  117. BOOST_GEOMETRY_ASSERT(queue.top().is_start_event());
  118. event_time_type next_event_time
  119. = queue.top().interval().template get<0>();
  120. difference_type gap = next_event_time - event.time();
  121. if (gap > max_gap())
  122. {
  123. m_max_gap_left = event.time();
  124. m_max_gap_right = next_event_time;
  125. }
  126. }
  127. }
  128. }
  129. event_time_type const& max_gap_left() const
  130. {
  131. return m_max_gap_left;
  132. }
  133. event_time_type const& max_gap_right() const
  134. {
  135. return m_max_gap_right;
  136. }
  137. difference_type max_gap() const
  138. {
  139. return m_max_gap_right - m_max_gap_left;
  140. }
  141. private:
  142. std::size_t m_overlap_count;
  143. event_time_type m_max_gap_left, m_max_gap_right;
  144. };
  145. }} // namespace detail::max_interval_gap
  146. #endif // DOXYGEN_NO_DETAIL
  147. // Given a range of intervals I1, I2, ..., In, maximum_gap() returns
  148. // the maximum length of an interval M that satisfies the following
  149. // properties:
  150. //
  151. // 1. M.left >= min(I1, I2, ..., In)
  152. // 2. M.right <= max(I1, I2, ..., In)
  153. // 3. intersection(interior(M), Ik) is the empty set for all k=1, ..., n
  154. // 4. length(M) is maximal
  155. //
  156. // where M.left and M.right denote the left and right extreme values
  157. // for the interval M, and length(M) is equal to M.right - M.left.
  158. //
  159. // If M does not exist (or, alternatively, M is identified as the
  160. // empty set), 0 is returned.
  161. //
  162. // The algorithm proceeds for performing a sweep: the left endpoints
  163. // are inserted into a min-priority queue with the priority being the
  164. // value of the endpoint. The sweep algorithm maintains an "overlap
  165. // counter" that counts the number of overlaping intervals at any
  166. // specific sweep-time value.
  167. // There are two types of events encountered during the sweep:
  168. // (a) a start event: the left endpoint of an interval is found.
  169. // In this case the overlap count is increased by one and the
  170. // right endpoint of the interval in inserted into the event queue
  171. // (b) an end event: the right endpoint of an interval is found.
  172. // In this case the overlap count is decreased by one. If the
  173. // updated overlap count is 0, then we could expect to have a gap
  174. // in-between intervals. This gap is measured as the (absolute)
  175. // distance of the current interval right endpoint (being
  176. // processed) to the upcoming left endpoint of the next interval
  177. // to be processed (if such an interval exists). If the measured
  178. // gap is greater than the current maximum gap, it is recorded.
  179. // The initial maximum gap is initialized to 0. This value is returned
  180. // if no gap is found during the sweeping procedure.
  181. template <typename RangeOfIntervals, typename T>
  182. inline typename boost::range_value<RangeOfIntervals>::type::difference_type
  183. maximum_gap(RangeOfIntervals const& range_of_intervals,
  184. T& max_gap_left, T& max_gap_right)
  185. {
  186. typedef typename boost::range_value<RangeOfIntervals>::type interval_type;
  187. typedef detail::max_interval_gap::sweep_event<interval_type> event_type;
  188. // create a min-priority queue for the events
  189. std::priority_queue
  190. <
  191. event_type,
  192. std::vector<event_type>,
  193. detail::max_interval_gap::event_greater<event_type>
  194. > queue;
  195. // define initialization and event-process visitors
  196. detail::max_interval_gap::initialization_visitor init_visitor;
  197. detail::max_interval_gap::event_visitor<event_type> sweep_visitor;
  198. // perform the sweep
  199. geometry::sweep(range_of_intervals,
  200. queue,
  201. init_visitor,
  202. sweep_visitor);
  203. max_gap_left = sweep_visitor.max_gap_left();
  204. max_gap_right = sweep_visitor.max_gap_right();
  205. return sweep_visitor.max_gap();
  206. }
  207. template <typename RangeOfIntervals>
  208. inline typename boost::range_value<RangeOfIntervals>::type::difference_type
  209. maximum_gap(RangeOfIntervals const& range_of_intervals)
  210. {
  211. typedef typename boost::range_value<RangeOfIntervals>::type interval_type;
  212. typename interval_type::value_type left, right;
  213. return maximum_gap(range_of_intervals, left, right);
  214. }
  215. }} // namespace boost::geometry
  216. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_MAX_INTERVAL_GAP_HPP