• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
4 
5 // Use, modification and distribution is subject to the Boost Software License,
6 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8 
9 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RING_HPP
10 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RING_HPP
11 
12 
13 #include <boost/range.hpp>
14 
15 #include <boost/geometry/core/assert.hpp>
16 #include <boost/geometry/core/exterior_ring.hpp>
17 #include <boost/geometry/core/interior_rings.hpp>
18 #include <boost/geometry/core/ring_type.hpp>
19 #include <boost/geometry/core/tags.hpp>
20 #include <boost/geometry/algorithms/detail/ring_identifier.hpp>
21 #include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
22 #include <boost/geometry/algorithms/num_points.hpp>
23 #include <boost/geometry/geometries/concepts/check.hpp>
24 #include <boost/geometry/util/range.hpp>
25 
26 
27 namespace boost { namespace geometry
28 {
29 
30 
31 #ifndef DOXYGEN_NO_DETAIL
32 namespace detail { namespace overlay
33 {
34 
35 
36 template<typename Tag>
37 struct get_ring
38 {};
39 
40 // A range of rings (multi-ring but that does not exist)
41 // gets the "void" tag and is dispatched here.
42 template<>
43 struct get_ring<void>
44 {
45     template<typename Range>
46     static inline typename boost::range_value<Range>::type const&
applyboost::geometry::detail::overlay::get_ring47                 apply(ring_identifier const& id, Range const& container)
48     {
49         return range::at(container, id.multi_index);
50     }
51 };
52 
53 
54 template<>
55 struct get_ring<ring_tag>
56 {
57     template<typename Ring>
applyboost::geometry::detail::overlay::get_ring58     static inline Ring const& apply(ring_identifier const& , Ring const& ring)
59     {
60         return ring;
61     }
62 };
63 
64 
65 template<>
66 struct get_ring<box_tag>
67 {
68     template<typename Box>
applyboost::geometry::detail::overlay::get_ring69     static inline Box const& apply(ring_identifier const& ,
70                     Box const& box)
71     {
72         return box;
73     }
74 };
75 
76 
77 template<>
78 struct get_ring<polygon_tag>
79 {
80     template<typename Polygon>
applyboost::geometry::detail::overlay::get_ring81     static inline typename ring_return_type<Polygon const>::type const apply(
82                 ring_identifier const& id,
83                 Polygon const& polygon)
84     {
85         BOOST_GEOMETRY_ASSERT
86             (
87                 id.ring_index >= -1
88                 && id.ring_index < int(boost::size(interior_rings(polygon)))
89             );
90         return id.ring_index < 0
91             ? exterior_ring(polygon)
92             : range::at(interior_rings(polygon), id.ring_index);
93     }
94 };
95 
96 
97 template<>
98 struct get_ring<multi_polygon_tag>
99 {
100     template<typename MultiPolygon>
applyboost::geometry::detail::overlay::get_ring101     static inline typename ring_type<MultiPolygon>::type const& apply(
102                 ring_identifier const& id,
103                 MultiPolygon const& multi_polygon)
104     {
105         BOOST_GEOMETRY_ASSERT
106             (
107                 id.multi_index >= 0
108                 && id.multi_index < int(boost::size(multi_polygon))
109             );
110         return get_ring<polygon_tag>::apply(id,
111                     range::at(multi_polygon, id.multi_index));
112     }
113 };
114 
115 
116 template <typename Geometry>
segment_count_on_ring(Geometry const & geometry,segment_identifier const & seg_id)117 inline std::size_t segment_count_on_ring(Geometry const& geometry,
118                                          segment_identifier const& seg_id)
119 {
120     typedef typename geometry::tag<Geometry>::type tag;
121     ring_identifier const rid(0, seg_id.multi_index, seg_id.ring_index);
122     // A closed polygon, a triangle of 4 points, including starting point,
123     // contains 3 segments. So handle as if closed and subtract one.
124     return geometry::num_points(detail::overlay::get_ring<tag>::apply(rid, geometry), true) - 1;
125 }
126 
127 }} // namespace detail::overlay
128 #endif // DOXYGEN_NO_DETAIL
129 
130 
131 }} // namespace boost::geometry
132 
133 
134 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RING_HPP
135