Imported Upstream version 1.57.0
[platform/upstream/boost.git] / boost / geometry / algorithms / detail / sections / range_by_section.hpp
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
4 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
5 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
6
7 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
8 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
9
10 // This file was modified by Oracle on 2013, 2014.
11 // Modifications copyright (c) 2013, 2014, Oracle and/or its affiliates.
12
13 // Use, modification and distribution is subject to the Boost Software License,
14 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
15 // http://www.boost.org/LICENSE_1_0.txt)
16
17 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
18
19 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_RANGE_BY_SECTION_HPP
20 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_RANGE_BY_SECTION_HPP
21
22 #include <boost/assert.hpp>
23 #include <boost/mpl/assert.hpp>
24 #include <boost/range.hpp>
25
26 #include <boost/geometry/core/access.hpp>
27 #include <boost/geometry/core/closure.hpp>
28 #include <boost/geometry/core/exterior_ring.hpp>
29 #include <boost/geometry/core/interior_rings.hpp>
30 #include <boost/geometry/core/ring_type.hpp>
31 #include <boost/geometry/core/tags.hpp>
32 #include <boost/geometry/geometries/concepts/check.hpp>
33 #include <boost/geometry/util/range.hpp>
34
35
36 namespace boost { namespace geometry
37 {
38
39 #ifndef DOXYGEN_NO_DETAIL
40 namespace detail { namespace section
41 {
42
43
44 template <typename Range, typename Section>
45 struct full_section_range
46 {
47     static inline Range const& apply(Range const& range, Section const& )
48     {
49         return range;
50     }
51 };
52
53
54 template <typename Polygon, typename Section>
55 struct full_section_polygon
56 {
57     static inline typename ring_return_type<Polygon const>::type apply(Polygon const& polygon, Section const& section)
58     {
59         return section.ring_id.ring_index < 0
60             ? geometry::exterior_ring(polygon)
61             : range::at(geometry::interior_rings(polygon), section.ring_id.ring_index);
62     }
63 };
64
65
66 template
67 <
68     typename MultiGeometry,
69     typename Section,
70     typename Policy
71 >
72 struct full_section_multi
73 {
74     static inline typename ring_return_type<MultiGeometry const>::type apply(
75                 MultiGeometry const& multi, Section const& section)
76     {
77         BOOST_ASSERT
78             (
79                 section.ring_id.multi_index >= 0
80                 && section.ring_id.multi_index < int(boost::size(multi))
81             );
82
83         return Policy::apply(range::at(multi, section.ring_id.multi_index), section);
84     }
85 };
86
87
88 }} // namespace detail::section
89 #endif
90
91
92 #ifndef DOXYGEN_NO_DISPATCH
93 namespace dispatch
94 {
95
96
97 template
98 <
99     typename Tag,
100     typename Geometry,
101     typename Section
102 >
103 struct range_by_section
104 {
105     BOOST_MPL_ASSERT_MSG
106         (
107             false, NOT_OR_NOT_YET_IMPLEMENTED_FOR_THIS_GEOMETRY_TYPE
108             , (types<Geometry>)
109         );
110 };
111
112
113 template <typename LineString, typename Section>
114 struct range_by_section<linestring_tag, LineString, Section>
115     : detail::section::full_section_range<LineString, Section>
116 {};
117
118
119 template <typename Ring, typename Section>
120 struct range_by_section<ring_tag, Ring, Section>
121     : detail::section::full_section_range<Ring, Section>
122 {};
123
124
125 template <typename Polygon, typename Section>
126 struct range_by_section<polygon_tag, Polygon, Section>
127     : detail::section::full_section_polygon<Polygon, Section>
128 {};
129
130
131 template <typename MultiPolygon, typename Section>
132 struct range_by_section<multi_polygon_tag, MultiPolygon, Section>
133     : detail::section::full_section_multi
134         <
135             MultiPolygon,
136             Section,
137             detail::section::full_section_polygon
138                 <
139                     typename boost::range_value<MultiPolygon>::type,
140                     Section
141                 >
142        >
143 {};
144
145 template <typename MultiLinestring, typename Section>
146 struct range_by_section<multi_linestring_tag, MultiLinestring, Section>
147     : detail::section::full_section_multi
148         <
149             MultiLinestring,
150             Section,
151             detail::section::full_section_range
152                 <
153                     typename boost::range_value<MultiLinestring>::type,
154                     Section
155                 >
156        >
157 {};
158
159
160 } // namespace dispatch
161 #endif
162
163
164 /*!
165     \brief Get full ring (exterior, one of interiors, one from multi)
166         indicated by the specified section
167     \ingroup sectionalize
168     \tparam Geometry type
169     \tparam Section type of section to get from
170     \param geometry geometry to take section of
171     \param section structure with section
172  */
173 template <typename Geometry, typename Section>
174 inline typename ring_return_type<Geometry const>::type
175             range_by_section(Geometry const& geometry, Section const& section)
176 {
177     concept::check<Geometry const>();
178
179     return dispatch::range_by_section
180         <
181             typename tag<Geometry>::type,
182             Geometry,
183             Section
184         >::apply(geometry, section);
185 }
186
187
188 }} // namespace boost::geometry
189
190 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_RANGE_BY_SECTION_HPP