Back to home page

EIC code displayed by LXR

 
 

    


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

0001 // Boost.Geometry
0002 
0003 // Copyright (c) 2021-2023, Oracle and/or its affiliates.
0004 
0005 // Contributed and/or modified by Vissarion Fysikopoulos, on behalf of Oracle
0006 
0007 // Licensed under the Boost Software License version 1.0.
0008 // http://www.boost.org/users/license.html
0009 
0010 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_POINT_TO_GEOMETRY_HPP
0011 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_POINT_TO_GEOMETRY_HPP
0012 
0013 #include <iterator>
0014 #include <type_traits>
0015 
0016 #include <boost/core/ignore_unused.hpp>
0017 #include <boost/range/begin.hpp>
0018 #include <boost/range/end.hpp>
0019 #include <boost/range/size.hpp>
0020 #include <boost/range/value_type.hpp>
0021 
0022 #include <boost/geometry/algorithms/assign.hpp>
0023 #include <boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp>
0024 #include <boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp>
0025 #include <boost/geometry/algorithms/detail/closest_points/utilities.hpp>
0026 #include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
0027 #include <boost/geometry/algorithms/detail/distance/iterator_selector.hpp>
0028 #include <boost/geometry/algorithms/detail/distance/strategy_utils.hpp>
0029 #include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
0030 #include <boost/geometry/algorithms/dispatch/closest_points.hpp>
0031 #include <boost/geometry/algorithms/dispatch/distance.hpp>
0032 
0033 #include <boost/geometry/core/closure.hpp>
0034 #include <boost/geometry/core/point_type.hpp>
0035 #include <boost/geometry/core/exterior_ring.hpp>
0036 #include <boost/geometry/core/interior_rings.hpp>
0037 #include <boost/geometry/core/radian_access.hpp>
0038 #include <boost/geometry/core/tag.hpp>
0039 #include <boost/geometry/core/tags.hpp>
0040 
0041 #include <boost/geometry/strategies/distance.hpp>
0042 #include <boost/geometry/strategies/relate/services.hpp>
0043 #include <boost/geometry/strategies/tags.hpp>
0044 
0045 #include <boost/geometry/util/math.hpp>
0046 
0047 
0048 namespace boost { namespace geometry
0049 {
0050 
0051 #ifndef DOXYGEN_NO_DETAIL
0052 namespace detail { namespace closest_points
0053 {
0054 
0055 struct point_to_point
0056 {
0057     template <typename P1, typename P2, typename Segment, typename Strategies>
0058     static inline void apply(P1 const& p1, P2 const& p2,
0059                              Segment& shortest_seg, Strategies const&)
0060     {
0061         set_segment_from_points::apply(p1, p2, shortest_seg);
0062     }
0063 };
0064 
0065 struct point_to_segment
0066 {
0067     template <typename Point, typename Segment, typename OutputSegment, typename Strategies>
0068     static inline void apply(Point const& point, Segment const& segment,
0069                              OutputSegment& shortest_seg, Strategies const& strategies)
0070     {
0071         typename point_type<Segment>::type p[2];
0072         geometry::detail::assign_point_from_index<0>(segment, p[0]);
0073         geometry::detail::assign_point_from_index<1>(segment, p[1]);
0074 
0075         boost::ignore_unused(strategies);
0076 
0077         auto closest_point = strategies.closest_points(point, segment)
0078             .apply(point, p[0], p[1]);
0079 
0080         set_segment_from_points::apply(point, closest_point, shortest_seg);
0081     }
0082 };
0083 
0084 /*
0085 struct point_to_box
0086 {
0087     template<typename Point, typename Box, typename Strategies>
0088 static inline auto apply(Point const& point, Box const& box,
0089                              Strategies const& strategies)
0090     {
0091         boost::ignore_unused(strategies);
0092         return strategies.closest_points(point, box).apply(point, box);
0093     }
0094 };
0095 */
0096 
0097 template <closure_selector Closure>
0098 class point_to_range
0099 {
0100 public:
0101 
0102     template <typename Point, typename Range, typename Segment, typename Strategies>
0103     static inline void apply(Point const& point, Range const& range,
0104                              Segment& shortest_seg,
0105                              Strategies const& strategies)
0106     {
0107         using point_to_point_range = detail::closest_feature::point_to_point_range
0108             <
0109                 Point, Range, Closure
0110             >;
0111 
0112         if (boost::size(range) == 0)
0113         {
0114             set_segment_from_points::apply(point, point, shortest_seg);
0115             return;
0116         }
0117 
0118         closest_points::creturn_t<Point, Range, Strategies> cd_min;
0119 
0120         auto comparable_distance = strategy::distance::services::get_comparable
0121             <
0122                 decltype(strategies.distance(point, range))
0123             >::apply(strategies.distance(point, range));
0124 
0125         auto closest_segment = point_to_point_range::apply(point,
0126                                                            boost::begin(range),
0127                                                            boost::end(range),
0128                                                            comparable_distance,
0129                                                            cd_min);
0130 
0131         auto closest_point = strategies.closest_points(point, range)
0132             .apply(point, *closest_segment.first, *closest_segment.second);
0133 
0134         set_segment_from_points::apply(point, closest_point, shortest_seg);
0135     }
0136 };
0137 
0138 
0139 template<closure_selector Closure>
0140 struct point_to_ring
0141 {
0142     template <typename Point, typename Ring, typename Segment, typename Strategies>
0143     static inline auto apply(Point const& point,
0144                              Ring const& ring,
0145                              Segment& shortest_seg,
0146                              Strategies const& strategies)
0147     {
0148         if (within::within_point_geometry(point, ring, strategies))
0149         {
0150             set_segment_from_points::apply(point, point, shortest_seg);
0151         }
0152         else
0153         {
0154             point_to_range
0155             <
0156                 closure<Ring>::value
0157             >::apply(point, ring, shortest_seg, strategies);
0158         }
0159 
0160     }
0161 };
0162 
0163 
0164 template <closure_selector Closure>
0165 class point_to_polygon
0166 {
0167     template <typename Polygon>
0168     struct distance_to_interior_rings
0169     {
0170         template
0171         <
0172             typename Point,
0173             typename InteriorRingIterator,
0174             typename Segment,
0175             typename Strategies
0176         >
0177         static inline void apply(Point const& point,
0178                                  InteriorRingIterator first,
0179                                  InteriorRingIterator last,
0180                                  Segment& shortest_seg,
0181                                  Strategies const& strategies)
0182         {
0183             using per_ring = point_to_range<Closure>;
0184 
0185             for (InteriorRingIterator it = first; it != last; ++it)
0186             {
0187                 if (within::within_point_geometry(point, *it, strategies))
0188                 {
0189                     // the point is inside a polygon hole, so its distance
0190                     // to the polygon is its distance to the polygon's
0191                     // hole boundary
0192                     per_ring::apply(point, *it, shortest_seg, strategies);
0193                     return;
0194                 }
0195             }
0196             set_segment_from_points::apply(point, point, shortest_seg);
0197         }
0198 
0199         template
0200         <
0201             typename Point,
0202             typename InteriorRings,
0203             typename Segment,
0204             typename Strategies
0205         >
0206         static inline void apply(Point const& point, InteriorRings const& interior_rings,
0207                                  Segment& shortest_seg, Strategies const& strategies)
0208         {
0209             apply(point,
0210                   boost::begin(interior_rings),
0211                   boost::end(interior_rings),
0212                   shortest_seg,
0213                   strategies);
0214         }
0215     };
0216 
0217 
0218 public:
0219     template
0220     <
0221         typename Point,
0222         typename Polygon,
0223         typename Segment,
0224         typename Strategies
0225     >
0226     static inline void apply(Point const& point,
0227                              Polygon const& polygon,
0228                              Segment& shortest_seg,
0229                              Strategies const& strategies)
0230     {
0231         using per_ring = point_to_range<Closure>;
0232 
0233         if (! within::covered_by_point_geometry(point, exterior_ring(polygon),
0234                                                 strategies))
0235         {
0236             // the point is outside the exterior ring, so its distance
0237             // to the polygon is its distance to the polygon's exterior ring
0238             per_ring::apply(point, exterior_ring(polygon), shortest_seg, strategies);
0239             return;
0240         }
0241 
0242         // Check interior rings
0243         distance_to_interior_rings<Polygon>::apply(point,
0244                                                    interior_rings(polygon),
0245                                                    shortest_seg,
0246                                                    strategies);
0247     }
0248 };
0249 
0250 
0251 template
0252 <
0253     typename MultiGeometry,
0254     bool CheckCoveredBy = std::is_same
0255         <
0256             typename tag<MultiGeometry>::type, multi_polygon_tag
0257         >::value
0258 >
0259 class point_to_multigeometry
0260 {
0261 private:
0262     using geometry_to_range = detail::closest_feature::geometry_to_range;
0263 
0264 public:
0265 
0266     template
0267     <
0268         typename Point,
0269         typename Segment,
0270         typename Strategies
0271     >
0272     static inline void apply(Point const& point,
0273                              MultiGeometry const& multigeometry,
0274                              Segment& shortest_seg,
0275                              Strategies const& strategies)
0276     {
0277         using selector_type = distance::iterator_selector<MultiGeometry const>;
0278 
0279         closest_points::creturn_t<Point, MultiGeometry, Strategies> cd;
0280 
0281         auto comparable_distance = strategy::distance::services::get_comparable
0282             <
0283                 decltype(strategies.distance(point, multigeometry))
0284             >::apply(strategies.distance(point, multigeometry));
0285 
0286         typename selector_type::iterator_type it_min
0287             = geometry_to_range::apply(point,
0288                                        selector_type::begin(multigeometry),
0289                                        selector_type::end(multigeometry),
0290                                        comparable_distance,
0291                                        cd);
0292 
0293         dispatch::closest_points
0294             <
0295                 Point,
0296                 typename std::iterator_traits
0297                     <
0298                         typename selector_type::iterator_type
0299                     >::value_type
0300             >::apply(point, *it_min, shortest_seg, strategies);
0301     }
0302 };
0303 
0304 
0305 // this is called only for multipolygons, hence the change in the
0306 // template parameter name MultiGeometry to MultiPolygon
0307 template <typename MultiPolygon>
0308 struct point_to_multigeometry<MultiPolygon, true>
0309 {
0310     template
0311     <
0312         typename Point,
0313         typename Segment,
0314         typename Strategies
0315     >
0316     static inline void apply(Point const& point,
0317                              MultiPolygon const& multipolygon,
0318                              Segment& shortest_seg,
0319                              Strategies const& strategies)
0320     {
0321         if (within::covered_by_point_geometry(point, multipolygon, strategies))
0322         {
0323             set_segment_from_points::apply(point, point, shortest_seg);
0324             return;
0325         }
0326 
0327         return point_to_multigeometry
0328             <
0329                 MultiPolygon, false
0330             >::apply(point, multipolygon, shortest_seg, strategies);
0331     }
0332 };
0333 
0334 
0335 }} // namespace detail::closest_points
0336 #endif // DOXYGEN_NO_DETAIL
0337 
0338 
0339 
0340 
0341 #ifndef DOXYGEN_NO_DISPATCH
0342 namespace dispatch
0343 {
0344 
0345 
0346 template <typename P1, typename P2>
0347 struct closest_points
0348     <
0349         P1, P2, point_tag, point_tag, false
0350     > : detail::closest_points::point_to_point
0351 {};
0352 
0353 
0354 template <typename Point, typename Linestring>
0355 struct closest_points
0356     <
0357         Point, Linestring, point_tag, linestring_tag, false
0358     > : detail::closest_points::point_to_range<closed>
0359 {};
0360 
0361 
0362 template <typename Point, typename Ring>
0363 struct closest_points
0364     <
0365         Point, Ring, point_tag, ring_tag, false
0366     > : detail::closest_points::point_to_ring
0367         <
0368             closure<Ring>::value
0369         >
0370 {};
0371 
0372 
0373 template <typename Point, typename Polygon>
0374 struct closest_points
0375     <
0376         Point, Polygon, point_tag, polygon_tag, false
0377     > : detail::closest_points::point_to_polygon
0378         <
0379             closure<Polygon>::value
0380         >
0381 {};
0382 
0383 
0384 template <typename Point, typename Segment>
0385 struct closest_points
0386     <
0387         Point, Segment, point_tag, segment_tag, false
0388     > : detail::closest_points::point_to_segment
0389 {};
0390 
0391 /*
0392 template <typename Point, typename Box>
0393 struct closest_points
0394     <
0395          Point, Box, point_tag, box_tag,
0396          strategy_tag_distance_point_box, false
0397     > : detail::closest_points::point_to_box<Point, Box>
0398 {};
0399 */
0400 
0401 template<typename Point, typename MultiPoint>
0402 struct closest_points
0403     <
0404         Point, MultiPoint, point_tag, multi_point_tag, false
0405     > : detail::closest_points::point_to_multigeometry<MultiPoint>
0406 {};
0407 
0408 
0409 template<typename Point, typename MultiLinestring>
0410 struct closest_points
0411     <
0412         Point, MultiLinestring, point_tag, multi_linestring_tag, false
0413     > : detail::closest_points::point_to_multigeometry<MultiLinestring>
0414 {};
0415 
0416 
0417 template<typename Point, typename MultiPolygon>
0418 struct closest_points
0419     <
0420         Point, MultiPolygon, point_tag, multi_polygon_tag, false
0421     > : detail::closest_points::point_to_multigeometry<MultiPolygon>
0422 {};
0423 
0424 
0425 template <typename Point, typename Linear>
0426 struct closest_points
0427     <
0428          Point, Linear, point_tag, linear_tag, false
0429     > : closest_points
0430         <
0431             Point, Linear,
0432             point_tag, typename tag<Linear>::type, false
0433         >
0434 {};
0435 
0436 
0437 template <typename Point, typename Areal>
0438 struct closest_points
0439     <
0440          Point, Areal, point_tag, areal_tag, false
0441     > : closest_points
0442         <
0443             Point, Areal,
0444             point_tag, typename tag<Areal>::type, false
0445         >
0446 {};
0447 
0448 
0449 } // namespace dispatch
0450 #endif // DOXYGEN_NO_DISPATCH
0451 
0452 
0453 }} // namespace boost::geometry
0454 
0455 
0456 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_POINTS_POINT_TO_GEOMETRY_HPP