Imported Upstream version 1.57.0
[platform/upstream/boost.git] / boost / geometry / algorithms / assign.hpp
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 Samuel Debionne, Grenoble, France.
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_ASSIGN_HPP
16 #define BOOST_GEOMETRY_ALGORITHMS_ASSIGN_HPP
17
18
19 #include <cstddef>
20
21 #include <boost/concept/requires.hpp>
22 #include <boost/concept_check.hpp>
23 #include <boost/mpl/assert.hpp>
24 #include <boost/mpl/if.hpp>
25 #include <boost/numeric/conversion/bounds.hpp>
26 #include <boost/numeric/conversion/cast.hpp>
27 #include <boost/type_traits.hpp>
28
29 #include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
30 #include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
31 #include <boost/geometry/algorithms/detail/assign_values.hpp>
32 #include <boost/geometry/algorithms/convert.hpp>
33 #include <boost/geometry/algorithms/append.hpp>
34 #include <boost/geometry/algorithms/clear.hpp>
35 #include <boost/geometry/arithmetic/arithmetic.hpp>
36 #include <boost/geometry/core/access.hpp>
37 #include <boost/geometry/core/exterior_ring.hpp>
38 #include <boost/geometry/core/tags.hpp>
39
40 #include <boost/geometry/geometries/concepts/check.hpp>
41
42 #include <boost/geometry/util/for_each_coordinate.hpp>
43
44 #include <boost/variant/variant_fwd.hpp>
45
46 namespace boost { namespace geometry
47 {
48
49 /*!
50 \brief Assign a range of points to a linestring, ring or polygon
51 \note The point-type of the range might be different from the point-type of the geometry
52 \ingroup assign
53 \tparam Geometry \tparam_geometry
54 \tparam Range \tparam_range_point
55 \param geometry \param_geometry
56 \param range \param_range_point
57
58 \qbk{
59 [heading Notes]
60 [note Assign automatically clears the geometry before assigning (use append if you don't want that)]
61 [heading Example]
62 [assign_points] [assign_points_output]
63
64 [heading See also]
65 \* [link geometry.reference.algorithms.append append]
66 }
67  */
68 template <typename Geometry, typename Range>
69 inline void assign_points(Geometry& geometry, Range const& range)
70 {
71     concept::check<Geometry>();
72
73     clear(geometry);
74     geometry::append(geometry, range, -1, 0);
75 }
76
77
78 /*!
79 \brief assign to a box inverse infinite
80 \details The assign_inverse function initialize a 2D or 3D box with large coordinates, the
81 min corner is very large, the max corner is very small. This is a convenient starting point to
82 collect the minimum bounding box of a geometry.
83 \ingroup assign
84 \tparam Geometry \tparam_geometry
85 \param geometry \param_geometry
86
87 \qbk{
88 [heading Example]
89 [assign_inverse] [assign_inverse_output]
90
91 [heading See also]
92 \* [link geometry.reference.algorithms.make.make_inverse make_inverse]
93 }
94  */
95 template <typename Geometry>
96 inline void assign_inverse(Geometry& geometry)
97 {
98     concept::check<Geometry>();
99
100     dispatch::assign_inverse
101         <
102             typename tag<Geometry>::type,
103             Geometry
104         >::apply(geometry);
105 }
106
107 /*!
108 \brief assign zero values to a box, point
109 \ingroup assign
110 \details The assign_zero function initializes a 2D or 3D point or box with coordinates of zero
111 \tparam Geometry \tparam_geometry
112 \param geometry \param_geometry
113
114  */
115 template <typename Geometry>
116 inline void assign_zero(Geometry& geometry)
117 {
118     concept::check<Geometry>();
119
120     dispatch::assign_zero
121         <
122             typename tag<Geometry>::type,
123             Geometry
124         >::apply(geometry);
125 }
126
127 /*!
128 \brief Assign two coordinates to a geometry (usually a 2D point)
129 \ingroup assign
130 \tparam Geometry \tparam_geometry
131 \tparam Type \tparam_numeric to specify the coordinates
132 \param geometry \param_geometry
133 \param c1 \param_x
134 \param c2 \param_y
135
136 \qbk{distinguish, 2 coordinate values}
137 \qbk{
138 [heading Example]
139 [assign_2d_point] [assign_2d_point_output]
140
141 [heading See also]
142 \* [link geometry.reference.algorithms.make.make_2_2_coordinate_values make]
143 }
144  */
145 template <typename Geometry, typename Type>
146 inline void assign_values(Geometry& geometry, Type const& c1, Type const& c2)
147 {
148     concept::check<Geometry>();
149
150     dispatch::assign
151         <
152             typename tag<Geometry>::type,
153             Geometry,
154             geometry::dimension<Geometry>::type::value
155         >::apply(geometry, c1, c2);
156 }
157
158 /*!
159 \brief Assign three values to a geometry (usually a 3D point)
160 \ingroup assign
161 \tparam Geometry \tparam_geometry
162 \tparam Type \tparam_numeric to specify the coordinates
163 \param geometry \param_geometry
164 \param c1 \param_x
165 \param c2 \param_y
166 \param c3 \param_z
167
168 \qbk{distinguish, 3 coordinate values}
169 \qbk{
170 [heading Example]
171 [assign_3d_point] [assign_3d_point_output]
172
173 [heading See also]
174 \* [link geometry.reference.algorithms.make.make_3_3_coordinate_values make]
175 }
176  */
177 template <typename Geometry, typename Type>
178 inline void assign_values(Geometry& geometry,
179             Type const& c1, Type const& c2, Type const& c3)
180 {
181     concept::check<Geometry>();
182
183     dispatch::assign
184         <
185             typename tag<Geometry>::type,
186             Geometry,
187             geometry::dimension<Geometry>::type::value
188         >::apply(geometry, c1, c2, c3);
189 }
190
191 /*!
192 \brief Assign four values to a geometry (usually a box or segment)
193 \ingroup assign
194 \tparam Geometry \tparam_geometry
195 \tparam Type \tparam_numeric to specify the coordinates
196 \param geometry \param_geometry
197 \param c1 First coordinate (usually x1)
198 \param c2 Second coordinate (usually y1)
199 \param c3 Third coordinate (usually x2)
200 \param c4 Fourth coordinate (usually y2)
201
202 \qbk{distinguish, 4 coordinate values}
203  */
204 template <typename Geometry, typename Type>
205 inline void assign_values(Geometry& geometry,
206                 Type const& c1, Type const& c2, Type const& c3, Type const& c4)
207 {
208     concept::check<Geometry>();
209
210     dispatch::assign
211         <
212             typename tag<Geometry>::type,
213             Geometry,
214             geometry::dimension<Geometry>::type::value
215         >::apply(geometry, c1, c2, c3, c4);
216 }
217
218
219
220 namespace resolve_variant
221 {
222
223 template <typename Geometry1, typename Geometry2>
224 struct assign
225 {
226     static inline void
227     apply(
228             Geometry1& geometry1,
229             const Geometry2& geometry2)
230     {
231         concept::check<Geometry1>();
232         concept::check<Geometry2 const>();
233         concept::check_concepts_and_equal_dimensions<Geometry1, Geometry2 const>();
234             
235         bool const same_point_order =
236             point_order<Geometry1>::value == point_order<Geometry2>::value;
237         bool const same_closure =
238             closure<Geometry1>::value == closure<Geometry2>::value;
239             
240         BOOST_MPL_ASSERT_MSG
241         (
242                 same_point_order, ASSIGN_IS_NOT_SUPPORTED_FOR_DIFFERENT_POINT_ORDER
243                 , (types<Geometry1, Geometry2>)
244         );
245         BOOST_MPL_ASSERT_MSG
246         (
247                 same_closure, ASSIGN_IS_NOT_SUPPORTED_FOR_DIFFERENT_CLOSURE
248                 , (types<Geometry1, Geometry2>)
249         );
250             
251         dispatch::convert<Geometry2, Geometry1>::apply(geometry2, geometry1);
252     }
253 };
254     
255     
256 template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
257 struct assign<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
258 {
259     struct visitor: static_visitor<void>
260     {
261         Geometry2 const& m_geometry2;
262             
263         visitor(Geometry2 const& geometry2)
264         : m_geometry2(geometry2)
265         {}
266             
267         template <typename Geometry1>
268         result_type operator()(Geometry1& geometry1) const
269         {
270             return assign
271             <
272                 Geometry1,
273                 Geometry2
274             >::apply
275             (geometry1, m_geometry2);
276         }
277     };
278         
279     static inline void
280     apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry1,
281           Geometry2 const& geometry2)
282     {
283         return apply_visitor(visitor(geometry2), geometry1);
284     }
285 };
286     
287     
288 template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
289 struct assign<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
290 {
291     struct visitor: static_visitor<void>
292     {
293         Geometry1& m_geometry1;
294             
295         visitor(Geometry1 const& geometry1)
296         : m_geometry1(geometry1)
297         {}
298             
299         template <typename Geometry2>
300         result_type operator()(Geometry2 const& geometry2) const
301         {
302             return assign
303             <
304                 Geometry1,
305                 Geometry2
306             >::apply
307             (m_geometry1, geometry2);
308         }
309     };
310         
311     static inline void
312     apply(Geometry1& geometry1,
313           variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2)
314     {
315         return apply_visitor(visitor(geometry1), geometry2);
316     }
317 };
318     
319     
320 template <BOOST_VARIANT_ENUM_PARAMS(typename A), BOOST_VARIANT_ENUM_PARAMS(typename B)>
321 struct assign<variant<BOOST_VARIANT_ENUM_PARAMS(A)>, variant<BOOST_VARIANT_ENUM_PARAMS(B)> >
322 {
323     struct visitor: static_visitor<void>
324     {
325         template <typename Geometry1, typename Geometry2>
326         result_type operator()(
327                                 Geometry1& geometry1,
328                                 Geometry2 const& geometry2) const
329         {
330             return assign
331             <
332                 Geometry1,
333                 Geometry2
334             >::apply
335             (geometry1, geometry2);
336         }
337     };
338         
339     static inline void
340     apply(variant<BOOST_VARIANT_ENUM_PARAMS(A)>& geometry1,
341           variant<BOOST_VARIANT_ENUM_PARAMS(B)> const& geometry2)
342     {
343         return apply_visitor(visitor(), geometry1, geometry2);
344     }
345 };
346     
347 } // namespace resolve_variant
348     
349
350 /*!
351 \brief Assigns one geometry to another geometry
352 \details The assign algorithm assigns one geometry, e.g. a BOX, to another
353 geometry, e.g. a RING. This only works if it is possible and applicable.
354 \ingroup assign
355 \tparam Geometry1 \tparam_geometry
356 \tparam Geometry2 \tparam_geometry
357 \param geometry1 \param_geometry (target)
358 \param geometry2 \param_geometry (source)
359
360 \qbk{
361 [heading Example]
362 [assign] [assign_output]
363
364 [heading See also]
365 \* [link geometry.reference.algorithms.convert convert]
366 }
367  */
368 template <typename Geometry1, typename Geometry2>
369 inline void assign(Geometry1& geometry1, Geometry2 const& geometry2)
370 {
371     resolve_variant::assign<Geometry1, Geometry2>::apply(geometry1, geometry2);
372 }
373
374
375 }} // namespace boost::geometry
376
377
378
379 #endif // BOOST_GEOMETRY_ALGORITHMS_ASSIGN_HPP