Chris@16: // Boost.Geometry (aka GGL, Generic Geometry Library) Chris@16: Chris@16: // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands. Chris@16: Chris@16: // Use, modification and distribution is subject to the Boost Software License, Chris@16: // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at Chris@16: // http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_SPHERICAL_HPP Chris@16: #define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_SPHERICAL_HPP Chris@16: Chris@16: #include Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: Chris@16: namespace boost { namespace geometry Chris@16: { Chris@16: Chris@16: Chris@16: namespace strategy { namespace compare Chris@16: { Chris@16: Chris@16: Chris@16: #ifndef DOXYGEN_NO_DETAIL Chris@16: namespace detail Chris@16: { Chris@16: Chris@16: template Chris@16: struct shift Chris@16: { Chris@16: }; Chris@16: Chris@16: template <> Chris@16: struct shift Chris@16: { Chris@16: static inline double full() { return 360.0; } Chris@16: static inline double half() { return 180.0; } Chris@16: }; Chris@16: Chris@16: template <> Chris@16: struct shift Chris@16: { Chris@16: static inline double full() { return 2.0 * boost::math::constants::pi(); } Chris@16: static inline double half() { return boost::math::constants::pi(); } Chris@16: }; Chris@16: Chris@16: } // namespace detail Chris@16: #endif Chris@16: Chris@16: /*! Chris@16: \brief Compare (in one direction) strategy for spherical coordinates Chris@16: \ingroup strategies Chris@16: \tparam Point point-type Chris@16: \tparam Dimension dimension Chris@16: */ Chris@16: template Chris@16: struct circular_comparator Chris@16: { Chris@16: static inline CoordinateType put_in_range(CoordinateType const& c, Chris@16: double min_border, double max_border) Chris@16: { Chris@16: CoordinateType value = c; Chris@16: while (value < min_border) Chris@16: { Chris@16: value += detail::shift::full(); Chris@16: } Chris@16: while (value > max_border) Chris@16: { Chris@16: value -= detail::shift::full(); Chris@16: } Chris@16: return value; Chris@16: } Chris@16: Chris@16: inline bool operator()(CoordinateType const& c1, CoordinateType const& c2) const Chris@16: { Chris@16: Compare compare; Chris@16: Chris@16: // Check situation that one of them is e.g. std::numeric_limits. Chris@16: static const double full = detail::shift::full(); Chris@16: double mx = 10.0 * full; Chris@16: if (c1 < -mx || c1 > mx || c2 < -mx || c2 > mx) Chris@16: { Chris@16: // do normal comparison, using circular is not useful Chris@16: return compare(c1, c2); Chris@16: } Chris@16: Chris@16: static const double half = full / 2.0; Chris@16: CoordinateType v1 = put_in_range(c1, -half, half); Chris@16: CoordinateType v2 = put_in_range(c2, -half, half); Chris@16: Chris@16: // Two coordinates on a circle are Chris@16: // at max <= half a circle away from each other. Chris@16: // So if it is more, shift origin. Chris@16: CoordinateType diff = geometry::math::abs(v1 - v2); Chris@16: if (diff > half) Chris@16: { Chris@16: v1 = put_in_range(v1, 0, full); Chris@16: v2 = put_in_range(v2, 0, full); Chris@16: } Chris@16: Chris@16: return compare(v1, v2); Chris@16: } Chris@16: }; Chris@16: Chris@16: }} // namespace strategy::compare Chris@16: Chris@16: #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS Chris@16: Chris@16: // Specialize for the longitude (dim 0) Chris@16: template Chris@16: < Chris@16: typename Point, Chris@16: template class CoordinateSystem, Chris@16: typename Units Chris@16: > Chris@16: struct strategy_compare, 0> Chris@16: { Chris@16: typedef typename coordinate_type::type coordinate_type; Chris@16: typedef strategy::compare::circular_comparator Chris@16: < Chris@16: coordinate_type, Chris@16: Units, Chris@16: std::less Chris@16: > type; Chris@16: }; Chris@16: Chris@16: template Chris@16: < Chris@16: typename Point, Chris@16: template class CoordinateSystem, Chris@16: typename Units Chris@16: > Chris@16: struct strategy_compare, 0> Chris@16: { Chris@16: typedef typename coordinate_type::type coordinate_type; Chris@16: typedef strategy::compare::circular_comparator Chris@16: < Chris@16: coordinate_type, Chris@16: Units, Chris@16: std::greater Chris@16: > type; Chris@16: }; Chris@16: Chris@16: #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS Chris@16: Chris@16: }} // namespace boost::geometry Chris@16: Chris@16: #endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_SPHERICAL_HPP