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 
7 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
8 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
9 
10 // This file was modified by Oracle on 2018-2020.
11 // Modifications copyright (c) 2018-2020, Oracle and/or its affiliates.
12 
13 // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
14 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
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_VALUES_HPP
21 #define BOOST_GEOMETRY_ALGORITHMS_ASSIGN_VALUES_HPP
22 
23 
24 #include <cstddef>
25 #include <type_traits>
26 
27 #include <boost/concept/requires.hpp>
28 #include <boost/concept_check.hpp>
29 #include <boost/numeric/conversion/bounds.hpp>
30 #include <boost/numeric/conversion/cast.hpp>
31 
32 #include <boost/geometry/arithmetic/arithmetic.hpp>
33 #include <boost/geometry/algorithms/append.hpp>
34 #include <boost/geometry/algorithms/clear.hpp>
35 #include <boost/geometry/core/access.hpp>
36 #include <boost/geometry/core/exterior_ring.hpp>
37 #include <boost/geometry/core/static_assert.hpp>
38 #include <boost/geometry/core/tags.hpp>
39 
40 #include <boost/geometry/geometries/concepts/check.hpp>
41 
42 #include <boost/geometry/util/is_inverse_spheroidal_coordinates.hpp>
43 #include <boost/geometry/util/for_each_coordinate.hpp>
44 
45 
46 namespace boost { namespace geometry
47 {
48 
49 #ifndef DOXYGEN_NO_DETAIL
50 namespace detail { namespace assign
51 {
52 
53 
54 template <std::size_t Index, std::size_t Dimension, std::size_t DimensionCount>
55 struct initialize
56 {
57     template <typename Box>
applyboost::geometry::detail::assign::initialize58     static inline void apply(Box& box, typename coordinate_type<Box>::type const& value)
59     {
60         geometry::set<Index, Dimension>(box, value);
61         initialize<Index, Dimension + 1, DimensionCount>::apply(box, value);
62     }
63 };
64 
65 
66 template <std::size_t Index, std::size_t DimensionCount>
67 struct initialize<Index, DimensionCount, DimensionCount>
68 {
69     template <typename Box>
applyboost::geometry::detail::assign::initialize70     static inline void apply(Box&, typename coordinate_type<Box>::type const&)
71     {}
72 };
73 
74 
75 struct assign_zero_point
76 {
77     template <typename Point>
applyboost::geometry::detail::assign::assign_zero_point78     static inline void apply(Point& point)
79     {
80         geometry::assign_value(point, 0);
81     }
82 };
83 
84 
85 struct assign_inverse_box_or_segment
86 {
87 
88     template <typename BoxOrSegment>
applyboost::geometry::detail::assign::assign_inverse_box_or_segment89     static inline void apply(BoxOrSegment& geometry)
90     {
91         typedef typename point_type<BoxOrSegment>::type point_type;
92         typedef typename coordinate_type<point_type>::type bound_type;
93 
94         initialize<0, 0, dimension<BoxOrSegment>::type::value>::apply(
95             geometry, geometry::bounds<bound_type>::highest()
96         );
97         initialize<1, 0, dimension<BoxOrSegment>::type::value>::apply(
98             geometry, geometry::bounds<bound_type>::lowest()
99         );
100     }
101 
102 };
103 
104 
105 struct assign_zero_box_or_segment
106 {
107     template <typename BoxOrSegment>
applyboost::geometry::detail::assign::assign_zero_box_or_segment108     static inline void apply(BoxOrSegment& geometry)
109     {
110         typedef typename coordinate_type<BoxOrSegment>::type coordinate_type;
111 
112         initialize<0, 0, dimension<BoxOrSegment>::type::value>::apply(
113             geometry, coordinate_type()
114         );
115         initialize<1, 0, dimension<BoxOrSegment>::type::value>::apply(
116             geometry, coordinate_type()
117         );
118     }
119 };
120 
121 
122 template
123 <
124     std::size_t Corner1, std::size_t Corner2,
125     typename Box, typename Point
126 >
assign_box_2d_corner(Box const & box,Point & point)127 inline void assign_box_2d_corner(Box const& box, Point& point)
128 {
129     // Be sure both are 2-Dimensional
130     assert_dimension<Box, 2>();
131     assert_dimension<Point, 2>();
132 
133     // Copy coordinates
134     typedef typename coordinate_type<Point>::type coordinate_type;
135 
136     geometry::set<0>(point, boost::numeric_cast<coordinate_type>(get<Corner1, 0>(box)));
137     geometry::set<1>(point, boost::numeric_cast<coordinate_type>(get<Corner2, 1>(box)));
138 }
139 
140 
141 
142 template
143 <
144     typename Geometry, typename Point,
145     std::size_t Index,
146     std::size_t Dimension, std::size_t DimensionCount
147 >
148 struct assign_point_to_index
149 {
150 
applyboost::geometry::detail::assign::assign_point_to_index151     static inline void apply(Point const& point, Geometry& geometry)
152     {
153         geometry::set<Index, Dimension>(geometry, boost::numeric_cast
154             <
155                 typename coordinate_type<Geometry>::type
156             >(geometry::get<Dimension>(point)));
157 
158         assign_point_to_index
159             <
160                 Geometry, Point, Index, Dimension + 1, DimensionCount
161             >::apply(point, geometry);
162     }
163 };
164 
165 template
166 <
167     typename Geometry, typename Point,
168     std::size_t Index,
169     std::size_t DimensionCount
170 >
171 struct assign_point_to_index
172     <
173         Geometry, Point,
174         Index,
175         DimensionCount, DimensionCount
176     >
177 {
applyboost::geometry::detail::assign::assign_point_to_index178     static inline void apply(Point const& , Geometry& )
179     {
180     }
181 };
182 
183 
184 template
185 <
186     typename Geometry, typename Point,
187     std::size_t Index,
188     std::size_t Dimension, std::size_t DimensionCount
189 >
190 struct assign_point_from_index
191 {
192 
applyboost::geometry::detail::assign::assign_point_from_index193     static inline void apply(Geometry const& geometry, Point& point)
194     {
195         geometry::set<Dimension>( point, boost::numeric_cast
196             <
197                 typename coordinate_type<Point>::type
198             >(geometry::get<Index, Dimension>(geometry)));
199 
200         assign_point_from_index
201             <
202                 Geometry, Point, Index, Dimension + 1, DimensionCount
203             >::apply(geometry, point);
204     }
205 };
206 
207 template
208 <
209     typename Geometry, typename Point,
210     std::size_t Index,
211     std::size_t DimensionCount
212 >
213 struct assign_point_from_index
214     <
215         Geometry, Point,
216         Index,
217         DimensionCount, DimensionCount
218     >
219 {
applyboost::geometry::detail::assign::assign_point_from_index220     static inline void apply(Geometry const&, Point&)
221     {
222     }
223 };
224 
225 
226 template <typename Geometry>
227 struct assign_2d_box_or_segment
228 {
229     typedef typename coordinate_type<Geometry>::type coordinate_type;
230 
231     // Here we assign 4 coordinates to a box of segment
232     // -> Most logical is: x1,y1,x2,y2
233     // In case the user reverses x1/x2 or y1/y2, for a box, we could reverse them (THAT IS NOT IMPLEMENTED)
234 
235     template <typename Type>
applyboost::geometry::detail::assign::assign_2d_box_or_segment236     static inline void apply(Geometry& geometry,
237                 Type const& x1, Type const& y1, Type const& x2, Type const& y2)
238     {
239         geometry::set<0, 0>(geometry, boost::numeric_cast<coordinate_type>(x1));
240         geometry::set<0, 1>(geometry, boost::numeric_cast<coordinate_type>(y1));
241         geometry::set<1, 0>(geometry, boost::numeric_cast<coordinate_type>(x2));
242         geometry::set<1, 1>(geometry, boost::numeric_cast<coordinate_type>(y2));
243     }
244 };
245 
246 
247 }} // namespace detail::assign
248 #endif // DOXYGEN_NO_DETAIL
249 
250 #ifndef DOXYGEN_NO_DISPATCH
251 namespace dispatch
252 {
253 
254 template <typename GeometryTag, typename Geometry, std::size_t DimensionCount>
255 struct assign
256 {
257     BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
258         "Not or not yet implemented for this Geometry type.",
259         GeometryTag, Geometry, std::integral_constant<std::size_t, DimensionCount>);
260 };
261 
262 template <typename Point>
263 struct assign<point_tag, Point, 2>
264 {
265     typedef typename coordinate_type<Point>::type coordinate_type;
266 
267     template <typename T>
applyboost::geometry::dispatch::assign268     static inline void apply(Point& point, T const& c1, T const& c2)
269     {
270         set<0>(point, boost::numeric_cast<coordinate_type>(c1));
271         set<1>(point, boost::numeric_cast<coordinate_type>(c2));
272     }
273 };
274 
275 template <typename Point>
276 struct assign<point_tag, Point, 3>
277 {
278     typedef typename coordinate_type<Point>::type coordinate_type;
279 
280     template <typename T>
applyboost::geometry::dispatch::assign281     static inline void apply(Point& point, T const& c1, T const& c2, T const& c3)
282     {
283         set<0>(point, boost::numeric_cast<coordinate_type>(c1));
284         set<1>(point, boost::numeric_cast<coordinate_type>(c2));
285         set<2>(point, boost::numeric_cast<coordinate_type>(c3));
286     }
287 };
288 
289 template <typename Box>
290 struct assign<box_tag, Box, 2>
291     : detail::assign::assign_2d_box_or_segment<Box>
292 {};
293 
294 template <typename Segment>
295 struct assign<segment_tag, Segment, 2>
296     : detail::assign::assign_2d_box_or_segment<Segment>
297 {};
298 
299 
300 
301 template <typename GeometryTag, typename Geometry>
302 struct assign_zero {};
303 
304 
305 template <typename Point>
306 struct assign_zero<point_tag, Point>
307     : detail::assign::assign_zero_point
308 {};
309 
310 template <typename Box>
311 struct assign_zero<box_tag, Box>
312     : detail::assign::assign_zero_box_or_segment
313 {};
314 
315 template <typename Segment>
316 struct assign_zero<segment_tag, Segment>
317     : detail::assign::assign_zero_box_or_segment
318 {};
319 
320 
321 template <typename GeometryTag, typename Geometry>
322 struct assign_inverse {};
323 
324 template <typename Box>
325 struct assign_inverse<box_tag, Box>
326     : detail::assign::assign_inverse_box_or_segment
327 {};
328 
329 template <typename Segment>
330 struct assign_inverse<segment_tag, Segment>
331     : detail::assign::assign_inverse_box_or_segment
332 {};
333 
334 
335 } // namespace dispatch
336 #endif // DOXYGEN_NO_DISPATCH
337 
338 }} // namespace boost::geometry
339 
340 
341 #endif // BOOST_GEOMETRY_ALGORITHMS_ASSIGN_VALUES_HPP
342