// Boost.Geometry (aka GGL, Generic Geometry Library) // Copyright (c) 2007-2013 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2008-2013 Bruno Lalande, Paris, France. // Copyright (c) 2009-2013 Mateusz Loskot, London, UK. // Copyright (c) 2013 Adam Wulkiewicz, Lodz, Poland. // Copyright (c) 2017 Artem Pavlenko, UK // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_GEOMETRY_ALGORITHMS_CLOSEST_POINT_HPP #define BOOST_GEOMETRY_ALGORITHMS_CLOSEST_POINT_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace geometry { #ifndef DOXYGEN_NO_DETAIL namespace detail { namespace closest_point { template struct point_point { template static inline void apply(Point1 const& point1, Point2 const& point2, Strategy const& strategy, Result& result) { result.distance = strategy.apply_point_point(point1, point2); geometry::convert(point2, result.closest_point); } }; template struct point_range { template static inline void apply(Point const& point, Range const& range, Strategy const& strategy, Result& result) { // This should not occur (see exception on empty input below) if (boost::begin(range) == boost::end(range)) { return; } // line of one point: same case as point-point typedef typename boost::range_const_iterator::type iterator_type; iterator_type it = boost::begin(range); iterator_type prev = it++; if (it == boost::end(range)) { point_point::type>::apply(point, *prev, strategy, result); return; } // Initialize with first segment strategy.apply(point, *prev, *it, result); // Check other segments for(prev = it++; it != boost::end(range); prev = it++) { Result other; strategy.apply(point, *prev, *it, other); if (other.distance < result.distance) { result = other; } } } }; }} // namespace detail::closest_point #endif // DOXYGEN_NO_DETAIL #ifndef DOXYGEN_NO_DISPATCH namespace dispatch { template < typename Geometry1, typename Geometry2, typename Tag1 = typename tag::type, typename Tag2 = typename tag::type, bool Reverse = reverse_dispatch::type::value > struct closest_point : not_implemented { }; template < typename Geometry1, typename Geometry2, typename Tag1, typename Tag2 > struct closest_point { template static inline void apply(Geometry1 const& geometry1, Geometry2 const& geometry2, Strategy const& strategy, Result& result) { // Reversed version just calls dispatch with reversed arguments closest_point < Geometry2, Geometry1, Tag2, Tag1, false >::apply(geometry2, geometry1, strategy, result); } }; template struct closest_point < Point1, Point2, point_tag, point_tag, false > : public detail::closest_point::point_point {}; template struct closest_point < Point, Segment, point_tag, segment_tag, false > { template static inline void apply(Point const& point, Segment const& segment, Strategy const& strategy, Result& result) { typename point_type::type p[2]; geometry::detail::assign_point_from_index<0>(segment, p[0]); geometry::detail::assign_point_from_index<1>(segment, p[1]); strategy.apply(point, p[0], p[1], result); } }; template struct closest_point : detail::closest_point::point_range {}; // template struct closest_point < Point, Linestring, point_tag, linestring_tag, false > : detail::closest_point::point_range {}; } // namespace dispatch #endif // DOXYGEN_NO_DISPATCH template inline void closest_point(Geometry1 const& geometry1, Geometry2 const& geometry2, Result& result) { concepts::check(); concepts::check(); concepts::check(); assert_dimension_equal(); assert_dimension_equal(); detail::throw_on_empty_input(geometry1); detail::throw_on_empty_input(geometry2); strategy::distance::calculate_closest_point<> info_strategy; dispatch::closest_point < Geometry1, Geometry2 >::apply(geometry1, geometry2, info_strategy, result); } }} // namespace boost::geometry #endif // BOOST_GEOMETRY_ALGORITHMS_CLOSEST_POINT_HPP