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, 2014, 2018.
6 // Modifications copyright (c) 2013-2018, 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 <boost/mpl/if.hpp>
18 #include <boost/type_traits/is_base_of.hpp>
19 
20 #include <boost/geometry/algorithms/not_implemented.hpp>
21 
22 #include <boost/geometry/core/assert.hpp>
23 #include <boost/geometry/core/exterior_ring.hpp>
24 #include <boost/geometry/core/interior_rings.hpp>
25 #include <boost/geometry/core/tag.hpp>
26 #include <boost/geometry/core/tags.hpp>
27 
28 #include <boost/geometry/util/range.hpp>
29 
30 namespace boost { namespace geometry {
31 
32 #ifndef DOXYGEN_NO_DETAIL
33 
34 #ifndef DOXYGEN_NO_DISPATCH
35 namespace detail_dispatch {
36 
37 template <typename Geometry,
38           typename Tag = typename geometry::tag<Geometry>::type,
39           bool IsMulti = boost::is_base_of<multi_tag, Tag>::value>
40 struct sub_range : not_implemented<Tag>
41 {};
42 
43 template <typename Geometry, typename Tag>
44 struct sub_range<Geometry, Tag, false>
45 {
46     typedef Geometry & return_type;
47 
48     template <typename Id> static inline
applyboost::geometry::detail_dispatch::sub_range49     return_type apply(Geometry & geometry, Id const&)
50     {
51         return geometry;
52     }
53 };
54 
55 template <typename Geometry>
56 struct sub_range<Geometry, polygon_tag, false>
57 {
58     typedef typename geometry::ring_return_type<Geometry>::type return_type;
59 
60     template <typename Id> static inline
applyboost::geometry::detail_dispatch::sub_range61     return_type apply(Geometry & geometry, Id const& id)
62     {
63         if ( id.ring_index < 0 )
64         {
65             return geometry::exterior_ring(geometry);
66         }
67         else
68         {
69             typedef typename boost::range_size
70                 <
71                     typename geometry::interior_type<Geometry>::type
72                 >::type size_type;
73             size_type const ri = static_cast<size_type>(id.ring_index);
74             return range::at(geometry::interior_rings(geometry), ri);
75         }
76     }
77 };
78 
79 template <typename Geometry, typename Tag>
80 struct sub_range<Geometry, Tag, true>
81 {
82     typedef typename boost::range_value<Geometry>::type value_type;
83     typedef typename boost::mpl::if_c
84         <
85             boost::is_const<Geometry>::value,
86             typename boost::add_const<value_type>::type,
87             value_type
88         >::type sub_type;
89 
90     typedef detail_dispatch::sub_range<sub_type> sub_sub_range;
91 
92     // TODO: shouldn't it be return_type?
93     typedef typename sub_sub_range::return_type return_type;
94 
95     template <typename Id> static inline
applyboost::geometry::detail_dispatch::sub_range96     return_type apply(Geometry & geometry, Id const& id)
97     {
98         BOOST_GEOMETRY_ASSERT(0 <= id.multi_index);
99         typedef typename boost::range_size<Geometry>::type size_type;
100         size_type const mi = static_cast<size_type>(id.multi_index);
101         return sub_sub_range::apply(range::at(geometry, mi), id);
102     }
103 };
104 
105 } // namespace detail_dispatch
106 #endif // DOXYGEN_NO_DISPATCH
107 
108 namespace detail {
109 
110 template <typename Geometry>
111 struct sub_range_return_type
112 {
113     typedef typename detail_dispatch::sub_range<Geometry>::return_type type;
114 };
115 
116 // This function also works for geometry::segment_identifier
117 
118 template <typename Geometry, typename Id> inline
119 typename sub_range_return_type<Geometry>::type
sub_range(Geometry & geometry,Id const & id)120 sub_range(Geometry & geometry, Id const& id)
121 {
122     return detail_dispatch::sub_range<Geometry>::apply(geometry, id);
123 }
124 
125 template <typename Geometry, typename Id> inline
126 typename sub_range_return_type<Geometry const>::type
sub_range(Geometry const & geometry,Id const & id)127 sub_range(Geometry const& geometry, Id const& id)
128 {
129     return detail_dispatch::sub_range<Geometry const>::apply(geometry, id);
130 }
131 
132 } // namespace detail
133 #endif // DOXYGEN_NO_DETAIL
134 
135 }} // namespace boost::geometry
136 
137 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SUB_RANGE_HPP
138