153 lines
3.9 KiB
C++
153 lines
3.9 KiB
C++
// Boost.Geometry (aka GGL, Generic Geometry Library)
|
|
|
|
// Copyright (c) 2007-2012 Barend Gehrels, 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_SPHERICAL_COMPARE_SPHERICAL_HPP
|
|
#define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_SPHERICAL_HPP
|
|
|
|
#include <boost/math/constants/constants.hpp>
|
|
|
|
#include <boost/geometry/core/cs.hpp>
|
|
#include <boost/geometry/core/tags.hpp>
|
|
#include <boost/geometry/strategies/compare.hpp>
|
|
#include <boost/geometry/util/math.hpp>
|
|
|
|
|
|
namespace boost { namespace geometry
|
|
{
|
|
|
|
|
|
namespace strategy { namespace compare
|
|
{
|
|
|
|
|
|
#ifndef DOXYGEN_NO_DETAIL
|
|
namespace detail
|
|
{
|
|
|
|
template <typename Units>
|
|
struct shift
|
|
{
|
|
};
|
|
|
|
template <>
|
|
struct shift<degree>
|
|
{
|
|
static inline double full() { return 360.0; }
|
|
static inline double half() { return 180.0; }
|
|
};
|
|
|
|
template <>
|
|
struct shift<radian>
|
|
{
|
|
static inline double full() { return 2.0 * boost::math::constants::pi<double>(); }
|
|
static inline double half() { return boost::math::constants::pi<double>(); }
|
|
};
|
|
|
|
} // namespace detail
|
|
#endif
|
|
|
|
/*!
|
|
\brief Compare (in one direction) strategy for spherical coordinates
|
|
\ingroup strategies
|
|
\tparam Point point-type
|
|
\tparam Dimension dimension
|
|
*/
|
|
template <typename CoordinateType, typename Units, typename Compare>
|
|
struct circular_comparator
|
|
{
|
|
static inline CoordinateType put_in_range(CoordinateType const& c,
|
|
double min_border, double max_border)
|
|
{
|
|
CoordinateType value = c;
|
|
while (value < min_border)
|
|
{
|
|
value += detail::shift<Units>::full();
|
|
}
|
|
while (value > max_border)
|
|
{
|
|
value -= detail::shift<Units>::full();
|
|
}
|
|
return value;
|
|
}
|
|
|
|
inline bool operator()(CoordinateType const& c1, CoordinateType const& c2) const
|
|
{
|
|
Compare compare;
|
|
|
|
// Check situation that one of them is e.g. std::numeric_limits.
|
|
static const double full = detail::shift<Units>::full();
|
|
double mx = 10.0 * full;
|
|
if (c1 < -mx || c1 > mx || c2 < -mx || c2 > mx)
|
|
{
|
|
// do normal comparison, using circular is not useful
|
|
return compare(c1, c2);
|
|
}
|
|
|
|
static const double half = full / 2.0;
|
|
CoordinateType v1 = put_in_range(c1, -half, half);
|
|
CoordinateType v2 = put_in_range(c2, -half, half);
|
|
|
|
// Two coordinates on a circle are
|
|
// at max <= half a circle away from each other.
|
|
// So if it is more, shift origin.
|
|
CoordinateType diff = geometry::math::abs(v1 - v2);
|
|
if (diff > half)
|
|
{
|
|
v1 = put_in_range(v1, 0, full);
|
|
v2 = put_in_range(v2, 0, full);
|
|
}
|
|
|
|
return compare(v1, v2);
|
|
}
|
|
};
|
|
|
|
}} // namespace strategy::compare
|
|
|
|
#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
|
|
|
// Specialize for the longitude (dim 0)
|
|
template
|
|
<
|
|
typename Point,
|
|
template<typename> class CoordinateSystem,
|
|
typename Units
|
|
>
|
|
struct strategy_compare<spherical_polar_tag, 1, Point, CoordinateSystem<Units>, 0>
|
|
{
|
|
typedef typename coordinate_type<Point>::type coordinate_type;
|
|
typedef strategy::compare::circular_comparator
|
|
<
|
|
coordinate_type,
|
|
Units,
|
|
std::less<coordinate_type>
|
|
> type;
|
|
};
|
|
|
|
template
|
|
<
|
|
typename Point,
|
|
template<typename> class CoordinateSystem,
|
|
typename Units
|
|
>
|
|
struct strategy_compare<spherical_polar_tag, -1, Point, CoordinateSystem<Units>, 0>
|
|
{
|
|
typedef typename coordinate_type<Point>::type coordinate_type;
|
|
typedef strategy::compare::circular_comparator
|
|
<
|
|
coordinate_type,
|
|
Units,
|
|
std::greater<coordinate_type>
|
|
> type;
|
|
};
|
|
|
|
#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
|
|
|
}} // namespace boost::geometry
|
|
|
|
#endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_SPHERICAL_HPP
|