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// This file was modified by Oracle on 2020.
8// Modifications copyright (c) 2020, Oracle and/or its affiliates.
9// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
10
11// Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
12// (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
13
14// Use, modification and distribution is subject to the Boost Software License,
15// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
16// http://www.boost.org/LICENSE_1_0.txt)
17
18#ifndef BOOST_GEOMETRY_CORE_ACCESS_HPP
19#define BOOST_GEOMETRY_CORE_ACCESS_HPP
20
21
22#include <cstddef>
23
24#include <boost/geometry/core/coordinate_type.hpp>
25#include <boost/geometry/core/point_type.hpp>
26#include <boost/geometry/core/static_assert.hpp>
27#include <boost/geometry/core/tag.hpp>
28#include <boost/geometry/util/type_traits_std.hpp>
29
30
31namespace boost { namespace geometry
32{
33
34/// Index of minimum corner of the box.
35int const min_corner = 0;
36
37/// Index of maximum corner of the box.
38int const max_corner = 1;
39
40namespace traits
41{
42
43/*!
44\brief Traits class which gives access (get,set) to points.
45\ingroup traits
46\par Geometries:
47/// @li point
48\par Specializations should provide, per Dimension
49/// @li static inline T get(G const&)
50/// @li static inline void set(G&, T const&)
51\tparam Geometry geometry-type
52\tparam Dimension dimension to access
53*/
54template <typename Geometry, std::size_t Dimension, typename Enable = void>
55struct access
56{
57 BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
58 "Not implemented for this Geometry type.",
59 Geometry);
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 constexpr CoordinateType get(Geometry const& geometry)
97 {
98 return traits::indexed_access<Geometry, Index, Dimension>::get(geometry);
99 }
100 static 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 constexpr CoordinateType get(Geometry const* geometry)
116 {
117 return traits::indexed_access<typename std::remove_pointer<Geometry>::type, Index, Dimension>::get(*geometry);
118 }
119 static void set(Geometry* geometry, CoordinateType const& value)
120 {
121 traits::indexed_access<typename std::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, std::false_type>
166{
167 static constexpr CoordinateType get(Point const& point)
168 {
169 return traits::access<Point, Dimension>::get(point);
170 }
171 static 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, std::true_type>
179{
180 static constexpr CoordinateType get(Point const* point)
181 {
182 return traits::access<typename std::remove_pointer<Point>::type, Dimension>::get(*point);
183 }
184 static void set(Point* p, CoordinateType const& value)
185 {
186 traits::access<typename std::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, std::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, std::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, std::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, std::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>
268constexpr inline typename coordinate_type<Geometry>::type get(Geometry const& geometry
269#ifndef DOXYGEN_SHOULD_SKIP_THIS
270 , detail::signature_getset_dimension* = 0
271#endif
272 )
273{
274 typedef core_dispatch::access
275 <
276 typename tag<Geometry>::type,
277 typename util::remove_cptrref<Geometry>::type,
278 typename coordinate_type<Geometry>::type,
279 Dimension,
280 typename std::is_pointer<Geometry>::type
281 > coord_access_type;
282
283 return coord_access_type::get(geometry);
284}
285
286
287/*!
288\brief Set coordinate value of a geometry (usually a point)
289\details \details_get_set
290\tparam Dimension \tparam_dimension_required
291\tparam Geometry \tparam_geometry (usually a Point Concept)
292\param geometry geometry to assign coordinate to
293\param geometry \param_geometry (usually a point)
294\param value The coordinate value to set
295\ingroup set
296
297\qbk{[include reference/core/set_point.qbk]}
298*/
299template <std::size_t Dimension, typename Geometry>
300inline void set(Geometry& geometry
301 , typename coordinate_type<Geometry>::type const& value
302#ifndef DOXYGEN_SHOULD_SKIP_THIS
303 , detail::signature_getset_dimension* = 0
304#endif
305 )
306{
307 typedef core_dispatch::access
308 <
309 typename tag<Geometry>::type,
310 typename util::remove_cptrref<Geometry>::type,
311 typename coordinate_type<Geometry>::type,
312 Dimension,
313 typename std::is_pointer<Geometry>::type
314 > coord_access_type;
315
316 coord_access_type::set(geometry, value);
317}
318
319
320/*!
321\brief get coordinate value of a Box or Segment
322\details \details_get_set
323\tparam Index \tparam_index_required
324\tparam Dimension \tparam_dimension_required
325\tparam Geometry \tparam_box_or_segment
326\param geometry \param_geometry
327\return coordinate value
328\ingroup get
329
330\qbk{distinguish,with index}
331\qbk{[include reference/core/get_box.qbk]}
332*/
333template <std::size_t Index, std::size_t Dimension, typename Geometry>
334constexpr inline typename coordinate_type<Geometry>::type get(Geometry const& geometry
335#ifndef DOXYGEN_SHOULD_SKIP_THIS
336 , detail::signature_getset_index_dimension* = 0
337#endif
338 )
339{
340 typedef core_dispatch::indexed_access
341 <
342 typename tag<Geometry>::type,
343 typename util::remove_cptrref<Geometry>::type,
344 typename coordinate_type<Geometry>::type,
345 Index,
346 Dimension,
347 typename std::is_pointer<Geometry>::type
348 > coord_access_type;
349
350 return coord_access_type::get(geometry);
351}
352
353/*!
354\brief set coordinate value of a Box / Segment
355\details \details_get_set
356\tparam Index \tparam_index_required
357\tparam Dimension \tparam_dimension_required
358\tparam Geometry \tparam_box_or_segment
359\param geometry geometry to assign coordinate to
360\param geometry \param_geometry
361\param value The coordinate value to set
362\ingroup set
363
364\qbk{distinguish,with index}
365\qbk{[include reference/core/set_box.qbk]}
366*/
367template <std::size_t Index, std::size_t Dimension, typename Geometry>
368inline void set(Geometry& geometry
369 , typename coordinate_type<Geometry>::type const& value
370#ifndef DOXYGEN_SHOULD_SKIP_THIS
371 , detail::signature_getset_index_dimension* = 0
372#endif
373 )
374{
375 typedef core_dispatch::indexed_access
376 <
377 typename tag<Geometry>::type,
378 typename util::remove_cptrref<Geometry>::type,
379 typename coordinate_type<Geometry>::type,
380 Index,
381 Dimension,
382 typename std::is_pointer<Geometry>::type
383 > coord_access_type;
384
385 coord_access_type::set(geometry, value);
386}
387
388}} // namespace boost::geometry
389
390#endif // BOOST_GEOMETRY_CORE_ACCESS_HPP
391

source code of boost/libs/geometry/include/boost/geometry/core/access.hpp