]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/geometry/algorithms/detail/overlay/get_ring.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / geometry / algorithms / detail / overlay / get_ring.hpp
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 2020.
6 // Modifications copyright (c) 2020 Oracle and/or its affiliates.
7 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
8
9 // Use, modification and distribution is subject to the Boost Software License,
10 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
11 // http://www.boost.org/LICENSE_1_0.txt)
12
13 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RING_HPP
14 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RING_HPP
15
16
17 #include <boost/range/size.hpp>
18 #include <boost/range/value_type.hpp>
19
20 #include <boost/geometry/core/assert.hpp>
21 #include <boost/geometry/core/exterior_ring.hpp>
22 #include <boost/geometry/core/interior_rings.hpp>
23 #include <boost/geometry/core/ring_type.hpp>
24 #include <boost/geometry/core/tags.hpp>
25 #include <boost/geometry/algorithms/detail/ring_identifier.hpp>
26 #include <boost/geometry/algorithms/detail/overlay/segment_identifier.hpp>
27 #include <boost/geometry/algorithms/num_points.hpp>
28 #include <boost/geometry/geometries/concepts/check.hpp>
29 #include <boost/geometry/util/range.hpp>
30
31
32 namespace boost { namespace geometry
33 {
34
35
36 #ifndef DOXYGEN_NO_DETAIL
37 namespace detail { namespace overlay
38 {
39
40
41 template<typename Tag>
42 struct get_ring
43 {};
44
45 // A range of rings (multi-ring but that does not exist)
46 // gets the "void" tag and is dispatched here.
47 template<>
48 struct get_ring<void>
49 {
50 template<typename Range>
51 static inline typename boost::range_value<Range>::type const&
52 apply(ring_identifier const& id, Range const& container)
53 {
54 return range::at(container, id.multi_index);
55 }
56 };
57
58
59 template<>
60 struct get_ring<ring_tag>
61 {
62 template<typename Ring>
63 static inline Ring const& apply(ring_identifier const& , Ring const& ring)
64 {
65 return ring;
66 }
67 };
68
69
70 template<>
71 struct get_ring<box_tag>
72 {
73 template<typename Box>
74 static inline Box const& apply(ring_identifier const& ,
75 Box const& box)
76 {
77 return box;
78 }
79 };
80
81
82 template<>
83 struct get_ring<polygon_tag>
84 {
85 template<typename Polygon>
86 static inline typename ring_return_type<Polygon const>::type const apply(
87 ring_identifier const& id,
88 Polygon const& polygon)
89 {
90 BOOST_GEOMETRY_ASSERT
91 (
92 id.ring_index >= -1
93 && id.ring_index < int(boost::size(interior_rings(polygon)))
94 );
95 return id.ring_index < 0
96 ? exterior_ring(polygon)
97 : range::at(interior_rings(polygon), id.ring_index);
98 }
99 };
100
101
102 template<>
103 struct get_ring<multi_polygon_tag>
104 {
105 template<typename MultiPolygon>
106 static inline typename ring_type<MultiPolygon>::type const& apply(
107 ring_identifier const& id,
108 MultiPolygon const& multi_polygon)
109 {
110 BOOST_GEOMETRY_ASSERT
111 (
112 id.multi_index >= 0
113 && id.multi_index < int(boost::size(multi_polygon))
114 );
115 return get_ring<polygon_tag>::apply(id,
116 range::at(multi_polygon, id.multi_index));
117 }
118 };
119
120 // Returns the number of segments on a ring (regardless whether the ring is open or closed)
121 template <typename Geometry>
122 inline signed_size_type segment_count_on_ring(Geometry const& geometry,
123 ring_identifier const& ring_id)
124 {
125 using tag = typename geometry::tag<Geometry>::type;
126
127 // A closed polygon, a triangle of 4 points, including starting point,
128 // contains 3 segments. So handle as if it is closed, and subtract one.
129 return geometry::num_points(detail::overlay::get_ring<tag>::apply(ring_id, geometry), true) - 1;
130 }
131
132 // Returns the number of segments on a ring (regardless whether the ring is open or closed)
133 template <typename Geometry>
134 inline signed_size_type segment_count_on_ring(Geometry const& geometry,
135 segment_identifier const& seg_id)
136 {
137 return segment_count_on_ring(geometry, ring_identifier(0, seg_id.multi_index, seg_id.ring_index));
138 }
139
140
141 // Returns the distance between the second and the first segment identifier (second-first)
142 // It supports circular behavior and for this it is necessary to pass the geometry.
143 // It will not report negative values
144 template <typename Geometry>
145 inline signed_size_type segment_distance(Geometry const& geometry,
146 segment_identifier const& first, segment_identifier const& second)
147 {
148 // It is an internal function, make sure the preconditions are met
149 BOOST_ASSERT(second.source_index == first.source_index);
150 BOOST_ASSERT(second.multi_index == first.multi_index);
151 BOOST_ASSERT(second.ring_index == first.ring_index);
152
153 signed_size_type const result = second.segment_index - first.segment_index;
154 if (second.segment_index >= first.segment_index)
155 {
156 return result;
157 }
158 // Take wrap into account, counting segments on the ring (passing any of the ids is fine).
159 // Suppose point_count=10 (10 points, 9 segments), first.seg_id=7, second.seg_id=2,
160 // then distance=9-7+2=4, being segments 7,8,0,1
161 return segment_count_on_ring(geometry, first) + result;
162 }
163
164 }} // namespace detail::overlay
165 #endif // DOXYGEN_NO_DETAIL
166
167
168 }} // namespace boost::geometry
169
170
171 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_GET_RING_HPP