]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
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> | |
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> | |
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> | |
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> | |
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> | |
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> | |
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 | |
228 | 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 | ||
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 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 | ||
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 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> | |
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(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> | |
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 |