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

source code of boost/boost/geometry/algorithms/assign.hpp