1 // Boost.Geometry (aka GGL, Generic Geometry Library)
3 // Copyright (c) 2014, Oracle and/or its affiliates.
5 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
7 // Licensed under the Boost Software License version 1.0.
8 // http://www.boost.org/users/license.html
10 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_POINT_TO_RANGE_HPP
11 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_POINT_TO_RANGE_HPP
15 #include <boost/range.hpp>
17 #include <boost/geometry/core/assert.hpp>
18 #include <boost/geometry/core/closure.hpp>
19 #include <boost/geometry/strategies/distance.hpp>
20 #include <boost/geometry/util/math.hpp>
23 namespace boost { namespace geometry
26 #ifndef DOXYGEN_NO_DETAIL
27 namespace detail { namespace closest_feature
31 // returns the segment (pair of iterators) that realizes the closest
32 // distance of the point to the range
37 closure_selector Closure,
40 class point_to_point_range
43 typedef typename boost::range_iterator<Range const>::type iterator_type;
45 template <typename Distance>
46 static inline void apply(Point const& point,
49 Strategy const& strategy,
50 iterator_type& it_min1,
51 iterator_type& it_min2,
54 BOOST_GEOMETRY_ASSERT( first != last );
56 Distance const zero = Distance(0);
58 iterator_type it = first;
59 iterator_type prev = it++;
62 it_min1 = it_min2 = first;
63 dist_min = strategy.apply(point, *first, *first);
67 // start with first segment distance
68 dist_min = strategy.apply(point, *prev, *it);
69 iterator_type prev_min_dist = prev;
71 // check if other segments are closer
72 for (++prev, ++it; it != last; ++prev, ++it)
74 Distance const dist = strategy.apply(point, *prev, *it);
76 // Stop only if we find exactly zero distance
77 // otherwise it may stop at some very small value and miss the min
85 else if (dist < dist_min)
92 it_min1 = it_min2 = prev_min_dist;
97 typedef typename std::pair<iterator_type, iterator_type> return_type;
99 template <typename Distance>
100 static inline return_type apply(Point const& point,
103 Strategy const& strategy,
106 iterator_type it_min1, it_min2;
107 apply(point, first, last, strategy, it_min1, it_min2, dist_min);
109 return std::make_pair(it_min1, it_min2);
112 static inline return_type apply(Point const& point,
115 Strategy const& strategy)
117 typename strategy::distance::services::return_type
121 typename boost::range_value<Range>::type
124 return apply(point, first, last, strategy, dist_min);
127 template <typename Distance>
128 static inline return_type apply(Point const& point,
130 Strategy const& strategy,
140 static inline return_type apply(Point const& point,
142 Strategy const& strategy)
144 return apply(point, boost::begin(range), boost::end(range), strategy);
150 // specialization for open ranges
151 template <typename Point, typename Range, typename Strategy>
152 class point_to_point_range<Point, Range, open, Strategy>
153 : point_to_point_range<Point, Range, closed, Strategy>
156 typedef point_to_point_range<Point, Range, closed, Strategy> base_type;
157 typedef typename base_type::iterator_type iterator_type;
159 template <typename Distance>
160 static inline void apply(Point const& point,
163 Strategy const& strategy,
164 iterator_type& it_min1,
165 iterator_type& it_min2,
168 BOOST_GEOMETRY_ASSERT( first != last );
170 base_type::apply(point, first, last, strategy,
171 it_min1, it_min2, dist_min);
173 iterator_type it_back = --last;
174 Distance const zero = Distance(0);
175 Distance dist = strategy.apply(point, *it_back, *first);
177 if (geometry::math::equals(dist, zero))
183 else if (dist < dist_min)
192 typedef typename std::pair<iterator_type, iterator_type> return_type;
194 template <typename Distance>
195 static inline return_type apply(Point const& point,
198 Strategy const& strategy,
201 iterator_type it_min1, it_min2;
203 apply(point, first, last, strategy, it_min1, it_min2, dist_min);
205 return std::make_pair(it_min1, it_min2);
208 static inline return_type apply(Point const& point,
211 Strategy const& strategy)
213 typedef typename strategy::distance::services::return_type
217 typename boost::range_value<Range>::type
218 >::type distance_return_type;
220 distance_return_type dist_min;
222 return apply(point, first, last, strategy, dist_min);
225 template <typename Distance>
226 static inline return_type apply(Point const& point,
228 Strategy const& strategy,
238 static inline return_type apply(Point const& point,
240 Strategy const& strategy)
242 return apply(point, boost::begin(range), boost::end(range), strategy);
247 }} // namespace detail::closest_feature
248 #endif // DOXYGEN_NO_DETAIL
250 }} // namespace boost::geometry
253 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_POINT_TO_RANGE_HPP