File indexing completed on 2025-09-16 08:34:11
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
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
0080
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
0113
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
0146
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
0272
0273
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
0301
0302 return per_ring::apply(point, exterior_ring(polygon), strategies);
0303 }
0304
0305
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
0349
0350
0351
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
0371
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 }}
0395 #endif
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 }
0530 #endif
0531
0532
0533 }}
0534
0535
0536 #endif