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