diff --git a/include/boost/geometry/strategies/cartesian/distance_pythagoras_box_box.hpp b/include/boost/geometry/strategies/cartesian/distance_pythagoras_box_box.hpp new file mode 100644 index 000000000..d4c94b5c0 --- /dev/null +++ b/include/boost/geometry/strategies/cartesian/distance_pythagoras_box_box.hpp @@ -0,0 +1,338 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2008-2014 Bruno Lalande, Paris, France. +// Copyright (c) 2008-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// 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_BOX_BOX_HPP +#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_BOX_BOX_HPP + + +#include + +#include + +#include + + + + +namespace boost { namespace geometry +{ + +namespace strategy { namespace distance +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +template +struct compute_pythagoras_box_box +{ + template + static inline void apply(Box1 const& box1, Box2 const& box2, T& result) + { + T const b1_min_coord = + boost::numeric_cast(geometry::get(box1)); + T const b1_max_coord = + boost::numeric_cast(geometry::get(box1)); + + T const b2_min_coord = + boost::numeric_cast(geometry::get(box2)); + T const b2_max_coord = + boost::numeric_cast(geometry::get(box2)); + + if ( b1_max_coord < b2_min_coord ) + { + T diff = b2_min_coord - b1_max_coord; + result += diff * diff; + } + if ( b1_min_coord > b2_max_coord ) + { + T diff = b1_min_coord - b2_max_coord; + result += diff * diff; + } + + compute_pythagoras_box_box::apply(box1, box2, result); + } +}; + +template <> +struct compute_pythagoras_box_box<0> +{ + template + static inline void apply(Box1 const&, Box2 const&, T&) + { + } +}; + +} +#endif // DOXYGEN_NO_DETAIL + + +namespace comparable +{ + +/*! +\brief Strategy to calculate comparable distance between two boxes +\ingroup strategies +\tparam Box1 \tparam_first_box +\tparam Box2 \tparam_second_box +\tparam CalculationType \tparam_calculation +*/ +template +class pythagoras_box_box +{ +public : + + template + struct calculation_type + { + typedef typename util::calculation_type::geometric::binary + < + Box1, + Box2, + CalculationType + >::type type; + }; + + template + static inline typename calculation_type::type + apply(Box1 const& box1, Box2 const& box2) + { + BOOST_CONCEPT_ASSERT + ( (concept::ConstPoint::type>) ); + BOOST_CONCEPT_ASSERT + ( (concept::ConstPoint::type>) ); + + // Calculate distance using Pythagoras + // (Leave comment above for Doxygen) + + assert_dimension_equal(); + + typename calculation_type::type result(0); + + detail::compute_pythagoras_box_box + < + dimension::value + >::apply(box1, box2, result); + + return result; + } +}; + +} // namespace comparable + + +/*! +\brief Strategy to calculate the distance between two points or boxes +\ingroup strategies +\tparam CalculationType \tparam_calculation + +\qbk{ +[heading Notes] +[note Can be used for boxes 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_box_box +{ +public : + + template + struct calculation_type + : util::calculation_type::geometric::binary + < + Box1, + Box2, + CalculationType, + double, + double // promote integer to double + > + {}; + + /*! + \brief applies the distance calculation using pythagoras_box_box + \return the calculated distance (including taking the square root) + \param box1 first box + \param box2 second box + */ + template + static inline typename calculation_type::type + apply(Box1 const& box1, Box2 const& box2) + { + // Don't add std:: for ttmath + // The cast is necessary for MSVC which considers sqrt __int64 as an ambiguous call + return sqrt + ( + boost::numeric_cast::type> + ( + comparable::pythagoras_box_box + < + CalculationType + >::apply(box1, box2) + ) + ); + } +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS +namespace services +{ + +template +struct tag > +{ + typedef strategy_tag_distance_box_box type; +}; + + +template +struct return_type, Box1, Box2> + : pythagoras_box_box::template calculation_type +{}; + + +template +struct comparable_type > +{ + typedef comparable::pythagoras_box_box type; +}; + + +template +struct get_comparable > +{ + typedef comparable::pythagoras_box_box comparable_type; +public : + static inline comparable_type + apply(pythagoras_box_box const& ) + { + return comparable_type(); + } +}; + + +template +struct result_from_distance, Box1, Box2> +{ +private: + typedef typename return_type + < + pythagoras_box_box, Box1, Box2 + >::type return_type; +public: + template + static inline return_type + apply(pythagoras_box_box const& , T const& value) + { + return return_type(value); + } +}; + + +// Specializations for comparable::pythagoras_box_box +template +struct tag > +{ + typedef strategy_tag_distance_box_box type; +}; + + +template +struct return_type, Box1, Box2> + : comparable::pythagoras_box_box + < + CalculationType + >::template calculation_type +{}; + + + + +template +struct comparable_type > +{ + typedef comparable::pythagoras_box_box type; +}; + + +template +struct get_comparable > +{ + typedef comparable::pythagoras_box_box comparable_type; +public : + static inline comparable_type apply(comparable_type const& ) + { + return comparable_type(); + } +}; + + +template +struct result_from_distance + < + comparable::pythagoras_box_box, Box1, Box2 + > +{ +private : + typedef typename return_type + < + comparable::pythagoras_box_box, Box1, Box2 + >::type return_type; +public : + template + static inline return_type + apply(comparable::pythagoras_box_box const&, + T const& value) + { + return_type const v = value; + return v * v; + } +}; + + +template +struct default_strategy + < + box_tag, Box1, Box2, cartesian_tag, cartesian_tag, void, box_tag + > +{ + typedef pythagoras_box_box<> type; +}; + + +} // namespace services +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +}} // namespace strategy::distance + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_BOX_BOX_HPP diff --git a/include/boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp b/include/boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp new file mode 100644 index 000000000..304250167 --- /dev/null +++ b/include/boost/geometry/strategies/cartesian/distance_pythagoras_point_box.hpp @@ -0,0 +1,333 @@ +// Boost.Geometry (aka GGL, Generic Geometry Library) + +// Copyright (c) 2008-2014 Bruno Lalande, Paris, France. +// Copyright (c) 2008-2014 Barend Gehrels, Amsterdam, the Netherlands. +// Copyright (c) 2009-2014 Mateusz Loskot, London, UK. + +// This file was modified by Oracle on 2014. +// Modifications copyright (c) 2014, Oracle and/or its affiliates. + +// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle + +// 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_POINT_BOX_HPP +#define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_POINT_BOX_HPP + + +#include + +#include + +#include + + + +namespace boost { namespace geometry +{ + +namespace strategy { namespace distance +{ + +#ifndef DOXYGEN_NO_DETAIL +namespace detail +{ + +template +struct compute_pythagoras_point_box +{ + template + static inline void apply(Point const& point, Box const& box, T& result) + { + T const p_coord = boost::numeric_cast(geometry::get(point)); + T const b_min_coord = + boost::numeric_cast(geometry::get(box)); + T const b_max_coord = + boost::numeric_cast(geometry::get(box)); + + if ( p_coord < b_min_coord ) + { + T diff = b_min_coord - p_coord; + result += diff * diff; + } + if ( p_coord > b_max_coord ) + { + T diff = p_coord - b_max_coord; + result += diff * diff; + } + + compute_pythagoras_point_box::apply(point, box, result); + } +}; + +template <> +struct compute_pythagoras_point_box<0> +{ + template + static inline void apply(Point const&, Box const&, T&) + { + } +}; + + +} // namespace detail +#endif // DOXYGEN_NO_DETAIL + + +namespace comparable +{ + +/*! +\brief Strategy to calculate comparable distance between two points +\ingroup strategies +\tparam Point \tparam_first_point +\tparam Box \tparam_second_box +\tparam CalculationType \tparam_calculation +*/ +template +class pythagoras_point_box +{ +public : + + template + struct calculation_type + { + typedef typename util::calculation_type::geometric::binary + < + Point, Box, CalculationType + >::type type; + }; + + template + static inline typename calculation_type::type + apply(Point const& point, Box const& box) + { + BOOST_CONCEPT_ASSERT( (concept::ConstPoint) ); + BOOST_CONCEPT_ASSERT + ( (concept::ConstPoint::type>) ); + + // Calculate distance using Pythagoras + // (Leave comment above for Doxygen) + + assert_dimension_equal(); + + typename calculation_type::type result(0); + + detail::compute_pythagoras_point_box + < + dimension::value + >::apply(point, box, result); + + return result; + } +}; + +} // namespace comparable + + +/*! +\brief Strategy to calculate the distance between two points or boxes +\ingroup strategies +\tparam CalculationType \tparam_calculation + +\qbk{ +[heading Notes] +[note Can be used for points and boxes 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_point_box +{ +public : + + template + struct calculation_type + : util::calculation_type::geometric::binary + < + Point, + Box, + CalculationType, + double, + double // promote integer to double + > + {}; + + /*! + \brief applies the distance calculation using pythagoras + \return the calculated distance (including taking the square root) + \param point point + \param box box + */ + template + static inline typename calculation_type::type + apply(Point const& point, Box const& box) + { + // Don't add std:: for ttmath + // The cast is necessary for MSVC which considers sqrt __int64 as an ambiguous call + return sqrt + ( + boost::numeric_cast::type> + ( + comparable::pythagoras_point_box + < + CalculationType + >::apply(point, box) + ) + ); + } +}; + + +#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS +namespace services +{ + +template +struct tag > +{ + typedef strategy_tag_distance_point_box type; +}; + + +template +struct return_type, Point, Box> + : pythagoras_point_box + < + CalculationType + >::template calculation_type +{}; + + +template +struct comparable_type > +{ + typedef comparable::pythagoras_point_box type; +}; + + +template +struct get_comparable > +{ + typedef comparable::pythagoras_point_box comparable_type; +public : + static inline comparable_type + apply(pythagoras_point_box const& ) + { + return comparable_type(); + } +}; + + +template +struct result_from_distance, Point, Box> +{ +private : + typedef typename return_type + < + pythagoras_point_box, Point, Box + >::type return_type; +public : + template + static inline return_type + apply(pythagoras_point_box const& , T const& value) + { + return return_type(value); + } +}; + + +// Specializations for comparable::pythagoras_point_box +template +struct tag > +{ + typedef strategy_tag_distance_point_box type; +}; + + +template +struct return_type + < + comparable::pythagoras_point_box, Point, Box + > : comparable::pythagoras_point_box + < + CalculationType + >::template calculation_type +{}; + + + + +template +struct comparable_type > +{ + typedef comparable::pythagoras_point_box type; +}; + + +template +struct get_comparable > +{ + typedef comparable::pythagoras_point_box comparable_type; +public : + static inline comparable_type apply(comparable_type const& ) + { + return comparable_type(); + } +}; + + +template +struct result_from_distance + < + comparable::pythagoras_point_box, Point, Box + > +{ +private : + typedef typename return_type + < + comparable::pythagoras_point_box, Point, Box + >::type return_type; +public : + template + static inline return_type + apply(comparable::pythagoras_point_box const& , + T const& value) + { + return_type const v = value; + return v * v; + } +}; + + +template +struct default_strategy +{ + typedef pythagoras_point_box<> type; +}; + + +} // namespace services +#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS + + +}} // namespace strategy::distance + + +}} // namespace boost::geometry + + +#endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PYTHAGORAS_POINT_BOX_HPP