// Boost.Geometry (aka GGL, Generic Geometry Library) // Copyright (c) 2008-2012 Bruno Lalande, Paris, France. // Copyright (c) 2008-2012 Barend Gehrels, Amsterdam, the Netherlands. // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. // 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_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP #include #include #include #include namespace boost { namespace geometry { namespace strategy { namespace distance { #ifndef DOXYGEN_NO_DETAIL namespace detail { template struct compute_pythagoras { template static inline T apply(Point1 const& p1, Point2 const& p2) { T const c1 = boost::numeric_cast(get(p1)); T const c2 = boost::numeric_cast(get(p2)); T const d = c1 - c2; return d * d + compute_pythagoras::apply(p1, p2); } }; template struct compute_pythagoras<0, T> { template static inline T apply(Point1 const&, Point2 const&) { return boost::numeric_cast(0); } }; } #endif // DOXYGEN_NO_DETAIL namespace comparable { /*! \brief Strategy to calculate comparable distance between two points \ingroup strategies \tparam Point1 \tparam_first_point \tparam Point2 \tparam_second_point \tparam CalculationType \tparam_calculation */ template class pythagoras { public : template struct calculation_type : util::calculation_type::geometric::binary < Point1, Point2, CalculationType, double, double > {}; template static inline typename calculation_type::type apply(Point1 const& p1, Point2 const& p2) { BOOST_CONCEPT_ASSERT( (concepts::ConstPoint) ); BOOST_CONCEPT_ASSERT( (concepts::ConstPoint) ); // Calculate distance using Pythagoras // (Leave comment above for Doxygen) assert_dimension_equal(); return detail::compute_pythagoras < dimension::value, typename calculation_type::type >::apply(p1, p2); } }; } // namespace comparable /*! \brief Strategy to calculate the distance between two points \ingroup strategies \tparam CalculationType \tparam_calculation \qbk{ [heading Notes] [note Can be used for points with two\, three or more dimensions] [heading See also] [link geometry.reference.algorithms.distance.distance_3_with_strategy distance (with strategy)] } */ template < typename CalculationType = void > class pythagoras { public : template struct calculation_type : util::calculation_type::geometric::binary < P1, P2, CalculationType, double, double // promote integer to double > {}; /*! \brief applies the distance calculation using pythagoras \return the calculated distance (including taking the square root) \param p1 first point \param p2 second point */ template static inline typename calculation_type::type apply(P1 const& p1, P2 const& p2) { // The cast is necessary for MSVC which considers sqrt __int64 as an ambiguous call return math::sqrt ( boost::numeric_cast::type> ( comparable::pythagoras::apply(p1, p2) ) ); } }; #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS namespace services { template struct tag > { typedef strategy_tag_distance_point_point type; }; template struct return_type, P1, P2> : pythagoras::template calculation_type {}; template struct comparable_type > { typedef comparable::pythagoras type; }; template struct get_comparable > { typedef comparable::pythagoras comparable_type; public : static inline comparable_type apply(pythagoras const& ) { return comparable_type(); } }; template struct result_from_distance, Point1, Point2> { private : typedef typename return_type, Point1, Point2>::type return_type; public : template static inline return_type apply(pythagoras const& , T const& value) { return return_type(value); } }; // Specializations for comparable::pythagoras template struct tag > { typedef strategy_tag_distance_point_point type; }; template struct return_type, P1, P2> : comparable::pythagoras::template calculation_type {}; template struct comparable_type > { typedef comparable::pythagoras type; }; template struct get_comparable > { typedef comparable::pythagoras comparable_type; public : static inline comparable_type apply(comparable::pythagoras const& ) { return comparable_type(); } }; template struct result_from_distance, Point1, Point2> { private : typedef typename return_type, Point1, Point2>::type return_type; public : template static inline return_type apply(comparable::pythagoras const& , T const& value) { return_type const v = value; return v * v; } }; template struct default_strategy < point_tag, point_tag, Point1, Point2, cartesian_tag, cartesian_tag > { typedef pythagoras<> type; }; } // namespace services #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS }} // namespace strategy::distance }} // namespace boost::geometry #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_HPP