File indexing completed on 2025-01-18 09:35:04
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 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
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 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
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, 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
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
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
0352
0353
0354
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
0374
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 }}
0398 #endif
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 }
0533 #endif
0534
0535
0536 }}
0537
0538
0539 #endif