]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Boost.Geometry (aka GGL, Generic Geometry Library) |
2 | ||
3 | // Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands. | |
4 | // Copyright (c) 2008-2014 Bruno Lalande, Paris, France. | |
5 | // Copyright (c) 2009-2014 Mateusz Loskot, London, UK. | |
6 | ||
20effc67 TL |
7 | // This file was modified by Oracle on 2014-2020. |
8 | // Modifications copyright (c) 2014-2020, Oracle and/or its affiliates. | |
7c673cae FG |
9 | // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle |
10 | // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle | |
11 | ||
12 | // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library | |
13 | // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. | |
14 | ||
15 | // Use, modification and distribution is subject to the Boost Software License, | |
16 | // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at | |
17 | // http://www.boost.org/LICENSE_1_0.txt) | |
18 | ||
19 | #ifndef BOOST_GEOMETRY_ALGORITHMS_APPEND_HPP | |
20 | #define BOOST_GEOMETRY_ALGORITHMS_APPEND_HPP | |
21 | ||
22 | ||
20effc67 TL |
23 | #include <boost/range/begin.hpp> |
24 | #include <boost/range/end.hpp> | |
25 | #include <boost/range/value_type.hpp> | |
7c673cae FG |
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/num_interior_rings.hpp> | |
32 | #include <boost/geometry/algorithms/detail/convert_point_to_point.hpp> | |
33 | #include <boost/geometry/core/access.hpp> | |
34 | #include <boost/geometry/core/mutable_range.hpp> | |
35 | #include <boost/geometry/core/point_type.hpp> | |
36 | #include <boost/geometry/core/tags.hpp> | |
37 | #include <boost/geometry/geometries/concepts/check.hpp> | |
38 | #include <boost/geometry/geometries/variant.hpp> | |
39 | #include <boost/geometry/util/range.hpp> | |
40 | ||
41 | ||
42 | namespace boost { namespace geometry | |
43 | { | |
44 | ||
45 | ||
46 | #ifndef DOXYGEN_NO_DETAIL | |
47 | namespace detail { namespace append | |
48 | { | |
49 | ||
50 | template <typename Geometry, typename Point> | |
51 | struct append_no_action | |
52 | { | |
53 | static inline void apply(Geometry& , Point const& , | |
54 | int = 0, int = 0) | |
55 | { | |
56 | } | |
57 | }; | |
58 | ||
59 | template <typename Geometry, typename Point> | |
60 | struct append_point | |
61 | { | |
62 | static inline void apply(Geometry& geometry, Point const& point, | |
63 | int = 0, int = 0) | |
64 | { | |
65 | typename geometry::point_type<Geometry>::type copy; | |
66 | geometry::detail::conversion::convert_point_to_point(point, copy); | |
67 | traits::push_back<Geometry>::apply(geometry, copy); | |
68 | } | |
69 | }; | |
70 | ||
71 | ||
72 | template <typename Geometry, typename Range> | |
73 | struct append_range | |
74 | { | |
75 | typedef typename boost::range_value<Range>::type point_type; | |
76 | ||
77 | static inline void apply(Geometry& geometry, Range const& range, | |
78 | int = 0, int = 0) | |
79 | { | |
80 | for (typename boost::range_iterator<Range const>::type | |
81 | it = boost::begin(range); | |
82 | it != boost::end(range); | |
83 | ++it) | |
84 | { | |
85 | append_point<Geometry, point_type>::apply(geometry, *it); | |
86 | } | |
87 | } | |
88 | }; | |
89 | ||
90 | ||
91 | template <typename Polygon, typename Point> | |
92 | struct point_to_polygon | |
93 | { | |
94 | typedef typename ring_type<Polygon>::type ring_type; | |
92f5a8d4 TL |
95 | typedef typename ring_return_type<Polygon>::type exterior_ring_type; |
96 | typedef typename interior_return_type<Polygon>::type interior_ring_range_type; | |
7c673cae FG |
97 | |
98 | static inline void apply(Polygon& polygon, Point const& point, | |
99 | int ring_index, int = 0) | |
100 | { | |
101 | if (ring_index == -1) | |
102 | { | |
92f5a8d4 | 103 | exterior_ring_type ext_ring = exterior_ring(polygon); |
7c673cae | 104 | append_point<ring_type, Point>::apply( |
92f5a8d4 | 105 | ext_ring, point); |
7c673cae FG |
106 | } |
107 | else if (ring_index < int(num_interior_rings(polygon))) | |
108 | { | |
92f5a8d4 | 109 | interior_ring_range_type int_rings = interior_rings(polygon); |
7c673cae | 110 | append_point<ring_type, Point>::apply( |
92f5a8d4 | 111 | range::at(int_rings, ring_index), point); |
7c673cae FG |
112 | } |
113 | } | |
114 | }; | |
115 | ||
116 | ||
117 | template <typename Polygon, typename Range> | |
118 | struct range_to_polygon | |
119 | { | |
120 | typedef typename ring_type<Polygon>::type ring_type; | |
92f5a8d4 TL |
121 | typedef typename ring_return_type<Polygon>::type exterior_ring_type; |
122 | typedef typename interior_return_type<Polygon>::type interior_ring_range_type; | |
7c673cae FG |
123 | |
124 | static inline void apply(Polygon& polygon, Range const& range, | |
125 | int ring_index, int = 0) | |
126 | { | |
127 | if (ring_index == -1) | |
128 | { | |
92f5a8d4 | 129 | exterior_ring_type ext_ring = exterior_ring(polygon); |
7c673cae | 130 | append_range<ring_type, Range>::apply( |
92f5a8d4 | 131 | ext_ring, range); |
7c673cae FG |
132 | } |
133 | else if (ring_index < int(num_interior_rings(polygon))) | |
134 | { | |
92f5a8d4 | 135 | interior_ring_range_type int_rings = interior_rings(polygon); |
7c673cae | 136 | append_range<ring_type, Range>::apply( |
92f5a8d4 | 137 | range::at(int_rings, ring_index), range); |
7c673cae FG |
138 | } |
139 | } | |
140 | }; | |
141 | ||
142 | ||
143 | }} // namespace detail::append | |
144 | #endif // DOXYGEN_NO_DETAIL | |
145 | ||
146 | ||
147 | #ifndef DOXYGEN_NO_DISPATCH | |
148 | namespace dispatch | |
149 | { | |
150 | ||
151 | namespace splitted_dispatch | |
152 | { | |
153 | ||
154 | template <typename Tag, typename Geometry, typename Point> | |
155 | struct append_point | |
156 | : detail::append::append_no_action<Geometry, Point> | |
157 | {}; | |
158 | ||
159 | template <typename Geometry, typename Point> | |
160 | struct append_point<linestring_tag, Geometry, Point> | |
161 | : detail::append::append_point<Geometry, Point> | |
162 | {}; | |
163 | ||
164 | template <typename Geometry, typename Point> | |
165 | struct append_point<ring_tag, Geometry, Point> | |
166 | : detail::append::append_point<Geometry, Point> | |
167 | {}; | |
168 | ||
169 | ||
170 | template <typename Polygon, typename Point> | |
171 | struct append_point<polygon_tag, Polygon, Point> | |
172 | : detail::append::point_to_polygon<Polygon, Point> | |
173 | {}; | |
174 | ||
175 | ||
176 | template <typename Tag, typename Geometry, typename Range> | |
177 | struct append_range | |
178 | : detail::append::append_no_action<Geometry, Range> | |
179 | {}; | |
180 | ||
181 | template <typename Geometry, typename Range> | |
182 | struct append_range<linestring_tag, Geometry, Range> | |
183 | : detail::append::append_range<Geometry, Range> | |
184 | {}; | |
185 | ||
186 | template <typename Geometry, typename Range> | |
187 | struct append_range<ring_tag, Geometry, Range> | |
188 | : detail::append::append_range<Geometry, Range> | |
189 | {}; | |
190 | ||
191 | ||
192 | template <typename Polygon, typename Range> | |
193 | struct append_range<polygon_tag, Polygon, Range> | |
194 | : detail::append::range_to_polygon<Polygon, Range> | |
195 | {}; | |
196 | ||
197 | } // namespace splitted_dispatch | |
198 | ||
199 | ||
200 | // Default: append a range (or linestring or ring or whatever) to any geometry | |
201 | template | |
202 | < | |
203 | typename Geometry, typename RangeOrPoint, | |
204 | typename TagRangeOrPoint = typename tag<RangeOrPoint>::type | |
205 | > | |
206 | struct append | |
207 | : splitted_dispatch::append_range<typename tag<Geometry>::type, Geometry, RangeOrPoint> | |
208 | {}; | |
209 | ||
210 | // Specialization for point to append a point to any geometry | |
211 | template <typename Geometry, typename RangeOrPoint> | |
212 | struct append<Geometry, RangeOrPoint, point_tag> | |
213 | : splitted_dispatch::append_point<typename tag<Geometry>::type, Geometry, RangeOrPoint> | |
214 | {}; | |
215 | ||
216 | } // namespace dispatch | |
217 | #endif // DOXYGEN_NO_DISPATCH | |
218 | ||
219 | #ifndef DOXYGEN_NO_DETAIL | |
220 | namespace detail { namespace append | |
221 | { | |
222 | ||
223 | template <typename MultiGeometry, typename RangeOrPoint> | |
224 | struct append_to_multigeometry | |
225 | { | |
226 | static inline void apply(MultiGeometry& multigeometry, | |
227 | RangeOrPoint const& range_or_point, | |
228 | int ring_index, int multi_index) | |
229 | { | |
230 | ||
231 | dispatch::append | |
232 | < | |
233 | typename boost::range_value<MultiGeometry>::type, | |
234 | RangeOrPoint | |
235 | >::apply(range::at(multigeometry, multi_index), range_or_point, ring_index); | |
236 | } | |
237 | }; | |
238 | ||
239 | }} // namespace detail::append | |
240 | #endif // DOXYGEN_NO_DETAIL | |
241 | ||
242 | #ifndef DOXYGEN_NO_DISPATCH | |
243 | namespace dispatch | |
244 | { | |
245 | ||
246 | namespace splitted_dispatch | |
247 | { | |
248 | ||
249 | template <typename Geometry, typename Point> | |
250 | struct append_point<multi_point_tag, Geometry, Point> | |
251 | : detail::append::append_point<Geometry, Point> | |
252 | {}; | |
253 | ||
254 | template <typename Geometry, typename Range> | |
255 | struct append_range<multi_point_tag, Geometry, Range> | |
256 | : detail::append::append_range<Geometry, Range> | |
257 | {}; | |
258 | ||
259 | template <typename MultiGeometry, typename RangeOrPoint> | |
260 | struct append_point<multi_linestring_tag, MultiGeometry, RangeOrPoint> | |
261 | : detail::append::append_to_multigeometry<MultiGeometry, RangeOrPoint> | |
262 | {}; | |
263 | ||
264 | template <typename MultiGeometry, typename RangeOrPoint> | |
265 | struct append_range<multi_linestring_tag, MultiGeometry, RangeOrPoint> | |
266 | : detail::append::append_to_multigeometry<MultiGeometry, RangeOrPoint> | |
267 | {}; | |
268 | ||
269 | template <typename MultiGeometry, typename RangeOrPoint> | |
270 | struct append_point<multi_polygon_tag, MultiGeometry, RangeOrPoint> | |
271 | : detail::append::append_to_multigeometry<MultiGeometry, RangeOrPoint> | |
272 | {}; | |
273 | ||
274 | template <typename MultiGeometry, typename RangeOrPoint> | |
275 | struct append_range<multi_polygon_tag, MultiGeometry, RangeOrPoint> | |
276 | : detail::append::append_to_multigeometry<MultiGeometry, RangeOrPoint> | |
277 | {}; | |
278 | ||
279 | } // namespace splitted_dispatch | |
280 | ||
281 | } // namespace dispatch | |
282 | #endif // DOXYGEN_NO_DISPATCH | |
283 | ||
284 | ||
285 | namespace resolve_variant { | |
286 | ||
287 | template <typename Geometry> | |
288 | struct append | |
289 | { | |
290 | template <typename RangeOrPoint> | |
291 | static inline void apply(Geometry& geometry, | |
292 | RangeOrPoint const& range_or_point, | |
293 | int ring_index, | |
294 | int multi_index) | |
295 | { | |
296 | concepts::check<Geometry>(); | |
297 | dispatch::append<Geometry, RangeOrPoint>::apply(geometry, | |
298 | range_or_point, | |
299 | ring_index, | |
300 | multi_index); | |
301 | } | |
302 | }; | |
303 | ||
304 | ||
305 | template <BOOST_VARIANT_ENUM_PARAMS(typename T)> | |
306 | struct append<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > | |
307 | { | |
308 | template <typename RangeOrPoint> | |
309 | struct visitor: boost::static_visitor<void> | |
310 | { | |
311 | RangeOrPoint const& m_range_or_point; | |
312 | int m_ring_index; | |
313 | int m_multi_index; | |
314 | ||
315 | visitor(RangeOrPoint const& range_or_point, | |
316 | int ring_index, | |
317 | int multi_index): | |
318 | m_range_or_point(range_or_point), | |
319 | m_ring_index(ring_index), | |
320 | m_multi_index(multi_index) | |
321 | {} | |
322 | ||
323 | template <typename Geometry> | |
324 | void operator()(Geometry& geometry) const | |
325 | { | |
326 | append<Geometry>::apply(geometry, | |
327 | m_range_or_point, | |
328 | m_ring_index, | |
329 | m_multi_index); | |
330 | } | |
331 | }; | |
332 | ||
333 | template <typename RangeOrPoint> | |
334 | static inline void apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& variant_geometry, | |
335 | RangeOrPoint const& range_or_point, | |
336 | int ring_index, | |
337 | int multi_index) | |
338 | { | |
339 | boost::apply_visitor( | |
340 | visitor<RangeOrPoint>( | |
341 | range_or_point, | |
342 | ring_index, | |
343 | multi_index | |
344 | ), | |
345 | variant_geometry | |
346 | ); | |
347 | } | |
348 | }; | |
349 | ||
350 | } // namespace resolve_variant; | |
351 | ||
352 | ||
353 | /*! | |
354 | \brief Appends one or more points to a linestring, ring, polygon, multi-geometry | |
355 | \ingroup append | |
356 | \tparam Geometry \tparam_geometry | |
357 | \tparam RangeOrPoint Either a range or a point, fullfilling Boost.Range concept or Boost.Geometry Point Concept | |
358 | \param geometry \param_geometry | |
359 | \param range_or_point The point or range to add | |
360 | \param ring_index The index of the ring in case of a polygon: | |
361 | exterior ring (-1, the default) or interior ring index | |
362 | \param multi_index The index of the geometry to which the points are appended | |
363 | ||
364 | \qbk{[include reference/algorithms/append.qbk]} | |
365 | } | |
366 | */ | |
367 | template <typename Geometry, typename RangeOrPoint> | |
368 | inline void append(Geometry& geometry, RangeOrPoint const& range_or_point, | |
369 | int ring_index = -1, int multi_index = 0) | |
370 | { | |
371 | resolve_variant::append<Geometry> | |
372 | ::apply(geometry, range_or_point, ring_index, multi_index); | |
373 | } | |
374 | ||
375 | ||
376 | }} // namespace boost::geometry | |
377 | ||
378 | ||
379 | #endif // BOOST_GEOMETRY_ALGORITHMS_APPEND_HPP |