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