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
48 namespace 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 */
70 template <typename Geometry, typename Range>
assign_points(Geometry & geometry,Range const & range)71 inline 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
83 min corner is very large, the max corner is very small. This is a convenient starting point to
84 collect 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 */
97 template <typename Geometry>
assign_inverse(Geometry & geometry)98 inline 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 */
117 template <typename Geometry>
assign_zero(Geometry & geometry)118 inline 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 */
147 template <typename Geometry, typename Type>
assign_values(Geometry & geometry,Type const & c1,Type const & c2)148 inline 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 */
179 template <typename Geometry, typename Type>
assign_values(Geometry & geometry,Type const & c1,Type const & c2,Type const & c3)180 inline 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 */
206 template <typename Geometry, typename Type>
assign_values(Geometry & geometry,Type const & c1,Type const & c2,Type const & c3,Type const & c4)207 inline 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
222 namespace resolve_variant
223 {
224
225 template <typename Geometry1, typename Geometry2>
226 struct assign
227 {
228 static inline void
applyboost::geometry::resolve_variant::assign229 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
257 template <BOOST_VARIANT_ENUM_PARAMS(typename T), typename Geometry2>
258 struct assign<variant<BOOST_VARIANT_ENUM_PARAMS(T)>, Geometry2>
259 {
260 struct visitor: static_visitor<void>
261 {
262 Geometry2 const& m_geometry2;
263
visitorboost::geometry::resolve_variant::assign::visitor264 visitor(Geometry2 const& geometry2)
265 : m_geometry2(geometry2)
266 {}
267
268 template <typename Geometry1>
operator ()boost::geometry::resolve_variant::assign::visitor269 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
applyboost::geometry::resolve_variant::assign281 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
289 template <typename Geometry1, BOOST_VARIANT_ENUM_PARAMS(typename T)>
290 struct assign<Geometry1, variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
291 {
292 struct visitor: static_visitor<void>
293 {
294 Geometry1& m_geometry1;
295
visitorboost::geometry::resolve_variant::assign::visitor296 visitor(Geometry1 const& geometry1)
297 : m_geometry1(geometry1)
298 {}
299
300 template <typename Geometry2>
operator ()boost::geometry::resolve_variant::assign::visitor301 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
applyboost::geometry::resolve_variant::assign313 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
321 template <BOOST_VARIANT_ENUM_PARAMS(typename T1), BOOST_VARIANT_ENUM_PARAMS(typename T2)>
322 struct 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>
operator ()boost::geometry::resolve_variant::assign::visitor327 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
applyboost::geometry::resolve_variant::assign341 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
354 geometry, 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 */
369 template <typename Geometry1, typename Geometry2>
assign(Geometry1 & geometry1,Geometry2 const & geometry2)370 inline 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