• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
28 #include <boost/variant/apply_visitor.hpp>
29 #include <boost/variant/static_visitor.hpp>
30 #include <boost/variant/variant_fwd.hpp>
31 
32 #include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
33 #include <boost/geometry/algorithms/detail/assign_indexed_point.hpp>
34 #include <boost/geometry/algorithms/detail/assign_values.hpp>
35 #include <boost/geometry/algorithms/convert.hpp>
36 #include <boost/geometry/algorithms/append.hpp>
37 #include <boost/geometry/algorithms/clear.hpp>
38 #include <boost/geometry/arithmetic/arithmetic.hpp>
39 #include <boost/geometry/core/access.hpp>
40 #include <boost/geometry/core/exterior_ring.hpp>
41 #include <boost/geometry/core/tags.hpp>
42 
43 #include <boost/geometry/geometries/concepts/check.hpp>
44 
45 #include <boost/geometry/util/for_each_coordinate.hpp>
46 
47 namespace boost { namespace geometry
48 {
49 
50 /*!
51 \brief Assign a range of points to a linestring, ring or polygon
52 \note The point-type of the range might be different from the point-type of the geometry
53 \ingroup assign
54 \tparam Geometry \tparam_geometry
55 \tparam Range \tparam_range_point
56 \param geometry \param_geometry
57 \param range \param_range_point
58 
59 \qbk{
60 [heading Notes]
61 [note Assign automatically clears the geometry before assigning (use append if you don't want that)]
62 [heading Example]
63 [assign_points] [assign_points_output]
64 
65 [heading See also]
66 \* [link geometry.reference.algorithms.append append]
67 }
68  */
69 template <typename Geometry, typename Range>
assign_points(Geometry & geometry,Range const & range)70 inline void assign_points(Geometry& geometry, Range const& range)
71 {
72     concepts::check<Geometry>();
73 
74     clear(geometry);
75     geometry::append(geometry, range, -1, 0);
76 }
77 
78 
79 /*!
80 \brief assign to a box inverse infinite
81 \details The assign_inverse function initialize a 2D or 3D box with large coordinates, the
82 min corner is very large, the max corner is very small. This is a convenient starting point to
83 collect the minimum bounding box of a geometry.
84 \ingroup assign
85 \tparam Geometry \tparam_geometry
86 \param geometry \param_geometry
87 
88 \qbk{
89 [heading Example]
90 [assign_inverse] [assign_inverse_output]
91 
92 [heading See also]
93 \* [link geometry.reference.algorithms.make.make_inverse make_inverse]
94 }
95  */
96 template <typename Geometry>
assign_inverse(Geometry & geometry)97 inline void assign_inverse(Geometry& geometry)
98 {
99     concepts::check<Geometry>();
100 
101     dispatch::assign_inverse
102         <
103             typename tag<Geometry>::type,
104             Geometry
105         >::apply(geometry);
106 }
107 
108 /*!
109 \brief assign zero values to a box, point
110 \ingroup assign
111 \details The assign_zero function initializes a 2D or 3D point or box with coordinates of zero
112 \tparam Geometry \tparam_geometry
113 \param geometry \param_geometry
114 
115  */
116 template <typename Geometry>
assign_zero(Geometry & geometry)117 inline void assign_zero(Geometry& geometry)
118 {
119     concepts::check<Geometry>();
120 
121     dispatch::assign_zero
122         <
123             typename tag<Geometry>::type,
124             Geometry
125         >::apply(geometry);
126 }
127 
128 /*!
129 \brief Assign two coordinates to a geometry (usually a 2D point)
130 \ingroup assign
131 \tparam Geometry \tparam_geometry
132 \tparam Type \tparam_numeric to specify the coordinates
133 \param geometry \param_geometry
134 \param c1 \param_x
135 \param c2 \param_y
136 
137 \qbk{distinguish, 2 coordinate values}
138 \qbk{
139 [heading Example]
140 [assign_2d_point] [assign_2d_point_output]
141 
142 [heading See also]
143 \* [link geometry.reference.algorithms.make.make_2_2_coordinate_values make]
144 }
145  */
146 template <typename Geometry, typename Type>
assign_values(Geometry & geometry,Type const & c1,Type const & c2)147 inline void assign_values(Geometry& geometry, Type const& c1, Type const& c2)
148 {
149     concepts::check<Geometry>();
150 
151     dispatch::assign
152         <
153             typename tag<Geometry>::type,
154             Geometry,
155             geometry::dimension<Geometry>::type::value
156         >::apply(geometry, c1, c2);
157 }
158 
159 /*!
160 \brief Assign three values to a geometry (usually a 3D point)
161 \ingroup assign
162 \tparam Geometry \tparam_geometry
163 \tparam Type \tparam_numeric to specify the coordinates
164 \param geometry \param_geometry
165 \param c1 \param_x
166 \param c2 \param_y
167 \param c3 \param_z
168 
169 \qbk{distinguish, 3 coordinate values}
170 \qbk{
171 [heading Example]
172 [assign_3d_point] [assign_3d_point_output]
173 
174 [heading See also]
175 \* [link geometry.reference.algorithms.make.make_3_3_coordinate_values make]
176 }
177  */
178 template <typename Geometry, typename Type>
assign_values(Geometry & geometry,Type const & c1,Type const & c2,Type const & c3)179 inline void assign_values(Geometry& geometry,
180             Type const& c1, Type const& c2, Type const& c3)
181 {
182     concepts::check<Geometry>();
183 
184     dispatch::assign
185         <
186             typename tag<Geometry>::type,
187             Geometry,
188             geometry::dimension<Geometry>::type::value
189         >::apply(geometry, c1, c2, c3);
190 }
191 
192 /*!
193 \brief Assign four values to a geometry (usually a box or segment)
194 \ingroup assign
195 \tparam Geometry \tparam_geometry
196 \tparam Type \tparam_numeric to specify the coordinates
197 \param geometry \param_geometry
198 \param c1 First coordinate (usually x1)
199 \param c2 Second coordinate (usually y1)
200 \param c3 Third coordinate (usually x2)
201 \param c4 Fourth coordinate (usually y2)
202 
203 \qbk{distinguish, 4 coordinate values}
204  */
205 template <typename Geometry, typename Type>
assign_values(Geometry & geometry,Type const & c1,Type const & c2,Type const & c3,Type const & c4)206 inline void assign_values(Geometry& geometry,
207                 Type const& c1, Type const& c2, Type const& c3, Type const& c4)
208 {
209     concepts::check<Geometry>();
210 
211     dispatch::assign
212         <
213             typename tag<Geometry>::type,
214             Geometry,
215             geometry::dimension<Geometry>::type::value
216         >::apply(geometry, c1, c2, c3, c4);
217 }
218 
219 
220 
221 namespace resolve_variant
222 {
223 
224 template <typename Geometry1, typename Geometry2>
225 struct assign
226 {
227     static inline void
applyboost::geometry::resolve_variant::assign228     apply(Geometry1& geometry1, const Geometry2& geometry2)
229     {
230         concepts::check<Geometry1>();
231         concepts::check<Geometry2 const>();
232         concepts::check_concepts_and_equal_dimensions<Geometry1, Geometry2 const>();
233 
234         static bool const same_point_order
235             = point_order<Geometry1>::value == point_order<Geometry2>::value;
236         BOOST_MPL_ASSERT_MSG
237         (
238             (same_point_order),
239             ASSIGN_IS_NOT_SUPPORTED_FOR_DIFFERENT_POINT_ORDER,
240             (types<Geometry1, Geometry2>)
241         );
242         static bool const same_closure
243             = closure<Geometry1>::value == closure<Geometry2>::value;
244         BOOST_MPL_ASSERT_MSG
245         (
246             (same_closure),
247             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 
visitorboost::geometry::resolve_variant::assign::visitor263         visitor(Geometry2 const& geometry2)
264         : m_geometry2(geometry2)
265         {}
266 
267         template <typename Geometry1>
operator ()boost::geometry::resolve_variant::assign::visitor268         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
applyboost::geometry::resolve_variant::assign280     apply(variant<BOOST_VARIANT_ENUM_PARAMS(T)>& geometry1,
281           Geometry2 const& geometry2)
282     {
283         return boost::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 
visitorboost::geometry::resolve_variant::assign::visitor295         visitor(Geometry1 const& geometry1)
296         : m_geometry1(geometry1)
297         {}
298 
299         template <typename Geometry2>
operator ()boost::geometry::resolve_variant::assign::visitor300         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
applyboost::geometry::resolve_variant::assign312     apply(Geometry1& geometry1,
313           variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry2)
314     {
315         return boost::apply_visitor(visitor(geometry1), geometry2);
316     }
317 };
318 
319 
320 template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
321 struct assign<variant<BOOST_VARIANT_ENUM_PARAMS(T1)>, variant<BOOST_VARIANT_ENUM_PARAMS(T2)> >
322 {
323     struct visitor: static_visitor<void>
324     {
325         template <typename Geometry1, typename Geometry2>
operator ()boost::geometry::resolve_variant::assign::visitor326         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
applyboost::geometry::resolve_variant::assign340     apply(variant<BOOST_VARIANT_ENUM_PARAMS(T1)>& geometry1,
341           variant<BOOST_VARIANT_ENUM_PARAMS(T2)> const& geometry2)
342     {
343         return boost::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>
assign(Geometry1 & geometry1,Geometry2 const & 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
380