range.hpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2015 Barend Gehrels, Amsterdam, the Netherlands.
  3. // Copyright (c) 2008-2015 Bruno Lalande, Paris, France.
  4. // Copyright (c) 2009-2015 Mateusz Loskot, London, UK.
  5. // This file was modified by Oracle on 2015, 2016.
  6. // Modifications copyright (c) 2015-2016, Oracle and/or its affiliates.
  7. // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
  8. // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
  9. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
  10. // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
  11. // Distributed under the Boost Software License, Version 1.0.
  12. // (See accompanying file LICENSE_1_0.txt or copy at
  13. // http://www.boost.org/LICENSE_1_0.txt)
  14. #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_HPP
  15. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_HPP
  16. #include <iterator>
  17. #include <vector>
  18. #include <boost/range.hpp>
  19. #include <boost/geometry/core/coordinate_dimension.hpp>
  20. #include <boost/geometry/util/range.hpp>
  21. #include <boost/geometry/algorithms/is_empty.hpp>
  22. #include <boost/geometry/algorithms/detail/envelope/initialize.hpp>
  23. #include <boost/geometry/algorithms/detail/envelope/range_of_boxes.hpp>
  24. #include <boost/geometry/algorithms/detail/expand/box.hpp>
  25. #include <boost/geometry/algorithms/detail/expand/point.hpp>
  26. #include <boost/geometry/algorithms/detail/expand/segment.hpp>
  27. #include <boost/geometry/algorithms/dispatch/envelope.hpp>
  28. namespace boost { namespace geometry
  29. {
  30. #ifndef DOXYGEN_NO_DETAIL
  31. namespace detail { namespace envelope
  32. {
  33. // implementation for simple ranges
  34. struct envelope_range
  35. {
  36. template <typename Iterator, typename Box, typename Strategy>
  37. static inline void apply(Iterator first,
  38. Iterator last,
  39. Box& mbr,
  40. Strategy const& strategy)
  41. {
  42. typedef typename std::iterator_traits<Iterator>::value_type value_type;
  43. // initialize MBR
  44. initialize<Box, 0, dimension<Box>::value>::apply(mbr);
  45. Iterator it = first;
  46. if (it != last)
  47. {
  48. // initialize box with first element in range
  49. dispatch::envelope<value_type>::apply(*it, mbr, strategy);
  50. // consider now the remaining elements in the range (if any)
  51. for (++it; it != last; ++it)
  52. {
  53. dispatch::expand<Box, value_type>::apply(mbr, *it, strategy);
  54. }
  55. }
  56. }
  57. template <typename Range, typename Box, typename Strategy>
  58. static inline void apply(Range const& range, Box& mbr, Strategy const& strategy)
  59. {
  60. return apply(boost::begin(range), boost::end(range), mbr, strategy);
  61. }
  62. };
  63. // implementation for multi-ranges
  64. template <typename EnvelopePolicy>
  65. struct envelope_multi_range
  66. {
  67. template <typename MultiRange, typename Box, typename Strategy>
  68. static inline void apply(MultiRange const& multirange,
  69. Box& mbr,
  70. Strategy const& strategy)
  71. {
  72. typedef typename boost::range_iterator
  73. <
  74. MultiRange const
  75. >::type iterator_type;
  76. bool initialized = false;
  77. for (iterator_type it = boost::begin(multirange);
  78. it != boost::end(multirange);
  79. ++it)
  80. {
  81. if (! geometry::is_empty(*it))
  82. {
  83. if (initialized)
  84. {
  85. Box helper_mbr;
  86. EnvelopePolicy::apply(*it, helper_mbr, strategy);
  87. dispatch::expand<Box, Box>::apply(mbr, helper_mbr, strategy);
  88. }
  89. else
  90. {
  91. // compute the initial envelope
  92. EnvelopePolicy::apply(*it, mbr, strategy);
  93. initialized = true;
  94. }
  95. }
  96. }
  97. if (! initialized)
  98. {
  99. // if not already initialized, initialize MBR
  100. initialize<Box, 0, dimension<Box>::value>::apply(mbr);
  101. }
  102. }
  103. };
  104. // implementation for multi-range on a spheroid (longitude is periodic)
  105. template <typename EnvelopePolicy>
  106. struct envelope_multi_range_on_spheroid
  107. {
  108. template <typename MultiRange, typename Box, typename Strategy>
  109. static inline void apply(MultiRange const& multirange,
  110. Box& mbr,
  111. Strategy const& strategy)
  112. {
  113. typedef typename boost::range_iterator
  114. <
  115. MultiRange const
  116. >::type iterator_type;
  117. // due to the periodicity of longitudes we need to compute the boxes
  118. // of all the single geometries and keep them in a container
  119. std::vector<Box> boxes;
  120. for (iterator_type it = boost::begin(multirange);
  121. it != boost::end(multirange);
  122. ++it)
  123. {
  124. if (! geometry::is_empty(*it))
  125. {
  126. Box helper_box;
  127. EnvelopePolicy::apply(*it, helper_box, strategy);
  128. boxes.push_back(helper_box);
  129. }
  130. }
  131. // now we need to compute the envelope of the range of boxes
  132. // (cannot be done in an incremental fashion as in the
  133. // Cartesian coordinate system)
  134. // if all single geometries are empty no boxes have been found
  135. // and the MBR is simply initialized
  136. if (! boxes.empty())
  137. {
  138. envelope_range_of_boxes::apply(boxes, mbr, strategy);
  139. }
  140. else
  141. {
  142. initialize<Box, 0, dimension<Box>::value>::apply(mbr);
  143. }
  144. }
  145. };
  146. }} // namespace detail::envelope
  147. #endif // DOXYGEN_NO_DETAIL
  148. }} // namespace boost::geometry
  149. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_ENVELOPE_RANGE_HPP