#ifndef MY_QUANTITY_CARTESIAN_DISTANCE_H #define MY_QUANTITY_CARTESIAN_DISTANCE_H #pragma once #include #include #include #include #include #include #include #include #include namespace boost { namespace geometry { template struct cartesian_distance< ::boost::units::quantity > { private: typedef ::boost::units::quantity coord_type; typedef typename ::boost::units::multiply_typeof_helper< coord_type, coord_type >::type squared_type; cartesian_distance m_distance; typedef typename ::boost::mpl::if_< ::boost::is_integral, double, T>::type value_cast_type; typedef ::boost::units::quantity cast_type; public: explicit cartesian_distance(const squared_type& v) : m_distance(v.value()) { } operator cast_type() const { return cast_type::from_value(static_cast(m_distance)); } bool very_small() const { return m_distance.very_small(); } squared_type squared_value() const { return squared_type::from_value(m_distance.squared_value()); } friend bool operator==(const cartesian_distance& lhs, const cartesian_distance& rhs) { return (lhs.m_distance == rhs.m_distance); } friend bool operator!=(const cartesian_distance& lhs, const cartesian_distance& rhs) { return !(lhs == rhs); } friend bool operator<(const cartesian_distance& lhs, const cartesian_distance& rhs) { return (lhs.m_distance < rhs.m_distance); } friend bool operator>(const cartesian_distance& lhs, const cartesian_distance& rhs) { return (rhs < lhs); } friend bool operator>=(const cartesian_distance& lhs, const cartesian_distance& rhs) { return !(lhs < rhs); } friend bool operator<=(const cartesian_distance& lhs, const cartesian_distance& rhs) { return !(rhs < lhs); } template friend std::basic_ostream& operator<<(std::basic_ostream& os, const cartesian_distance& d) { return os << static_cast(d); } }; // cartesian_distance for ::boost::units::quantity namespace strategy { namespace distance { namespace detail { template struct compute_pythagoras > { private: typedef ::boost::units::quantity coord_type; typedef typename ::boost::units::multiply_typeof_helper< coord_type, coord_type >::type result_type; public: static result_type apply(const Point1& p1, const Point2& p2) { coord_type c1 = ::boost::numeric_cast(get(p1)); coord_type c2 = ::boost::numeric_cast(get(p2)); coord_type d = c2 - c1; return d * d + compute_pythagoras::apply(p1, p2); } // apply }; // compute_pythagoras specialization for units template struct compute_pythagoras > { private: typedef ::boost::units::quantity coord_type; typedef typename ::boost::units::multiply_typeof_helper< coord_type, coord_type >::type result_type; public: static result_type apply(const Point1& p1, const Point2& p2) { coord_type c1 = ::boost::numeric_cast(get<0>(p1)); coord_type c2 = ::boost::numeric_cast(get<0>(p2)); coord_type d = c2 - c1; return d * d; } // apply }; // compute_pythagoras specialization for units template struct compute_pythagoras > { private: typedef ::boost::units::quantity coord_type; typedef typename ::boost::units::multiply_typeof_helper< coord_type, coord_type >::type result_type; public: static result_type apply(const Point1&, const Point2&) { return result_type::from_value(::boost::numeric_cast(0)); } }; // compute_pythagoras specialization for units } // detail template struct pythagoras< point<::boost::units::quantity, Dim, System>, point<::boost::units::quantity, Dim, System>, CalculationType> { typedef point<::boost::units::quantity, Dim, System> first_point_type; typedef point<::boost::units::quantity, Dim, System> second_point_type; typedef typename select_calculation_type< first_point_type, second_point_type, CalculationType >::type calculation_type; typedef cartesian_distance return_type; return_type apply(const first_point_type& p1, const second_point_type& p2) const { BOOST_CONCEPT_ASSERT( (concept::ConstPoint) ); BOOST_CONCEPT_ASSERT( (concept::ConstPoint) ); return return_type( detail::compute_pythagoras< first_point_type, second_point_type, Dim, calculation_type >::apply(p1, p2) ); } // apply }; // pythagoras specialied for cartesian } } } } // boost::geometry::strategy::distance #endif