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