1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2 
3 // Copyright (c) 2012-2015 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_BUFFER_BUFFERED_RING
10 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFERED_RING
11 
12 
13 #include <cstddef>
14 
15 #include <boost/range.hpp>
16 
17 #include <boost/geometry/core/assert.hpp>
18 #include <boost/geometry/core/coordinate_type.hpp>
19 #include <boost/geometry/core/point_type.hpp>
20 
21 #include <boost/geometry/strategies/buffer.hpp>
22 
23 #include <boost/geometry/algorithms/within.hpp>
24 
25 #include <boost/geometry/algorithms/detail/overlay/copy_segments.hpp>
26 #include <boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp>
27 #include <boost/geometry/algorithms/detail/overlay/enrichment_info.hpp>
28 #include <boost/geometry/algorithms/detail/overlay/get_ring.hpp>
29 #include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp>
30 #include <boost/geometry/algorithms/detail/overlay/turn_info.hpp>
31 
32 
33 namespace boost { namespace geometry
34 {
35 
36 #ifndef DOXYGEN_NO_DETAIL
37 namespace detail { namespace buffer
38 {
39 
40 struct buffered_ring_collection_tag : polygonal_tag, multi_tag
41 {};
42 
43 
44 template <typename Ring>
45 struct buffered_ring : public Ring
46 {
47     bool has_concave;
48     bool has_accepted_intersections;
49     bool has_discarded_intersections;
50     bool is_untouched_outside_original;
51 
buffered_ringboost::geometry::detail::buffer::buffered_ring52     inline buffered_ring()
53         : has_concave(false)
54         , has_accepted_intersections(false)
55         , has_discarded_intersections(false)
56         , is_untouched_outside_original(false)
57     {}
58 
discardedboost::geometry::detail::buffer::buffered_ring59     inline bool discarded() const
60     {
61         return has_discarded_intersections && ! has_accepted_intersections;
62     }
has_intersectionsboost::geometry::detail::buffer::buffered_ring63     inline bool has_intersections() const
64     {
65         return has_discarded_intersections || has_accepted_intersections;
66     }
67 };
68 
69 // This is a collection now special for overlay (needs vector of rings)
70 template <typename Ring>
71 struct buffered_ring_collection : public std::vector<Ring>
72 {
73 };
74 
75 }} // namespace detail::buffer
76 
77 
78 // Turn off concept checking (for now)
79 namespace dispatch
80 {
81 template <typename Geometry, bool IsConst>
82 struct check<Geometry, detail::buffer::buffered_ring_collection_tag, IsConst>
83 {
84 };
85 
86 }
87 
88 
89 #endif // DOXYGEN_NO_DETAIL
90 
91 
92 
93 // Register the types
94 namespace traits
95 {
96 
97 
98 template <typename Ring>
99 struct tag<detail::buffer::buffered_ring<Ring> >
100 {
101     typedef ring_tag type;
102 };
103 
104 
105 template <typename Ring>
106 struct point_order<detail::buffer::buffered_ring<Ring> >
107 {
108     static const order_selector value = geometry::point_order<Ring>::value;
109 };
110 
111 
112 template <typename Ring>
113 struct closure<detail::buffer::buffered_ring<Ring> >
114 {
115     static const closure_selector value = geometry::closure<Ring>::value;
116 };
117 
118 
119 template <typename Ring>
120 struct point_type<detail::buffer::buffered_ring_collection<Ring> >
121 {
122     typedef typename geometry::point_type<Ring>::type type;
123 };
124 
125 template <typename Ring>
126 struct tag<detail::buffer::buffered_ring_collection<Ring> >
127 {
128     typedef detail::buffer::buffered_ring_collection_tag type;
129 };
130 
131 
132 } // namespace traits
133 
134 
135 
136 
137 namespace core_dispatch
138 {
139 
140 template <typename Ring>
141 struct ring_type
142 <
143     detail::buffer::buffered_ring_collection_tag,
144     detail::buffer::buffered_ring_collection<Ring>
145 >
146 {
147     typedef Ring type;
148 };
149 
150 }
151 
152 namespace dispatch
153 {
154 
155 template
156 <
157     typename MultiRing,
158     bool Reverse,
159     typename SegmentIdentifier,
160     typename PointOut
161 >
162 struct copy_segment_point
163     <
164         detail::buffer::buffered_ring_collection_tag,
165         MultiRing,
166         Reverse,
167         SegmentIdentifier,
168         PointOut
169     >
170     : detail::copy_segments::copy_segment_point_multi
171         <
172             MultiRing,
173             SegmentIdentifier,
174             PointOut,
175             detail::copy_segments::copy_segment_point_range
176                 <
177                     typename boost::range_value<MultiRing>::type,
178                     Reverse,
179                     SegmentIdentifier,
180                     PointOut
181                 >
182         >
183 {};
184 
185 
186 template<bool Reverse>
187 struct copy_segments
188     <
189         detail::buffer::buffered_ring_collection_tag,
190         Reverse
191     >
192     : detail::copy_segments::copy_segments_multi
193         <
194             detail::copy_segments::copy_segments_ring<Reverse>
195         >
196 {};
197 
198 template <typename Point, typename MultiGeometry>
199 struct within
200 <
201     Point,
202     MultiGeometry,
203     point_tag,
204     detail::buffer::buffered_ring_collection_tag
205 >
206 {
207     template <typename Strategy>
applyboost::geometry::dispatch::within208     static inline bool apply(Point const& point,
209                 MultiGeometry const& multi, Strategy const& strategy)
210     {
211         return detail::within::point_in_geometry(point, multi, strategy) == 1;
212     }
213 };
214 
215 
216 } // namespace dispatch
217 
218 namespace detail { namespace overlay
219 {
220 
221 template<>
222 struct get_ring<detail::buffer::buffered_ring_collection_tag>
223 {
224     template<typename MultiGeometry>
applyboost::geometry::detail::overlay::get_ring225     static inline typename ring_type<MultiGeometry>::type const& apply(
226                 ring_identifier const& id,
227                 MultiGeometry const& multi_ring)
228     {
229         BOOST_GEOMETRY_ASSERT
230             (
231                 id.multi_index >= 0
232                 && id.multi_index < int(boost::size(multi_ring))
233             );
234         return get_ring<ring_tag>::apply(id, multi_ring[id.multi_index]);
235     }
236 };
237 
238 }}
239 
240 
241 }} // namespace boost::geometry
242 
243 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFERED_RING
244