1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2007-2014 Barend Gehrels, Amsterdam, the Netherlands.
4 // Copyright (c) 2008-2014 Bruno Lalande, Paris, France.
5 // Copyright (c) 2009-2014 Mateusz Loskot, London, UK.
6 // Copyright (c) 2013-2014 Adam Wulkiewicz, Lodz, Poland.
8 // This file was modified by Oracle on 2014.
9 // Modifications copyright (c) 2014, Oracle and/or its affiliates.
11 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
13 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
14 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
16 // Use, modification and distribution is subject to the Boost Software License,
17 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
18 // http://www.boost.org/LICENSE_1_0.txt)
20 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_POINT_TO_GEOMETRY_HPP
21 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_POINT_TO_GEOMETRY_HPP
25 #include <boost/core/ignore_unused.hpp>
26 #include <boost/range.hpp>
27 #include <boost/type_traits/is_same.hpp>
29 #include <boost/geometry/core/closure.hpp>
30 #include <boost/geometry/core/point_type.hpp>
31 #include <boost/geometry/core/exterior_ring.hpp>
32 #include <boost/geometry/core/interior_rings.hpp>
33 #include <boost/geometry/core/tag.hpp>
34 #include <boost/geometry/core/tags.hpp>
36 #include <boost/geometry/util/math.hpp>
38 #include <boost/geometry/strategies/distance.hpp>
39 #include <boost/geometry/strategies/tags.hpp>
41 #include <boost/geometry/algorithms/assign.hpp>
42 #include <boost/geometry/algorithms/covered_by.hpp>
43 #include <boost/geometry/algorithms/within.hpp>
45 #include <boost/geometry/algorithms/detail/closest_feature/geometry_to_range.hpp>
46 #include <boost/geometry/algorithms/detail/closest_feature/point_to_range.hpp>
47 #include <boost/geometry/algorithms/detail/distance/is_comparable.hpp>
48 #include <boost/geometry/algorithms/detail/distance/iterator_selector.hpp>
50 #include <boost/geometry/algorithms/dispatch/distance.hpp>
53 namespace boost { namespace geometry
56 #ifndef DOXYGEN_NO_DETAIL
57 namespace detail { namespace distance
61 template <typename P1, typename P2, typename Strategy>
65 typename strategy::distance::services::return_type<Strategy, P1, P2>::type
66 apply(P1 const& p1, P2 const& p2, Strategy const& strategy)
68 boost::ignore_unused(strategy);
69 return strategy.apply(p1, p2);
78 closure_selector Closure,
84 typedef typename strategy::distance::services::comparable_type
87 >::type comparable_strategy;
89 typedef detail::closest_feature::point_to_point_range
91 Point, Range, Closure, comparable_strategy
92 > point_to_point_range;
95 typedef typename strategy::distance::services::return_type
99 typename boost::range_value<Range>::type
102 static inline return_type apply(Point const& point, Range const& range,
103 Strategy const& strategy)
105 return_type const zero = return_type(0);
107 if (boost::size(range) == 0)
112 namespace sds = strategy::distance::services;
114 typename sds::return_type
118 typename point_type<Range>::type
123 typename boost::range_iterator<Range const>::type,
124 typename boost::range_iterator<Range const>::type
126 = point_to_point_range::apply(point,
136 is_comparable<Strategy>::value
140 strategy.apply(point, *it_pair.first, *it_pair.second);
149 closure_selector Closure,
154 typedef typename strategy::distance::services::return_type
156 Strategy, Point, typename point_type<Ring>::type
159 static inline return_type apply(Point const& point,
161 Strategy const& strategy)
163 if (geometry::within(point, ring))
165 return return_type(0);
168 return point_to_range
170 Point, Ring, closure<Ring>::value, Strategy
171 >::apply(point, ring, strategy);
180 closure_selector Closure,
183 class point_to_polygon
186 typedef typename strategy::distance::services::return_type
188 Strategy, Point, typename point_type<Polygon>::type
192 typedef point_to_range
194 Point, typename ring_type<Polygon>::type, Closure, Strategy
197 struct distance_to_interior_rings
199 template <typename InteriorRingIterator>
200 static inline return_type apply(Point const& point,
201 InteriorRingIterator first,
202 InteriorRingIterator last,
203 Strategy const& strategy)
205 for (InteriorRingIterator it = first; it != last; ++it)
207 if (geometry::within(point, *it))
209 // the point is inside a polygon hole, so its distance
210 // to the polygon its distance to the polygon's
212 return per_ring::apply(point, *it, strategy);
218 template <typename InteriorRings>
219 static inline return_type apply(Point const& point,
220 InteriorRings const& interior_rings,
221 Strategy const& strategy)
224 boost::begin(interior_rings),
225 boost::end(interior_rings),
232 static inline return_type apply(Point const& point,
233 Polygon const& polygon,
234 Strategy const& strategy)
236 if (!geometry::covered_by(point, exterior_ring(polygon)))
238 // the point is outside the exterior ring, so its distance
239 // to the polygon is its distance to the polygon's exterior ring
240 return per_ring::apply(point, exterior_ring(polygon), strategy);
243 // Check interior rings
244 return distance_to_interior_rings::apply(point,
245 interior_rings(polygon),
254 typename MultiGeometry,
256 bool CheckCoveredBy = boost::is_same
258 typename tag<MultiGeometry>::type, multi_polygon_tag
261 class point_to_multigeometry
264 typedef detail::closest_feature::geometry_to_range geometry_to_range;
267 typedef typename strategy::distance::services::return_type
271 typename point_type<MultiGeometry>::type
274 static inline return_type apply(Point const& point,
275 MultiGeometry const& multigeometry,
276 Strategy const& strategy)
278 typedef iterator_selector<MultiGeometry const> selector_type;
280 namespace sds = strategy::distance::services;
282 typename sds::return_type
284 typename sds::comparable_type<Strategy>::type,
286 typename point_type<MultiGeometry>::type
289 typename selector_type::iterator_type it_min
290 = geometry_to_range::apply(point,
291 selector_type::begin(multigeometry),
292 selector_type::end(multigeometry),
300 is_comparable<Strategy>::value
307 typename std::iterator_traits
309 typename selector_type::iterator_type
312 >::apply(point, *it_min, strategy);
317 // this is called only for multipolygons, hence the change in the
318 // template parameter name MultiGeometry to MultiPolygon
319 template <typename Point, typename MultiPolygon, typename Strategy>
320 struct point_to_multigeometry<Point, MultiPolygon, Strategy, true>
322 typedef typename strategy::distance::services::return_type
326 typename point_type<MultiPolygon>::type
329 static inline return_type apply(Point const& point,
330 MultiPolygon const& multipolygon,
331 Strategy const& strategy)
333 if (geometry::covered_by(point, multipolygon))
338 return point_to_multigeometry
340 Point, MultiPolygon, Strategy, false
341 >::apply(point, multipolygon, strategy);
346 }} // namespace detail::distance
347 #endif // DOXYGEN_NO_DETAIL
352 #ifndef DOXYGEN_NO_DISPATCH
358 template <typename P1, typename P2, typename Strategy>
361 P1, P2, Strategy, point_tag, point_tag,
362 strategy_tag_distance_point_point, false
363 > : detail::distance::point_to_point<P1, P2, Strategy>
367 // Point-line version 2, where point-segment strategy is specified
368 template <typename Point, typename Linestring, typename Strategy>
371 Point, Linestring, Strategy, point_tag, linestring_tag,
372 strategy_tag_distance_point_segment, false
373 > : detail::distance::point_to_range<Point, Linestring, closed, Strategy>
377 // Point-ring , where point-segment strategy is specified
378 template <typename Point, typename Ring, typename Strategy>
381 Point, Ring, Strategy, point_tag, ring_tag,
382 strategy_tag_distance_point_segment, false
383 > : detail::distance::point_to_ring
385 Point, Ring, closure<Ring>::value, Strategy
390 // Point-polygon , where point-segment strategy is specified
391 template <typename Point, typename Polygon, typename Strategy>
394 Point, Polygon, Strategy, point_tag, polygon_tag,
395 strategy_tag_distance_point_segment, false
396 > : detail::distance::point_to_polygon
398 Point, Polygon, closure<Polygon>::value, Strategy
403 // Point-segment version 2, with point-segment strategy
404 template <typename Point, typename Segment, typename Strategy>
407 Point, Segment, Strategy, point_tag, segment_tag,
408 strategy_tag_distance_point_segment, false
411 static inline typename strategy::distance::services::return_type
413 Strategy, Point, typename point_type<Segment>::type
414 >::type apply(Point const& point,
415 Segment const& segment,
416 Strategy const& strategy)
418 typename point_type<Segment>::type p[2];
419 geometry::detail::assign_point_from_index<0>(segment, p[0]);
420 geometry::detail::assign_point_from_index<1>(segment, p[1]);
422 boost::ignore_unused(strategy);
423 return strategy.apply(point, p[0], p[1]);
428 template <typename Point, typename Box, typename Strategy>
431 Point, Box, Strategy, point_tag, box_tag,
432 strategy_tag_distance_point_box, false
435 static inline typename strategy::distance::services::return_type
437 Strategy, Point, typename point_type<Box>::type
439 apply(Point const& point, Box const& box, Strategy const& strategy)
441 boost::ignore_unused(strategy);
442 return strategy.apply(point, box);
447 template<typename Point, typename MultiPoint, typename Strategy>
450 Point, MultiPoint, Strategy, point_tag, multi_point_tag,
451 strategy_tag_distance_point_point, false
452 > : detail::distance::point_to_multigeometry
454 Point, MultiPoint, Strategy
459 template<typename Point, typename MultiLinestring, typename Strategy>
462 Point, MultiLinestring, Strategy, point_tag, multi_linestring_tag,
463 strategy_tag_distance_point_segment, false
464 > : detail::distance::point_to_multigeometry
466 Point, MultiLinestring, Strategy
471 template<typename Point, typename MultiPolygon, typename Strategy>
474 Point, MultiPolygon, Strategy, point_tag, multi_polygon_tag,
475 strategy_tag_distance_point_segment, false
476 > : detail::distance::point_to_multigeometry
478 Point, MultiPolygon, Strategy
483 template <typename Point, typename Linear, typename Strategy>
486 Point, Linear, Strategy, point_tag, linear_tag,
487 strategy_tag_distance_point_segment, false
490 Point, Linear, Strategy,
491 point_tag, typename tag<Linear>::type,
492 strategy_tag_distance_point_segment, false
497 template <typename Point, typename Areal, typename Strategy>
500 Point, Areal, Strategy, point_tag, areal_tag,
501 strategy_tag_distance_point_segment, false
504 Point, Areal, Strategy,
505 point_tag, typename tag<Areal>::type,
506 strategy_tag_distance_point_segment, false
511 } // namespace dispatch
512 #endif // DOXYGEN_NO_DISPATCH
515 }} // namespace boost::geometry
518 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_DISTANCE_POINT_TO_GEOMETRY_HPP