Back to home page

EIC code displayed by LXR

 
 

    


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

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         typename point_type<Segment>::type 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         typename point_type<Segment>::type 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, typename ring_type<Polygon>::type, 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
0319         <
0320             typename tag<MultiGeometry>::type, multi_polygon_tag
0321         >::value
0322 >
0323 class point_to_multigeometry
0324 {
0325 private:
0326     typedef detail::closest_feature::geometry_to_range geometry_to_range;
0327 
0328     typedef distance::strategy_t<Point, MultiGeometry, Strategies> strategy_type;
0329 
0330 public:
0331     typedef distance::return_t<Point, MultiGeometry, Strategies> return_type;
0332 
0333     static inline return_type apply(Point const& point,
0334                                     MultiGeometry const& multigeometry,
0335                                     Strategies const& strategies)
0336     {
0337         typedef iterator_selector<MultiGeometry const> selector_type;
0338 
0339         distance::creturn_t<Point, MultiGeometry, Strategies> cd;
0340 
0341         typename selector_type::iterator_type it_min
0342             = geometry_to_range::apply(point,
0343                                        selector_type::begin(multigeometry),
0344                                        selector_type::end(multigeometry),
0345                                        strategy::distance::services::get_comparable
0346                                            <
0347                                                strategy_type
0348                                            >::apply(strategies.distance(point, multigeometry)),
0349                                        cd);
0350 
0351         // TODO - It would be possible to use a tool similar to result_from_distance
0352         //        but working in the opposite way, i.e. calculating the distance
0353         //        value from comparable distance value. This way the additional distance
0354         //        call would not be needed.
0355         return
0356             is_comparable<strategy_type>::value
0357             ?
0358             cd
0359             :
0360             dispatch::distance
0361                 <
0362                     Point,
0363                     typename std::iterator_traits
0364                         <
0365                             typename selector_type::iterator_type
0366                         >::value_type,
0367                     Strategies
0368                 >::apply(point, *it_min, strategies);
0369     }
0370 };
0371 
0372 
0373 // this is called only for multipolygons, hence the change in the
0374 // template parameter name MultiGeometry to MultiPolygon
0375 template <typename Point, typename MultiPolygon, typename Strategies>
0376 struct point_to_multigeometry<Point, MultiPolygon, Strategies, true>
0377 {
0378     typedef distance::return_t<Point, MultiPolygon, Strategies> return_type;
0379 
0380     static inline return_type apply(Point const& point,
0381                                     MultiPolygon const& multipolygon,
0382                                     Strategies const& strategies)
0383     {
0384         if (within::covered_by_point_geometry(point, multipolygon, strategies))
0385         {
0386             return return_type(0);
0387         }
0388 
0389         return point_to_multigeometry
0390             <
0391                 Point, MultiPolygon, Strategies, false
0392             >::apply(point, multipolygon, strategies);
0393     }
0394 };
0395 
0396 
0397 }} // namespace detail::distance
0398 #endif // DOXYGEN_NO_DETAIL
0399 
0400 
0401 
0402 
0403 #ifndef DOXYGEN_NO_DISPATCH
0404 namespace dispatch
0405 {
0406 
0407 
0408 template <typename P1, typename P2, typename Strategy>
0409 struct distance
0410     <
0411         P1, P2, Strategy, point_tag, point_tag,
0412         strategy_tag_distance_point_point, false
0413     > : detail::distance::point_to_point<P1, P2, Strategy>
0414 {};
0415 
0416 
0417 template <typename Point, typename Linestring, typename Strategy>
0418 struct distance
0419     <
0420         Point, Linestring, Strategy, point_tag, linestring_tag,
0421         strategy_tag_distance_point_segment, false
0422     > : detail::distance::point_to_range<Point, Linestring, closed, Strategy>
0423 {};
0424 
0425 
0426 template <typename Point, typename Ring, typename Strategy>
0427 struct distance
0428     <
0429         Point, Ring, Strategy, point_tag, ring_tag,
0430         strategy_tag_distance_point_segment, false
0431     > : detail::distance::point_to_ring
0432         <
0433             Point, Ring, closure<Ring>::value, Strategy
0434         >
0435 {};
0436 
0437 
0438 template <typename Point, typename Polygon, typename Strategy>
0439 struct distance
0440     <
0441         Point, Polygon, Strategy, point_tag, polygon_tag,
0442         strategy_tag_distance_point_segment, false
0443     > : detail::distance::point_to_polygon
0444         <
0445             Point, Polygon, closure<Polygon>::value, Strategy
0446         >
0447 {};
0448 
0449 
0450 template <typename Point, typename Segment, typename Strategy>
0451 struct distance
0452     <
0453         Point, Segment, Strategy, point_tag, segment_tag,
0454         strategy_tag_distance_point_segment, false
0455     > : detail::distance::point_to_segment<Point, Segment, Strategy>
0456 {};
0457 
0458 
0459 template <typename Point, typename Box, typename Strategy>
0460 struct distance
0461     <
0462          Point, Box, Strategy, point_tag, box_tag,
0463          strategy_tag_distance_point_box, false
0464     > : detail::distance::point_to_box<Point, Box, Strategy>
0465 {};
0466 
0467 
0468 template<typename Point, typename MultiPoint, typename Strategy>
0469 struct distance
0470     <
0471         Point, MultiPoint, Strategy, point_tag, multi_point_tag,
0472         strategy_tag_distance_point_point, false
0473     > : detail::distance::point_to_multigeometry
0474         <
0475             Point, MultiPoint, Strategy
0476         >
0477 {};
0478 
0479 
0480 template<typename Point, typename MultiLinestring, typename Strategy>
0481 struct distance
0482     <
0483         Point, MultiLinestring, Strategy, point_tag, multi_linestring_tag,
0484         strategy_tag_distance_point_segment, false
0485     > : detail::distance::point_to_multigeometry
0486         <
0487             Point, MultiLinestring, Strategy
0488         >
0489 {};
0490 
0491 
0492 template<typename Point, typename MultiPolygon, typename Strategy>
0493 struct distance
0494     <
0495         Point, MultiPolygon, Strategy, point_tag, multi_polygon_tag,
0496         strategy_tag_distance_point_segment, false
0497     > : detail::distance::point_to_multigeometry
0498         <
0499             Point, MultiPolygon, Strategy
0500         >
0501 {};
0502 
0503 
0504 template <typename Point, typename Linear, typename Strategy>
0505 struct distance
0506     <
0507          Point, Linear, Strategy, point_tag, linear_tag,
0508          strategy_tag_distance_point_segment, false
0509     > : distance
0510         <
0511             Point, Linear, Strategy,
0512             point_tag, typename tag<Linear>::type,
0513             strategy_tag_distance_point_segment, false
0514         >
0515 {};
0516 
0517 
0518 template <typename Point, typename Areal, typename Strategy>
0519 struct distance
0520     <
0521          Point, Areal, Strategy, point_tag, areal_tag,
0522          strategy_tag_distance_point_segment, false
0523     > : distance
0524         <
0525             Point, Areal, Strategy,
0526             point_tag, typename tag<Areal>::type,
0527             strategy_tag_distance_point_segment, false
0528         >
0529 {};
0530 
0531 
0532 } // namespace dispatch
0533 #endif // DOXYGEN_NO_DISPATCH
0534 
0535 
0536 }} // namespace boost::geometry
0537 
0538 
0539 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_POINT_TO_GEOMETRY_HPP