Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 08:34:11

0001 // Boost.Geometry (aka GGL, Generic Geometry Library)
0002 
0003 // Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
0004 // Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
0005 // Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
0006 // Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
0007 
0008 // This file was modified by Oracle on 2014-2021.
0009 // Modifications copyright (c) 2014-2021, Oracle and/or its affiliates.
0010 
0011 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
0012 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
0013 
0014 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
0015 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
0016 
0017 // Use, modification and distribution is subject to the Boost Software License,
0018 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0019 // http://www.boost.org/LICENSE_1_0.txt)
0020 
0021 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_POINT_TO_GEOMETRY_HPP
0022 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_POINT_TO_GEOMETRY_HPP
0023 
0024 #include <iterator>
0025 #include <type_traits>
0026 
0027 #include <boost/core/ignore_unused.hpp>
0028 #include <boost/range/begin.hpp>
0029 #include <boost/range/end.hpp>
0030 #include <boost/range/size.hpp>
0031 #include <boost/range/value_type.hpp>
0032 
0033 #include <boost/geometry/algorithms/assign.hpp>
0034 #include <boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp>
0035 #include <boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp>
0036 #include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
0037 #include <boost/geometry/algorithms/detail/distance/iterator_selector.hpp>
0038 #include <boost/geometry/algorithms/detail/distance/strategy_utils.hpp>
0039 #include <boost/geometry/algorithms/detail/within/point_in_geometry.hpp>
0040 #include <boost/geometry/algorithms/dispatch/distance.hpp>
0041 
0042 #include <boost/geometry/core/closure.hpp>
0043 #include <boost/geometry/core/point_type.hpp>
0044 #include <boost/geometry/core/exterior_ring.hpp>
0045 #include <boost/geometry/core/interior_rings.hpp>
0046 #include <boost/geometry/core/tag.hpp>
0047 #include <boost/geometry/core/tags.hpp>
0048 
0049 #include <boost/geometry/strategies/distance.hpp>
0050 #include <boost/geometry/strategies/relate/services.hpp>
0051 #include <boost/geometry/strategies/tags.hpp>
0052 
0053 #include <boost/geometry/util/math.hpp>
0054 
0055 
0056 namespace boost { namespace geometry
0057 {
0058 
0059 #ifndef DOXYGEN_NO_DETAIL
0060 namespace detail { namespace distance
0061 {
0062 
0063 
0064 template
0065 <
0066     typename P1, typename P2, typename Strategies,
0067     bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategies>::value
0068 >
0069 struct point_to_point
0070 {
0071     static inline
0072     auto apply(P1 const& p1, P2 const& p2, Strategies const& strategies)
0073     {
0074         boost::ignore_unused(strategies);
0075         return strategies.distance(p1, p2).apply(p1, p2);
0076     }
0077 };
0078 
0079 // TEMP?
0080 // called by geometry_to_range
0081 template <typename P1, typename P2, typename Strategy>
0082 struct point_to_point<P1, P2, Strategy, false>
0083 {
0084     static inline
0085     auto apply(P1 const& p1, P2 const& p2, Strategy const& strategy)
0086     {
0087         boost::ignore_unused(strategy);
0088         return strategy.apply(p1, p2);
0089     }
0090 };
0091 
0092 
0093 template
0094 <
0095     typename Point, typename Segment, typename Strategies,
0096     bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategies>::value
0097 >
0098 struct point_to_segment
0099 {
0100     static inline auto apply(Point const& point, Segment const& segment,
0101                              Strategies const& strategies)
0102     {
0103         point_type_t<Segment> p[2];
0104         geometry::detail::assign_point_from_index<0>(segment, p[0]);
0105         geometry::detail::assign_point_from_index<1>(segment, p[1]);
0106 
0107         boost::ignore_unused(strategies);
0108         return strategies.distance(point, segment).apply(point, p[0], p[1]);
0109     }
0110 };
0111 
0112 // TEMP?
0113 // called by geometry_to_range
0114 template <typename Point, typename Segment, typename Strategy>
0115 struct point_to_segment<Point, Segment, Strategy, false>
0116 {
0117     static inline auto apply(Point const& point, Segment const& segment,
0118                              Strategy const& strategy)
0119     {
0120         point_type_t<Segment> p[2];
0121         geometry::detail::assign_point_from_index<0>(segment, p[0]);
0122         geometry::detail::assign_point_from_index<1>(segment, p[1]);
0123 
0124         boost::ignore_unused(strategy);
0125         return strategy.apply(point, p[0], p[1]);
0126     }
0127 };
0128 
0129 
0130 template
0131 <
0132     typename Point, typename Box, typename Strategies,
0133     bool IsUmbrella = strategies::detail::is_umbrella_strategy<Strategies>::value
0134 >
0135 struct point_to_box
0136 {
0137     static inline auto apply(Point const& point, Box const& box,
0138                              Strategies const& strategies)
0139     {
0140         boost::ignore_unused(strategies);
0141         return strategies.distance(point, box).apply(point, box);
0142     }
0143 };
0144 
0145 // TEMP?
0146 // called by geometry_to_range
0147 template <typename Point, typename Box, typename Strategy>
0148 struct point_to_box<Point, Box, Strategy, false>
0149 {
0150     static inline auto apply(Point const& point, Box const& box,
0151                              Strategy const& strategy)
0152     {
0153         boost::ignore_unused(strategy);
0154         return strategy.apply(point, box);
0155     }
0156 };
0157 
0158 
0159 template
0160 <
0161     typename Point,
0162     typename Range,
0163     closure_selector Closure,
0164     typename Strategies
0165 >
0166 class point_to_range
0167 {
0168 private:
0169     typedef distance::strategy_t<Point, Range, Strategies> strategy_type;
0170 
0171     typedef detail::closest_feature::point_to_point_range
0172         <
0173             Point, Range, Closure
0174         > point_to_point_range;
0175 
0176 public:
0177     typedef distance::return_t<Point, Range, Strategies> return_type;
0178 
0179     static inline return_type apply(Point const& point, Range const& range,
0180                                     Strategies const& strategies)
0181     {
0182         if (boost::size(range) == 0)
0183         {
0184             return return_type(0);
0185         }
0186 
0187         distance::creturn_t<Point, Range, Strategies> cd_min;
0188 
0189         std::pair
0190             <
0191                 typename boost::range_iterator<Range const>::type,
0192                 typename boost::range_iterator<Range const>::type
0193             > it_pair
0194             = point_to_point_range::apply(point,
0195                                           boost::begin(range),
0196                                           boost::end(range),
0197                                           strategy::distance::services::get_comparable
0198                                               <
0199                                                   strategy_type
0200                                               >::apply(strategies.distance(point, range)),
0201                                           cd_min);
0202 
0203         return
0204             is_comparable<strategy_type>::value
0205             ?
0206             cd_min
0207             :
0208             strategies.distance(point, range).apply(point, *it_pair.first, *it_pair.second);
0209     }
0210 };
0211 
0212 
0213 template
0214 <
0215     typename Point,
0216     typename Ring,
0217     closure_selector Closure,
0218     typename Strategies
0219 >
0220 struct point_to_ring
0221 {
0222     typedef distance::return_t<Point, Ring, Strategies> return_type;
0223 
0224     static inline return_type apply(Point const& point,
0225                                     Ring const& ring,
0226                                     Strategies const& strategies)
0227     {
0228         if (within::within_point_geometry(point, ring, strategies))
0229         {
0230             return return_type(0);
0231         }
0232 
0233         return point_to_range
0234             <
0235                 Point, Ring, closure<Ring>::value, Strategies
0236             >::apply(point, ring, strategies);
0237     }
0238 };
0239 
0240 
0241 template
0242 <
0243     typename Point,
0244     typename Polygon,
0245     closure_selector Closure,
0246     typename Strategies
0247 >
0248 class point_to_polygon
0249 {
0250 public:
0251     typedef distance::return_t<Point, Polygon, Strategies> return_type;
0252 
0253 private:
0254     typedef point_to_range
0255         <
0256             Point, ring_type_t<Polygon>, Closure, Strategies
0257         > per_ring;
0258 
0259     struct distance_to_interior_rings
0260     {
0261         template <typename InteriorRingIterator>
0262         static inline return_type apply(Point const& point,
0263                                         InteriorRingIterator first,
0264                                         InteriorRingIterator last,
0265                                         Strategies const& strategies)
0266         {
0267             for (InteriorRingIterator it = first; it != last; ++it)
0268             {
0269                 if (within::within_point_geometry(point, *it, strategies))
0270                 {
0271                     // the point is inside a polygon hole, so its distance
0272                     // to the polygon its distance to the polygon's
0273                     // hole boundary
0274                     return per_ring::apply(point, *it, strategies);
0275                 }
0276             }
0277             return return_type(0);
0278         }
0279 
0280         template <typename InteriorRings>
0281         static inline return_type apply(Point const& point, InteriorRings const& interior_rings,
0282                                         Strategies const& strategies)
0283         {
0284             return apply(point,
0285                          boost::begin(interior_rings),
0286                          boost::end(interior_rings),
0287                          strategies);
0288         }
0289     };
0290 
0291 
0292 public:
0293     static inline return_type apply(Point const& point,
0294                                     Polygon const& polygon,
0295                                     Strategies const& strategies)
0296     {
0297         if (! within::covered_by_point_geometry(point, exterior_ring(polygon),
0298                                                 strategies))
0299         {
0300             // the point is outside the exterior ring, so its distance
0301             // to the polygon is its distance to the polygon's exterior ring
0302             return per_ring::apply(point, exterior_ring(polygon), strategies);
0303         }
0304 
0305         // Check interior rings
0306         return distance_to_interior_rings::apply(point,
0307                                                  interior_rings(polygon),
0308                                                  strategies);
0309     }
0310 };
0311 
0312 
0313 template
0314 <
0315     typename Point,
0316     typename MultiGeometry,
0317     typename Strategies,
0318     bool CheckCoveredBy = std::is_same<tag_t<MultiGeometry>, multi_polygon_tag>::value
0319 >
0320 class point_to_multigeometry
0321 {
0322 private:
0323     typedef detail::closest_feature::geometry_to_range geometry_to_range;
0324 
0325     typedef distance::strategy_t<Point, MultiGeometry, Strategies> strategy_type;
0326 
0327 public:
0328     typedef distance::return_t<Point, MultiGeometry, Strategies> return_type;
0329 
0330     static inline return_type apply(Point const& point,
0331                                     MultiGeometry const& multigeometry,
0332                                     Strategies const& strategies)
0333     {
0334         typedef iterator_selector<MultiGeometry const> selector_type;
0335 
0336         distance::creturn_t<Point, MultiGeometry, Strategies> cd;
0337 
0338         typename selector_type::iterator_type it_min
0339             = geometry_to_range::apply(point,
0340                                        selector_type::begin(multigeometry),
0341                                        selector_type::end(multigeometry),
0342                                        strategy::distance::services::get_comparable
0343                                            <
0344                                                strategy_type
0345                                            >::apply(strategies.distance(point, multigeometry)),
0346                                        cd);
0347 
0348         // TODO - It would be possible to use a tool similar to result_from_distance
0349         //        but working in the opposite way, i.e. calculating the distance
0350         //        value from comparable distance value. This way the additional distance
0351         //        call would not be needed.
0352         return
0353             is_comparable<strategy_type>::value
0354             ?
0355             cd
0356             :
0357             dispatch::distance
0358                 <
0359                     Point,
0360                     typename std::iterator_traits
0361                         <
0362                             typename selector_type::iterator_type
0363                         >::value_type,
0364                     Strategies
0365                 >::apply(point, *it_min, strategies);
0366     }
0367 };
0368 
0369 
0370 // this is called only for multipolygons, hence the change in the
0371 // template parameter name MultiGeometry to MultiPolygon
0372 template <typename Point, typename MultiPolygon, typename Strategies>
0373 struct point_to_multigeometry<Point, MultiPolygon, Strategies, true>
0374 {
0375     typedef distance::return_t<Point, MultiPolygon, Strategies> return_type;
0376 
0377     static inline return_type apply(Point const& point,
0378                                     MultiPolygon const& multipolygon,
0379                                     Strategies const& strategies)
0380     {
0381         if (within::covered_by_point_geometry(point, multipolygon, strategies))
0382         {
0383             return return_type(0);
0384         }
0385 
0386         return point_to_multigeometry
0387             <
0388                 Point, MultiPolygon, Strategies, false
0389             >::apply(point, multipolygon, strategies);
0390     }
0391 };
0392 
0393 
0394 }} // namespace detail::distance
0395 #endif // DOXYGEN_NO_DETAIL
0396 
0397 
0398 
0399 
0400 #ifndef DOXYGEN_NO_DISPATCH
0401 namespace dispatch
0402 {
0403 
0404 
0405 template <typename P1, typename P2, typename Strategy>
0406 struct distance
0407     <
0408         P1, P2, Strategy, point_tag, point_tag,
0409         strategy_tag_distance_point_point, false
0410     > : detail::distance::point_to_point<P1, P2, Strategy>
0411 {};
0412 
0413 
0414 template <typename Point, typename Linestring, typename Strategy>
0415 struct distance
0416     <
0417         Point, Linestring, Strategy, point_tag, linestring_tag,
0418         strategy_tag_distance_point_segment, false
0419     > : detail::distance::point_to_range<Point, Linestring, closed, Strategy>
0420 {};
0421 
0422 
0423 template <typename Point, typename Ring, typename Strategy>
0424 struct distance
0425     <
0426         Point, Ring, Strategy, point_tag, ring_tag,
0427         strategy_tag_distance_point_segment, false
0428     > : detail::distance::point_to_ring
0429         <
0430             Point, Ring, closure<Ring>::value, Strategy
0431         >
0432 {};
0433 
0434 
0435 template <typename Point, typename Polygon, typename Strategy>
0436 struct distance
0437     <
0438         Point, Polygon, Strategy, point_tag, polygon_tag,
0439         strategy_tag_distance_point_segment, false
0440     > : detail::distance::point_to_polygon
0441         <
0442             Point, Polygon, closure<Polygon>::value, Strategy
0443         >
0444 {};
0445 
0446 
0447 template <typename Point, typename Segment, typename Strategy>
0448 struct distance
0449     <
0450         Point, Segment, Strategy, point_tag, segment_tag,
0451         strategy_tag_distance_point_segment, false
0452     > : detail::distance::point_to_segment<Point, Segment, Strategy>
0453 {};
0454 
0455 
0456 template <typename Point, typename Box, typename Strategy>
0457 struct distance
0458     <
0459          Point, Box, Strategy, point_tag, box_tag,
0460          strategy_tag_distance_point_box, false
0461     > : detail::distance::point_to_box<Point, Box, Strategy>
0462 {};
0463 
0464 
0465 template<typename Point, typename MultiPoint, typename Strategy>
0466 struct distance
0467     <
0468         Point, MultiPoint, Strategy, point_tag, multi_point_tag,
0469         strategy_tag_distance_point_point, false
0470     > : detail::distance::point_to_multigeometry
0471         <
0472             Point, MultiPoint, Strategy
0473         >
0474 {};
0475 
0476 
0477 template<typename Point, typename MultiLinestring, typename Strategy>
0478 struct distance
0479     <
0480         Point, MultiLinestring, Strategy, point_tag, multi_linestring_tag,
0481         strategy_tag_distance_point_segment, false
0482     > : detail::distance::point_to_multigeometry
0483         <
0484             Point, MultiLinestring, Strategy
0485         >
0486 {};
0487 
0488 
0489 template<typename Point, typename MultiPolygon, typename Strategy>
0490 struct distance
0491     <
0492         Point, MultiPolygon, Strategy, point_tag, multi_polygon_tag,
0493         strategy_tag_distance_point_segment, false
0494     > : detail::distance::point_to_multigeometry
0495         <
0496             Point, MultiPolygon, Strategy
0497         >
0498 {};
0499 
0500 
0501 template <typename Point, typename Linear, typename Strategy>
0502 struct distance
0503     <
0504          Point, Linear, Strategy, point_tag, linear_tag,
0505          strategy_tag_distance_point_segment, false
0506     > : distance
0507         <
0508             Point, Linear, Strategy,
0509             point_tag, tag_t<Linear>,
0510             strategy_tag_distance_point_segment, false
0511         >
0512 {};
0513 
0514 
0515 template <typename Point, typename Areal, typename Strategy>
0516 struct distance
0517     <
0518          Point, Areal, Strategy, point_tag, areal_tag,
0519          strategy_tag_distance_point_segment, false
0520     > : distance
0521         <
0522             Point, Areal, Strategy,
0523             point_tag, tag_t<Areal>,
0524             strategy_tag_distance_point_segment, false
0525         >
0526 {};
0527 
0528 
0529 } // namespace dispatch
0530 #endif // DOXYGEN_NO_DISPATCH
0531 
0532 
0533 }} // namespace boost::geometry
0534 
0535 
0536 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_POINT_TO_GEOMETRY_HPP