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