text: // Boost.Geometry (aka GGL, Generic Geometry Library)
  
  // Copyright (c) 2014, Oracle and/or its affiliates.
  
  // Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
  
  // Licensed under the Boost Software License version 1.0.
  // http://www.boost.org/users/license.html
  
  #ifndef BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_GEOMETRY_TO_RANGE_HPP
  #define BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_GEOMETRY_TO_RANGE_HPP
  
  #include <iterator>
  
  #include <boost/geometry/core/assert.hpp>
  #include <boost/geometry/core/point_type.hpp>
  #include <boost/geometry/strategies/distance.hpp>
  #include <boost/geometry/util/math.hpp>
  
  #include <boost/geometry/algorithms/dispatch/distance.hpp>
  
  
  namespace boost { namespace geometry
  {
  
  #ifndef DOXYGEN_NO_DETAIL
  namespace detail { namespace closest_feature
  {
  
  
  
  // returns the range iterator the realizes the closest
  // distance between the geometry and the element of the range
  class geometry_to_range
  {
  private:
      template
      <
          typename Geometry,
          typename RangeIterator,
          typename Strategy,
          typename Distance
      >
      static inline void apply(Geometry const& geometry,
                               RangeIterator first,
                               RangeIterator last,
                               Strategy const& strategy,
                               RangeIterator& it_min,
                               Distance& dist_min)
      {
          BOOST_GEOMETRY_ASSERT( first != last );
  
          Distance const zero = Distance(0);
  
          // start with first distance
          it_min = first;
          dist_min = dispatch::distance
              <
                  Geometry,
                  typename std::iterator_traits<RangeIterator>::value_type,
                  Strategy
              >::apply(geometry, *it_min, strategy);
  
          // check if other elements in the range are closer
          for (RangeIterator it = ++first; it != last; ++it)
          {
              Distance dist = dispatch::distance
                  <
                      Geometry,
                      typename std::iterator_traits<RangeIterator>::value_type,
                      Strategy
                  >::apply(geometry, *it, strategy);
  
              if (geometry::math::equals(dist, zero))
              {
                  dist_min = dist;
                  it_min = it;
                  return;
              }
              else if (dist < dist_min)
              {
                  dist_min = dist;
                  it_min = it;
              }
          }
      }
  
  public:
      template
      <
          typename Geometry,
          typename RangeIterator,
          typename Strategy,
          typename Distance
      >    
      static inline RangeIterator apply(Geometry const& geometry,
                                        RangeIterator first,
                                        RangeIterator last,
                                        Strategy const& strategy,
                                        Distance& dist_min)
      {
          RangeIterator it_min;
          apply(geometry, first, last, strategy, it_min, dist_min);
  
          return it_min;
      }
  
  
      template
      <
          typename Geometry,
          typename RangeIterator,
          typename Strategy
      >    
      static inline RangeIterator apply(Geometry const& geometry,
                                        RangeIterator first,
                                        RangeIterator last,
                                        Strategy const& strategy)
      {
          typename strategy::distance::services::return_type
              <
                  Strategy,
                  typename point_type<Geometry>::type,
                  typename point_type
                      <
                          typename std::iterator_traits
                              <
                                  RangeIterator
                              >::value_type
                      >::type
              >::type dist_min;
  
          return apply(geometry, first, last, strategy, dist_min);
      }
  };
  
  
  
  }} // namespace detail::closest_feature
  #endif // DOXYGEN_NO_DETAIL
  
  }} // namespace boost::geometry
  
  
  #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_CLOSEST_FEATURE_GEOMETRY_TO_RANGE_HPP
  