]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/geometry/include/boost/geometry/algorithms/transform.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / geometry / include / boost / geometry / algorithms / transform.hpp
CommitLineData
7c673cae
FG
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// Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
7
8// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
9// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
10
11// Use, modification and distribution is subject to the Boost Software License,
12// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
13// http://www.boost.org/LICENSE_1_0.txt)
14
15#ifndef BOOST_GEOMETRY_ALGORITHMS_TRANSFORM_HPP
16#define BOOST_GEOMETRY_ALGORITHMS_TRANSFORM_HPP
17
18#include <cmath>
19#include <iterator>
20
21#include <boost/range.hpp>
22#include <boost/type_traits/remove_reference.hpp>
23
24#include <boost/variant/apply_visitor.hpp>
25#include <boost/variant/static_visitor.hpp>
26#include <boost/variant/variant_fwd.hpp>
27
28#include <boost/geometry/algorithms/assign.hpp>
29#include <boost/geometry/algorithms/clear.hpp>
30#include <boost/geometry/algorithms/detail/interior_iterator.hpp>
31#include <boost/geometry/algorithms/num_interior_rings.hpp>
32
33#include <boost/geometry/core/cs.hpp>
34#include <boost/geometry/core/exterior_ring.hpp>
35#include <boost/geometry/core/interior_rings.hpp>
36#include <boost/geometry/core/mutable_range.hpp>
37#include <boost/geometry/core/ring_type.hpp>
38#include <boost/geometry/core/tag_cast.hpp>
39#include <boost/geometry/core/tags.hpp>
40#include <boost/geometry/geometries/concepts/check.hpp>
41#include <boost/geometry/strategies/default_strategy.hpp>
42#include <boost/geometry/strategies/transform.hpp>
43
44
45namespace boost { namespace geometry
46{
47
48#ifndef DOXYGEN_NO_DETAIL
49namespace detail { namespace transform
50{
51
52struct transform_point
53{
54 template <typename Point1, typename Point2, typename Strategy>
55 static inline bool apply(Point1 const& p1, Point2& p2,
56 Strategy const& strategy)
57 {
58 return strategy.apply(p1, p2);
59 }
60};
61
62
63struct transform_box
64{
65 template <typename Box1, typename Box2, typename Strategy>
66 static inline bool apply(Box1 const& b1, Box2& b2,
67 Strategy const& strategy)
68 {
69 typedef typename point_type<Box1>::type point_type1;
70 typedef typename point_type<Box2>::type point_type2;
71
72 point_type1 lower_left, upper_right;
73 geometry::detail::assign::assign_box_2d_corner<min_corner, min_corner>(
74 b1, lower_left);
75 geometry::detail::assign::assign_box_2d_corner<max_corner, max_corner>(
76 b1, upper_right);
77
78 point_type2 p1, p2;
79 if (strategy.apply(lower_left, p1) && strategy.apply(upper_right, p2))
80 {
81 // Create a valid box and therefore swap if necessary
82 typedef typename coordinate_type<point_type2>::type coordinate_type;
83 coordinate_type x1 = geometry::get<0>(p1)
84 , y1 = geometry::get<1>(p1)
85 , x2 = geometry::get<0>(p2)
86 , y2 = geometry::get<1>(p2);
87
88 if (x1 > x2) { std::swap(x1, x2); }
89 if (y1 > y2) { std::swap(y1, y2); }
90
91 geometry::set<min_corner, 0>(b2, x1);
92 geometry::set<min_corner, 1>(b2, y1);
93 geometry::set<max_corner, 0>(b2, x2);
94 geometry::set<max_corner, 1>(b2, y2);
95
96 return true;
97 }
98 return false;
99 }
100};
101
102struct transform_box_or_segment
103{
104 template <typename Geometry1, typename Geometry2, typename Strategy>
105 static inline bool apply(Geometry1 const& source, Geometry2& target,
106 Strategy const& strategy)
107 {
108 typedef typename point_type<Geometry1>::type point_type1;
109 typedef typename point_type<Geometry2>::type point_type2;
110
111 point_type1 source_point[2];
112 geometry::detail::assign_point_from_index<0>(source, source_point[0]);
113 geometry::detail::assign_point_from_index<1>(source, source_point[1]);
114
115 point_type2 target_point[2];
116 if (strategy.apply(source_point[0], target_point[0])
117 && strategy.apply(source_point[1], target_point[1]))
118 {
119 geometry::detail::assign_point_to_index<0>(target_point[0], target);
120 geometry::detail::assign_point_to_index<1>(target_point[1], target);
121 return true;
122 }
123 return false;
124 }
125};
126
127
128template
129<
130 typename PointOut,
131 typename OutputIterator,
132 typename Range,
133 typename Strategy
134>
135inline bool transform_range_out(Range const& range,
136 OutputIterator out, Strategy const& strategy)
137{
138 PointOut point_out;
139 for(typename boost::range_iterator<Range const>::type
140 it = boost::begin(range);
141 it != boost::end(range);
142 ++it)
143 {
144 if (! transform_point::apply(*it, point_out, strategy))
145 {
146 return false;
147 }
148 *out++ = point_out;
149 }
150 return true;
151}
152
153
154struct transform_polygon
155{
156 template <typename Polygon1, typename Polygon2, typename Strategy>
157 static inline bool apply(Polygon1 const& poly1, Polygon2& poly2,
158 Strategy const& strategy)
159 {
160 typedef typename point_type<Polygon2>::type point2_type;
161
162 geometry::clear(poly2);
163
164 if (!transform_range_out<point2_type>(geometry::exterior_ring(poly1),
165 range::back_inserter(geometry::exterior_ring(poly2)), strategy))
166 {
167 return false;
168 }
169
170 // Note: here a resizeable container is assumed.
171 traits::resize
172 <
173 typename boost::remove_reference
174 <
175 typename traits::interior_mutable_type<Polygon2>::type
176 >::type
177 >::apply(geometry::interior_rings(poly2),
178 geometry::num_interior_rings(poly1));
179
180 typename geometry::interior_return_type<Polygon1 const>::type
181 rings1 = geometry::interior_rings(poly1);
182 typename geometry::interior_return_type<Polygon2>::type
183 rings2 = geometry::interior_rings(poly2);
184
185 typename detail::interior_iterator<Polygon1 const>::type
186 it1 = boost::begin(rings1);
187 typename detail::interior_iterator<Polygon2>::type
188 it2 = boost::begin(rings2);
189 for ( ; it1 != boost::end(rings1); ++it1, ++it2)
190 {
191 if ( ! transform_range_out<point2_type>(*it1,
192 range::back_inserter(*it2),
193 strategy) )
194 {
195 return false;
196 }
197 }
198
199 return true;
200 }
201};
202
203
204template <typename Point1, typename Point2>
205struct select_strategy
206{
207 typedef typename strategy::transform::services::default_strategy
208 <
209 typename cs_tag<Point1>::type,
210 typename cs_tag<Point2>::type,
211 typename coordinate_system<Point1>::type,
212 typename coordinate_system<Point2>::type,
213 dimension<Point1>::type::value,
214 dimension<Point2>::type::value,
215 typename point_type<Point1>::type,
216 typename point_type<Point2>::type
217 >::type type;
218};
219
220struct transform_range
221{
222 template <typename Range1, typename Range2, typename Strategy>
223 static inline bool apply(Range1 const& range1,
224 Range2& range2, Strategy const& strategy)
225 {
226 typedef typename point_type<Range2>::type point_type;
227
228 // Should NOT be done here!
229 // geometry::clear(range2);
230 return transform_range_out<point_type>(range1,
231 range::back_inserter(range2), strategy);
232 }
233};
234
235
236/*!
237 \brief Is able to transform any multi-geometry, calling the single-version as policy
238*/
239template <typename Policy>
240struct transform_multi
241{
242 template <typename Multi1, typename Multi2, typename S>
243 static inline bool apply(Multi1 const& multi1, Multi2& multi2, S const& strategy)
244 {
245 traits::resize<Multi2>::apply(multi2, boost::size(multi1));
246
247 typename boost::range_iterator<Multi1 const>::type it1
248 = boost::begin(multi1);
249 typename boost::range_iterator<Multi2>::type it2
250 = boost::begin(multi2);
251
252 for (; it1 != boost::end(multi1); ++it1, ++it2)
253 {
254 if (! Policy::apply(*it1, *it2, strategy))
255 {
256 return false;
257 }
258 }
259
260 return true;
261 }
262};
263
264
265}} // namespace detail::transform
266#endif // DOXYGEN_NO_DETAIL
267
268
269#ifndef DOXYGEN_NO_DISPATCH
270namespace dispatch
271{
272
273template
274<
275 typename Geometry1, typename Geometry2,
276 typename Tag1 = typename tag_cast<typename tag<Geometry1>::type, multi_tag>::type,
277 typename Tag2 = typename tag_cast<typename tag<Geometry2>::type, multi_tag>::type
278>
279struct transform {};
280
281template <typename Point1, typename Point2>
282struct transform<Point1, Point2, point_tag, point_tag>
283 : detail::transform::transform_point
284{
285};
286
287
288template <typename Linestring1, typename Linestring2>
289struct transform
290 <
291 Linestring1, Linestring2,
292 linestring_tag, linestring_tag
293 >
294 : detail::transform::transform_range
295{
296};
297
298template <typename Range1, typename Range2>
299struct transform<Range1, Range2, ring_tag, ring_tag>
300 : detail::transform::transform_range
301{
302};
303
304template <typename Polygon1, typename Polygon2>
305struct transform<Polygon1, Polygon2, polygon_tag, polygon_tag>
306 : detail::transform::transform_polygon
307{
308};
309
310template <typename Box1, typename Box2>
311struct transform<Box1, Box2, box_tag, box_tag>
312 : detail::transform::transform_box
313{
314};
315
316template <typename Segment1, typename Segment2>
317struct transform<Segment1, Segment2, segment_tag, segment_tag>
318 : detail::transform::transform_box_or_segment
319{
320};
321
322template <typename Multi1, typename Multi2>
323struct transform
324 <
325 Multi1, Multi2,
326 multi_tag, multi_tag
327 >
328 : detail::transform::transform_multi
329 <
330 dispatch::transform
331 <
332 typename boost::range_value<Multi1>::type,
333 typename boost::range_value<Multi2>::type
334 >
335 >
336{};
337
338
339} // namespace dispatch
340#endif // DOXYGEN_NO_DISPATCH
341
342
343namespace resolve_strategy {
344
345struct transform
346{
347 template <typename Geometry1, typename Geometry2, typename Strategy>
348 static inline bool apply(Geometry1 const& geometry1,
349 Geometry2& geometry2,
350 Strategy const& strategy)
351 {
352 concepts::check<Geometry1 const>();
353 concepts::check<Geometry2>();
354
355 return dispatch::transform<Geometry1, Geometry2>::apply(
356 geometry1,
357 geometry2,
358 strategy
359 );
360 }
361
362 template <typename Geometry1, typename Geometry2>
363 static inline bool apply(Geometry1 const& geometry1,
364 Geometry2& geometry2,
365 default_strategy)
366 {
367 return apply(
368 geometry1,
369 geometry2,
370 typename detail::transform::select_strategy<Geometry1, Geometry2>::type()
371 );
372 }
373};
374
375} // namespace resolve_strategy
376
377
378namespace resolve_variant {
379
380template <typename Geometry1, typename Geometry2>
381struct transform
382{
383 template <typename Strategy>
384 static inline bool apply(Geometry1 const& geometry1,
385 Geometry2& geometry2,
386 Strategy const& strategy)
387 {
388 return resolve_strategy::transform::apply(
389 geometry1,
390 geometry2,
391 strategy
392 );
393 }
394};
395
396template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
397struct transform<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
398{
399 template <typename Strategy>
400 struct visitor: static_visitor<bool>
401 {
402 Geometry2& m_geometry2;
403 Strategy const& m_strategy;
404
405 visitor(Geometry2& geometry2, Strategy const& strategy)
406 : m_geometry2(geometry2)
407 , m_strategy(strategy)
408 {}
409
410 template <typename Geometry1>
411 inline bool operator()(Geometry1 const& geometry1) const
412 {
413 return transform<Geometry1, Geometry2>::apply(
414 geometry1,
415 m_geometry2,
416 m_strategy
417 );
418 }
419 };
420
421 template <typename Strategy>
422 static inline bool apply(
423 boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry1,
424 Geometry2& geometry2,
425 Strategy const& strategy
426 )
427 {
428 return boost::apply_visitor(visitor<Strategy>(geometry2, strategy), geometry1);
429 }
430};
431
432} // namespace resolve_variant
433
434
435/*!
436\brief Transforms from one geometry to another geometry \brief_strategy
437\ingroup transform
438\tparam Geometry1 \tparam_geometry
439\tparam Geometry2 \tparam_geometry
440\tparam Strategy strategy
441\param geometry1 \param_geometry
442\param geometry2 \param_geometry
443\param strategy The strategy to be used for transformation
444\return True if the transformation could be done
445
446\qbk{distinguish,with strategy}
447
448\qbk{[include reference/algorithms/transform_with_strategy.qbk]}
449 */
450template <typename Geometry1, typename Geometry2, typename Strategy>
451inline bool transform(Geometry1 const& geometry1, Geometry2& geometry2,
452 Strategy const& strategy)
453{
454 return resolve_variant::transform<Geometry1, Geometry2>
455 ::apply(geometry1, geometry2, strategy);
456}
457
458
459/*!
460\brief Transforms from one geometry to another geometry using a strategy
461\ingroup transform
462\tparam Geometry1 \tparam_geometry
463\tparam Geometry2 \tparam_geometry
464\param geometry1 \param_geometry
465\param geometry2 \param_geometry
466\return True if the transformation could be done
467
468\qbk{[include reference/algorithms/transform.qbk]}
469 */
470template <typename Geometry1, typename Geometry2>
471inline bool transform(Geometry1 const& geometry1, Geometry2& geometry2)
472{
473 return geometry::transform(geometry1, geometry2, default_strategy());
474}
475
476
477}} // namespace boost::geometry
478
479
480#endif // BOOST_GEOMETRY_ALGORITHMS_TRANSFORM_HPP