max_interval_gap.hpp 8.2 KB

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