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.
11 // Modifications copyright (c) 2018, Oracle and/or its affiliates.
12 
13 // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
14 
15 // Use, modification and distribution is subject to the Boost Software License,
16 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
17 // http://www.boost.org/LICENSE_1_0.txt)
18 
19 #ifndef BOOST_GEOMETRY_ALGORITHMS_ASSIGN_VALUES_HPP
20 #define BOOST_GEOMETRY_ALGORITHMS_ASSIGN_VALUES_HPP
21 
22 
23 #include <cstddef>
24 
25 #include <boost/concept/requires.hpp>
26 #include <boost/concept_check.hpp>
27 #include <boost/mpl/assert.hpp>
28 #include <boost/mpl/if.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/tags.hpp>
38 
39 #include <boost/geometry/geometries/concepts/check.hpp>
40 
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_MPL_ASSERT_MSG
258         (
259             false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
260             , (types<Geometry>)
261         );
262 };
263 
264 template <typename Point>
265 struct assign<point_tag, Point, 2>
266 {
267     typedef typename coordinate_type<Point>::type coordinate_type;
268 
269     template <typename T>
applyboost::geometry::dispatch::assign270     static inline void apply(Point& point, T const& c1, T const& c2)
271     {
272         set<0>(point, boost::numeric_cast<coordinate_type>(c1));
273         set<1>(point, boost::numeric_cast<coordinate_type>(c2));
274     }
275 };
276 
277 template <typename Point>
278 struct assign<point_tag, Point, 3>
279 {
280     typedef typename coordinate_type<Point>::type coordinate_type;
281 
282     template <typename T>
applyboost::geometry::dispatch::assign283     static inline void apply(Point& point, T const& c1, T const& c2, T const& c3)
284     {
285         set<0>(point, boost::numeric_cast<coordinate_type>(c1));
286         set<1>(point, boost::numeric_cast<coordinate_type>(c2));
287         set<2>(point, boost::numeric_cast<coordinate_type>(c3));
288     }
289 };
290 
291 template <typename Box>
292 struct assign<box_tag, Box, 2>
293     : detail::assign::assign_2d_box_or_segment<Box>
294 {};
295 
296 template <typename Segment>
297 struct assign<segment_tag, Segment, 2>
298     : detail::assign::assign_2d_box_or_segment<Segment>
299 {};
300 
301 
302 
303 template <typename GeometryTag, typename Geometry>
304 struct assign_zero {};
305 
306 
307 template <typename Point>
308 struct assign_zero<point_tag, Point>
309     : detail::assign::assign_zero_point
310 {};
311 
312 template <typename Box>
313 struct assign_zero<box_tag, Box>
314     : detail::assign::assign_zero_box_or_segment
315 {};
316 
317 template <typename Segment>
318 struct assign_zero<segment_tag, Segment>
319     : detail::assign::assign_zero_box_or_segment
320 {};
321 
322 
323 template <typename GeometryTag, typename Geometry>
324 struct assign_inverse {};
325 
326 template <typename Box>
327 struct assign_inverse<box_tag, Box>
328     : detail::assign::assign_inverse_box_or_segment
329 {};
330 
331 template <typename Segment>
332 struct assign_inverse<segment_tag, Segment>
333     : detail::assign::assign_inverse_box_or_segment
334 {};
335 
336 
337 } // namespace dispatch
338 #endif // DOXYGEN_NO_DISPATCH
339 
340 }} // namespace boost::geometry
341 
342 
343 #endif // BOOST_GEOMETRY_ALGORITHMS_ASSIGN_VALUES_HPP
344