File indexing completed on 2025-09-17 08:30:34
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENTS_HPP
0017 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENTS_HPP
0018
0019
0020 #include <array>
0021 #include <type_traits>
0022 #include <vector>
0023
0024 #include <boost/range/begin.hpp>
0025 #include <boost/range/end.hpp>
0026 #include <boost/range/size.hpp>
0027
0028 #include <boost/geometry/algorithms/detail/assign_box_corners.hpp>
0029 #include <boost/geometry/algorithms/detail/signed_size_type.hpp>
0030 #include <boost/geometry/algorithms/detail/overlay/append_no_duplicates.hpp>
0031 #include <boost/geometry/algorithms/detail/overlay/append_no_dups_or_spikes.hpp>
0032 #include <boost/geometry/algorithms/not_implemented.hpp>
0033
0034 #include <boost/geometry/core/assert.hpp>
0035 #include <boost/geometry/core/exterior_ring.hpp>
0036 #include <boost/geometry/core/interior_rings.hpp>
0037 #include <boost/geometry/core/ring_type.hpp>
0038 #include <boost/geometry/core/tags.hpp>
0039
0040 #include <boost/geometry/geometries/concepts/check.hpp>
0041
0042 #include <boost/geometry/iterators/ever_circling_iterator.hpp>
0043
0044 #include <boost/geometry/util/range.hpp>
0045
0046 #include <boost/geometry/views/detail/closed_clockwise_view.hpp>
0047
0048
0049 namespace boost { namespace geometry
0050 {
0051
0052
0053 #ifndef DOXYGEN_NO_DETAIL
0054 namespace detail { namespace copy_segments
0055 {
0056
0057
0058 template <bool Reverse>
0059 struct copy_segments_ring
0060 {
0061 template
0062 <
0063 typename Ring,
0064 typename SegmentIdentifier,
0065 typename Strategy,
0066 typename RangeOut
0067 >
0068 static inline void apply(Ring const& ring,
0069 SegmentIdentifier const& seg_id,
0070 signed_size_type to_index,
0071 Strategy const& strategy,
0072 RangeOut& current_output)
0073 {
0074 using view_type = detail::closed_clockwise_view
0075 <
0076 Ring const,
0077 closure<Ring>::value,
0078 Reverse ? counterclockwise : clockwise
0079 >;
0080
0081 using iterator = typename boost::range_iterator<view_type const>::type;
0082 using ec_iterator = geometry::ever_circling_iterator<iterator>;
0083
0084 view_type view(ring);
0085
0086
0087
0088
0089
0090
0091
0092 signed_size_type const from_index = seg_id.segment_index + 1;
0093
0094
0095 BOOST_GEOMETRY_ASSERT(from_index < static_cast<signed_size_type>(boost::size(view)));
0096
0097 ec_iterator it(boost::begin(view), boost::end(view),
0098 boost::begin(view) + from_index);
0099
0100
0101
0102
0103 signed_size_type const count = from_index <= to_index
0104 ? to_index - from_index + 1
0105 : static_cast<signed_size_type>(boost::size(view))
0106 - from_index + to_index + 1;
0107
0108 for (signed_size_type i = 0; i < count; ++i, ++it)
0109 {
0110 detail::overlay::append_no_dups_or_spikes(current_output, *it, strategy);
0111 }
0112 }
0113 };
0114
0115 template <bool Reverse, bool RemoveSpikes = true>
0116 class copy_segments_linestring
0117 {
0118 private:
0119
0120 template <typename RangeOut, typename Point, typename Strategy>
0121 static inline void append_to_output(RangeOut& current_output,
0122 Point const& point,
0123 Strategy const& strategy,
0124 std::true_type const&)
0125 {
0126 detail::overlay::append_no_dups_or_spikes(current_output, point,
0127 strategy);
0128 }
0129
0130
0131 template <typename RangeOut, typename Point, typename Strategy>
0132 static inline void append_to_output(RangeOut& current_output,
0133 Point const& point,
0134 Strategy const& strategy,
0135 std::false_type const&)
0136 {
0137 detail::overlay::append_no_duplicates(current_output, point, strategy);
0138 }
0139
0140 public:
0141 template
0142 <
0143 typename LineString,
0144 typename SegmentIdentifier,
0145 typename SideStrategy,
0146 typename RangeOut
0147 >
0148 static inline void apply(LineString const& ls,
0149 SegmentIdentifier const& seg_id,
0150 signed_size_type to_index,
0151 SideStrategy const& strategy,
0152 RangeOut& current_output)
0153 {
0154 signed_size_type const from_index = seg_id.segment_index + 1;
0155
0156
0157 if ( from_index > to_index
0158 || from_index < 0
0159 || to_index >= static_cast<signed_size_type>(boost::size(ls)) )
0160 {
0161 return;
0162 }
0163
0164 signed_size_type const count = to_index - from_index + 1;
0165 auto it = boost::begin(ls) + from_index;
0166 for (signed_size_type i = 0; i < count; ++i, ++it)
0167 {
0168 append_to_output(current_output, *it, strategy,
0169 std::integral_constant<bool, RemoveSpikes>());
0170 }
0171 }
0172 };
0173
0174 template <bool Reverse>
0175 struct copy_segments_polygon
0176 {
0177 template
0178 <
0179 typename Polygon,
0180 typename SegmentIdentifier,
0181 typename SideStrategy,
0182 typename RangeOut
0183 >
0184 static inline void apply(Polygon const& polygon,
0185 SegmentIdentifier const& seg_id,
0186 signed_size_type to_index,
0187 SideStrategy const& strategy,
0188 RangeOut& current_output)
0189 {
0190
0191 copy_segments_ring<Reverse>::apply
0192 (
0193 seg_id.ring_index < 0
0194 ? geometry::exterior_ring(polygon)
0195 : range::at(geometry::interior_rings(polygon), seg_id.ring_index),
0196 seg_id, to_index,
0197 strategy,
0198 current_output
0199 );
0200 }
0201 };
0202
0203
0204 template <bool Reverse>
0205 struct copy_segments_box
0206 {
0207 template
0208 <
0209 typename Box,
0210 typename SegmentIdentifier,
0211 typename SideStrategy,
0212 typename RangeOut
0213 >
0214 static inline void apply(Box const& box,
0215 SegmentIdentifier const& seg_id,
0216 signed_size_type to_index,
0217 SideStrategy const& strategy,
0218 RangeOut& current_output)
0219 {
0220 signed_size_type index = seg_id.segment_index + 1;
0221 BOOST_GEOMETRY_ASSERT(index < 5);
0222
0223 signed_size_type const count = index <= to_index
0224 ? to_index - index + 1
0225 : 5 - index + to_index + 1;
0226
0227
0228 std::array<point_type_t<Box>, 5> bp;
0229 assign_box_corners_oriented<Reverse>(box, bp);
0230 bp[4] = bp[0];
0231
0232
0233
0234 for (signed_size_type i = 0; i < count; i++, index++)
0235 {
0236 detail::overlay::append_no_dups_or_spikes(current_output,
0237 bp[index % 5], strategy);
0238
0239 }
0240 }
0241 };
0242
0243
0244 template<typename Policy>
0245 struct copy_segments_multi
0246 {
0247 template
0248 <
0249 typename MultiGeometry,
0250 typename SegmentIdentifier,
0251 typename SideStrategy,
0252 typename RangeOut
0253 >
0254 static inline void apply(MultiGeometry const& multi_geometry,
0255 SegmentIdentifier const& seg_id,
0256 signed_size_type to_index,
0257 SideStrategy const& strategy,
0258 RangeOut& current_output)
0259 {
0260
0261 BOOST_GEOMETRY_ASSERT
0262 (
0263 seg_id.multi_index >= 0
0264 && static_cast<std::size_t>(seg_id.multi_index) < boost::size(multi_geometry)
0265 );
0266
0267
0268 Policy::apply(range::at(multi_geometry, seg_id.multi_index),
0269 seg_id, to_index,
0270 strategy,
0271 current_output);
0272 }
0273 };
0274
0275
0276 }}
0277 #endif
0278
0279
0280 #ifndef DOXYGEN_NO_DISPATCH
0281 namespace dispatch
0282 {
0283
0284 template
0285 <
0286 typename Tag,
0287 bool Reverse
0288 >
0289 struct copy_segments : not_implemented<Tag>
0290 {};
0291
0292
0293 template <bool Reverse>
0294 struct copy_segments<ring_tag, Reverse>
0295 : detail::copy_segments::copy_segments_ring<Reverse>
0296 {};
0297
0298
0299 template <bool Reverse>
0300 struct copy_segments<linestring_tag, Reverse>
0301 : detail::copy_segments::copy_segments_linestring<Reverse>
0302 {};
0303
0304 template <bool Reverse>
0305 struct copy_segments<polygon_tag, Reverse>
0306 : detail::copy_segments::copy_segments_polygon<Reverse>
0307 {};
0308
0309
0310 template <bool Reverse>
0311 struct copy_segments<box_tag, Reverse>
0312 : detail::copy_segments::copy_segments_box<Reverse>
0313 {};
0314
0315
0316 template<bool Reverse>
0317 struct copy_segments<multi_polygon_tag, Reverse>
0318 : detail::copy_segments::copy_segments_multi
0319 <
0320 detail::copy_segments::copy_segments_polygon<Reverse>
0321 >
0322 {};
0323
0324
0325 }
0326 #endif
0327
0328
0329
0330
0331
0332
0333
0334 template
0335 <
0336 bool Reverse,
0337 typename Geometry,
0338 typename SegmentIdentifier,
0339 typename SideStrategy,
0340 typename RangeOut
0341 >
0342 inline void copy_segments(Geometry const& geometry,
0343 SegmentIdentifier const& seg_id,
0344 signed_size_type to_index,
0345 SideStrategy const& strategy,
0346 RangeOut& range_out)
0347 {
0348 concepts::check<Geometry const>();
0349
0350 dispatch::copy_segments
0351 <
0352 tag_t<Geometry>,
0353 Reverse
0354 >::apply(geometry, seg_id, to_index, strategy, range_out);
0355 }
0356
0357
0358 }}
0359
0360
0361 #endif