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