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.
6 // Modifications copyright (c) 2013-2014, Oracle and/or its affiliates.
7 
8 // Use, modification and distribution is subject to the Boost Software License,
9 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
10 // http://www.boost.org/LICENSE_1_0.txt)
11 
12 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
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 
19 #include <boost/geometry/core/assert.hpp>
20 #include <boost/geometry/util/range.hpp>
21 
22 namespace boost { namespace geometry {
23 
24 #ifndef DOXYGEN_NO_DETAIL
25 
26 #ifndef DOXYGEN_NO_DISPATCH
27 namespace detail_dispatch {
28 
29 template <typename Geometry,
30           typename Tag = typename geometry::tag<Geometry>::type,
31           bool IsMulti = boost::is_base_of<multi_tag, Tag>::value>
32 struct sub_range : not_implemented<Tag>
33 {};
34 
35 template <typename Geometry, typename Tag>
36 struct sub_range<Geometry, Tag, false>
37 {
38     typedef Geometry & return_type;
39 
40     template <typename Id> static inline
applyboost::geometry::detail_dispatch::sub_range41     return_type apply(Geometry & geometry, Id const&)
42     {
43         return geometry;
44     }
45 };
46 
47 template <typename Geometry>
48 struct sub_range<Geometry, polygon_tag, false>
49 {
50     typedef typename geometry::ring_return_type<Geometry>::type return_type;
51 
52     template <typename Id> static inline
applyboost::geometry::detail_dispatch::sub_range53     return_type apply(Geometry & geometry, Id const& id)
54     {
55         if ( id.ring_index < 0 )
56         {
57             return geometry::exterior_ring(geometry);
58         }
59         else
60         {
61             typedef typename boost::range_size
62                 <
63                     typename geometry::interior_type<Geometry>::type
64                 >::type size_type;
65             size_type const ri = static_cast<size_type>(id.ring_index);
66             return range::at(geometry::interior_rings(geometry), ri);
67         }
68     }
69 };
70 
71 template <typename Geometry, typename Tag>
72 struct sub_range<Geometry, Tag, true>
73 {
74     typedef typename boost::range_value<Geometry>::type value_type;
75     typedef typename boost::mpl::if_c
76         <
77             boost::is_const<Geometry>::value,
78             typename boost::add_const<value_type>::type,
79             value_type
80         >::type sub_type;
81 
82     typedef detail_dispatch::sub_range<sub_type> sub_sub_range;
83 
84     // TODO: shouldn't it be return_type?
85     typedef typename sub_sub_range::return_type return_type;
86 
87     template <typename Id> static inline
applyboost::geometry::detail_dispatch::sub_range88     return_type apply(Geometry & geometry, Id const& id)
89     {
90         BOOST_GEOMETRY_ASSERT(0 <= id.multi_index);
91         typedef typename boost::range_size<Geometry>::type size_type;
92         size_type const mi = static_cast<size_type>(id.multi_index);
93         return sub_sub_range::apply(range::at(geometry, mi), id);
94     }
95 };
96 
97 } // namespace detail_dispatch
98 #endif // DOXYGEN_NO_DISPATCH
99 
100 namespace detail {
101 
102 template <typename Geometry>
103 struct sub_range_return_type
104 {
105     typedef typename detail_dispatch::sub_range<Geometry>::return_type type;
106 };
107 
108 // This function also works for geometry::segment_identifier
109 
110 template <typename Geometry, typename Id> inline
111 typename sub_range_return_type<Geometry>::type
sub_range(Geometry & geometry,Id const & id)112 sub_range(Geometry & geometry, Id const& id)
113 {
114     return detail_dispatch::sub_range<Geometry>::apply(geometry, id);
115 }
116 
117 template <typename Geometry, typename Id> inline
118 typename sub_range_return_type<Geometry const>::type
sub_range(Geometry const & geometry,Id const & id)119 sub_range(Geometry const& geometry, Id const& id)
120 {
121     return detail_dispatch::sub_range<Geometry const>::apply(geometry, id);
122 }
123 
124 } // namespace detail
125 #endif // DOXYGEN_NO_DETAIL
126 
127 }} // namespace boost::geometry
128 
129 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SUB_RANGE_HPP
130