Chris@16
|
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
|
Chris@16
|
2
|
Chris@16
|
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
Chris@16
|
4 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
|
Chris@16
|
5 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
|
Chris@101
|
6 // Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
|
Chris@16
|
7
|
Chris@16
|
8 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
|
Chris@16
|
9 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
|
Chris@16
|
10
|
Chris@16
|
11 // Use, modification and distribution is subject to the Boost Software License,
|
Chris@16
|
12 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
13 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
14
|
Chris@16
|
15 #ifndef BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP
|
Chris@16
|
16 #define BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP
|
Chris@16
|
17
|
Chris@16
|
18
|
Chris@16
|
19 #include <cstddef>
|
Chris@16
|
20
|
Chris@16
|
21 #include <boost/numeric/conversion/cast.hpp>
|
Chris@16
|
22 #include <boost/range.hpp>
|
Chris@16
|
23 #include <boost/type_traits/is_array.hpp>
|
Chris@101
|
24 #include <boost/type_traits/remove_reference.hpp>
|
Chris@101
|
25
|
Chris@101
|
26 #include <boost/variant/apply_visitor.hpp>
|
Chris@101
|
27 #include <boost/variant/static_visitor.hpp>
|
Chris@101
|
28 #include <boost/variant/variant_fwd.hpp>
|
Chris@16
|
29
|
Chris@16
|
30 #include <boost/geometry/arithmetic/arithmetic.hpp>
|
Chris@16
|
31 #include <boost/geometry/algorithms/not_implemented.hpp>
|
Chris@16
|
32 #include <boost/geometry/algorithms/append.hpp>
|
Chris@16
|
33 #include <boost/geometry/algorithms/clear.hpp>
|
Chris@16
|
34 #include <boost/geometry/algorithms/for_each.hpp>
|
Chris@16
|
35 #include <boost/geometry/algorithms/detail/assign_values.hpp>
|
Chris@16
|
36 #include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
|
Chris@16
|
37 #include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
|
Chris@16
|
38 #include <boost/geometry/algorithms/detail/convert_point_to_point.hpp>
|
Chris@16
|
39 #include <boost/geometry/algorithms/detail/convert_indexed_to_indexed.hpp>
|
Chris@101
|
40 #include <boost/geometry/algorithms/detail/interior_iterator.hpp>
|
Chris@16
|
41
|
Chris@16
|
42 #include <boost/geometry/views/closeable_view.hpp>
|
Chris@16
|
43 #include <boost/geometry/views/reversible_view.hpp>
|
Chris@16
|
44
|
Chris@101
|
45 #include <boost/geometry/util/range.hpp>
|
Chris@101
|
46
|
Chris@16
|
47 #include <boost/geometry/core/cs.hpp>
|
Chris@16
|
48 #include <boost/geometry/core/closure.hpp>
|
Chris@16
|
49 #include <boost/geometry/core/point_order.hpp>
|
Chris@101
|
50 #include <boost/geometry/core/tags.hpp>
|
Chris@101
|
51
|
Chris@16
|
52 #include <boost/geometry/geometries/concepts/check.hpp>
|
Chris@16
|
53
|
Chris@16
|
54
|
Chris@16
|
55 namespace boost { namespace geometry
|
Chris@16
|
56 {
|
Chris@16
|
57
|
Chris@16
|
58 // Silence warning C4127: conditional expression is constant
|
Chris@16
|
59 // Silence warning C4512: assignment operator could not be generated
|
Chris@16
|
60 #if defined(_MSC_VER)
|
Chris@101
|
61 #pragma warning(push)
|
Chris@16
|
62 #pragma warning(disable : 4127 4512)
|
Chris@16
|
63 #endif
|
Chris@16
|
64
|
Chris@16
|
65
|
Chris@16
|
66 #ifndef DOXYGEN_NO_DETAIL
|
Chris@16
|
67 namespace detail { namespace conversion
|
Chris@16
|
68 {
|
Chris@16
|
69
|
Chris@16
|
70 template
|
Chris@16
|
71 <
|
Chris@16
|
72 typename Point,
|
Chris@16
|
73 typename Box,
|
Chris@16
|
74 std::size_t Index,
|
Chris@16
|
75 std::size_t Dimension,
|
Chris@16
|
76 std::size_t DimensionCount
|
Chris@16
|
77 >
|
Chris@16
|
78 struct point_to_box
|
Chris@16
|
79 {
|
Chris@16
|
80 static inline void apply(Point const& point, Box& box)
|
Chris@16
|
81 {
|
Chris@16
|
82 typedef typename coordinate_type<Box>::type coordinate_type;
|
Chris@16
|
83
|
Chris@16
|
84 set<Index, Dimension>(box,
|
Chris@16
|
85 boost::numeric_cast<coordinate_type>(get<Dimension>(point)));
|
Chris@16
|
86 point_to_box
|
Chris@16
|
87 <
|
Chris@16
|
88 Point, Box,
|
Chris@16
|
89 Index, Dimension + 1, DimensionCount
|
Chris@16
|
90 >::apply(point, box);
|
Chris@16
|
91 }
|
Chris@16
|
92 };
|
Chris@16
|
93
|
Chris@16
|
94
|
Chris@16
|
95 template
|
Chris@16
|
96 <
|
Chris@16
|
97 typename Point,
|
Chris@16
|
98 typename Box,
|
Chris@16
|
99 std::size_t Index,
|
Chris@16
|
100 std::size_t DimensionCount
|
Chris@16
|
101 >
|
Chris@16
|
102 struct point_to_box<Point, Box, Index, DimensionCount, DimensionCount>
|
Chris@16
|
103 {
|
Chris@16
|
104 static inline void apply(Point const& , Box& )
|
Chris@16
|
105 {}
|
Chris@16
|
106 };
|
Chris@16
|
107
|
Chris@16
|
108 template <typename Box, typename Range, bool Close, bool Reverse>
|
Chris@16
|
109 struct box_to_range
|
Chris@16
|
110 {
|
Chris@16
|
111 static inline void apply(Box const& box, Range& range)
|
Chris@16
|
112 {
|
Chris@16
|
113 traits::resize<Range>::apply(range, Close ? 5 : 4);
|
Chris@16
|
114 assign_box_corners_oriented<Reverse>(box, range);
|
Chris@16
|
115 if (Close)
|
Chris@16
|
116 {
|
Chris@101
|
117 range::at(range, 4) = range::at(range, 0);
|
Chris@16
|
118 }
|
Chris@16
|
119 }
|
Chris@16
|
120 };
|
Chris@16
|
121
|
Chris@16
|
122 template <typename Segment, typename Range>
|
Chris@16
|
123 struct segment_to_range
|
Chris@16
|
124 {
|
Chris@16
|
125 static inline void apply(Segment const& segment, Range& range)
|
Chris@16
|
126 {
|
Chris@16
|
127 traits::resize<Range>::apply(range, 2);
|
Chris@16
|
128
|
Chris@16
|
129 typename boost::range_iterator<Range>::type it = boost::begin(range);
|
Chris@16
|
130
|
Chris@16
|
131 assign_point_from_index<0>(segment, *it);
|
Chris@16
|
132 ++it;
|
Chris@16
|
133 assign_point_from_index<1>(segment, *it);
|
Chris@16
|
134 }
|
Chris@16
|
135 };
|
Chris@16
|
136
|
Chris@101
|
137 template
|
Chris@16
|
138 <
|
Chris@101
|
139 typename Range1,
|
Chris@101
|
140 typename Range2,
|
Chris@16
|
141 bool Reverse = false
|
Chris@16
|
142 >
|
Chris@16
|
143 struct range_to_range
|
Chris@16
|
144 {
|
Chris@16
|
145 typedef typename reversible_view
|
Chris@16
|
146 <
|
Chris@101
|
147 Range1 const,
|
Chris@16
|
148 Reverse ? iterate_reverse : iterate_forward
|
Chris@16
|
149 >::type rview_type;
|
Chris@16
|
150 typedef typename closeable_view
|
Chris@16
|
151 <
|
Chris@101
|
152 rview_type const,
|
Chris@16
|
153 geometry::closure<Range1>::value
|
Chris@16
|
154 >::type view_type;
|
Chris@16
|
155
|
Chris@16
|
156 static inline void apply(Range1 const& source, Range2& destination)
|
Chris@16
|
157 {
|
Chris@16
|
158 geometry::clear(destination);
|
Chris@16
|
159
|
Chris@16
|
160 rview_type rview(source);
|
Chris@16
|
161
|
Chris@16
|
162 // We consider input always as closed, and skip last
|
Chris@16
|
163 // point for open output.
|
Chris@16
|
164 view_type view(rview);
|
Chris@16
|
165
|
Chris@101
|
166 typedef typename boost::range_size<Range1>::type size_type;
|
Chris@101
|
167 size_type n = boost::size(view);
|
Chris@16
|
168 if (geometry::closure<Range2>::value == geometry::open)
|
Chris@16
|
169 {
|
Chris@16
|
170 n--;
|
Chris@16
|
171 }
|
Chris@16
|
172
|
Chris@101
|
173 // If size == 0 && geometry::open <=> n = numeric_limits<size_type>::max()
|
Chris@101
|
174 // but ok, sice below it == end()
|
Chris@101
|
175
|
Chris@101
|
176 size_type i = 0;
|
Chris@16
|
177 for (typename boost::range_iterator<view_type const>::type it
|
Chris@16
|
178 = boost::begin(view);
|
Chris@16
|
179 it != boost::end(view) && i < n;
|
Chris@16
|
180 ++it, ++i)
|
Chris@16
|
181 {
|
Chris@16
|
182 geometry::append(destination, *it);
|
Chris@16
|
183 }
|
Chris@16
|
184 }
|
Chris@16
|
185 };
|
Chris@16
|
186
|
Chris@16
|
187 template <typename Polygon1, typename Polygon2>
|
Chris@16
|
188 struct polygon_to_polygon
|
Chris@16
|
189 {
|
Chris@16
|
190 typedef range_to_range
|
Chris@16
|
191 <
|
Chris@101
|
192 typename geometry::ring_type<Polygon1>::type,
|
Chris@16
|
193 typename geometry::ring_type<Polygon2>::type,
|
Chris@16
|
194 geometry::point_order<Polygon1>::value
|
Chris@16
|
195 != geometry::point_order<Polygon2>::value
|
Chris@16
|
196 > per_ring;
|
Chris@16
|
197
|
Chris@16
|
198 static inline void apply(Polygon1 const& source, Polygon2& destination)
|
Chris@16
|
199 {
|
Chris@16
|
200 // Clearing managed per ring, and in the resizing of interior rings
|
Chris@16
|
201
|
Chris@101
|
202 per_ring::apply(geometry::exterior_ring(source),
|
Chris@16
|
203 geometry::exterior_ring(destination));
|
Chris@16
|
204
|
Chris@16
|
205 // Container should be resizeable
|
Chris@16
|
206 traits::resize
|
Chris@16
|
207 <
|
Chris@16
|
208 typename boost::remove_reference
|
Chris@16
|
209 <
|
Chris@16
|
210 typename traits::interior_mutable_type<Polygon2>::type
|
Chris@16
|
211 >::type
|
Chris@16
|
212 >::apply(interior_rings(destination), num_interior_rings(source));
|
Chris@16
|
213
|
Chris@101
|
214 typename interior_return_type<Polygon1 const>::type
|
Chris@101
|
215 rings_source = interior_rings(source);
|
Chris@101
|
216 typename interior_return_type<Polygon2>::type
|
Chris@101
|
217 rings_dest = interior_rings(destination);
|
Chris@16
|
218
|
Chris@101
|
219 typename detail::interior_iterator<Polygon1 const>::type
|
Chris@101
|
220 it_source = boost::begin(rings_source);
|
Chris@101
|
221 typename detail::interior_iterator<Polygon2>::type
|
Chris@101
|
222 it_dest = boost::begin(rings_dest);
|
Chris@16
|
223
|
Chris@16
|
224 for ( ; it_source != boost::end(rings_source); ++it_source, ++it_dest)
|
Chris@16
|
225 {
|
Chris@16
|
226 per_ring::apply(*it_source, *it_dest);
|
Chris@16
|
227 }
|
Chris@16
|
228 }
|
Chris@16
|
229 };
|
Chris@16
|
230
|
Chris@101
|
231 template <typename Single, typename Multi, typename Policy>
|
Chris@101
|
232 struct single_to_multi: private Policy
|
Chris@101
|
233 {
|
Chris@101
|
234 static inline void apply(Single const& single, Multi& multi)
|
Chris@101
|
235 {
|
Chris@101
|
236 traits::resize<Multi>::apply(multi, 1);
|
Chris@101
|
237 Policy::apply(single, *boost::begin(multi));
|
Chris@101
|
238 }
|
Chris@101
|
239 };
|
Chris@101
|
240
|
Chris@101
|
241
|
Chris@101
|
242
|
Chris@101
|
243 template <typename Multi1, typename Multi2, typename Policy>
|
Chris@101
|
244 struct multi_to_multi: private Policy
|
Chris@101
|
245 {
|
Chris@101
|
246 static inline void apply(Multi1 const& multi1, Multi2& multi2)
|
Chris@101
|
247 {
|
Chris@101
|
248 traits::resize<Multi2>::apply(multi2, boost::size(multi1));
|
Chris@101
|
249
|
Chris@101
|
250 typename boost::range_iterator<Multi1 const>::type it1
|
Chris@101
|
251 = boost::begin(multi1);
|
Chris@101
|
252 typename boost::range_iterator<Multi2>::type it2
|
Chris@101
|
253 = boost::begin(multi2);
|
Chris@101
|
254
|
Chris@101
|
255 for (; it1 != boost::end(multi1); ++it1, ++it2)
|
Chris@101
|
256 {
|
Chris@101
|
257 Policy::apply(*it1, *it2);
|
Chris@101
|
258 }
|
Chris@101
|
259 }
|
Chris@101
|
260 };
|
Chris@101
|
261
|
Chris@16
|
262
|
Chris@16
|
263 }} // namespace detail::conversion
|
Chris@16
|
264 #endif // DOXYGEN_NO_DETAIL
|
Chris@16
|
265
|
Chris@16
|
266
|
Chris@16
|
267 #ifndef DOXYGEN_NO_DISPATCH
|
Chris@16
|
268 namespace dispatch
|
Chris@16
|
269 {
|
Chris@16
|
270
|
Chris@16
|
271 template
|
Chris@16
|
272 <
|
Chris@16
|
273 typename Geometry1, typename Geometry2,
|
Chris@16
|
274 typename Tag1 = typename tag_cast<typename tag<Geometry1>::type, multi_tag>::type,
|
Chris@16
|
275 typename Tag2 = typename tag_cast<typename tag<Geometry2>::type, multi_tag>::type,
|
Chris@16
|
276 std::size_t DimensionCount = dimension<Geometry1>::type::value,
|
Chris@16
|
277 bool UseAssignment = boost::is_same<Geometry1, Geometry2>::value
|
Chris@16
|
278 && !boost::is_array<Geometry1>::value
|
Chris@16
|
279 >
|
Chris@101
|
280 struct convert: not_implemented<Tag1, Tag2, boost::mpl::int_<DimensionCount> >
|
Chris@16
|
281 {};
|
Chris@16
|
282
|
Chris@16
|
283
|
Chris@16
|
284 template
|
Chris@16
|
285 <
|
Chris@16
|
286 typename Geometry1, typename Geometry2,
|
Chris@16
|
287 typename Tag,
|
Chris@16
|
288 std::size_t DimensionCount
|
Chris@16
|
289 >
|
Chris@16
|
290 struct convert<Geometry1, Geometry2, Tag, Tag, DimensionCount, true>
|
Chris@16
|
291 {
|
Chris@16
|
292 // Same geometry type -> copy whole geometry
|
Chris@16
|
293 static inline void apply(Geometry1 const& source, Geometry2& destination)
|
Chris@16
|
294 {
|
Chris@16
|
295 destination = source;
|
Chris@16
|
296 }
|
Chris@16
|
297 };
|
Chris@16
|
298
|
Chris@16
|
299
|
Chris@16
|
300 template
|
Chris@16
|
301 <
|
Chris@16
|
302 typename Geometry1, typename Geometry2,
|
Chris@16
|
303 std::size_t DimensionCount
|
Chris@16
|
304 >
|
Chris@16
|
305 struct convert<Geometry1, Geometry2, point_tag, point_tag, DimensionCount, false>
|
Chris@16
|
306 : detail::conversion::point_to_point<Geometry1, Geometry2, 0, DimensionCount>
|
Chris@16
|
307 {};
|
Chris@16
|
308
|
Chris@16
|
309
|
Chris@16
|
310 template
|
Chris@16
|
311 <
|
Chris@16
|
312 typename Box1, typename Box2,
|
Chris@16
|
313 std::size_t DimensionCount
|
Chris@16
|
314 >
|
Chris@16
|
315 struct convert<Box1, Box2, box_tag, box_tag, DimensionCount, false>
|
Chris@16
|
316 : detail::conversion::indexed_to_indexed<Box1, Box2, 0, DimensionCount>
|
Chris@16
|
317 {};
|
Chris@16
|
318
|
Chris@16
|
319
|
Chris@16
|
320 template
|
Chris@16
|
321 <
|
Chris@16
|
322 typename Segment1, typename Segment2,
|
Chris@16
|
323 std::size_t DimensionCount
|
Chris@16
|
324 >
|
Chris@16
|
325 struct convert<Segment1, Segment2, segment_tag, segment_tag, DimensionCount, false>
|
Chris@16
|
326 : detail::conversion::indexed_to_indexed<Segment1, Segment2, 0, DimensionCount>
|
Chris@16
|
327 {};
|
Chris@16
|
328
|
Chris@16
|
329
|
Chris@16
|
330 template <typename Segment, typename LineString, std::size_t DimensionCount>
|
Chris@16
|
331 struct convert<Segment, LineString, segment_tag, linestring_tag, DimensionCount, false>
|
Chris@16
|
332 : detail::conversion::segment_to_range<Segment, LineString>
|
Chris@16
|
333 {};
|
Chris@16
|
334
|
Chris@16
|
335
|
Chris@16
|
336 template <typename Ring1, typename Ring2, std::size_t DimensionCount>
|
Chris@16
|
337 struct convert<Ring1, Ring2, ring_tag, ring_tag, DimensionCount, false>
|
Chris@16
|
338 : detail::conversion::range_to_range
|
Chris@101
|
339 <
|
Chris@101
|
340 Ring1,
|
Chris@16
|
341 Ring2,
|
Chris@16
|
342 geometry::point_order<Ring1>::value
|
Chris@16
|
343 != geometry::point_order<Ring2>::value
|
Chris@16
|
344 >
|
Chris@16
|
345 {};
|
Chris@16
|
346
|
Chris@16
|
347 template <typename LineString1, typename LineString2, std::size_t DimensionCount>
|
Chris@16
|
348 struct convert<LineString1, LineString2, linestring_tag, linestring_tag, DimensionCount, false>
|
Chris@16
|
349 : detail::conversion::range_to_range<LineString1, LineString2>
|
Chris@16
|
350 {};
|
Chris@16
|
351
|
Chris@16
|
352 template <typename Polygon1, typename Polygon2, std::size_t DimensionCount>
|
Chris@16
|
353 struct convert<Polygon1, Polygon2, polygon_tag, polygon_tag, DimensionCount, false>
|
Chris@16
|
354 : detail::conversion::polygon_to_polygon<Polygon1, Polygon2>
|
Chris@16
|
355 {};
|
Chris@16
|
356
|
Chris@16
|
357 template <typename Box, typename Ring>
|
Chris@16
|
358 struct convert<Box, Ring, box_tag, ring_tag, 2, false>
|
Chris@16
|
359 : detail::conversion::box_to_range
|
Chris@16
|
360 <
|
Chris@101
|
361 Box,
|
Chris@101
|
362 Ring,
|
Chris@16
|
363 geometry::closure<Ring>::value == closed,
|
Chris@16
|
364 geometry::point_order<Ring>::value == counterclockwise
|
Chris@16
|
365 >
|
Chris@16
|
366 {};
|
Chris@16
|
367
|
Chris@16
|
368
|
Chris@16
|
369 template <typename Box, typename Polygon>
|
Chris@16
|
370 struct convert<Box, Polygon, box_tag, polygon_tag, 2, false>
|
Chris@16
|
371 {
|
Chris@16
|
372 static inline void apply(Box const& box, Polygon& polygon)
|
Chris@16
|
373 {
|
Chris@16
|
374 typedef typename ring_type<Polygon>::type ring_type;
|
Chris@16
|
375
|
Chris@16
|
376 convert
|
Chris@16
|
377 <
|
Chris@16
|
378 Box, ring_type,
|
Chris@16
|
379 box_tag, ring_tag,
|
Chris@16
|
380 2, false
|
Chris@16
|
381 >::apply(box, exterior_ring(polygon));
|
Chris@16
|
382 }
|
Chris@16
|
383 };
|
Chris@16
|
384
|
Chris@16
|
385
|
Chris@16
|
386 template <typename Point, typename Box, std::size_t DimensionCount>
|
Chris@16
|
387 struct convert<Point, Box, point_tag, box_tag, DimensionCount, false>
|
Chris@16
|
388 {
|
Chris@16
|
389 static inline void apply(Point const& point, Box& box)
|
Chris@16
|
390 {
|
Chris@16
|
391 detail::conversion::point_to_box
|
Chris@16
|
392 <
|
Chris@16
|
393 Point, Box, min_corner, 0, DimensionCount
|
Chris@16
|
394 >::apply(point, box);
|
Chris@16
|
395 detail::conversion::point_to_box
|
Chris@16
|
396 <
|
Chris@16
|
397 Point, Box, max_corner, 0, DimensionCount
|
Chris@16
|
398 >::apply(point, box);
|
Chris@16
|
399 }
|
Chris@16
|
400 };
|
Chris@16
|
401
|
Chris@16
|
402
|
Chris@16
|
403 template <typename Ring, typename Polygon, std::size_t DimensionCount>
|
Chris@16
|
404 struct convert<Ring, Polygon, ring_tag, polygon_tag, DimensionCount, false>
|
Chris@16
|
405 {
|
Chris@16
|
406 static inline void apply(Ring const& ring, Polygon& polygon)
|
Chris@16
|
407 {
|
Chris@16
|
408 typedef typename ring_type<Polygon>::type ring_type;
|
Chris@16
|
409 convert
|
Chris@16
|
410 <
|
Chris@16
|
411 Ring, ring_type,
|
Chris@16
|
412 ring_tag, ring_tag,
|
Chris@16
|
413 DimensionCount, false
|
Chris@16
|
414 >::apply(ring, exterior_ring(polygon));
|
Chris@16
|
415 }
|
Chris@16
|
416 };
|
Chris@16
|
417
|
Chris@16
|
418
|
Chris@16
|
419 template <typename Polygon, typename Ring, std::size_t DimensionCount>
|
Chris@16
|
420 struct convert<Polygon, Ring, polygon_tag, ring_tag, DimensionCount, false>
|
Chris@16
|
421 {
|
Chris@16
|
422 static inline void apply(Polygon const& polygon, Ring& ring)
|
Chris@16
|
423 {
|
Chris@16
|
424 typedef typename ring_type<Polygon>::type ring_type;
|
Chris@16
|
425
|
Chris@16
|
426 convert
|
Chris@16
|
427 <
|
Chris@16
|
428 ring_type, Ring,
|
Chris@16
|
429 ring_tag, ring_tag,
|
Chris@16
|
430 DimensionCount, false
|
Chris@16
|
431 >::apply(exterior_ring(polygon), ring);
|
Chris@16
|
432 }
|
Chris@16
|
433 };
|
Chris@16
|
434
|
Chris@16
|
435
|
Chris@101
|
436 // Dispatch for multi <-> multi, specifying their single-version as policy.
|
Chris@101
|
437 // Note that, even if the multi-types are mutually different, their single
|
Chris@101
|
438 // version types might be the same and therefore we call boost::is_same again
|
Chris@101
|
439
|
Chris@101
|
440 template <typename Multi1, typename Multi2, std::size_t DimensionCount>
|
Chris@101
|
441 struct convert<Multi1, Multi2, multi_tag, multi_tag, DimensionCount, false>
|
Chris@101
|
442 : detail::conversion::multi_to_multi
|
Chris@101
|
443 <
|
Chris@101
|
444 Multi1,
|
Chris@101
|
445 Multi2,
|
Chris@101
|
446 convert
|
Chris@101
|
447 <
|
Chris@101
|
448 typename boost::range_value<Multi1>::type,
|
Chris@101
|
449 typename boost::range_value<Multi2>::type,
|
Chris@101
|
450 typename single_tag_of
|
Chris@101
|
451 <
|
Chris@101
|
452 typename tag<Multi1>::type
|
Chris@101
|
453 >::type,
|
Chris@101
|
454 typename single_tag_of
|
Chris@101
|
455 <
|
Chris@101
|
456 typename tag<Multi2>::type
|
Chris@101
|
457 >::type,
|
Chris@101
|
458 DimensionCount
|
Chris@101
|
459 >
|
Chris@101
|
460 >
|
Chris@101
|
461 {};
|
Chris@101
|
462
|
Chris@101
|
463
|
Chris@101
|
464 template <typename Single, typename Multi, typename SingleTag, std::size_t DimensionCount>
|
Chris@101
|
465 struct convert<Single, Multi, SingleTag, multi_tag, DimensionCount, false>
|
Chris@101
|
466 : detail::conversion::single_to_multi
|
Chris@101
|
467 <
|
Chris@101
|
468 Single,
|
Chris@101
|
469 Multi,
|
Chris@101
|
470 convert
|
Chris@101
|
471 <
|
Chris@101
|
472 Single,
|
Chris@101
|
473 typename boost::range_value<Multi>::type,
|
Chris@101
|
474 typename tag<Single>::type,
|
Chris@101
|
475 typename single_tag_of
|
Chris@101
|
476 <
|
Chris@101
|
477 typename tag<Multi>::type
|
Chris@101
|
478 >::type,
|
Chris@101
|
479 DimensionCount,
|
Chris@101
|
480 false
|
Chris@101
|
481 >
|
Chris@101
|
482 >
|
Chris@101
|
483 {};
|
Chris@101
|
484
|
Chris@101
|
485
|
Chris@101
|
486 } // namespace dispatch
|
Chris@101
|
487 #endif // DOXYGEN_NO_DISPATCH
|
Chris@101
|
488
|
Chris@101
|
489
|
Chris@101
|
490 namespace resolve_variant {
|
Chris@101
|
491
|
Chris@16
|
492 template <typename Geometry1, typename Geometry2>
|
Chris@101
|
493 struct convert
|
Chris@16
|
494 {
|
Chris@16
|
495 static inline void apply(Geometry1 const& geometry1, Geometry2& geometry2)
|
Chris@16
|
496 {
|
Chris@16
|
497 concept::check_concepts_and_equal_dimensions<Geometry1 const, Geometry2>();
|
Chris@101
|
498 dispatch::convert<Geometry1, Geometry2>::apply(geometry1, geometry2);
|
Chris@16
|
499 }
|
Chris@16
|
500 };
|
Chris@16
|
501
|
Chris@16
|
502 template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
|
Chris@101
|
503 struct convert<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
|
Chris@16
|
504 {
|
Chris@16
|
505 struct visitor: static_visitor<void>
|
Chris@16
|
506 {
|
Chris@16
|
507 Geometry2& m_geometry2;
|
Chris@16
|
508
|
Chris@16
|
509 visitor(Geometry2& geometry2)
|
Chris@16
|
510 : m_geometry2(geometry2)
|
Chris@16
|
511 {}
|
Chris@16
|
512
|
Chris@16
|
513 template <typename Geometry1>
|
Chris@16
|
514 inline void operator()(Geometry1 const& geometry1) const
|
Chris@16
|
515 {
|
Chris@101
|
516 convert<Geometry1, Geometry2>::apply(geometry1, m_geometry2);
|
Chris@16
|
517 }
|
Chris@16
|
518 };
|
Chris@16
|
519
|
Chris@16
|
520 static inline void apply(
|
Chris@16
|
521 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
|
Chris@16
|
522 Geometry2& geometry2
|
Chris@16
|
523 )
|
Chris@16
|
524 {
|
Chris@16
|
525 apply_visitor(visitor(geometry2), geometry1);
|
Chris@16
|
526 }
|
Chris@16
|
527 };
|
Chris@16
|
528
|
Chris@101
|
529 }
|
Chris@16
|
530
|
Chris@16
|
531
|
Chris@16
|
532 /*!
|
Chris@16
|
533 \brief Converts one geometry to another geometry
|
Chris@16
|
534 \details The convert algorithm converts one geometry, e.g. a BOX, to another
|
Chris@16
|
535 geometry, e.g. a RING. This only works if it is possible and applicable.
|
Chris@101
|
536 If the point-order is different, or the closure is different between two
|
Chris@101
|
537 geometry types, it will be converted correctly by explicitly reversing the
|
Chris@16
|
538 points or closing or opening the polygon rings.
|
Chris@16
|
539 \ingroup convert
|
Chris@16
|
540 \tparam Geometry1 \tparam_geometry
|
Chris@16
|
541 \tparam Geometry2 \tparam_geometry
|
Chris@16
|
542 \param geometry1 \param_geometry (source)
|
Chris@16
|
543 \param geometry2 \param_geometry (target)
|
Chris@16
|
544
|
Chris@16
|
545 \qbk{[include reference/algorithms/convert.qbk]}
|
Chris@16
|
546 */
|
Chris@16
|
547 template <typename Geometry1, typename Geometry2>
|
Chris@16
|
548 inline void convert(Geometry1 const& geometry1, Geometry2& geometry2)
|
Chris@16
|
549 {
|
Chris@101
|
550 resolve_variant::convert<Geometry1, Geometry2>::apply(geometry1, geometry2);
|
Chris@16
|
551 }
|
Chris@16
|
552
|
Chris@16
|
553 #if defined(_MSC_VER)
|
Chris@16
|
554 #pragma warning(pop)
|
Chris@16
|
555 #endif
|
Chris@16
|
556
|
Chris@16
|
557 }} // namespace boost::geometry
|
Chris@16
|
558
|
Chris@16
|
559 #endif // BOOST_GEOMETRY_ALGORITHMS_CONVERT_HPP
|