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/closure.hpp> 20 #include <boost/geometry/core/point_order.hpp> 21 #include <boost/geometry/core/point_type.hpp> 22 23 #include <boost/geometry/strategies/buffer.hpp> 24 25 #include <boost/geometry/algorithms/within.hpp> 26 27 #include <boost/geometry/algorithms/detail/overlay/copy_segments.hpp> 28 #include <boost/geometry/algorithms/detail/overlay/copy_segment_point.hpp> 29 #include <boost/geometry/algorithms/detail/overlay/enrichment_info.hpp> 30 #include <boost/geometry/algorithms/detail/overlay/get_ring.hpp> 31 #include <boost/geometry/algorithms/detail/overlay/traversal_info.hpp> 32 #include <boost/geometry/algorithms/detail/overlay/turn_info.hpp> 33 34 35 namespace boost { namespace geometry 36 { 37 38 #ifndef DOXYGEN_NO_DETAIL 39 namespace detail { namespace buffer 40 { 41 42 struct buffered_ring_collection_tag : polygonal_tag, multi_tag 43 {}; 44 45 46 template <typename Ring> 47 struct buffered_ring : public Ring 48 { 49 bool has_concave; 50 bool has_accepted_intersections; 51 bool has_discarded_intersections; 52 bool is_untouched_outside_original; 53 buffered_ringboost::geometry::detail::buffer::buffered_ring54 inline buffered_ring() 55 : has_concave(false) 56 , has_accepted_intersections(false) 57 , has_discarded_intersections(false) 58 , is_untouched_outside_original(false) 59 {} 60 discardedboost::geometry::detail::buffer::buffered_ring61 inline bool discarded() const 62 { 63 return has_discarded_intersections && ! has_accepted_intersections; 64 } has_intersectionsboost::geometry::detail::buffer::buffered_ring65 inline bool has_intersections() const 66 { 67 return has_discarded_intersections || has_accepted_intersections; 68 } 69 }; 70 71 // This is a collection now special for overlay (needs vector of rings) 72 template <typename Ring> 73 struct buffered_ring_collection : public std::vector<Ring> 74 { 75 }; 76 77 }} // namespace detail::buffer 78 79 80 // Turn off concept checking (for now) 81 namespace dispatch 82 { 83 template <typename Geometry, bool IsConst> 84 struct check<Geometry, detail::buffer::buffered_ring_collection_tag, IsConst> 85 { 86 }; 87 88 } 89 90 91 #endif // DOXYGEN_NO_DETAIL 92 93 94 95 // Register the types 96 namespace traits 97 { 98 99 100 template <typename Ring> 101 struct tag<geometry::detail::buffer::buffered_ring<Ring> > 102 { 103 typedef ring_tag type; 104 }; 105 106 107 template <typename Ring> 108 struct point_order<geometry::detail::buffer::buffered_ring<Ring> > 109 { 110 static const order_selector value = geometry::point_order<Ring>::value; 111 }; 112 113 114 template <typename Ring> 115 struct closure<geometry::detail::buffer::buffered_ring<Ring> > 116 { 117 static const closure_selector value = geometry::closure<Ring>::value; 118 }; 119 120 121 template <typename Ring> 122 struct point_type<geometry::detail::buffer::buffered_ring_collection<Ring> > 123 { 124 typedef typename geometry::point_type<Ring>::type type; 125 }; 126 127 template <typename Ring> 128 struct tag<geometry::detail::buffer::buffered_ring_collection<Ring> > 129 { 130 typedef geometry::detail::buffer::buffered_ring_collection_tag type; 131 }; 132 133 134 } // namespace traits 135 136 137 138 139 namespace core_dispatch 140 { 141 142 template <typename Ring> 143 struct ring_type 144 < 145 detail::buffer::buffered_ring_collection_tag, 146 detail::buffer::buffered_ring_collection<Ring> 147 > 148 { 149 typedef Ring type; 150 }; 151 152 153 // There is a specific tag, so this specialization cannot be placed in traits 154 template <typename Ring> 155 struct point_order<detail::buffer::buffered_ring_collection_tag, 156 geometry::detail::buffer::buffered_ring_collection 157 < 158 geometry::detail::buffer::buffered_ring<Ring> 159 > > 160 { 161 static const order_selector value 162 = core_dispatch::point_order<ring_tag, Ring>::value; 163 }; 164 165 166 } 167 168 169 template <> 170 struct single_tag_of<detail::buffer::buffered_ring_collection_tag> 171 { 172 typedef ring_tag type; 173 }; 174 175 176 namespace dispatch 177 { 178 179 template 180 < 181 typename MultiRing, 182 bool Reverse, 183 typename SegmentIdentifier, 184 typename PointOut 185 > 186 struct copy_segment_point 187 < 188 detail::buffer::buffered_ring_collection_tag, 189 MultiRing, 190 Reverse, 191 SegmentIdentifier, 192 PointOut 193 > 194 : detail::copy_segments::copy_segment_point_multi 195 < 196 MultiRing, 197 SegmentIdentifier, 198 PointOut, 199 detail::copy_segments::copy_segment_point_range 200 < 201 typename boost::range_value<MultiRing>::type, 202 Reverse, 203 SegmentIdentifier, 204 PointOut 205 > 206 > 207 {}; 208 209 210 template<bool Reverse> 211 struct copy_segments 212 < 213 detail::buffer::buffered_ring_collection_tag, 214 Reverse 215 > 216 : detail::copy_segments::copy_segments_multi 217 < 218 detail::copy_segments::copy_segments_ring<Reverse> 219 > 220 {}; 221 222 template <typename Point, typename MultiGeometry> 223 struct within 224 < 225 Point, 226 MultiGeometry, 227 point_tag, 228 detail::buffer::buffered_ring_collection_tag 229 > 230 { 231 template <typename Strategy> applyboost::geometry::dispatch::within232 static inline bool apply(Point const& point, 233 MultiGeometry const& multi, Strategy const& strategy) 234 { 235 return detail::within::point_in_geometry(point, multi, strategy) == 1; 236 } 237 }; 238 239 240 template <typename Geometry> 241 struct is_empty<Geometry, detail::buffer::buffered_ring_collection_tag> 242 : detail::is_empty::multi_is_empty<detail::is_empty::range_is_empty> 243 {}; 244 245 246 template <typename Geometry> 247 struct envelope<Geometry, detail::buffer::buffered_ring_collection_tag> 248 : detail::envelope::envelope_multi_range 249 < 250 detail::envelope::envelope_range 251 > 252 {}; 253 254 255 } // namespace dispatch 256 257 namespace detail { namespace overlay 258 { 259 260 template<> 261 struct get_ring<detail::buffer::buffered_ring_collection_tag> 262 { 263 template<typename MultiGeometry> applyboost::geometry::detail::overlay::get_ring264 static inline typename ring_type<MultiGeometry>::type const& apply( 265 ring_identifier const& id, 266 MultiGeometry const& multi_ring) 267 { 268 BOOST_GEOMETRY_ASSERT 269 ( 270 id.multi_index >= 0 271 && id.multi_index < int(boost::size(multi_ring)) 272 ); 273 return get_ring<ring_tag>::apply(id, multi_ring[id.multi_index]); 274 } 275 }; 276 277 }} 278 279 280 }} // namespace boost::geometry 281 282 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_BUFFER_BUFFERED_RING 283