buffer.hpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  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, 2019.
  6. // Modifications copyright (c) 2017, 2019 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_box.hpp>
  30. #include <boost/geometry/algorithms/detail/buffer/buffer_inserter.hpp>
  31. namespace boost { namespace geometry
  32. {
  33. #ifndef DOXYGEN_NO_DISPATCH
  34. namespace dispatch
  35. {
  36. template
  37. <
  38. typename Input,
  39. typename Output,
  40. typename TagIn = typename tag<Input>::type,
  41. typename TagOut = typename tag<Output>::type
  42. >
  43. struct buffer: not_implemented<TagIn, TagOut>
  44. {};
  45. template <typename BoxIn, typename BoxOut>
  46. struct buffer<BoxIn, BoxOut, box_tag, box_tag>
  47. {
  48. template <typename Distance>
  49. static inline void apply(BoxIn const& box_in, Distance const& distance,
  50. Distance const& , BoxOut& box_out)
  51. {
  52. detail::buffer::buffer_box(box_in, distance, box_out);
  53. }
  54. };
  55. } // namespace dispatch
  56. #endif // DOXYGEN_NO_DISPATCH
  57. namespace resolve_variant {
  58. template <typename Geometry>
  59. struct buffer
  60. {
  61. template <typename Distance, typename GeometryOut>
  62. static inline void apply(Geometry const& geometry,
  63. Distance const& distance,
  64. Distance const& chord_length,
  65. GeometryOut& out)
  66. {
  67. dispatch::buffer<Geometry, GeometryOut>::apply(geometry, distance, chord_length, out);
  68. }
  69. };
  70. template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
  71. struct buffer<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
  72. {
  73. template <typename Distance, typename GeometryOut>
  74. struct visitor: boost::static_visitor<void>
  75. {
  76. Distance const& m_distance;
  77. Distance const& m_chord_length;
  78. GeometryOut& m_out;
  79. visitor(Distance const& distance,
  80. Distance const& chord_length,
  81. GeometryOut& out)
  82. : m_distance(distance),
  83. m_chord_length(chord_length),
  84. m_out(out)
  85. {}
  86. template <typename Geometry>
  87. void operator()(Geometry const& geometry) const
  88. {
  89. buffer<Geometry>::apply(geometry, m_distance, m_chord_length, m_out);
  90. }
  91. };
  92. template <typename Distance, typename GeometryOut>
  93. static inline void apply(
  94. boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
  95. Distance const& distance,
  96. Distance const& chord_length,
  97. GeometryOut& out
  98. )
  99. {
  100. boost::apply_visitor(visitor<Distance, GeometryOut>(distance, chord_length, out), geometry);
  101. }
  102. };
  103. } // namespace resolve_variant
  104. /*!
  105. \brief \brief_calc{buffer}
  106. \ingroup buffer
  107. \details \details_calc{buffer, \det_buffer}.
  108. \tparam Input \tparam_geometry
  109. \tparam Output \tparam_geometry
  110. \tparam Distance \tparam_numeric
  111. \param geometry_in \param_geometry
  112. \param geometry_out \param_geometry
  113. \param distance The distance to be used for the buffer
  114. \param chord_length (optional) The length of the chord's in the generated arcs around points or bends
  115. \qbk{[include reference/algorithms/buffer.qbk]}
  116. */
  117. template <typename Input, typename Output, typename Distance>
  118. inline void buffer(Input const& geometry_in, Output& geometry_out,
  119. Distance const& distance, Distance const& chord_length = -1)
  120. {
  121. concepts::check<Input const>();
  122. concepts::check<Output>();
  123. resolve_variant::buffer<Input>::apply(geometry_in, distance, chord_length, geometry_out);
  124. }
  125. /*!
  126. \brief \brief_calc{buffer}
  127. \ingroup buffer
  128. \details \details_calc{return_buffer, \det_buffer}. \details_return{buffer}.
  129. \tparam Input \tparam_geometry
  130. \tparam Output \tparam_geometry
  131. \tparam Distance \tparam_numeric
  132. \param geometry \param_geometry
  133. \param distance The distance to be used for the buffer
  134. \param chord_length (optional) The length of the chord's in the generated arcs
  135. around points or bends (RESERVED, NOT YET USED)
  136. \return \return_calc{buffer}
  137. */
  138. template <typename Output, typename Input, typename Distance>
  139. Output return_buffer(Input const& geometry, Distance const& distance, Distance const& chord_length = -1)
  140. {
  141. concepts::check<Input const>();
  142. concepts::check<Output>();
  143. Output geometry_out;
  144. resolve_variant::buffer<Input>::apply(geometry, distance, chord_length, geometry_out);
  145. return geometry_out;
  146. }
  147. /*!
  148. \brief \brief_calc{buffer}
  149. \ingroup buffer
  150. \details \details_calc{buffer, \det_buffer}.
  151. \tparam GeometryIn \tparam_geometry
  152. \tparam MultiPolygon \tparam_geometry{MultiPolygon}
  153. \tparam DistanceStrategy A strategy defining distance (or radius)
  154. \tparam SideStrategy A strategy defining creation along sides
  155. \tparam JoinStrategy A strategy defining creation around convex corners
  156. \tparam EndStrategy A strategy defining creation at linestring ends
  157. \tparam PointStrategy A strategy defining creation around points
  158. \param geometry_in \param_geometry
  159. \param geometry_out output multi polygon (or std:: collection of polygons),
  160. will contain a buffered version of the input geometry
  161. \param distance_strategy The distance strategy to be used
  162. \param side_strategy The side strategy to be used
  163. \param join_strategy The join strategy to be used
  164. \param end_strategy The end strategy to be used
  165. \param point_strategy The point strategy to be used
  166. \qbk{distinguish,with strategies}
  167. \qbk{[include reference/algorithms/buffer_with_strategies.qbk]}
  168. */
  169. template
  170. <
  171. typename GeometryIn,
  172. typename MultiPolygon,
  173. typename DistanceStrategy,
  174. typename SideStrategy,
  175. typename JoinStrategy,
  176. typename EndStrategy,
  177. typename PointStrategy
  178. >
  179. inline void buffer(GeometryIn const& geometry_in,
  180. MultiPolygon& geometry_out,
  181. DistanceStrategy const& distance_strategy,
  182. SideStrategy const& side_strategy,
  183. JoinStrategy const& join_strategy,
  184. EndStrategy const& end_strategy,
  185. PointStrategy const& point_strategy)
  186. {
  187. typedef typename boost::range_value<MultiPolygon>::type polygon_type;
  188. concepts::check<GeometryIn const>();
  189. concepts::check<polygon_type>();
  190. typedef typename point_type<GeometryIn>::type point_type;
  191. typedef typename rescale_policy_type
  192. <
  193. point_type,
  194. typename geometry::cs_tag<point_type>::type
  195. >::type rescale_policy_type;
  196. geometry_out.clear();
  197. if (geometry::is_empty(geometry_in))
  198. {
  199. // Then output geometry is kept empty as well
  200. return;
  201. }
  202. model::box<point_type> box;
  203. geometry::envelope(geometry_in, box);
  204. geometry::buffer(box, box, distance_strategy.max_distance(join_strategy, end_strategy));
  205. typename strategy::intersection::services::default_strategy
  206. <
  207. typename cs_tag<GeometryIn>::type
  208. >::type intersection_strategy;
  209. rescale_policy_type rescale_policy
  210. = boost::geometry::get_rescale_policy<rescale_policy_type>(
  211. box, intersection_strategy);
  212. detail::buffer::buffer_inserter<polygon_type>(geometry_in, range::back_inserter(geometry_out),
  213. distance_strategy,
  214. side_strategy,
  215. join_strategy,
  216. end_strategy,
  217. point_strategy,
  218. intersection_strategy,
  219. rescale_policy);
  220. }
  221. }} // namespace boost::geometry
  222. #endif // BOOST_GEOMETRY_ALGORITHMS_BUFFER_HPP