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
30namespace boost { namespace geometry
31{
32
33/// Index of minimum corner of the box.
34int const min_corner = 0;
35
36/// Index of maximum corner of the box.
37int const max_corner = 1;
38
39namespace 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*/
53template <typename Geometry, std::size_t Dimension, typename Enable = void>
54struct 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*/
77template <typename Geometry, std::size_t Index, std::size_t Dimension>
78struct indexed_access {};
79
80
81} // namespace traits
82
83#ifndef DOXYGEN_NO_DETAIL
84namespace detail
85{
86
87template
88<
89 typename Geometry,
90 typename CoordinateType,
91 std::size_t Index,
92 std::size_t Dimension
93>
94struct 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
106template
107<
108 typename Geometry,
109 typename CoordinateType,
110 std::size_t Index,
111 std::size_t Dimension
112>
113struct 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
131namespace core_dispatch
132{
133
134template
135<
136 typename Tag,
137 typename Geometry,
138 typename
139 CoordinateType,
140 std::size_t Dimension,
141 typename IsPointer
142>
143struct access
144{
145 //static inline T get(G const&) {}
146 //static inline void set(G& g, T const& value) {}
147};
148
149template
150<
151 typename Tag,
152 typename Geometry,
153 typename CoordinateType,
154 std::size_t Index,
155 std::size_t Dimension,
156 typename IsPointer
157>
158struct indexed_access
159{
160 //static inline T get(G const&) {}
161 //static inline void set(G& g, T const& value) {}
162};
163
164template <typename Point, typename CoordinateType, std::size_t Dimension>
165struct 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
177template <typename Point, typename CoordinateType, std::size_t Dimension>
178struct 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
191template
192<
193 typename Box,
194 typename CoordinateType,
195 std::size_t Index,
196 std::size_t Dimension
197>
198struct indexed_access<box_tag, Box, CoordinateType, Index, Dimension, boost::false_type>
199 : detail::indexed_access_non_pointer<Box, CoordinateType, Index, Dimension>
200{};
201
202template
203<
204 typename Box,
205 typename CoordinateType,
206 std::size_t Index,
207 std::size_t Dimension
208>
209struct indexed_access<box_tag, Box, CoordinateType, Index, Dimension, boost::true_type>
210 : detail::indexed_access_pointer<Box, CoordinateType, Index, Dimension>
211{};
212
213
214template
215<
216 typename Segment,
217 typename CoordinateType,
218 std::size_t Index,
219 std::size_t Dimension
220>
221struct indexed_access<segment_tag, Segment, CoordinateType, Index, Dimension, boost::false_type>
222 : detail::indexed_access_non_pointer<Segment, CoordinateType, Index, Dimension>
223{};
224
225
226template
227<
228 typename Segment,
229 typename CoordinateType,
230 std::size_t Index,
231 std::size_t Dimension
232>
233struct 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
242namespace 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.
249struct signature_getset_dimension {};
250struct 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*/
267template <std::size_t Dimension, typename Geometry>
268inline 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*/
301template <std::size_t Dimension, typename Geometry>
302inline 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*/
337template <std::size_t Index, std::size_t Dimension, typename Geometry>
338inline 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*/
373template <std::size_t Index, std::size_t Dimension, typename Geometry>
374inline 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