Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:35:08

0001 // Boost.Geometry (aka GGL, Generic Geometry Library)
0002 
0003 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
0004 // Copyright (c) 2023 Adam Wulkiewicz, Lodz, Poland.
0005 
0006 // This file was modified by Oracle on 2020-2021.
0007 // Modifications copyright (c) 2020-2021, Oracle and/or its affiliates.
0008 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
0009 
0010 // Use, modification and distribution is subject to the Boost Software License,
0011 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0012 // http://www.boost.org/LICENSE_1_0.txt)
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         // Call ring-version with the right ring
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         // Call the single-version
0148         return Policy::apply(range::at(multi, seg_id.multi_index), seg_id, offset, point);
0149     }
0150 };
0151 
0152 
0153 }} // namespace detail::copy_segments
0154 #endif // DOXYGEN_NO_DETAIL
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 } // namespace dispatch
0275 #endif // DOXYGEN_NO_DISPATCH
0276 
0277 
0278 /*!
0279     \brief Helper function, copies a point from a segment
0280     \ingroup overlay
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     \brief Helper function, to avoid the same construct several times,
0302         copies a point, based on a source-index and two geometries
0303     \ingroup overlay
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     // Exception?
0344     return false;
0345 }
0346 
0347 
0348 /*!
0349     \brief Helper function, to avoid the same construct several times,
0350         copies a point, based on a source-index and two geometries
0351     \ingroup overlay
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     \brief Helper function, copies three points: two from the specified segment
0373     (from, to) and the next one
0374     \ingroup overlay
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 }} // namespace boost::geometry
0397 
0398 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_OVERLAY_COPY_SEGMENT_POINT_HPP