buffer.hpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. // Boost.Geometry (aka GGL, Generic Geometry Library)
  2. // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
  3. // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
  4. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
  5. // This file was modified by Oracle on 2017.
  6. // Modifications copyright (c) 2017 Oracle and/or its affiliates.
  7. // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
  8. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
  9. // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
  10. // Use, modification and distribution is subject to the Boost Software License,
  11. // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  12. // http://www.boost.org/LICENSE_1_0.txt)
  13. #ifndef BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP
  14. #define BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP
  15. #include <cstddef>
  16. #include <boost/numeric/conversion/cast.hpp>
  17. #include <boost/range.hpp>
  18. #include <boost/variant/apply_visitor.hpp>
  19. #include <boost/variant/static_visitor.hpp>
  20. #include <boost/variant/variant_fwd.hpp>
  21. #include <boost/geometry/algorithms/clear.hpp>
  22. #include <boost/geometry/algorithms/envelope.hpp>
  23. #include <boost/geometry/algorithms/is_empty.hpp>
  24. #include <boost/geometry/algorithms/not_implemented.hpp>
  25. #include <boost/geometry/arithmetic/arithmetic.hpp>
  26. #include <boost/geometry/geometries/concepts/check.hpp>
  27. #include <boost/geometry/geometries/box.hpp>
  28. #include <boost/geometry/util/math.hpp>
  29. #include <boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp>
  30. namespace boost { namespace geometry
  31. {
  32. #ifndef DOXYGEN_NO_DETAIL
  33. namespace detail { namespace buffer
  34. {
  35. template <typename BoxIn, typename BoxOut, typename T, std::size_t C, std::size_t D, std::size_t N>
  36. struct box_loop
  37. {
  38. typedef typename coordinate_type<BoxOut>::type coordinate_type;
  39. static inline void apply(BoxIn const& box_in, T const& distance, BoxOut& box_out)
  40. {
  41. coordinate_type d = distance;
  42. set<C, D>(box_out, get<C, D>(box_in) + d);
  43. box_loop<BoxIn, BoxOut, T, C, D + 1, N>::apply(box_in, distance, box_out);
  44. }
  45. };
  46. template <typename BoxIn, typename BoxOut, typename T, std::size_t C, std::size_t N>
  47. struct box_loop<BoxIn, BoxOut, T, C, N, N>
  48. {
  49. static inline void apply(BoxIn const&, T const&, BoxOut&) {}
  50. };
  51. // Extends a box with the same amount in all directions
  52. template<typename BoxIn, typename BoxOut, typename T>
  53. inline void buffer_box(BoxIn const& box_in, T const& distance, BoxOut& box_out)
  54. {
  55. assert_dimension_equal<BoxIn, BoxOut>();
  56. static const std::size_t N = dimension<BoxIn>::value;
  57. box_loop<BoxIn, BoxOut, T, min_corner, 0, N>::apply(box_in, -distance, box_out);
  58. box_loop<BoxIn, BoxOut, T, max_corner, 0, N>::apply(box_in, distance, box_out);
  59. }
  60. }} // namespace detail::buffer
  61. #endif // DOXYGEN_NO_DETAIL
  62. #ifndef DOXYGEN_NO_DISPATCH
  63. namespace dispatch
  64. {
  65. template
  66. <
  67. typename Input,
  68. typename Output,
  69. typename TagIn = typename tag<Input>::type,
  70. typename TagOut = typename tag<Output>::type
  71. >
  72. struct buffer: not_implemented<TagIn, TagOut>
  73. {};
  74. template <typename BoxIn, typename BoxOut>
  75. struct buffer<BoxIn, BoxOut, box_tag, box_tag>
  76. {
  77. template <typename Distance>
  78. static inline void apply(BoxIn const& box_in, Distance const& distance,
  79. Distance const& , BoxOut& box_out)
  80. {
  81. detail::buffer::buffer_box(box_in, distance, box_out);
  82. }
  83. };
  84. } // namespace dispatch
  85. #endif // DOXYGEN_NO_DISPATCH
  86. namespace resolve_variant {
  87. template <typename Geometry>
  88. struct buffer
  89. {
  90. template <typename Distance, typename GeometryOut>
  91. static inline void apply(Geometry const& geometry,
  92. Distance const& distance,
  93. Distance const& chord_length,
  94. GeometryOut& out)
  95. {
  96. dispatch::buffer<Geometry, GeometryOut>::apply(geometry, distance, chord_length, out);
  97. }
  98. };
  99. template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
  100. struct buffer<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
  101. {
  102. template <typename Distance, typename GeometryOut>
  103. struct visitor: boost::static_visitor<void>
  104. {
  105. Distance const& m_distance;
  106. Distance const& m_chord_length;
  107. GeometryOut& m_out;
  108. visitor(Distance const& distance,
  109. Distance const& chord_length,
  110. GeometryOut& out)
  111. : m_distance(distance),
  112. m_chord_length(chord_length),
  113. m_out(out)
  114. {}
  115. template <typename Geometry>
  116. void operator()(Geometry const& geometry) const
  117. {
  118. buffer<Geometry>::apply(geometry, m_distance, m_chord_length, m_out);
  119. }
  120. };
  121. template <typename Distance, typename GeometryOut>
  122. static inline void apply(
  123. boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
  124. Distance const& distance,
  125. Distance const& chord_length,
  126. GeometryOut& out
  127. )
  128. {
  129. boost::apply_visitor(visitor<Distance, GeometryOut>(distance, chord_length, out), geometry);
  130. }
  131. };
  132. } // namespace resolve_variant
  133. /*!
  134. \brief \brief_calc{buffer}
  135. \ingroup buffer
  136. \details \details_calc{buffer, \det_buffer}.
  137. \tparam Input \tparam_geometry
  138. \tparam Output \tparam_geometry
  139. \tparam Distance \tparam_numeric
  140. \param geometry_in \param_geometry
  141. \param geometry_out \param_geometry
  142. \param distance The distance to be used for the buffer
  143. \param chord_length (optional) The length of the chord's in the generated arcs around points or bends
  144. \qbk{[include reference/algorithms/buffer.qbk]}
  145. */
  146. template <typename Input, typename Output, typename Distance>
  147. inline void buffer(Input const& geometry_in, Output& geometry_out,
  148. Distance const& distance, Distance const& chord_length = -1)
  149. {
  150. concepts::check<Input const>();
  151. concepts::check<Output>();
  152. resolve_variant::buffer<Input>::apply(geometry_in, distance, chord_length, geometry_out);
  153. }
  154. /*!
  155. \brief \brief_calc{buffer}
  156. \ingroup buffer
  157. \details \details_calc{return_buffer, \det_buffer}. \details_return{buffer}.
  158. \tparam Input \tparam_geometry
  159. \tparam Output \tparam_geometry
  160. \tparam Distance \tparam_numeric
  161. \param geometry \param_geometry
  162. \param distance The distance to be used for the buffer
  163. \param chord_length (optional) The length of the chord's in the generated arcs
  164. around points or bends (RESERVED, NOT YET USED)
  165. \return \return_calc{buffer}
  166. */
  167. template <typename Output, typename Input, typename Distance>
  168. Output return_buffer(Input const& geometry, Distance const& distance, Distance const& chord_length = -1)
  169. {
  170. concepts::check<Input const>();
  171. concepts::check<Output>();
  172. Output geometry_out;
  173. resolve_variant::buffer<Input>::apply(geometry, distance, chord_length, geometry_out);
  174. return geometry_out;
  175. }
  176. /*!
  177. \brief \brief_calc{buffer}
  178. \ingroup buffer
  179. \details \details_calc{buffer, \det_buffer}.
  180. \tparam GeometryIn \tparam_geometry
  181. \tparam MultiPolygon \tparam_geometry{MultiPolygon}
  182. \tparam DistanceStrategy A strategy defining distance (or radius)
  183. \tparam SideStrategy A strategy defining creation along sides
  184. \tparam JoinStrategy A strategy defining creation around convex corners
  185. \tparam EndStrategy A strategy defining creation at linestring ends
  186. \tparam PointStrategy A strategy defining creation around points
  187. \param geometry_in \param_geometry
  188. \param geometry_out output multi polygon (or std:: collection of polygons),
  189. will contain a buffered version of the input geometry
  190. \param distance_strategy The distance strategy to be used
  191. \param side_strategy The side strategy to be used
  192. \param join_strategy The join strategy to be used
  193. \param end_strategy The end strategy to be used
  194. \param point_strategy The point strategy to be used
  195. \qbk{distinguish,with strategies}
  196. \qbk{[include reference/algorithms/buffer_with_strategies.qbk]}
  197. */
  198. template
  199. <
  200. typename GeometryIn,
  201. typename MultiPolygon,
  202. typename DistanceStrategy,
  203. typename SideStrategy,
  204. typename JoinStrategy,
  205. typename EndStrategy,
  206. typename PointStrategy
  207. >
  208. inline void buffer(GeometryIn const& geometry_in,
  209. MultiPolygon& geometry_out,
  210. DistanceStrategy const& distance_strategy,
  211. SideStrategy const& side_strategy,
  212. JoinStrategy const& join_strategy,
  213. EndStrategy const& end_strategy,
  214. PointStrategy const& point_strategy)
  215. {
  216. typedef typename boost::range_value<MultiPolygon>::type polygon_type;
  217. concepts::check<GeometryIn const>();
  218. concepts::check<polygon_type>();
  219. typedef typename point_type<GeometryIn>::type point_type;
  220. typedef typename rescale_policy_type<point_type>::type rescale_policy_type;
  221. geometry_out.clear();
  222. if (geometry::is_empty(geometry_in))
  223. {
  224. // Then output geometry is kept empty as well
  225. return;
  226. }
  227. model::box<point_type> box;
  228. geometry::envelope(geometry_in, box);
  229. geometry::buffer(box, box, distance_strategy.max_distance(join_strategy, end_strategy));
  230. typename strategy::intersection::services::default_strategy
  231. <
  232. typename cs_tag<GeometryIn>::type
  233. >::type intersection_strategy;
  234. rescale_policy_type rescale_policy
  235. = boost::geometry::get_rescale_policy<rescale_policy_type>(box);
  236. detail::buffer::buffer_inserter<polygon_type>(geometry_in, range::back_inserter(geometry_out),
  237. distance_strategy,
  238. side_strategy,
  239. join_strategy,
  240. end_strategy,
  241. point_strategy,
  242. intersection_strategy,
  243. rescale_policy);
  244. }
  245. }} // namespace boost::geometry
  246. #endif // BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP