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 // Use, modification and distribution is subject to the Boost Software License,
11 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
12 // http://www.boost.org/LICENSE_1_0.txt)
13 
14 #ifndef BOOST_GEOMETRY_ALGORITHMS_ASSIGN_VALUES_HPP
15 #define BOOST_GEOMETRY_ALGORITHMS_ASSIGN_VALUES_HPP
16 
17 
18 #include <cstddef>
19 
20 #include <boost/concept/requires.hpp>
21 #include <boost/concept_check.hpp>
22 #include <boost/mpl/assert.hpp>
23 #include <boost/mpl/if.hpp>
24 #include <boost/numeric/conversion/bounds.hpp>
25 #include <boost/numeric/conversion/cast.hpp>
26 #include <boost/type_traits.hpp>
27 
28 #include <boost/geometry/arithmetic/arithmetic.hpp>
29 #include <boost/geometry/algorithms/append.hpp>
30 #include <boost/geometry/algorithms/clear.hpp>
31 #include <boost/geometry/core/access.hpp>
32 #include <boost/geometry/core/exterior_ring.hpp>
33 #include <boost/geometry/core/tags.hpp>
34 
35 #include <boost/geometry/geometries/concepts/check.hpp>
36 
37 
38 #include <boost/geometry/util/for_each_coordinate.hpp>
39 
40 
41 namespace boost { namespace geometry
42 {
43 
44 #ifndef DOXYGEN_NO_DETAIL
45 namespace detail { namespace assign
46 {
47 
48 
49 template <std::size_t Index, std::size_t Dimension, std::size_t DimensionCount>
50 struct initialize
51 {
52     template <typename Box>
applyboost::geometry::detail::assign::initialize53     static inline void apply(Box& box, typename coordinate_type<Box>::type const& value)
54     {
55         geometry::set<Index, Dimension>(box, value);
56         initialize<Index, Dimension + 1, DimensionCount>::apply(box, value);
57     }
58 };
59 
60 
61 template <std::size_t Index, std::size_t DimensionCount>
62 struct initialize<Index, DimensionCount, DimensionCount>
63 {
64     template <typename Box>
applyboost::geometry::detail::assign::initialize65     static inline void apply(Box&, typename coordinate_type<Box>::type const&)
66     {}
67 };
68 
69 
70 struct assign_zero_point
71 {
72     template <typename Point>
applyboost::geometry::detail::assign::assign_zero_point73     static inline void apply(Point& point)
74     {
75         geometry::assign_value(point, 0);
76     }
77 };
78 
79 
80 struct assign_inverse_box_or_segment
81 {
82 
83     template <typename BoxOrSegment>
applyboost::geometry::detail::assign::assign_inverse_box_or_segment84     static inline void apply(BoxOrSegment& geometry)
85     {
86         typedef typename point_type<BoxOrSegment>::type point_type;
87         typedef typename coordinate_type<point_type>::type bound_type;
88 
89         initialize<0, 0, dimension<BoxOrSegment>::type::value>::apply(
90             geometry, boost::numeric::bounds<bound_type>::highest()
91         );
92         initialize<1, 0, dimension<BoxOrSegment>::type::value>::apply(
93             geometry, boost::numeric::bounds<bound_type>::lowest()
94         );
95     }
96 };
97 
98 
99 struct assign_zero_box_or_segment
100 {
101     template <typename BoxOrSegment>
applyboost::geometry::detail::assign::assign_zero_box_or_segment102     static inline void apply(BoxOrSegment& geometry)
103     {
104         typedef typename coordinate_type<BoxOrSegment>::type coordinate_type;
105 
106         initialize<0, 0, dimension<BoxOrSegment>::type::value>::apply(
107             geometry, coordinate_type()
108         );
109         initialize<1, 0, dimension<BoxOrSegment>::type::value>::apply(
110             geometry, coordinate_type()
111         );
112     }
113 };
114 
115 
116 template
117 <
118     std::size_t Corner1, std::size_t Corner2,
119     typename Box, typename Point
120 >
assign_box_2d_corner(Box const & box,Point & point)121 inline void assign_box_2d_corner(Box const& box, Point& point)
122 {
123     // Be sure both are 2-Dimensional
124     assert_dimension<Box, 2>();
125     assert_dimension<Point, 2>();
126 
127     // Copy coordinates
128     typedef typename coordinate_type<Point>::type coordinate_type;
129 
130     geometry::set<0>(point, boost::numeric_cast<coordinate_type>(get<Corner1, 0>(box)));
131     geometry::set<1>(point, boost::numeric_cast<coordinate_type>(get<Corner2, 1>(box)));
132 }
133 
134 
135 
136 template
137 <
138     typename Geometry, typename Point,
139     std::size_t Index,
140     std::size_t Dimension, std::size_t DimensionCount
141 >
142 struct assign_point_to_index
143 {
144 
applyboost::geometry::detail::assign::assign_point_to_index145     static inline void apply(Point const& point, Geometry& geometry)
146     {
147         geometry::set<Index, Dimension>(geometry, boost::numeric_cast
148             <
149                 typename coordinate_type<Geometry>::type
150             >(geometry::get<Dimension>(point)));
151 
152         assign_point_to_index
153             <
154                 Geometry, Point, Index, Dimension + 1, DimensionCount
155             >::apply(point, geometry);
156     }
157 };
158 
159 template
160 <
161     typename Geometry, typename Point,
162     std::size_t Index,
163     std::size_t DimensionCount
164 >
165 struct assign_point_to_index
166     <
167         Geometry, Point,
168         Index,
169         DimensionCount, DimensionCount
170     >
171 {
applyboost::geometry::detail::assign::assign_point_to_index172     static inline void apply(Point const& , Geometry& )
173     {
174     }
175 };
176 
177 
178 template
179 <
180     typename Geometry, typename Point,
181     std::size_t Index,
182     std::size_t Dimension, std::size_t DimensionCount
183 >
184 struct assign_point_from_index
185 {
186 
applyboost::geometry::detail::assign::assign_point_from_index187     static inline void apply(Geometry const& geometry, Point& point)
188     {
189         geometry::set<Dimension>( point, boost::numeric_cast
190             <
191                 typename coordinate_type<Point>::type
192             >(geometry::get<Index, Dimension>(geometry)));
193 
194         assign_point_from_index
195             <
196                 Geometry, Point, Index, Dimension + 1, DimensionCount
197             >::apply(geometry, point);
198     }
199 };
200 
201 template
202 <
203     typename Geometry, typename Point,
204     std::size_t Index,
205     std::size_t DimensionCount
206 >
207 struct assign_point_from_index
208     <
209         Geometry, Point,
210         Index,
211         DimensionCount, DimensionCount
212     >
213 {
applyboost::geometry::detail::assign::assign_point_from_index214     static inline void apply(Geometry const&, Point&)
215     {
216     }
217 };
218 
219 
220 template <typename Geometry>
221 struct assign_2d_box_or_segment
222 {
223     typedef typename coordinate_type<Geometry>::type coordinate_type;
224 
225     // Here we assign 4 coordinates to a box of segment
226     // -> Most logical is: x1,y1,x2,y2
227     // In case the user reverses x1/x2 or y1/y2, for a box, we could reverse them (THAT IS NOT IMPLEMENTED)
228 
229     template <typename Type>
applyboost::geometry::detail::assign::assign_2d_box_or_segment230     static inline void apply(Geometry& geometry,
231                 Type const& x1, Type const& y1, Type const& x2, Type const& y2)
232     {
233         geometry::set<0, 0>(geometry, boost::numeric_cast<coordinate_type>(x1));
234         geometry::set<0, 1>(geometry, boost::numeric_cast<coordinate_type>(y1));
235         geometry::set<1, 0>(geometry, boost::numeric_cast<coordinate_type>(x2));
236         geometry::set<1, 1>(geometry, boost::numeric_cast<coordinate_type>(y2));
237     }
238 };
239 
240 
241 }} // namespace detail::assign
242 #endif // DOXYGEN_NO_DETAIL
243 
244 #ifndef DOXYGEN_NO_DISPATCH
245 namespace dispatch
246 {
247 
248 template <typename GeometryTag, typename Geometry, std::size_t DimensionCount>
249 struct assign
250 {
251     BOOST_MPL_ASSERT_MSG
252         (
253             false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
254             , (types<Geometry>)
255         );
256 };
257 
258 template <typename Point>
259 struct assign<point_tag, Point, 2>
260 {
261     typedef typename coordinate_type<Point>::type coordinate_type;
262 
263     template <typename T>
applyboost::geometry::dispatch::assign264     static inline void apply(Point& point, T const& c1, T const& c2)
265     {
266         set<0>(point, boost::numeric_cast<coordinate_type>(c1));
267         set<1>(point, boost::numeric_cast<coordinate_type>(c2));
268     }
269 };
270 
271 template <typename Point>
272 struct assign<point_tag, Point, 3>
273 {
274     typedef typename coordinate_type<Point>::type coordinate_type;
275 
276     template <typename T>
applyboost::geometry::dispatch::assign277     static inline void apply(Point& point, T const& c1, T const& c2, T const& c3)
278     {
279         set<0>(point, boost::numeric_cast<coordinate_type>(c1));
280         set<1>(point, boost::numeric_cast<coordinate_type>(c2));
281         set<2>(point, boost::numeric_cast<coordinate_type>(c3));
282     }
283 };
284 
285 template <typename Box>
286 struct assign<box_tag, Box, 2>
287     : detail::assign::assign_2d_box_or_segment<Box>
288 {};
289 
290 template <typename Segment>
291 struct assign<segment_tag, Segment, 2>
292     : detail::assign::assign_2d_box_or_segment<Segment>
293 {};
294 
295 
296 
297 template <typename GeometryTag, typename Geometry>
298 struct assign_zero {};
299 
300 
301 template <typename Point>
302 struct assign_zero<point_tag, Point>
303     : detail::assign::assign_zero_point
304 {};
305 
306 template <typename Box>
307 struct assign_zero<box_tag, Box>
308     : detail::assign::assign_zero_box_or_segment
309 {};
310 
311 template <typename Segment>
312 struct assign_zero<segment_tag, Segment>
313     : detail::assign::assign_zero_box_or_segment
314 {};
315 
316 
317 template <typename GeometryTag, typename Geometry>
318 struct assign_inverse {};
319 
320 template <typename Box>
321 struct assign_inverse<box_tag, Box>
322     : detail::assign::assign_inverse_box_or_segment
323 {};
324 
325 template <typename Segment>
326 struct assign_inverse<segment_tag, Segment>
327     : detail::assign::assign_inverse_box_or_segment
328 {};
329 
330 
331 } // namespace dispatch
332 #endif // DOXYGEN_NO_DISPATCH
333 
334 }} // namespace boost::geometry
335 
336 
337 #endif // BOOST_GEOMETRY_ALGORITHMS_ASSIGN_VALUES_HPP
338