Chris@16
|
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
|
Chris@16
|
2
|
Chris@16
|
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
|
Chris@16
|
4
|
Chris@16
|
5 // Use, modification and distribution is subject to the Boost Software License,
|
Chris@16
|
6 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
|
Chris@16
|
7 // http://www.boost.org/LICENSE_1_0.txt)
|
Chris@16
|
8
|
Chris@16
|
9 #ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_SPHERICAL_HPP
|
Chris@16
|
10 #define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_SPHERICAL_HPP
|
Chris@16
|
11
|
Chris@16
|
12 #include <boost/math/constants/constants.hpp>
|
Chris@16
|
13
|
Chris@16
|
14 #include <boost/geometry/core/cs.hpp>
|
Chris@16
|
15 #include <boost/geometry/core/tags.hpp>
|
Chris@16
|
16 #include <boost/geometry/strategies/compare.hpp>
|
Chris@16
|
17 #include <boost/geometry/util/math.hpp>
|
Chris@16
|
18
|
Chris@16
|
19
|
Chris@16
|
20 namespace boost { namespace geometry
|
Chris@16
|
21 {
|
Chris@16
|
22
|
Chris@16
|
23
|
Chris@16
|
24 namespace strategy { namespace compare
|
Chris@16
|
25 {
|
Chris@16
|
26
|
Chris@16
|
27
|
Chris@16
|
28 #ifndef DOXYGEN_NO_DETAIL
|
Chris@16
|
29 namespace detail
|
Chris@16
|
30 {
|
Chris@16
|
31
|
Chris@16
|
32 template <typename Units>
|
Chris@16
|
33 struct shift
|
Chris@16
|
34 {
|
Chris@16
|
35 };
|
Chris@16
|
36
|
Chris@16
|
37 template <>
|
Chris@16
|
38 struct shift<degree>
|
Chris@16
|
39 {
|
Chris@16
|
40 static inline double full() { return 360.0; }
|
Chris@16
|
41 static inline double half() { return 180.0; }
|
Chris@16
|
42 };
|
Chris@16
|
43
|
Chris@16
|
44 template <>
|
Chris@16
|
45 struct shift<radian>
|
Chris@16
|
46 {
|
Chris@16
|
47 static inline double full() { return 2.0 * boost::math::constants::pi<double>(); }
|
Chris@16
|
48 static inline double half() { return boost::math::constants::pi<double>(); }
|
Chris@16
|
49 };
|
Chris@16
|
50
|
Chris@16
|
51 } // namespace detail
|
Chris@16
|
52 #endif
|
Chris@16
|
53
|
Chris@16
|
54 /*!
|
Chris@16
|
55 \brief Compare (in one direction) strategy for spherical coordinates
|
Chris@16
|
56 \ingroup strategies
|
Chris@16
|
57 \tparam Point point-type
|
Chris@16
|
58 \tparam Dimension dimension
|
Chris@16
|
59 */
|
Chris@16
|
60 template <typename CoordinateType, typename Units, typename Compare>
|
Chris@16
|
61 struct circular_comparator
|
Chris@16
|
62 {
|
Chris@16
|
63 static inline CoordinateType put_in_range(CoordinateType const& c,
|
Chris@16
|
64 double min_border, double max_border)
|
Chris@16
|
65 {
|
Chris@16
|
66 CoordinateType value = c;
|
Chris@16
|
67 while (value < min_border)
|
Chris@16
|
68 {
|
Chris@16
|
69 value += detail::shift<Units>::full();
|
Chris@16
|
70 }
|
Chris@16
|
71 while (value > max_border)
|
Chris@16
|
72 {
|
Chris@16
|
73 value -= detail::shift<Units>::full();
|
Chris@16
|
74 }
|
Chris@16
|
75 return value;
|
Chris@16
|
76 }
|
Chris@16
|
77
|
Chris@16
|
78 inline bool operator()(CoordinateType const& c1, CoordinateType const& c2) const
|
Chris@16
|
79 {
|
Chris@16
|
80 Compare compare;
|
Chris@16
|
81
|
Chris@16
|
82 // Check situation that one of them is e.g. std::numeric_limits.
|
Chris@16
|
83 static const double full = detail::shift<Units>::full();
|
Chris@16
|
84 double mx = 10.0 * full;
|
Chris@16
|
85 if (c1 < -mx || c1 > mx || c2 < -mx || c2 > mx)
|
Chris@16
|
86 {
|
Chris@16
|
87 // do normal comparison, using circular is not useful
|
Chris@16
|
88 return compare(c1, c2);
|
Chris@16
|
89 }
|
Chris@16
|
90
|
Chris@16
|
91 static const double half = full / 2.0;
|
Chris@16
|
92 CoordinateType v1 = put_in_range(c1, -half, half);
|
Chris@16
|
93 CoordinateType v2 = put_in_range(c2, -half, half);
|
Chris@16
|
94
|
Chris@16
|
95 // Two coordinates on a circle are
|
Chris@16
|
96 // at max <= half a circle away from each other.
|
Chris@16
|
97 // So if it is more, shift origin.
|
Chris@16
|
98 CoordinateType diff = geometry::math::abs(v1 - v2);
|
Chris@16
|
99 if (diff > half)
|
Chris@16
|
100 {
|
Chris@16
|
101 v1 = put_in_range(v1, 0, full);
|
Chris@16
|
102 v2 = put_in_range(v2, 0, full);
|
Chris@16
|
103 }
|
Chris@16
|
104
|
Chris@16
|
105 return compare(v1, v2);
|
Chris@16
|
106 }
|
Chris@16
|
107 };
|
Chris@16
|
108
|
Chris@16
|
109 }} // namespace strategy::compare
|
Chris@16
|
110
|
Chris@16
|
111 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
Chris@16
|
112
|
Chris@16
|
113 // Specialize for the longitude (dim 0)
|
Chris@16
|
114 template
|
Chris@16
|
115 <
|
Chris@16
|
116 typename Point,
|
Chris@16
|
117 template<typename> class CoordinateSystem,
|
Chris@16
|
118 typename Units
|
Chris@16
|
119 >
|
Chris@16
|
120 struct strategy_compare<spherical_polar_tag, 1, Point, CoordinateSystem<Units>, 0>
|
Chris@16
|
121 {
|
Chris@16
|
122 typedef typename coordinate_type<Point>::type coordinate_type;
|
Chris@16
|
123 typedef strategy::compare::circular_comparator
|
Chris@16
|
124 <
|
Chris@16
|
125 coordinate_type,
|
Chris@16
|
126 Units,
|
Chris@16
|
127 std::less<coordinate_type>
|
Chris@16
|
128 > type;
|
Chris@16
|
129 };
|
Chris@16
|
130
|
Chris@16
|
131 template
|
Chris@16
|
132 <
|
Chris@16
|
133 typename Point,
|
Chris@16
|
134 template<typename> class CoordinateSystem,
|
Chris@16
|
135 typename Units
|
Chris@16
|
136 >
|
Chris@16
|
137 struct strategy_compare<spherical_polar_tag, -1, Point, CoordinateSystem<Units>, 0>
|
Chris@16
|
138 {
|
Chris@16
|
139 typedef typename coordinate_type<Point>::type coordinate_type;
|
Chris@16
|
140 typedef strategy::compare::circular_comparator
|
Chris@16
|
141 <
|
Chris@16
|
142 coordinate_type,
|
Chris@16
|
143 Units,
|
Chris@16
|
144 std::greater<coordinate_type>
|
Chris@16
|
145 > type;
|
Chris@16
|
146 };
|
Chris@16
|
147
|
Chris@16
|
148 #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
|
Chris@16
|
149
|
Chris@16
|
150 }} // namespace boost::geometry
|
Chris@16
|
151
|
Chris@16
|
152 #endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_SPHERICAL_HPP
|