File indexing completed on 2025-01-18 09:35:02
0001
0002
0003
0004
0005
0006
0007
0008
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
0086
0087
0088
0089
0090
0091
0092
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
0190
0191
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
0237
0238 per_ring::apply(point, exterior_ring(polygon), shortest_seg, strategies);
0239 return;
0240 }
0241
0242
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
0306
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 }}
0336 #endif
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
0393
0394
0395
0396
0397
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 }
0450 #endif
0451
0452
0453 }}
0454
0455
0456 #endif