File indexing completed on 2025-01-18 09:35:08
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP
0015 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP
0016
0017
0018 #include <array>
0019
0020 #include <boost/range/begin.hpp>
0021 #include <boost/range/end.hpp>
0022 #include <boost/range/size.hpp>
0023 #include <boost/range/value_type.hpp>
0024
0025 #include <boost/geometry/algorithms/convert.hpp>
0026 #include <boost/geometry/algorithms/detail/signed_size_type.hpp>
0027 #include <boost/geometry/core/assert.hpp>
0028 #include <boost/geometry/core/exterior_ring.hpp>
0029 #include <boost/geometry/core/interior_rings.hpp>
0030 #include <boost/geometry/core/ring_type.hpp>
0031 #include <boost/geometry/core/static_assert.hpp>
0032 #include <boost/geometry/core/tags.hpp>
0033 #include <boost/geometry/geometries/concepts/check.hpp>
0034 #include <boost/geometry/util/range.hpp>
0035 #include <boost/geometry/views/detail/closed_clockwise_view.hpp>
0036
0037
0038 namespace boost { namespace geometry
0039 {
0040
0041
0042 #ifndef DOXYGEN_NO_DETAIL
0043 namespace detail { namespace copy_segments
0044 {
0045
0046 inline signed_size_type circular_offset(signed_size_type segment_count, signed_size_type index,
0047 signed_size_type offset)
0048 {
0049 signed_size_type result = (index + offset) % segment_count;
0050 if (result < 0)
0051 {
0052 result += segment_count;
0053 }
0054 return result;
0055 }
0056
0057 template <typename Range, bool Reverse, typename SegmentIdentifier, typename PointOut>
0058 struct copy_segment_point_range
0059 {
0060 static inline bool apply(Range const& range,
0061 SegmentIdentifier const& seg_id, signed_size_type offset,
0062 PointOut& point)
0063 {
0064 using view_type = detail::closed_clockwise_view
0065 <
0066 Range const,
0067 closure<Range>::value,
0068 Reverse ? counterclockwise : clockwise
0069 >;
0070
0071 view_type view(range);
0072
0073 std::size_t const segment_count = boost::size(view) - 1;
0074 signed_size_type const target = circular_offset(segment_count, seg_id.segment_index, offset);
0075 BOOST_GEOMETRY_ASSERT(target >= 0
0076 && std::size_t(target) < boost::size(view));
0077
0078 geometry::convert(range::at(view, target), point);
0079
0080 return true;
0081 }
0082 };
0083
0084
0085 template <typename Polygon, bool Reverse, typename SegmentIdentifier, typename PointOut>
0086 struct copy_segment_point_polygon
0087 {
0088 static inline bool apply(Polygon const& polygon,
0089 SegmentIdentifier const& seg_id, signed_size_type offset,
0090 PointOut& point)
0091 {
0092
0093 return copy_segment_point_range
0094 <
0095 typename geometry::ring_type<Polygon>::type,
0096 Reverse,
0097 SegmentIdentifier,
0098 PointOut
0099 >::apply
0100 (
0101 seg_id.ring_index < 0
0102 ? geometry::exterior_ring(polygon)
0103 : range::at(geometry::interior_rings(polygon), seg_id.ring_index),
0104 seg_id, offset,
0105 point
0106 );
0107 }
0108 };
0109
0110
0111 template <typename Box, bool Reverse, typename SegmentIdentifier, typename PointOut>
0112 struct copy_segment_point_box
0113 {
0114 static inline bool apply(Box const& box,
0115 SegmentIdentifier const& seg_id, signed_size_type offset,
0116 PointOut& point)
0117 {
0118 std::array<typename point_type<Box>::type, 4> bp;
0119 assign_box_corners_oriented<Reverse>(box, bp);
0120
0121 signed_size_type const target = circular_offset(4, seg_id.segment_index, offset);
0122 BOOST_GEOMETRY_ASSERT(target >= 0
0123 && std::size_t(target) < bp.size());
0124
0125 point = bp[target];
0126 return true;
0127 }
0128 };
0129
0130
0131 template
0132 <
0133 typename MultiGeometry,
0134 typename SegmentIdentifier,
0135 typename PointOut,
0136 typename Policy
0137 >
0138 struct copy_segment_point_multi
0139 {
0140 static inline bool apply(MultiGeometry const& multi,
0141 SegmentIdentifier const& seg_id, signed_size_type offset,
0142 PointOut& point)
0143 {
0144 BOOST_GEOMETRY_ASSERT(seg_id.multi_index >= 0
0145 && std::size_t(seg_id.multi_index) < boost::size(multi));
0146
0147
0148 return Policy::apply(range::at(multi, seg_id.multi_index), seg_id, offset, point);
0149 }
0150 };
0151
0152
0153 }}
0154 #endif
0155
0156
0157 #ifndef DOXYGEN_NO_DISPATCH
0158 namespace dispatch
0159 {
0160
0161
0162 template
0163 <
0164 typename Tag,
0165 typename GeometryIn,
0166 bool Reverse,
0167 typename SegmentIdentifier,
0168 typename PointOut
0169 >
0170 struct copy_segment_point
0171 {
0172 BOOST_GEOMETRY_STATIC_ASSERT_FALSE(
0173 "Not or not yet implemented for this Geometry type.",
0174 Tag, GeometryIn);
0175 };
0176
0177
0178 template <typename LineString, bool Reverse, typename SegmentIdentifier, typename PointOut>
0179 struct copy_segment_point<linestring_tag, LineString, Reverse, SegmentIdentifier, PointOut>
0180 : detail::copy_segments::copy_segment_point_range
0181 <
0182 LineString, Reverse, SegmentIdentifier, PointOut
0183 >
0184 {};
0185
0186
0187 template <typename Ring, bool Reverse, typename SegmentIdentifier, typename PointOut>
0188 struct copy_segment_point<ring_tag, Ring, Reverse, SegmentIdentifier, PointOut>
0189 : detail::copy_segments::copy_segment_point_range
0190 <
0191 Ring, Reverse, SegmentIdentifier, PointOut
0192 >
0193 {};
0194
0195 template <typename Polygon, bool Reverse, typename SegmentIdentifier, typename PointOut>
0196 struct copy_segment_point<polygon_tag, Polygon, Reverse, SegmentIdentifier, PointOut>
0197 : detail::copy_segments::copy_segment_point_polygon
0198 <
0199 Polygon, Reverse, SegmentIdentifier, PointOut
0200 >
0201 {};
0202
0203
0204 template <typename Box, bool Reverse, typename SegmentIdentifier, typename PointOut>
0205 struct copy_segment_point<box_tag, Box, Reverse, SegmentIdentifier, PointOut>
0206 : detail::copy_segments::copy_segment_point_box
0207 <
0208 Box, Reverse, SegmentIdentifier, PointOut
0209 >
0210 {};
0211
0212
0213 template
0214 <
0215 typename MultiGeometry,
0216 bool Reverse,
0217 typename SegmentIdentifier,
0218 typename PointOut
0219 >
0220 struct copy_segment_point
0221 <
0222 multi_polygon_tag,
0223 MultiGeometry,
0224 Reverse,
0225 SegmentIdentifier,
0226 PointOut
0227 >
0228 : detail::copy_segments::copy_segment_point_multi
0229 <
0230 MultiGeometry,
0231 SegmentIdentifier,
0232 PointOut,
0233 detail::copy_segments::copy_segment_point_polygon
0234 <
0235 typename boost::range_value<MultiGeometry>::type,
0236 Reverse,
0237 SegmentIdentifier,
0238 PointOut
0239 >
0240 >
0241 {};
0242
0243 template
0244 <
0245 typename MultiGeometry,
0246 bool Reverse,
0247 typename SegmentIdentifier,
0248 typename PointOut
0249 >
0250 struct copy_segment_point
0251 <
0252 multi_linestring_tag,
0253 MultiGeometry,
0254 Reverse,
0255 SegmentIdentifier,
0256 PointOut
0257 >
0258 : detail::copy_segments::copy_segment_point_multi
0259 <
0260 MultiGeometry,
0261 SegmentIdentifier,
0262 PointOut,
0263 detail::copy_segments::copy_segment_point_range
0264 <
0265 typename boost::range_value<MultiGeometry>::type,
0266 Reverse,
0267 SegmentIdentifier,
0268 PointOut
0269 >
0270 >
0271 {};
0272
0273
0274 }
0275 #endif
0276
0277
0278
0279
0280
0281
0282 template<bool Reverse, typename Geometry, typename SegmentIdentifier, typename PointOut>
0283 inline bool copy_segment_point(Geometry const& geometry,
0284 SegmentIdentifier const& seg_id, signed_size_type offset,
0285 PointOut& point_out)
0286 {
0287 concepts::check<Geometry const>();
0288
0289 return dispatch::copy_segment_point
0290 <
0291 typename tag<Geometry>::type,
0292 Geometry,
0293 Reverse,
0294 SegmentIdentifier,
0295 PointOut
0296 >::apply(geometry, seg_id, offset, point_out);
0297 }
0298
0299
0300
0301
0302
0303
0304
0305 template
0306 <
0307 bool Reverse1, bool Reverse2,
0308 typename Geometry1, typename Geometry2,
0309 typename SegmentIdentifier,
0310 typename PointOut
0311 >
0312 inline bool copy_segment_point(Geometry1 const& geometry1, Geometry2 const& geometry2,
0313 SegmentIdentifier const& seg_id, signed_size_type offset,
0314 PointOut& point_out)
0315 {
0316 concepts::check<Geometry1 const>();
0317 concepts::check<Geometry2 const>();
0318
0319 BOOST_GEOMETRY_ASSERT(seg_id.source_index == 0 || seg_id.source_index == 1);
0320
0321 if (seg_id.source_index == 0)
0322 {
0323 return dispatch::copy_segment_point
0324 <
0325 typename tag<Geometry1>::type,
0326 Geometry1,
0327 Reverse1,
0328 SegmentIdentifier,
0329 PointOut
0330 >::apply(geometry1, seg_id, offset, point_out);
0331 }
0332 else if (seg_id.source_index == 1)
0333 {
0334 return dispatch::copy_segment_point
0335 <
0336 typename tag<Geometry2>::type,
0337 Geometry2,
0338 Reverse2,
0339 SegmentIdentifier,
0340 PointOut
0341 >::apply(geometry2, seg_id, offset, point_out);
0342 }
0343
0344 return false;
0345 }
0346
0347
0348
0349
0350
0351
0352
0353 template
0354 <
0355 bool Reverse1, bool Reverse2,
0356 typename Geometry1, typename Geometry2,
0357 typename SegmentIdentifier,
0358 typename PointOut
0359 >
0360 inline bool copy_segment_points(Geometry1 const& geometry1, Geometry2 const& geometry2,
0361 SegmentIdentifier const& seg_id,
0362 PointOut& point1, PointOut& point2)
0363 {
0364 concepts::check<Geometry1 const>();
0365 concepts::check<Geometry2 const>();
0366
0367 return copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, 0, point1)
0368 && copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, 1, point2);
0369 }
0370
0371
0372
0373
0374
0375
0376 template
0377 <
0378 bool Reverse1, bool Reverse2,
0379 typename Geometry1, typename Geometry2,
0380 typename SegmentIdentifier,
0381 typename PointOut
0382 >
0383 inline bool copy_segment_points(Geometry1 const& geometry1, Geometry2 const& geometry2,
0384 SegmentIdentifier const& seg_id,
0385 PointOut& point1, PointOut& point2, PointOut& point3)
0386 {
0387 concepts::check<Geometry1 const>();
0388 concepts::check<Geometry2 const>();
0389
0390 return copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, 0, point1)
0391 && copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, 1, point2)
0392 && copy_segment_point<Reverse1, Reverse2>(geometry1, geometry2, seg_id, 2, point3);
0393 }
0394
0395
0396 }}
0397
0398 #endif