1 // Boost.Geometry (aka GGL, Generic Geometry Library) 2 3 // Copyright (c) 2014, Oracle and/or its affiliates. 4 5 // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle 6 7 // Licensed under the Boost Software License version 1.0. 8 // http://www.boost.org/users/license.html 9 10 #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_GEOMETRY_TO_RANGE_HPP 11 #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_GEOMETRY_TO_RANGE_HPP 12 13 #include <iterator> 14 15 #include <boost/geometry/core/assert.hpp> 16 #include <boost/geometry/core/point_type.hpp> 17 #include <boost/geometry/strategies/distance.hpp> 18 #include <boost/geometry/util/math.hpp> 19 20 #include <boost/geometry/algorithms/dispatch/distance.hpp> 21 22 23 namespace boost { namespace geometry 24 { 25 26 #ifndef DOXYGEN_NO_DETAIL 27 namespace detail { namespace closest_feature 28 { 29 30 31 32 // returns the range iterator the realizes the closest 33 // distance between the geometry and the element of the range 34 class geometry_to_range 35 { 36 private: 37 template 38 < 39 typename Geometry, 40 typename RangeIterator, 41 typename Strategy, 42 typename Distance 43 > apply(Geometry const & geometry,RangeIterator first,RangeIterator last,Strategy const & strategy,RangeIterator & it_min,Distance & dist_min)44 static inline void apply(Geometry const& geometry, 45 RangeIterator first, 46 RangeIterator last, 47 Strategy const& strategy, 48 RangeIterator& it_min, 49 Distance& dist_min) 50 { 51 BOOST_GEOMETRY_ASSERT( first != last ); 52 53 Distance const zero = Distance(0); 54 55 // start with first distance 56 it_min = first; 57 dist_min = dispatch::distance 58 < 59 Geometry, 60 typename std::iterator_traits<RangeIterator>::value_type, 61 Strategy 62 >::apply(geometry, *it_min, strategy); 63 64 // check if other elements in the range are closer 65 for (RangeIterator it = ++first; it != last; ++it) 66 { 67 Distance dist = dispatch::distance 68 < 69 Geometry, 70 typename std::iterator_traits<RangeIterator>::value_type, 71 Strategy 72 >::apply(geometry, *it, strategy); 73 74 if (geometry::math::equals(dist, zero)) 75 { 76 dist_min = dist; 77 it_min = it; 78 return; 79 } 80 else if (dist < dist_min) 81 { 82 dist_min = dist; 83 it_min = it; 84 } 85 } 86 } 87 88 public: 89 template 90 < 91 typename Geometry, 92 typename RangeIterator, 93 typename Strategy, 94 typename Distance 95 > apply(Geometry const & geometry,RangeIterator first,RangeIterator last,Strategy const & strategy,Distance & dist_min)96 static inline RangeIterator apply(Geometry const& geometry, 97 RangeIterator first, 98 RangeIterator last, 99 Strategy const& strategy, 100 Distance& dist_min) 101 { 102 RangeIterator it_min; 103 apply(geometry, first, last, strategy, it_min, dist_min); 104 105 return it_min; 106 } 107 108 109 template 110 < 111 typename Geometry, 112 typename RangeIterator, 113 typename Strategy 114 > apply(Geometry const & geometry,RangeIterator first,RangeIterator last,Strategy const & strategy)115 static inline RangeIterator apply(Geometry const& geometry, 116 RangeIterator first, 117 RangeIterator last, 118 Strategy const& strategy) 119 { 120 typename strategy::distance::services::return_type 121 < 122 Strategy, 123 typename point_type<Geometry>::type, 124 typename point_type 125 < 126 typename std::iterator_traits 127 < 128 RangeIterator 129 >::value_type 130 >::type 131 >::type dist_min; 132 133 return apply(geometry, first, last, strategy, dist_min); 134 } 135 }; 136 137 138 139 }} // namespace detail::closest_feature 140 #endif // DOXYGEN_NO_DETAIL 141 142 }} // namespace boost::geometry 143 144 145 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_GEOMETRY_TO_RANGE_HPP 146