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