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 dist = strategy.apply(point, *prev, *it);
75 if (geometry::math::equals(dist, zero))
82 else if (dist < dist_min)
89 it_min1 = it_min2 = prev_min_dist;
94 typedef typename std::pair<iterator_type, iterator_type> return_type;
96 template <typename Distance>
97 static inline return_type apply(Point const& point,
100 Strategy const& strategy,
103 iterator_type it_min1, it_min2;
104 apply(point, first, last, strategy, it_min1, it_min2, dist_min);
106 return std::make_pair(it_min1, it_min2);
109 static inline return_type apply(Point const& point,
112 Strategy const& strategy)
114 typename strategy::distance::services::return_type
118 typename boost::range_value<Range>::type
121 return apply(point, first, last, strategy, dist_min);
124 template <typename Distance>
125 static inline return_type apply(Point const& point,
127 Strategy const& strategy,
137 static inline return_type apply(Point const& point,
139 Strategy const& strategy)
141 return apply(point, boost::begin(range), boost::end(range), strategy);
147 // specialization for open ranges
148 template <typename Point, typename Range, typename Strategy>
149 class point_to_point_range<Point, Range, open, Strategy>
150 : point_to_point_range<Point, Range, closed, Strategy>
153 typedef point_to_point_range<Point, Range, closed, Strategy> base_type;
154 typedef typename base_type::iterator_type iterator_type;
156 template <typename Distance>
157 static inline void apply(Point const& point,
160 Strategy const& strategy,
161 iterator_type& it_min1,
162 iterator_type& it_min2,
165 BOOST_GEOMETRY_ASSERT( first != last );
167 base_type::apply(point, first, last, strategy,
168 it_min1, it_min2, dist_min);
170 iterator_type it_back = --last;
171 Distance const zero = Distance(0);
172 Distance dist = strategy.apply(point, *it_back, *first);
174 if (geometry::math::equals(dist, zero))
180 else if (dist < dist_min)
189 typedef typename std::pair<iterator_type, iterator_type> return_type;
191 template <typename Distance>
192 static inline return_type apply(Point const& point,
195 Strategy const& strategy,
198 iterator_type it_min1, it_min2;
200 apply(point, first, last, strategy, it_min1, it_min2, dist_min);
202 return std::make_pair(it_min1, it_min2);
205 static inline return_type apply(Point const& point,
208 Strategy const& strategy)
210 typedef typename strategy::distance::services::return_type
214 typename boost::range_value<Range>::type
215 >::type distance_return_type;
217 distance_return_type dist_min;
219 return apply(point, first, last, strategy, dist_min);
222 template <typename Distance>
223 static inline return_type apply(Point const& point,
225 Strategy const& strategy,
235 static inline return_type apply(Point const& point,
237 Strategy const& strategy)
239 return apply(point, boost::begin(range), boost::end(range), strategy);
244 }} // namespace detail::closest_feature
245 #endif // DOXYGEN_NO_DETAIL
247 }} // namespace boost::geometry
250 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_POINT_TO_RANGE_HPP