1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
4 
5 // This file was modified by Oracle on 2013-2020.
6 // Modifications copyright (c) 2013-2020, Oracle and/or its affiliates.
7 
8 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
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_DETAIL_SUB_RANGE_HPP
15 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SUB_RANGE_HPP
16 
17 #include <type_traits>
18 
19 #include <boost/geometry/algorithms/not_implemented.hpp>
20 
21 #include <boost/geometry/core/assert.hpp>
22 #include <boost/geometry/core/exterior_ring.hpp>
23 #include <boost/geometry/core/interior_rings.hpp>
24 #include <boost/geometry/core/tag.hpp>
25 #include <boost/geometry/core/tags.hpp>
26 
27 #include <boost/geometry/util/range.hpp>
28 
29 namespace boost { namespace geometry {
30 
31 #ifndef DOXYGEN_NO_DETAIL
32 
33 #ifndef DOXYGEN_NO_DISPATCH
34 namespace detail_dispatch {
35 
36 template <typename Geometry,
37           typename Tag = typename geometry::tag<Geometry>::type,
38           bool IsMulti = std::is_base_of<multi_tag, Tag>::value>
39 struct sub_range : not_implemented<Tag>
40 {};
41 
42 template <typename Geometry, typename Tag>
43 struct sub_range<Geometry, Tag, false>
44 {
45     typedef Geometry & return_type;
46 
47     template <typename Id> static inline
applyboost::geometry::detail_dispatch::sub_range48     return_type apply(Geometry & geometry, Id const&)
49     {
50         return geometry;
51     }
52 };
53 
54 template <typename Geometry>
55 struct sub_range<Geometry, polygon_tag, false>
56 {
57     typedef typename geometry::ring_return_type<Geometry>::type return_type;
58 
59     template <typename Id> static inline
applyboost::geometry::detail_dispatch::sub_range60     return_type apply(Geometry & geometry, Id const& id)
61     {
62         if ( id.ring_index < 0 )
63         {
64             return geometry::exterior_ring(geometry);
65         }
66         else
67         {
68             typedef typename boost::range_size
69                 <
70                     typename geometry::interior_type<Geometry>::type
71                 >::type size_type;
72             size_type const ri = static_cast<size_type>(id.ring_index);
73             return range::at(geometry::interior_rings(geometry), ri);
74         }
75     }
76 };
77 
78 template <typename Geometry, typename Tag>
79 struct sub_range<Geometry, Tag, true>
80 {
81     typedef typename boost::range_value<Geometry>::type value_type;
82     typedef std::conditional_t
83         <
84             std::is_const<Geometry>::value,
85             typename std::add_const<value_type>::type,
86             value_type
87         > sub_type;
88 
89     typedef detail_dispatch::sub_range<sub_type> sub_sub_range;
90 
91     // TODO: shouldn't it be return_type?
92     typedef typename sub_sub_range::return_type return_type;
93 
94     template <typename Id> static inline
applyboost::geometry::detail_dispatch::sub_range95     return_type apply(Geometry & geometry, Id const& id)
96     {
97         BOOST_GEOMETRY_ASSERT(0 <= id.multi_index);
98         typedef typename boost::range_size<Geometry>::type size_type;
99         size_type const mi = static_cast<size_type>(id.multi_index);
100         return sub_sub_range::apply(range::at(geometry, mi), id);
101     }
102 };
103 
104 } // namespace detail_dispatch
105 #endif // DOXYGEN_NO_DISPATCH
106 
107 namespace detail {
108 
109 template <typename Geometry>
110 struct sub_range_return_type
111 {
112     typedef typename detail_dispatch::sub_range<Geometry>::return_type type;
113 };
114 
115 // This function also works for geometry::segment_identifier
116 
117 template <typename Geometry, typename Id> inline
118 typename sub_range_return_type<Geometry>::type
sub_range(Geometry & geometry,Id const & id)119 sub_range(Geometry & geometry, Id const& id)
120 {
121     return detail_dispatch::sub_range<Geometry>::apply(geometry, id);
122 }
123 
124 template <typename Geometry, typename Id> inline
125 typename sub_range_return_type<Geometry const>::type
sub_range(Geometry const & geometry,Id const & id)126 sub_range(Geometry const& geometry, Id const& id)
127 {
128     return detail_dispatch::sub_range<Geometry const>::apply(geometry, id);
129 }
130 
131 } // namespace detail
132 #endif // DOXYGEN_NO_DETAIL
133 
134 }} // namespace boost::geometry
135 
136 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SUB_RANGE_HPP
137