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> |
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> |
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> |
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> |
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> |
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> |
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 |
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 | |
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 | |
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 | |
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 | |
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 | |
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> |
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 |
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> |
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 | |