1 | // Boost.Geometry (aka GGL, Generic Geometry Library) |
2 | |
3 | // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. |
4 | // Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands. |
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_CORE_ACCESS_HPP |
15 | #define BOOST_GEOMETRY_CORE_ACCESS_HPP |
16 | |
17 | |
18 | #include <cstddef> |
19 | |
20 | #include <boost/mpl/assert.hpp> |
21 | #include <boost/concept_check.hpp> |
22 | #include <boost/type_traits/is_pointer.hpp> |
23 | |
24 | #include <boost/geometry/core/coordinate_type.hpp> |
25 | #include <boost/geometry/core/point_type.hpp> |
26 | #include <boost/geometry/core/tag.hpp> |
27 | #include <boost/geometry/util/bare_type.hpp> |
28 | |
29 | |
30 | namespace boost { namespace geometry |
31 | { |
32 | |
33 | /// Index of minimum corner of the box. |
34 | int const min_corner = 0; |
35 | |
36 | /// Index of maximum corner of the box. |
37 | int const max_corner = 1; |
38 | |
39 | namespace traits |
40 | { |
41 | |
42 | /*! |
43 | \brief Traits class which gives access (get,set) to points. |
44 | \ingroup traits |
45 | \par Geometries: |
46 | /// @li point |
47 | \par Specializations should provide, per Dimension |
48 | /// @li static inline T get(G const&) |
49 | /// @li static inline void set(G&, T const&) |
50 | \tparam Geometry geometry-type |
51 | \tparam Dimension dimension to access |
52 | */ |
53 | template <typename Geometry, std::size_t Dimension, typename Enable = void> |
54 | struct access |
55 | { |
56 | BOOST_MPL_ASSERT_MSG |
57 | ( |
58 | false, NOT_IMPLEMENTED_FOR_THIS_POINT_TYPE, (types<Geometry>) |
59 | ); |
60 | }; |
61 | |
62 | |
63 | /*! |
64 | \brief Traits class defining "get" and "set" to get |
65 | and set point coordinate values |
66 | \tparam Geometry geometry (box, segment) |
67 | \tparam Index index (min_corner/max_corner for box, 0/1 for segment) |
68 | \tparam Dimension dimension |
69 | \par Geometries: |
70 | - box |
71 | - segment |
72 | \par Specializations should provide: |
73 | - static inline T get(G const&) |
74 | - static inline void set(G&, T const&) |
75 | \ingroup traits |
76 | */ |
77 | template <typename Geometry, std::size_t Index, std::size_t Dimension> |
78 | struct indexed_access {}; |
79 | |
80 | |
81 | } // namespace traits |
82 | |
83 | #ifndef DOXYGEN_NO_DETAIL |
84 | namespace detail |
85 | { |
86 | |
87 | template |
88 | < |
89 | typename Geometry, |
90 | typename CoordinateType, |
91 | std::size_t Index, |
92 | std::size_t Dimension |
93 | > |
94 | struct indexed_access_non_pointer |
95 | { |
96 | static inline CoordinateType get(Geometry const& geometry) |
97 | { |
98 | return traits::indexed_access<Geometry, Index, Dimension>::get(geometry); |
99 | } |
100 | static inline void set(Geometry& b, CoordinateType const& value) |
101 | { |
102 | traits::indexed_access<Geometry, Index, Dimension>::set(b, value); |
103 | } |
104 | }; |
105 | |
106 | template |
107 | < |
108 | typename Geometry, |
109 | typename CoordinateType, |
110 | std::size_t Index, |
111 | std::size_t Dimension |
112 | > |
113 | struct indexed_access_pointer |
114 | { |
115 | static inline CoordinateType get(Geometry const* geometry) |
116 | { |
117 | return traits::indexed_access<typename boost::remove_pointer<Geometry>::type, Index, Dimension>::get(*geometry); |
118 | } |
119 | static inline void set(Geometry* geometry, CoordinateType const& value) |
120 | { |
121 | traits::indexed_access<typename boost::remove_pointer<Geometry>::type, Index, Dimension>::set(*geometry, value); |
122 | } |
123 | }; |
124 | |
125 | |
126 | } // namespace detail |
127 | #endif // DOXYGEN_NO_DETAIL |
128 | |
129 | |
130 | #ifndef DOXYGEN_NO_DISPATCH |
131 | namespace core_dispatch |
132 | { |
133 | |
134 | template |
135 | < |
136 | typename Tag, |
137 | typename Geometry, |
138 | typename |
139 | CoordinateType, |
140 | std::size_t Dimension, |
141 | typename IsPointer |
142 | > |
143 | struct access |
144 | { |
145 | //static inline T get(G const&) {} |
146 | //static inline void set(G& g, T const& value) {} |
147 | }; |
148 | |
149 | template |
150 | < |
151 | typename Tag, |
152 | typename Geometry, |
153 | typename CoordinateType, |
154 | std::size_t Index, |
155 | std::size_t Dimension, |
156 | typename IsPointer |
157 | > |
158 | struct indexed_access |
159 | { |
160 | //static inline T get(G const&) {} |
161 | //static inline void set(G& g, T const& value) {} |
162 | }; |
163 | |
164 | template <typename Point, typename CoordinateType, std::size_t Dimension> |
165 | struct access<point_tag, Point, CoordinateType, Dimension, boost::false_type> |
166 | { |
167 | static inline CoordinateType get(Point const& point) |
168 | { |
169 | return traits::access<Point, Dimension>::get(point); |
170 | } |
171 | static inline void set(Point& p, CoordinateType const& value) |
172 | { |
173 | traits::access<Point, Dimension>::set(p, value); |
174 | } |
175 | }; |
176 | |
177 | template <typename Point, typename CoordinateType, std::size_t Dimension> |
178 | struct access<point_tag, Point, CoordinateType, Dimension, boost::true_type> |
179 | { |
180 | static inline CoordinateType get(Point const* point) |
181 | { |
182 | return traits::access<typename boost::remove_pointer<Point>::type, Dimension>::get(*point); |
183 | } |
184 | static inline void set(Point* p, CoordinateType const& value) |
185 | { |
186 | traits::access<typename boost::remove_pointer<Point>::type, Dimension>::set(*p, value); |
187 | } |
188 | }; |
189 | |
190 | |
191 | template |
192 | < |
193 | typename Box, |
194 | typename CoordinateType, |
195 | std::size_t Index, |
196 | std::size_t Dimension |
197 | > |
198 | struct indexed_access<box_tag, Box, CoordinateType, Index, Dimension, boost::false_type> |
199 | : detail::indexed_access_non_pointer<Box, CoordinateType, Index, Dimension> |
200 | {}; |
201 | |
202 | template |
203 | < |
204 | typename Box, |
205 | typename CoordinateType, |
206 | std::size_t Index, |
207 | std::size_t Dimension |
208 | > |
209 | struct indexed_access<box_tag, Box, CoordinateType, Index, Dimension, boost::true_type> |
210 | : detail::indexed_access_pointer<Box, CoordinateType, Index, Dimension> |
211 | {}; |
212 | |
213 | |
214 | template |
215 | < |
216 | typename Segment, |
217 | typename CoordinateType, |
218 | std::size_t Index, |
219 | std::size_t Dimension |
220 | > |
221 | struct indexed_access<segment_tag, Segment, CoordinateType, Index, Dimension, boost::false_type> |
222 | : detail::indexed_access_non_pointer<Segment, CoordinateType, Index, Dimension> |
223 | {}; |
224 | |
225 | |
226 | template |
227 | < |
228 | typename Segment, |
229 | typename CoordinateType, |
230 | std::size_t Index, |
231 | std::size_t Dimension |
232 | > |
233 | struct indexed_access<segment_tag, Segment, CoordinateType, Index, Dimension, boost::true_type> |
234 | : detail::indexed_access_pointer<Segment, CoordinateType, Index, Dimension> |
235 | {}; |
236 | |
237 | } // namespace core_dispatch |
238 | #endif // DOXYGEN_NO_DISPATCH |
239 | |
240 | |
241 | #ifndef DOXYGEN_NO_DETAIL |
242 | namespace detail |
243 | { |
244 | |
245 | // Two dummy tags to distinguish get/set variants below. |
246 | // They don't have to be specified by the user. The functions are distinguished |
247 | // by template signature also, but for e.g. GCC this is not enough. So give them |
248 | // a different signature. |
249 | struct signature_getset_dimension {}; |
250 | struct signature_getset_index_dimension {}; |
251 | |
252 | } // namespace detail |
253 | #endif // DOXYGEN_NO_DETAIL |
254 | |
255 | |
256 | /*! |
257 | \brief Get coordinate value of a geometry (usually a point) |
258 | \details \details_get_set |
259 | \ingroup get |
260 | \tparam Dimension \tparam_dimension_required |
261 | \tparam Geometry \tparam_geometry (usually a Point Concept) |
262 | \param geometry \param_geometry (usually a point) |
263 | \return The coordinate value of specified dimension of specified geometry |
264 | |
265 | \qbk{[include reference/core/get_point.qbk]} |
266 | */ |
267 | template <std::size_t Dimension, typename Geometry> |
268 | inline typename coordinate_type<Geometry>::type get(Geometry const& geometry |
269 | #ifndef DOXYGEN_SHOULD_SKIP_THIS |
270 | , detail::signature_getset_dimension* dummy = 0 |
271 | #endif |
272 | ) |
273 | { |
274 | boost::ignore_unused_variable_warning(dummy); |
275 | |
276 | typedef core_dispatch::access |
277 | < |
278 | typename tag<Geometry>::type, |
279 | typename geometry::util::bare_type<Geometry>::type, |
280 | typename coordinate_type<Geometry>::type, |
281 | Dimension, |
282 | typename boost::is_pointer<Geometry>::type |
283 | > coord_access_type; |
284 | |
285 | return coord_access_type::get(geometry); |
286 | } |
287 | |
288 | |
289 | /*! |
290 | \brief Set coordinate value of a geometry (usually a point) |
291 | \details \details_get_set |
292 | \tparam Dimension \tparam_dimension_required |
293 | \tparam Geometry \tparam_geometry (usually a Point Concept) |
294 | \param geometry geometry to assign coordinate to |
295 | \param geometry \param_geometry (usually a point) |
296 | \param value The coordinate value to set |
297 | \ingroup set |
298 | |
299 | \qbk{[include reference/core/set_point.qbk]} |
300 | */ |
301 | template <std::size_t Dimension, typename Geometry> |
302 | inline void set(Geometry& geometry |
303 | , typename coordinate_type<Geometry>::type const& value |
304 | #ifndef DOXYGEN_SHOULD_SKIP_THIS |
305 | , detail::signature_getset_dimension* dummy = 0 |
306 | #endif |
307 | ) |
308 | { |
309 | boost::ignore_unused_variable_warning(dummy); |
310 | |
311 | typedef core_dispatch::access |
312 | < |
313 | typename tag<Geometry>::type, |
314 | typename geometry::util::bare_type<Geometry>::type, |
315 | typename coordinate_type<Geometry>::type, |
316 | Dimension, |
317 | typename boost::is_pointer<Geometry>::type |
318 | > coord_access_type; |
319 | |
320 | coord_access_type::set(geometry, value); |
321 | } |
322 | |
323 | |
324 | /*! |
325 | \brief get coordinate value of a Box or Segment |
326 | \details \details_get_set |
327 | \tparam Index \tparam_index_required |
328 | \tparam Dimension \tparam_dimension_required |
329 | \tparam Geometry \tparam_box_or_segment |
330 | \param geometry \param_geometry |
331 | \return coordinate value |
332 | \ingroup get |
333 | |
334 | \qbk{distinguish,with index} |
335 | \qbk{[include reference/core/get_box.qbk]} |
336 | */ |
337 | template <std::size_t Index, std::size_t Dimension, typename Geometry> |
338 | inline typename coordinate_type<Geometry>::type get(Geometry const& geometry |
339 | #ifndef DOXYGEN_SHOULD_SKIP_THIS |
340 | , detail::signature_getset_index_dimension* dummy = 0 |
341 | #endif |
342 | ) |
343 | { |
344 | boost::ignore_unused_variable_warning(dummy); |
345 | |
346 | typedef core_dispatch::indexed_access |
347 | < |
348 | typename tag<Geometry>::type, |
349 | typename geometry::util::bare_type<Geometry>::type, |
350 | typename coordinate_type<Geometry>::type, |
351 | Index, |
352 | Dimension, |
353 | typename boost::is_pointer<Geometry>::type |
354 | > coord_access_type; |
355 | |
356 | return coord_access_type::get(geometry); |
357 | } |
358 | |
359 | /*! |
360 | \brief set coordinate value of a Box / Segment |
361 | \details \details_get_set |
362 | \tparam Index \tparam_index_required |
363 | \tparam Dimension \tparam_dimension_required |
364 | \tparam Geometry \tparam_box_or_segment |
365 | \param geometry geometry to assign coordinate to |
366 | \param geometry \param_geometry |
367 | \param value The coordinate value to set |
368 | \ingroup set |
369 | |
370 | \qbk{distinguish,with index} |
371 | \qbk{[include reference/core/set_box.qbk]} |
372 | */ |
373 | template <std::size_t Index, std::size_t Dimension, typename Geometry> |
374 | inline void set(Geometry& geometry |
375 | , typename coordinate_type<Geometry>::type const& value |
376 | #ifndef DOXYGEN_SHOULD_SKIP_THIS |
377 | , detail::signature_getset_index_dimension* dummy = 0 |
378 | #endif |
379 | ) |
380 | { |
381 | boost::ignore_unused_variable_warning(dummy); |
382 | |
383 | typedef core_dispatch::indexed_access |
384 | < |
385 | typename tag<Geometry>::type, |
386 | typename geometry::util::bare_type<Geometry>::type, |
387 | typename coordinate_type<Geometry>::type, |
388 | Index, |
389 | Dimension, |
390 | typename boost::is_pointer<Geometry>::type |
391 | > coord_access_type; |
392 | |
393 | coord_access_type::set(geometry, value); |
394 | } |
395 | |
396 | }} // namespace boost::geometry |
397 | |
398 | #endif // BOOST_GEOMETRY_CORE_ACCESS_HPP |
399 | |