]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/geometry/strategies/spherical/compare.hpp
update sources to v12.2.3
[ceph.git] / ceph / src / boost / boost / geometry / strategies / spherical / compare.hpp
1 // Boost.Geometry (aka GGL, Generic Geometry Library)
2
3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
4
5 // This file was modified by Oracle on 2017.
6 // Modifications copyright (c) 2017, Oracle and/or its affiliates.
7
8 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
9
10 // Use, modification and distribution is subject to the Boost Software License,
11 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
12 // http://www.boost.org/LICENSE_1_0.txt)
13
14 #ifndef BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_HPP
15 #define BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_HPP
16
17
18 #include <boost/mpl/if.hpp>
19 #include <boost/mpl/min.hpp>
20
21 #include <boost/type_traits/is_same.hpp>
22
23 #include <boost/geometry/core/access.hpp>
24 #include <boost/geometry/core/coordinate_dimension.hpp>
25 #include <boost/geometry/core/coordinate_system.hpp>
26 #include <boost/geometry/core/coordinate_type.hpp>
27 #include <boost/geometry/core/cs.hpp>
28 #include <boost/geometry/core/tags.hpp>
29
30 #include <boost/geometry/strategies/compare.hpp>
31
32 #include <boost/geometry/util/math.hpp>
33 #include <boost/geometry/util/normalize_spheroidal_coordinates.hpp>
34
35
36 namespace boost { namespace geometry
37 {
38
39
40 namespace strategy { namespace compare
41 {
42
43
44 #ifndef DOXYGEN_NO_DETAIL
45 namespace detail
46 {
47
48 template <std::size_t I, typename P>
49 static inline typename geometry::coordinate_type<P>::type
50 get(P const& p, boost::true_type /*same units*/)
51 {
52 return geometry::get<I>(p);
53 }
54
55 template <std::size_t I, typename P>
56 static inline typename geometry::coordinate_type<P>::type
57 get(P const& p, boost::false_type /*different units*/)
58 {
59 return geometry::get_as_radian<I>(p);
60 }
61
62 template
63 <
64 typename ComparePolicy,
65 typename Point1,
66 typename Point2,
67 std::size_t DimensionCount
68 >
69 struct spherical_latitude
70 {
71 typedef typename geometry::coordinate_type<Point1>::type coordinate1_type;
72 typedef typename geometry::coordinate_system<Point1>::type::units units1_type;
73 typedef typename geometry::coordinate_type<Point2>::type coordinate2_type;
74 typedef typename geometry::coordinate_system<Point2>::type::units units2_type;
75 typedef typename boost::is_same<units1_type, units2_type>::type same_units_type;
76
77 template <typename T1, typename T2>
78 static inline bool apply(Point1 const& left, Point2 const& right,
79 T1 const& l1, T2 const& r1)
80 {
81 // latitudes equal
82 if (math::equals(l1, r1))
83 {
84 return compare::detail::compare_loop
85 <
86 ComparePolicy, 2, DimensionCount
87 >::apply(left, right);
88 }
89 else
90 {
91 return ComparePolicy::apply(l1, r1);
92 }
93 }
94
95 static inline bool apply(Point1 const& left, Point2 const& right)
96 {
97 coordinate1_type const& l1 = compare::detail::get<1>(left, same_units_type());
98 coordinate2_type const& r1 = compare::detail::get<1>(right, same_units_type());
99
100 return apply(left, right, l1, r1);
101 }
102 };
103
104 template
105 <
106 typename ComparePolicy,
107 typename Point1,
108 typename Point2
109 >
110 struct spherical_latitude<ComparePolicy, Point1, Point2, 1>
111 {
112 template <typename T1, typename T2>
113 static inline bool apply(Point1 const& left, Point2 const& right,
114 T1 const& , T2 const& )
115 {
116 return apply(left, right);
117 }
118
119 static inline bool apply(Point1 const& left, Point2 const& right)
120 {
121 return compare::detail::compare_loop
122 <
123 ComparePolicy, 1, 1
124 >::apply(left, right);
125 }
126 };
127
128 template
129 <
130 typename ComparePolicy,
131 typename Point1,
132 typename Point2,
133 std::size_t DimensionCount
134 >
135 struct spherical_longitude
136 {
137 typedef typename geometry::coordinate_type<Point1>::type coordinate1_type;
138 typedef typename geometry::coordinate_system<Point1>::type::units units1_type;
139 typedef typename geometry::coordinate_type<Point2>::type coordinate2_type;
140 typedef typename geometry::coordinate_system<Point2>::type::units units2_type;
141 typedef typename boost::is_same<units1_type, units2_type>::type same_units_type;
142 typedef typename boost::mpl::if_<same_units_type, units1_type, geometry::radian>::type units_type;
143
144 static const bool is_equatorial = ! boost::is_same
145 <
146 typename geometry::cs_tag<Point1>::type,
147 geometry::spherical_polar_tag
148 >::value;
149
150 static inline bool are_both_at_antimeridian(coordinate1_type const& l0,
151 coordinate2_type const& r0,
152 bool & is_left_at,
153 bool & is_right_at)
154 {
155 is_left_at = math::is_longitude_antimeridian<units_type>(l0);
156 is_right_at = math::is_longitude_antimeridian<units_type>(r0);
157 return is_left_at && is_right_at;
158 }
159
160 static inline bool apply(Point1 const& left, Point2 const& right)
161 {
162 // if units are different the coordinates are in radians
163 coordinate1_type const& l0 = compare::detail::get<0>(left, same_units_type());
164 coordinate2_type const& r0 = compare::detail::get<0>(right, same_units_type());
165 coordinate1_type const& l1 = compare::detail::get<1>(left, same_units_type());
166 coordinate2_type const& r1 = compare::detail::get<1>(right, same_units_type());
167
168 bool is_left_at_antimeridian = false;
169 bool is_right_at_antimeridian = false;
170
171 // longitudes equal
172 if (math::equals(l0, r0)
173 // both at antimeridian
174 || are_both_at_antimeridian(l0, r0, is_left_at_antimeridian, is_right_at_antimeridian)
175 // both at pole
176 || (math::equals(l1, r1)
177 && math::is_latitude_pole<units_type, is_equatorial>(l1)))
178 {
179 return spherical_latitude
180 <
181 ComparePolicy, Point1, Point2, DimensionCount
182 >::apply(left, right, l1, r1);
183 }
184 // if left is at antimeridian and right is not at antimeridian
185 // then left is greater than right
186 else if (is_left_at_antimeridian)
187 {
188 // less/equal_to -> false, greater -> true
189 return ComparePolicy::apply(1, 0);
190 }
191 // if right is at antimeridian and left is not at antimeridian
192 // then left is lesser than right
193 else if (is_right_at_antimeridian)
194 {
195 // less -> true, equal_to/greater -> false
196 return ComparePolicy::apply(0, 1);
197 }
198 else
199 {
200 return ComparePolicy::apply(l0, r0);
201 }
202 }
203 };
204
205
206 } // namespace detail
207 #endif // DOXYGEN_NO_DETAIL
208
209
210 /*!
211 \brief Compare strategy for spherical coordinates
212 \ingroup strategies
213 \tparam Point point-type
214 \tparam Dimension dimension
215 */
216 template
217 <
218 typename ComparePolicy,
219 int Dimension = -1
220 >
221 struct spherical
222 : cartesian<ComparePolicy, Dimension>
223 {};
224
225 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
226 // all dimensions starting from longitude
227 template <typename ComparePolicy>
228 struct spherical<ComparePolicy, -1>
229 {
230 template <typename Point1, typename Point2>
231 static inline bool apply(Point1 const& left, Point2 const& right)
232 {
233 return compare::detail::spherical_longitude
234 <
235 ComparePolicy,
236 Point1,
237 Point2,
238 boost::mpl::min
239 <
240 geometry::dimension<Point1>,
241 geometry::dimension<Point2>
242 >::type::value
243 >::apply(left, right);
244 }
245 };
246
247 // only longitudes (and latitudes to check poles)
248 template <typename ComparePolicy>
249 struct spherical<ComparePolicy, 0>
250 {
251 template <typename Point1, typename Point2>
252 static inline bool apply(Point1 const& left, Point2 const& right)
253 {
254 return compare::detail::spherical_longitude
255 <
256 ComparePolicy, Point1, Point2, 1
257 >::apply(left, right);
258 }
259 };
260
261 // only latitudes
262 template <typename ComparePolicy>
263 struct spherical<ComparePolicy, 1>
264 {
265 template <typename Point1, typename Point2>
266 static inline bool apply(Point1 const& left, Point2 const& right)
267 {
268 return compare::detail::spherical_latitude
269 <
270 ComparePolicy, Point1, Point2, 2
271 >::apply(left, right);
272 }
273 };
274
275 #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
276
277
278 namespace services
279 {
280
281
282 template <typename ComparePolicy, typename Point1, typename Point2, int Dimension>
283 struct default_strategy
284 <
285 ComparePolicy, Point1, Point2, Dimension,
286 spherical_polar_tag, spherical_polar_tag
287 >
288 {
289 typedef compare::spherical<ComparePolicy, Dimension> type;
290 };
291
292 template <typename ComparePolicy, typename Point1, typename Point2, int Dimension>
293 struct default_strategy
294 <
295 ComparePolicy, Point1, Point2, Dimension,
296 spherical_equatorial_tag, spherical_equatorial_tag
297 >
298 {
299 typedef compare::spherical<ComparePolicy, Dimension> type;
300 };
301
302 template <typename ComparePolicy, typename Point1, typename Point2, int Dimension>
303 struct default_strategy
304 <
305 ComparePolicy, Point1, Point2, Dimension,
306 geographic_tag, geographic_tag
307 >
308 {
309 typedef compare::spherical<ComparePolicy, Dimension> type;
310 };
311
312
313 } // namespace services
314
315
316 }} // namespace strategy::compare
317
318
319 }} // namespace boost::geometry
320
321 #endif // BOOST_GEOMETRY_STRATEGIES_SPHERICAL_COMPARE_HPP