add_rings.hpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
  3. // Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
  4. // This file was modified by Oracle on 2017.
  5. // Modifications copyright (c) 2017, Oracle and/or its affiliates.
  6. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  7. // Use, modification and distribution is subject to the Boost Software License,
  8. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  9. // http://www.boost.org/LICENSE_1_0.txt)
  10. #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ADD_RINGS_HPP
  11. #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ADD_RINGS_HPP
  12. #include <boost/range.hpp>
  13. #include <boost/throw_exception.hpp>
  14. #include <boost/geometry/core/closure.hpp>
  15. #include <boost/geometry/core/exception.hpp>
  16. #include <boost/geometry/algorithms/area.hpp>
  17. #include <boost/geometry/algorithms/detail/overlay/convert_ring.hpp>
  18. #include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
  19. namespace boost { namespace geometry
  20. {
  21. #ifndef DOXYGEN_NO_DETAIL
  22. namespace detail { namespace overlay
  23. {
  24. template
  25. <
  26. typename GeometryOut,
  27. typename Geometry1,
  28. typename Geometry2,
  29. typename RingCollection
  30. >
  31. inline void convert_and_add(GeometryOut& result,
  32. Geometry1 const& geometry1, Geometry2 const& geometry2,
  33. RingCollection const& collection,
  34. ring_identifier id,
  35. bool reversed, bool append)
  36. {
  37. typedef typename geometry::tag<Geometry1>::type tag1;
  38. typedef typename geometry::tag<Geometry2>::type tag2;
  39. typedef typename geometry::tag<GeometryOut>::type tag_out;
  40. if (id.source_index == 0)
  41. {
  42. convert_ring<tag_out>::apply(result,
  43. get_ring<tag1>::apply(id, geometry1),
  44. append, reversed);
  45. }
  46. else if (id.source_index == 1)
  47. {
  48. convert_ring<tag_out>::apply(result,
  49. get_ring<tag2>::apply(id, geometry2),
  50. append, reversed);
  51. }
  52. else if (id.source_index == 2)
  53. {
  54. convert_ring<tag_out>::apply(result,
  55. get_ring<void>::apply(id, collection),
  56. append, reversed);
  57. }
  58. }
  59. enum add_rings_error_handling
  60. {
  61. add_rings_ignore_unordered,
  62. add_rings_add_unordered,
  63. add_rings_throw_if_reversed
  64. };
  65. template
  66. <
  67. typename GeometryOut,
  68. typename SelectionMap,
  69. typename Geometry1,
  70. typename Geometry2,
  71. typename RingCollection,
  72. typename OutputIterator,
  73. typename AreaStrategy
  74. >
  75. inline OutputIterator add_rings(SelectionMap const& map,
  76. Geometry1 const& geometry1, Geometry2 const& geometry2,
  77. RingCollection const& collection,
  78. OutputIterator out,
  79. AreaStrategy const& area_strategy,
  80. add_rings_error_handling error_handling = add_rings_ignore_unordered)
  81. {
  82. typedef typename SelectionMap::const_iterator iterator;
  83. typedef typename AreaStrategy::template result_type
  84. <
  85. GeometryOut
  86. >::type area_type;
  87. area_type const zero = 0;
  88. std::size_t const min_num_points = core_detail::closure::minimum_ring_size
  89. <
  90. geometry::closure
  91. <
  92. typename boost::range_value
  93. <
  94. RingCollection const
  95. >::type
  96. >::value
  97. >::value;
  98. for (iterator it = boost::begin(map);
  99. it != boost::end(map);
  100. ++it)
  101. {
  102. if (! it->second.discarded
  103. && it->second.parent.source_index == -1)
  104. {
  105. GeometryOut result;
  106. convert_and_add(result, geometry1, geometry2, collection,
  107. it->first, it->second.reversed, false);
  108. // Add children
  109. for (typename std::vector<ring_identifier>::const_iterator child_it
  110. = it->second.children.begin();
  111. child_it != it->second.children.end();
  112. ++child_it)
  113. {
  114. iterator mit = map.find(*child_it);
  115. if (mit != map.end()
  116. && ! mit->second.discarded)
  117. {
  118. convert_and_add(result, geometry1, geometry2, collection,
  119. *child_it, mit->second.reversed, true);
  120. }
  121. }
  122. // Only add rings if they satisfy minimal requirements.
  123. // This cannot be done earlier (during traversal), not
  124. // everything is figured out yet (sum of positive/negative rings)
  125. if (geometry::num_points(result) >= min_num_points)
  126. {
  127. area_type const area = geometry::area(result, area_strategy);
  128. // Ignore if area is 0
  129. if (! math::equals(area, zero))
  130. {
  131. if (error_handling == add_rings_add_unordered
  132. || area > zero)
  133. {
  134. *out++ = result;
  135. }
  136. else if (error_handling == add_rings_throw_if_reversed)
  137. {
  138. BOOST_THROW_EXCEPTION(invalid_output_exception());
  139. }
  140. }
  141. }
  142. }
  143. }
  144. return out;
  145. }
  146. template
  147. <
  148. typename GeometryOut,
  149. typename SelectionMap,
  150. typename Geometry,
  151. typename RingCollection,
  152. typename OutputIterator,
  153. typename AreaStrategy
  154. >
  155. inline OutputIterator add_rings(SelectionMap const& map,
  156. Geometry const& geometry,
  157. RingCollection const& collection,
  158. OutputIterator out,
  159. AreaStrategy const& area_strategy)
  160. {
  161. Geometry empty;
  162. return add_rings<GeometryOut>(map, geometry, empty, collection, out, area_strategy);
  163. }
  164. }} // namespace detail::overlay
  165. #endif // DOXYGEN_NO_DETAIL
  166. }} // namespace geometry
  167. #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_ADD_RINGS_HPP