]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/boost/geometry/util/normalize_spheroidal_coordinates.hpp
Add patch for failing prerm scripts
[ceph.git] / ceph / src / boost / boost / geometry / util / normalize_spheroidal_coordinates.hpp
CommitLineData
7c673cae
FG
1// Boost.Geometry (aka GGL, Generic Geometry Library)
2
11fdf7f2
TL
3// Copyright (c) 2017 Adam Wulkiewicz, Lodz, Poland.
4
b32b8144 5// Copyright (c) 2015-2017, Oracle and/or its affiliates.
7c673cae
FG
6
7// Contributed and/or modified by Menelaos Karavelas, on behalf of Oracle
8// Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
9
10// Licensed under the Boost Software License version 1.0.
11// http://www.boost.org/users/license.html
12
13#ifndef BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_COORDINATES_HPP
14#define BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_COORDINATES_HPP
15
16#include <boost/geometry/core/assert.hpp>
17#include <boost/geometry/core/cs.hpp>
18#include <boost/geometry/util/math.hpp>
19
20
21namespace boost { namespace geometry
22{
23
24namespace math
25{
26
27#ifndef DOXYGEN_NO_DETAIL
28namespace detail
29{
30
b32b8144
FG
31// CoordinateType, radian, true
32template <typename CoordinateType, typename Units, bool IsEquatorial = true>
7c673cae
FG
33struct constants_on_spheroid
34{
35 static inline CoordinateType period()
36 {
37 return math::two_pi<CoordinateType>();
38 }
39
40 static inline CoordinateType half_period()
41 {
42 return math::pi<CoordinateType>();
43 }
44
b32b8144
FG
45 static inline CoordinateType quarter_period()
46 {
47 static CoordinateType const
48 pi_half = math::pi<CoordinateType>() / CoordinateType(2);
49 return pi_half;
50 }
51
7c673cae
FG
52 static inline CoordinateType min_longitude()
53 {
54 static CoordinateType const minus_pi = -math::pi<CoordinateType>();
55 return minus_pi;
56 }
57
58 static inline CoordinateType max_longitude()
59 {
60 return math::pi<CoordinateType>();
61 }
62
63 static inline CoordinateType min_latitude()
64 {
65 static CoordinateType const minus_half_pi
66 = -math::half_pi<CoordinateType>();
67 return minus_half_pi;
68 }
69
70 static inline CoordinateType max_latitude()
71 {
72 return math::half_pi<CoordinateType>();
73 }
74};
75
76template <typename CoordinateType>
b32b8144
FG
77struct constants_on_spheroid<CoordinateType, radian, false>
78 : constants_on_spheroid<CoordinateType, radian, true>
79{
80 static inline CoordinateType min_latitude()
81 {
82 return CoordinateType(0);
83 }
84
85 static inline CoordinateType max_latitude()
86 {
87 return math::pi<CoordinateType>();
88 }
89};
90
91template <typename CoordinateType>
92struct constants_on_spheroid<CoordinateType, degree, true>
7c673cae
FG
93{
94 static inline CoordinateType period()
95 {
96 return CoordinateType(360.0);
97 }
98
99 static inline CoordinateType half_period()
100 {
101 return CoordinateType(180.0);
102 }
103
b32b8144
FG
104 static inline CoordinateType quarter_period()
105 {
106 return CoordinateType(90.0);
107 }
108
7c673cae
FG
109 static inline CoordinateType min_longitude()
110 {
111 return CoordinateType(-180.0);
112 }
113
114 static inline CoordinateType max_longitude()
115 {
116 return CoordinateType(180.0);
117 }
118
119 static inline CoordinateType min_latitude()
120 {
121 return CoordinateType(-90.0);
122 }
123
124 static inline CoordinateType max_latitude()
125 {
126 return CoordinateType(90.0);
127 }
128};
129
b32b8144
FG
130template <typename CoordinateType>
131struct constants_on_spheroid<CoordinateType, degree, false>
132 : constants_on_spheroid<CoordinateType, degree, true>
133{
134 static inline CoordinateType min_latitude()
135 {
136 return CoordinateType(0);
137 }
138
139 static inline CoordinateType max_latitude()
140 {
141 return CoordinateType(180.0);
142 }
143};
144
145
146} // namespace detail
147#endif // DOXYGEN_NO_DETAIL
148
7c673cae
FG
149
150template <typename Units, typename CoordinateType>
b32b8144
FG
151inline CoordinateType latitude_convert_ep(CoordinateType const& lat)
152{
153 typedef math::detail::constants_on_spheroid
154 <
155 CoordinateType,
156 Units
157 > constants;
158
159 return constants::quarter_period() - lat;
160}
161
162
163template <typename Units, bool IsEquatorial, typename T>
164static bool is_latitude_pole(T const& lat)
165{
166 typedef math::detail::constants_on_spheroid
167 <
168 T,
169 Units
170 > constants;
171
172 return math::equals(math::abs(IsEquatorial
173 ? lat
174 : math::latitude_convert_ep<Units>(lat)),
175 constants::quarter_period());
176
177}
178
179
180template <typename Units, typename T>
181static bool is_longitude_antimeridian(T const& lon)
182{
183 typedef math::detail::constants_on_spheroid
184 <
185 T,
186 Units
187 > constants;
188
189 return math::equals(math::abs(lon), constants::half_period());
190
191}
192
193
194#ifndef DOXYGEN_NO_DETAIL
195namespace detail
196{
197
198
199template <typename Units, bool IsEquatorial>
200struct latitude_convert_if_polar
201{
202 template <typename T>
11fdf7f2 203 static inline void apply(T & /*lat*/) {}
b32b8144
FG
204};
205
206template <typename Units>
207struct latitude_convert_if_polar<Units, false>
208{
209 template <typename T>
210 static inline void apply(T & lat)
211 {
212 lat = latitude_convert_ep<Units>(lat);
213 }
214};
215
216
217template <typename Units, typename CoordinateType, bool IsEquatorial = true>
7c673cae
FG
218class normalize_spheroidal_coordinates
219{
220 typedef constants_on_spheroid<CoordinateType, Units> constants;
221
222protected:
223 static inline CoordinateType normalize_up(CoordinateType const& value)
224 {
225 return
226 math::mod(value + constants::half_period(), constants::period())
227 - constants::half_period();
228 }
229
230 static inline CoordinateType normalize_down(CoordinateType const& value)
231 {
232 return
233 math::mod(value - constants::half_period(), constants::period())
234 + constants::half_period();
235 }
236
237public:
238 static inline void apply(CoordinateType& longitude)
239 {
240 // normalize longitude
241 if (math::equals(math::abs(longitude), constants::half_period()))
242 {
243 longitude = constants::half_period();
244 }
245 else if (longitude > constants::half_period())
246 {
247 longitude = normalize_up(longitude);
248 if (math::equals(longitude, -constants::half_period()))
249 {
250 longitude = constants::half_period();
251 }
252 }
253 else if (longitude < -constants::half_period())
254 {
255 longitude = normalize_down(longitude);
256 }
257 }
258
259 static inline void apply(CoordinateType& longitude,
260 CoordinateType& latitude,
261 bool normalize_poles = true)
262 {
b32b8144
FG
263 latitude_convert_if_polar<Units, IsEquatorial>::apply(latitude);
264
7c673cae
FG
265#ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
266 // normalize latitude
267 if (math::larger(latitude, constants::half_period()))
268 {
269 latitude = normalize_up(latitude);
270 }
271 else if (math::smaller(latitude, -constants::half_period()))
272 {
273 latitude = normalize_down(latitude);
274 }
275
276 // fix latitude range
277 if (latitude < constants::min_latitude())
278 {
279 latitude = -constants::half_period() - latitude;
280 longitude -= constants::half_period();
281 }
282 else if (latitude > constants::max_latitude())
283 {
284 latitude = constants::half_period() - latitude;
285 longitude -= constants::half_period();
286 }
287#endif // BOOST_GEOMETRY_NORMALIZE_LATITUDE
288
289 // normalize longitude
290 apply(longitude);
291
292 // finally normalize poles
293 if (normalize_poles)
294 {
295 if (math::equals(math::abs(latitude), constants::max_latitude()))
296 {
297 // for the north and south pole we set the longitude to 0
298 // (works for both radians and degrees)
299 longitude = CoordinateType(0);
300 }
301 }
302
b32b8144
FG
303 latitude_convert_if_polar<Units, IsEquatorial>::apply(latitude);
304
7c673cae
FG
305#ifdef BOOST_GEOMETRY_NORMALIZE_LATITUDE
306 BOOST_GEOMETRY_ASSERT(! math::larger(constants::min_latitude(), latitude));
307 BOOST_GEOMETRY_ASSERT(! math::larger(latitude, constants::max_latitude()));
308#endif // BOOST_GEOMETRY_NORMALIZE_LATITUDE
309
310 BOOST_GEOMETRY_ASSERT(math::smaller(constants::min_longitude(), longitude));
311 BOOST_GEOMETRY_ASSERT(! math::larger(longitude, constants::max_longitude()));
312 }
313};
314
315
316} // namespace detail
317#endif // DOXYGEN_NO_DETAIL
318
319
320/*!
321\brief Short utility to normalize the coordinates on a spheroid
322\tparam Units The units of the coordindate system in the spheroid
323\tparam CoordinateType The type of the coordinates
324\param longitude Longitude
325\param latitude Latitude
326\ingroup utility
327*/
328template <typename Units, typename CoordinateType>
329inline void normalize_spheroidal_coordinates(CoordinateType& longitude,
330 CoordinateType& latitude)
331{
332 detail::normalize_spheroidal_coordinates
333 <
334 Units, CoordinateType
335 >::apply(longitude, latitude);
336}
337
b32b8144
FG
338template <typename Units, bool IsEquatorial, typename CoordinateType>
339inline void normalize_spheroidal_coordinates(CoordinateType& longitude,
340 CoordinateType& latitude)
341{
342 detail::normalize_spheroidal_coordinates
343 <
344 Units, CoordinateType, IsEquatorial
345 >::apply(longitude, latitude);
346}
7c673cae
FG
347
348/*!
349\brief Short utility to normalize the longitude on a spheroid.
350 Note that in general both coordinates should be normalized at once.
351 This utility is suitable e.g. for normalization of the difference of longitudes.
352\tparam Units The units of the coordindate system in the spheroid
353\tparam CoordinateType The type of the coordinates
354\param longitude Longitude
355\ingroup utility
356*/
357template <typename Units, typename CoordinateType>
358inline void normalize_longitude(CoordinateType& longitude)
359{
360 detail::normalize_spheroidal_coordinates
361 <
362 Units, CoordinateType
363 >::apply(longitude);
364}
365
366
367/*!
368\brief Short utility to calculate difference between two longitudes
369 normalized in range (-180, 180].
370\tparam Units The units of the coordindate system in the spheroid
371\tparam CoordinateType The type of the coordinates
372\param longitude1 Longitude 1
373\param longitude2 Longitude 2
374\ingroup utility
375*/
376template <typename Units, typename CoordinateType>
377inline CoordinateType longitude_distance_signed(CoordinateType const& longitude1,
378 CoordinateType const& longitude2)
379{
380 CoordinateType diff = longitude2 - longitude1;
381 math::normalize_longitude<Units, CoordinateType>(diff);
382 return diff;
383}
384
385
386/*!
387\brief Short utility to calculate difference between two longitudes
388 normalized in range [0, 360).
389\tparam Units The units of the coordindate system in the spheroid
390\tparam CoordinateType The type of the coordinates
391\param longitude1 Longitude 1
392\param longitude2 Longitude 2
393\ingroup utility
394*/
395template <typename Units, typename CoordinateType>
396inline CoordinateType longitude_distance_unsigned(CoordinateType const& longitude1,
397 CoordinateType const& longitude2)
398{
399 typedef math::detail::constants_on_spheroid
400 <
401 CoordinateType, Units
402 > constants;
403
404 CoordinateType const c0 = 0;
405 CoordinateType diff = longitude_distance_signed<Units>(longitude1, longitude2);
406 if (diff < c0) // (-180, 180] -> [0, 360)
407 {
408 diff += constants::period();
409 }
410 return diff;
411}
412
b32b8144
FG
413/*!
414\brief The abs difference between longitudes in range [0, 180].
415\tparam Units The units of the coordindate system in the spheroid
416\tparam CoordinateType The type of the coordinates
417\param longitude1 Longitude 1
418\param longitude2 Longitude 2
419\ingroup utility
420*/
421template <typename Units, typename CoordinateType>
422inline CoordinateType longitude_difference(CoordinateType const& longitude1,
423 CoordinateType const& longitude2)
424{
425 return math::abs(math::longitude_distance_signed<Units>(longitude1, longitude2));
426}
427
428template <typename Units, typename CoordinateType>
429inline CoordinateType longitude_interval_distance_signed(CoordinateType const& longitude_a1,
430 CoordinateType const& longitude_a2,
431 CoordinateType const& longitude_b)
432{
433 CoordinateType const c0 = 0;
434 CoordinateType dist_a12 = longitude_distance_signed<Units>(longitude_a1, longitude_a2);
435 CoordinateType dist_a1b = longitude_distance_signed<Units>(longitude_a1, longitude_b);
436 if (dist_a12 < c0)
437 {
438 dist_a12 = -dist_a12;
439 dist_a1b = -dist_a1b;
440 }
441
442 return dist_a1b < c0 ? dist_a1b
443 : dist_a1b > dist_a12 ? dist_a1b - dist_a12
444 : c0;
445}
446
447
7c673cae
FG
448} // namespace math
449
450
451}} // namespace boost::geometry
452
453#endif // BOOST_GEOMETRY_UTIL_NORMALIZE_SPHEROIDAL_COORDINATES_HPP