GeographicLib: Angle.hpp Source File

GeographicLib 2.7

Loading...
Searching...
No Matches
Angle.hpp
Go to the documentation of this file.
1/**
2 * \file Angle.hpp
3 * \brief Header for the GeographicLib::AngleT class
4 *
5 * The class provide an accurate representation of angle via 3 numbers, its
6 * sine and cosine, and the number of turns.
7 *
8 * Copyright (c) Charles Karney (2024-2025) <karney@alum.mit.edu> and licensed
9 * under the MIT/X11 License. For more information, see
10 * https://geographiclib.sourceforge.io/
11 **********************************************************************/
12
13#if !defined(GEOGRAPHICLIB_ANGLE_HPP)
14#define GEOGRAPHICLIB_ANGLE_HPP 1
15
16#include <string>
17#include <GeographicLib/Math.hpp>
18
19namespace GeographicLib {
20
21 /**
22 * \brief An accurate representation of angles.
23 *
24 * @tparam T the working floating point type.
25 *
26 * This class provides an accurate representation of angle via 3 numbers, its
27 * sine = \e s and cosine = \e c, and the number of turns = \e n. The angle
28 * is then 2\e n &pi; + atan2(\e s, \e c). This representation offers
29 * several advantages:
30 * - the cardinal directors (multiples of 90&deg;) are exactly represented (a
31 * benefit shared by representing angles as degrees);
32 * - angles very close to any cardinal direction are accurately represented;
33 * - there's no loss of precision with large angles (outside the "normal"
34 * range [&minus;180&deg;, +180&deg;]);
35 * - various operations, such as adding a multiple of 90&deg; to an angle are
36 * performed exactly.
37 * .
38 * This representation does not favor degrees over radians. However, the
39 * one-argument constructor, AngleT(T), does the conversion from degrees and
40 * the cast to T, AngleT::operator T(), returns the angle in degrees. There
41 * are alternatives, radians(T) and radians() const, to allow these
42 * conversions with radians.
43 *
44 * N.B. \e n is stored as a real. This allows it to be inf or nan.
45 *
46 * Example of use:
47 * \include example-Angle.cpp
48 **********************************************************************/
49 template<typename T = Math::real>
50 class AngleT {
51 // No GEOGRAPHICLIB_EXPORT because this is a template class (like
52 // PolygonAreaT). Not sure why Accumulator needs GEOGRAPHICLIB_EXPORT.
53 private:
54 T _s, _c, _n;
55 static T rnd(T x);
56 public:
57 /** \name Creating AngleT objects.
58 **********************************************************************/
59 ///@{
60 /**
61 * The default constructor.
62 *
63 * This sets the angle to 0.
64 **********************************************************************/
65 AngleT() : _s(0), _c(1), _n(0) {}
66 /**
67 * The general constructor.
68 *
69 * @param[in] s the sine component.
70 * @param[in] c the cosine component.
71 * @param[in] num the number of turns (default 0).
72 * @param[in] normp are \e s and \e c normalized (default false).
73 *
74 * \warning either \e s or \e c can be infinite, but not both.
75 *
76 * By default, the point (\e s, \e c) is scaled to lie on the unit circle.
77 * Setting \e normp = true skips this step; in this case (\e s, \e c)
78 * should already lie on the unit circle.
79 **********************************************************************/
80 AngleT(T s, T c, T num = 0, bool normp = false);
81 /**
82 * The 1-argument constructor.
83 *
84 * @param[in] deg the angle in degrees.
85 *
86 * \note This is an explicit constructor to avoid accidental conversions.
87 **********************************************************************/
88 explicit AngleT(T deg);
89 /**
90 * The convert an angle in degrees to an AngleT.
91 *
92 * @param[in] deg the angle in degrees.
93 * @return the AngleT.
94 *
95 * \note This mimics the behavior of AngleT(T deg);
96 **********************************************************************/
97 static AngleT degrees(T deg);
98 /**
99 * Convert an angle in radians to an AngleT.
100 *
101 * @param[in] rad the angle in radians.
102 * @return the AngleT.
103 *
104 * \note This is the radians analog of degrees(T).
105 **********************************************************************/
106 static AngleT radians(T rad);
107 /**
108 * Convert an lambertian to an AngleT.
109 *
110 * @param[in] q the lambertian of the angle.
111 * @return the AngleT.
112 *
113 * This sets the angle to atan(sinh(\e q)).
114 **********************************************************************/
115 static AngleT lam(T q);
116 /**
117 * Not an angle.
118 *
119 * @return the AngleT equivalent to not-a-number.
120 **********************************************************************/
121 static AngleT NaN();
122 /**
123 * A cardinal direction.
124 *
125 * @param[in] q the number of quarter turns.
126 * @return the AngleT equivalent to \e q quarter turns.
127 *
128 * \e q is rounded to an integer and \e q = &plusmn;0 are distinguished.
129 * NaN() is returned is \e q is not finite.
130 **********************************************************************/
131 static AngleT cardinal(T q);
132 /**
133 * Return a tiny angle.
134 *
135 * @return a tiny angle.
136 *
137 * This allows angles extremely close to the cardinal directions to be
138 * generated. The round() function will flush this angle to 0.
139 **********************************************************************/
140 static AngleT eps();
141 ///@}
142
143 /** \name Inspector functions.
144 **********************************************************************/
145 ///@{
146 /**
147 * @return the sine of the angle.
148 **********************************************************************/
149 T s() const { return _s; }
150 /**
151 * @return the cosine of the angle.
152 **********************************************************************/
153 T c() const { return _c; }
154 /**
155 * @return the tangent of the angle.
156 **********************************************************************/
157 T t() const { return _s/_c; }
158 /**
159 * @return the number of turns.
160 **********************************************************************/
161 T n() const {
162 return _n + 0; // Convert -0 to +0
163 }
164 /**
165 * @return the number of turns treating &minus;180&deg; as +180&deg; less 1
166 * turn.
167 **********************************************************************/
168 T n0() const;
169 ///@}
170
171 /** \name Converting AngleT into other representations
172 **********************************************************************/
173 ///@{
174 /**
175 * Convert an AngleT to degrees via a type conversion.
176 *
177 * @return the angle in degrees.
178 *
179 * \note This is an explicit type conversion to avoid accidental
180 * conversions.
181 **********************************************************************/
182 explicit operator T() const;
183 /**
184 * Convert an AngleT to degrees.
185 *
186 * @return the angle in degrees.
187 *
188 * \note This mimics the behavior of AngleT::operator T().
189 **********************************************************************/
190 T degrees() const;
191 /**
192 * Convert an AngleT to degrees ignoring the number of turns.
193 *
194 * @return the angle in degrees assuming n() is zero.
195 **********************************************************************/
196 T degrees0() const;
197 /**
198 * Convert an AngleT to radians.
199 *
200 * @return the angle in radians.
201 *
202 * \note This is the radians analog of degrees().
203 **********************************************************************/
204 T radians() const;
205 /**
206 * Convert an AngleT to radians ignoring the number of turns.
207 *
208 * @return the angle in radians assuming n() is zero.
209 *
210 * \note This is the radians analog of degrees0().
211 **********************************************************************/
212 T radians0() const;
213 /**
214 * Return the lambertian of the AngleT.
215 *
216 * @return the lambertian.
217 *
218 * The lambertian of &phi; is asinh tan &phi;.
219 **********************************************************************/
220 T lam() const;
221 /**
222 * Return the nearest cardinal direction as an AngleT.
223 *
224 * @param[in] ind an indicator.
225 * @return the nearest cardinal direction as an AngleT.
226 *
227 * If \e ind == 0 (the default) the closest cardinal direction is returned.
228 * Otherwise, if \e ind is even, the closest even (N/S) cardinal direction
229 * is returned; or, if \e ind is odd, the closest odd (E/W) cardinal
230 * direction is returned.
231 **********************************************************************/
232 AngleT nearest(unsigned ind = 0U) const;
233 /**
234 * Return the nearest cardinal direction as an integer.
235 *
236 * @return the nearest cardinal direction as an integer.
237 *
238 * \note This is the reverse of cardinal(T).
239 **********************************************************************/
240 T ncardinal() const;
241 unsigned quadrant() const;
242 ///@}
243
244 /** \name Elementary arithmetic operations on AngleT
245 **********************************************************************/
246 ///@{
247 /**
248 * Return the negated AngleT.
249 *
250 * @return minus the AngleT
251 **********************************************************************/
252 AngleT operator-() const;
253 /**
254 * Implement the += operator.
255 *
256 * @param[in] p the AngleT to be added.
257 * @return the current AngleT after the addition.
258 **********************************************************************/
259 AngleT& operator+=(const AngleT& p);
260 /**
261 * Implement the -= operator.
262 *
263 * @param[in] p the AngleT to be subtracted.
264 * @return the current AngleT after the subtraction.
265 **********************************************************************/
266 AngleT& operator-=(const AngleT& p);
267 /**
268 * Implement the + operator.
269 *
270 * @param[in] p the AngleT to be added.
271 * @return the result of the addition; the current AngleT is not modified.
272 **********************************************************************/
273 AngleT operator+(const AngleT& p) const;
274 /**
275 * Implement the - operator.
276 *
277 * @param[in] p the AngleT to be subtracted.
278 * @return the result of the subtraction; the current AngleT is not
279 * modified.
280 **********************************************************************/
281 AngleT operator-(const AngleT& p) const;
282 /**
283 * Test for a zero angle.
284 *
285 * @param[in] mult multiplier of machine epsilon used in test (default 0).
286 * @return true if this AngleT is withing \e mult &epsilon; of zero.
287 **********************************************************************/
288 bool zerop(T mult = 0) const;
289 /**
290 * Implement the == operator.
291 *
292 * @param[in] p the AngleT to be compared against
293 * @return *this == \e p.
294 **********************************************************************/
295 bool operator==(const AngleT& p) const;
296 ///@}
297
298 /** \name Operations which modify a AngleT
299 **********************************************************************/
300 ///@{
301 /**
302 * "Round" the AngleT the == operator.
303 *
304 * @return the AngleT with tiny values of s() and c() set to &plusmn;0.
305 *
306 * This ensures that the smallest gaps between sine and cosine values is
307 * &epsilon;/2048.
308 **********************************************************************/
309 AngleT& round();
310 /**
311 * Renormalize the sine and cosine values
312 *
313 * @return the modified AngleT.
314 *
315 * During arithmetic operations on AngleT object, no effort is mode to
316 * ensure that (s(), c()) remains on the unit circle. This function
317 * corrects this.
318 **********************************************************************/
319 AngleT& renormalize();
320 /**
321 * Reduce the angle to [&minus;180&deg;, +180&deg;]
322 *
323 * @return the modified AngleT, obtained by setting n() to zero.
324 **********************************************************************/
325 AngleT& setn(T n = 0);
326 /**
327 * Reduce the angle to (&minus;180&deg;, +180&deg;]
328 *
329 * @return the modified AngleT.
330 *
331 * This differs from setn(T) by treating &minus;180&deg; as +180&deg; less
332 * 1 turn.
333 **********************************************************************/
334 AngleT& setn0(T n = 0);
335 /**
336 * Set the quadrant of an AngleT the angle to (&minus;180&deg;, +180&deg;]
337 *
338 * @param[in] q the quadrant.
339 * @return the modified AngleT.
340 *
341 * This sets the signs of s() and c() according to e q.
342 *
343 * \note Only the low two bits of \e q are used. n() is unchanged.
344 **********************************************************************/
345 AngleT& setquadrant(unsigned q);
346 /**
347 * Reflect the angle is various ways
348 *
349 * @param[in] flips change the sign of s()
350 * @param[in] flipc change the sign of c()
351 * @param[in] swapp swap s() and c()
352 * @return the modified AngleT.
353 *
354 * \note The operations are carried out in the order of the parameters.
355 **********************************************************************/
356 AngleT& reflect(bool flips, bool flipc = false, bool swapp = false);
357 ///@}
358
359 /** \name Operations which return a new AngleT
360 **********************************************************************/
361 ///@{
362 /**
363 * Return an AngleT in [&minus;180&deg;, +180&deg;].
364 *
365 * @return the new AngleT.
366 *
367 * This returns the AngleT with n() set to zero.
368 **********************************************************************/
369 AngleT base() const;
370 /**
371 * Return an AngleT centered about another AngleT
372 *
373 * @param[in] c the center AngleT
374 * @return the new AngleT.
375 *
376 * This returns the result of adjusting n() so that the new AngleT is with
377 * &plusmn;180&deg; of \e c.
378 **********************************************************************/
379 AngleT rebase(const AngleT& c) const;
380 /**
381 * Return an AngleT with the sign optionally flipped
382 *
383 * @param[in] mult
384 * @return the new AngleT.
385 *
386 * return signbit(\e mult) ? -*this : *this.
387 **********************************************************************/
388 AngleT flipsign(T mult) const;
389 /**
390 * The "reduced latitude" operation.
391 *
392 * @param[in] m
393 * @return the atan(m * tan(*this))
394 *
395 * However the quadrant of the result tracking that of *this through
396 * multiples turns.
397 **********************************************************************/
398 AngleT modang(T m) const;
399 ///@}
400
401 /** \name Converting AngleT to and from a string representation
402 **********************************************************************/
403 ///@{
404 /**
405 * Interpret two strings as latitude and longitude.
406 *
407 * @param[in] stra the first string
408 * @param[in] strb the second string
409 * @param[out] lat the latitude
410 * @param[out] lon the longitude
411 * @param[in] longfirst (default false) whether the longitude is given
412 * first.
413 *
414 * In the absence of hemisphere indicators (N/S for latitude and E/W for
415 * longitude), it is assumed that the first string is the latitude.
416 * Setting \e longfirst = true uses the opposite convention. The
417 * hemisphere indicators can also be used to set the signs of the angles.
418 **********************************************************************/
419 static void DecodeLatLon(const std::string& stra, const std::string& strb,
420 AngleT& lat, AngleT& lon,
421 bool longfirst = false);
422 /**
423 * Interpret a string as azimuth
424 *
425 * @param[in] azistr the string representing the azimuth
426 * @return the azimuth
427 *
428 * The hemisphere indicators E/W can be used to set the sign of the
429 * azimuth.
430 **********************************************************************/
431 static AngleT DecodeAzimuth(const std::string& azistr);
432 /**
433 * Create a string for a latitude-longitude pair.
434 *
435 * @param[in] lat the latitude.
436 * @param[in] lon the longitude.
437 * @param[in] prec the precision relative to 1&deg;.
438 * @param[in] dms (default false) whether to use degrees/minutes/seconds as
439 * opposed to decimal degrees
440 * @param[in] dmssep (default NULL) the separator to use with the DMS
441 * representation instead of d ' ".
442 * @param[in] longfirst (default false) whether to list the longitude
443 * first.
444 * @return string representation
445 *
446 * With dms = true the hemisphere indicators N/S and E/W are used to
447 * indicator the signs of the latitude and longitude.
448 **********************************************************************/
449 static std::string LatLonString(AngleT lat, AngleT lon, int prec,
450 bool dms = false, char dmssep = '\0',
451 bool longfirst = false);
452 /**
453 * Create a string for an azimuth.
454 *
455 * @param[in] azi the azimuth.
456 * @param[in] prec the precision relative to 1&deg;.
457 * @param[in] dms (default false) whether to use degrees/minutes/seconds as
458 * opposed to decimal degrees
459 * @param[in] dmssep (default NULL) the separator to use with the DMS
460 * representation instead of d ' ".
461 * @return string representation
462 *
463 * With dms = true the hemisphere indicators and E/W is used to
464 * indicator the sign of the azimuth.
465 **********************************************************************/
466 static std::string AzimuthString(AngleT azi, int prec,
467 bool dms = false, char dmssep = '\0');
468 ///@}
469 };
470
471 template<typename T>
472 inline AngleT<T>::AngleT(T s, T c, T num, bool normp)
473 : _s(s)
474 , _c(c)
475 , _n(num)
476 {
477 using std::isfinite, std::isnan, std::isinf, std::hypot,
478 std::copysign, std::rint;
479 _n = rint(_n);
480 if (!normp) {
481 // Cannot just use Math::norm because of all the special cases
482 T h = hypot(_s, _c);
483 if (h == 0) {
484 // If y is +/-0 and x = -0, +/-pi is returned.
485 // If y is +/-0 and x = +0, +/-0 is returned.
486 // So retain the sign of _s = +/-0
487 _c = copysign(T(1), _c);
488 } else if (isfinite(h)) {
489 _s /= h; _c /= h;
490 } else if (isnan(h) || (isinf(_s) && isinf(_c)))
491 _s = _c = Math::NaN();
492 else if (isinf(_s)) {
493 // infinite, finite
494 _s = copysign(T(1), _s);
495 _c = copysign(T(0), _c);
496 } else {
497 // isinf(cos); finite, infinite
498 _s = copysign(T(0), _s);
499 _c = copysign(T(1), _c);
500 }
501 }
502 }
503
504 template<typename T>
505 inline AngleT<T>::AngleT(T deg) {
506 using std::rint;
507 Math::sincosd(deg, _s, _c);
508 _n = rint( (deg - Math::atan2d(_s, _c)) / Math::td );
509 }
510
511 template<typename T>
512 inline AngleT<T>::operator T() const {
513 T d = degrees0();
514 // Preserve sign of +/-0
515 return _n == 0 ? d : d + Math::td * _n;
516 }
517
518 template<typename T>
519 inline AngleT<T> AngleT<T>::degrees(T deg) {
520 return AngleT<T>(deg);
521 }
522
523 template<typename T>
524 inline T AngleT<T>::degrees() const {
525 return T(*this);
526 }
527
528 template<typename T>
529 inline T AngleT<T>::degrees0() const {
530 return Math::atan2d(_s, _c);
531 }
532
533 template<typename T>
534 inline AngleT<T> AngleT<T>::radians(T rad) {
535 using std::sin, std::cos, std::atan2, std::rint;
536 T sn = sin(rad), cs = cos(rad);
537 return AngleT<T>(sn, cs, rint( (rad - atan2(sn, cs)) / (2 * Math::pi()) ),
538 true);
539 }
540
541 template<typename T>
542 inline T AngleT<T>::radians() const {
543 T r = radians0();
544 // Preserve sign of +/-0
545 return _n == 0 ? r : r + 2 * Math::pi() * _n;
546 }
547
548 template<typename T>
549 inline T AngleT<T>::radians0() const {
550 using std::atan2;
551 return atan2(_s, _c);
552 }
553
554 template<typename T>
555 inline AngleT<T> AngleT<T>::lam(T psi) {
556 using std::sinh;
557 return AngleT<T>(sinh(psi), 1, 0);
558 }
559
560 template<typename T>
561 inline T AngleT<T>::lam() const {
562 using std::asinh;
563 return asinh(t());
564 }
565
566 template<typename T>
567 inline AngleT<T> AngleT<T>::NaN() {
568 return AngleT<T>(Math::NaN(), Math::NaN(), 0, true);
569 }
570
571 template<typename T>
572 inline T AngleT<T>::ncardinal() const {
573 using std::signbit, std::fabs;
574 int iq = (signbit(_s) ? -1 : 1) * (signbit(_c) ?
575 ( -_c >= fabs(_s) ? 2 : 1 ) :
576 ( _c >= fabs(_s) ? 0 : 1 ));
577 return 4 * _n + iq;
578 }
579
580 template<typename T>
581 inline AngleT<T> AngleT<T>::eps() {
582 return AngleT<T>(std::numeric_limits<T>::epsilon() / (1 << 20), 1, 0, true);
583 }
584
585 // AngleT<T> AngleT<T>::operator+() const { return *this; }
586 template<typename T>
587 inline AngleT<T> AngleT<T>::operator-() const {
588 return AngleT<T>(-_s, _c, -_n, true);
589 }
590
591 template<typename T>
592 inline AngleT<T>& AngleT<T>::operator+=(const AngleT<T>& p) {
593 using std::rint;
594 T q = ncardinal() + p.ncardinal();
595 T c = _c * p._c - _s * p._s;
596 _s = _s * p._c + _c * p._s;
597 _c = c;
598 _n += p._n;
599 q -= ncardinal();
600 _n += rint(q / 4);
601 return *this;
602 }
603
604 template<typename T>
605 inline AngleT<T> AngleT<T>::operator+(const AngleT<T>& p) const {
606 AngleT<T> t = *this; t += p;
607 return t;
608 }
609
610 template<typename T>
611 inline AngleT<T>& AngleT<T>::operator-=(const AngleT<T>& p) {
612 *this += -p;
613 return *this;
614 }
615
616 template<typename T>
617 inline AngleT<T> AngleT<T>::operator-(const AngleT<T>& p) const {
618 AngleT<T> t = *this; t -= p;
619 return t;
620 }
621
622 template<typename T>
623 inline bool AngleT<T>::zerop(T mult) const {
624 using std::fabs;
625 return _n == 0 &&_c > 0 &&
626 fabs(_s) <= mult * std::numeric_limits<T>::epsilon();
627 }
628
629 template<typename T>
630 inline bool AngleT<T>::operator==(const AngleT<T>& p) const {
631 AngleT<T> t = *this; t -= p;
632 return t.zerop();
633 }
634
635 template<typename T>
636 inline AngleT<T>& AngleT<T>::round() {
637 _s = rnd(_s); _c = rnd(_c);
638 return *this;
639 }
640
641 template<typename T>
642 inline AngleT<T> AngleT<T>::base() const {
643 return AngleT<T>(_s, _c, 0, true);
644 }
645
646 template<typename T>
647 inline AngleT<T> AngleT<T>::rebase(const AngleT<T>& c) const {
648 // This is exact for c = cardinal direction
649 // return (*this - c).base() + c;
650 AngleT<T> t = *this;
651 return t.setn0(((*this - c).base() + c).n0());
652 }
653
654 template<typename T>
655 inline AngleT<T>& AngleT<T>::renormalize() {
656 using std::hypot;
657 T h = hypot(_s, _c); _s /= h; _c /= h;
658 return *this;
659 }
660
661 template<typename T>
662 inline AngleT<T>& AngleT<T>::setn(T n) {
663 using std::rint;
664 _n = rint(n);
665 return *this;
666 }
667
668 template<typename T>
669 inline T AngleT<T>::n0() const {
670 using std::signbit;
671 return (_n - (_s == 0 && signbit(_s) && _c < 0 ? 1 : 0)) + 0;
672 }
673
674 template<typename T>
675 inline AngleT<T>& AngleT<T>::setn0(T n) {
676 using std::rint, std::signbit;
677 _n = rint(n) + (_s == 0 && signbit(_s) && _c < 0 ? 1 : 0);
678 return *this;
679 }
680
681 template<typename T>
682 inline AngleT<T>& AngleT<T>::setquadrant(unsigned q) {
683 using std::copysign;
684 _s = copysign(_s, T( q & 2U ? -1 : 1 ));
685 _c = copysign(_c, T( ((q >> 1) ^ q) & 1U ? -1 : 1 ));
686 return *this;
687 }
688
689 template<typename T>
690 inline unsigned AngleT<T>::quadrant() const {
691 using std::signbit;
692 return 2U * signbit(_s) + (signbit(_c) ^ signbit(_s));
693 }
694
695 template<typename T>
696 inline AngleT<T>& AngleT<T>::reflect(bool flips, bool flipc, bool swapp) {
697 using std::swap;
698 if (flips) _s *= -1;
699 if (flipc) _c *= -1;
700 if (swapp) swap(_s, _c);
701 return *this;
702 }
703
704 template<typename T>
705 inline AngleT<T> AngleT<T>::flipsign(T mult) const {
706 using std::signbit;
707 return signbit(mult) ? -*this : *this;
708 }
709
710 template<typename T>
711 inline AngleT<T> AngleT<T>::modang(T m) const {
712 using std::signbit;
713 return signbit(m) ? AngleT<T>::NaN() :
714 // Avoid nans if m == inf.
715 AngleT<T>( _s * (m > 1 ? 1 : m),
716 _c / (m > 1 ? m : 1),
717 _n );
718 }
719
720 template<typename T>
721 inline AngleT<T> AngleT<T>::cardinal(T q) {
722 using std::isfinite, std::rint, std::remainder;
723 if (!isfinite(q)) return AngleT<T>::NaN();
724 q = rint(q);
725 int iq = int(remainder(q, T(4)));
726 // iq is in [-2, 2];
727 // We could fold iq = -2 to iq = 2; but this way works too.
728 T s, c, z = 0;
729 switch (iq) {
730 case -2: s = -z; c = -1; break;
731 case -1: s = -1; c = z; break;
732 case 1: s = 1; c = z; break;
733 case 2: s = z; c = -1; break;
734 default:
735 // iq = 0, but distinguish q = +/-0
736 s = q != 0 ? z : q; c = 1;
737 break;
738 }
739 return AngleT<T>(s, c, rint((q - iq) / 4), true);
740 }
741
742 template<typename T>
743 inline AngleT<T> AngleT<T>::nearest(unsigned ind) const {
744 using std::fabs, std::copysign;
745 T s, c;
746 if (ind == 0U) {
747 if (fabs(_c) >= fabs(_s)) {
748 s = copysign(T(0), _s); c = copysign(T(1), _c);
749 } else {
750 s = copysign(T(1), _s); c = copysign(T(0), _c);
751 }
752 } else if ((ind & 1U) == 0U) { // ind nonzero and even
753 s = copysign(T(0), _s); c = copysign(T(1), _c);
754 } else { // ind odd
755 s = copysign(T(1), _s); c = copysign(T(0), _c);
756 }
757 return AngleT<T>(s, c, _n, true);
758 }
759
760 using Angle = AngleT<Math::real>;
761
762} // namespace GeographicLib
763
764#endif // GEOGRAPHICLIB_ANGLE_HPP
Math.hpp
Header for GeographicLib::Math class.
GeographicLib::AngleT
An accurate representation of angles.
Definition Angle.hpp:50
GeographicLib::AngleT::setn0
AngleT & setn0(T n=0)
Definition Angle.hpp:675
GeographicLib::AngleT::operator-
AngleT operator-() const
Definition Angle.hpp:587
GeographicLib::AngleT::operator+=
AngleT & operator+=(const AngleT &p)
Definition Angle.hpp:592
GeographicLib::AngleT::degrees0
T degrees0() const
Definition Angle.hpp:529
GeographicLib::AngleT::rebase
AngleT rebase(const AngleT &c) const
Definition Angle.hpp:647
GeographicLib::AngleT::lam
static AngleT lam(T q)
Definition Angle.hpp:555
GeographicLib::AngleT::eps
static AngleT eps()
Definition Angle.hpp:581
GeographicLib::AngleT::base
AngleT base() const
Definition Angle.hpp:642
GeographicLib::AngleT::operator-
AngleT operator-(const AngleT &p) const
Definition Angle.hpp:617
GeographicLib::AngleT< Math::real >::c
Math::real c() const
Definition Angle.hpp:153
GeographicLib::AngleT::cardinal
static AngleT cardinal(T q)
Definition Angle.hpp:721
GeographicLib::AngleT::operator==
bool operator==(const AngleT &p) const
Definition Angle.hpp:630
GeographicLib::AngleT::flipsign
AngleT flipsign(T mult) const
Definition Angle.hpp:705
GeographicLib::AngleT::NaN
static AngleT NaN()
Definition Angle.hpp:567
GeographicLib::AngleT::operator+
AngleT operator+(const AngleT &p) const
Definition Angle.hpp:605
GeographicLib::AngleT< Math::real >::s
Math::real s() const
Definition Angle.hpp:149
GeographicLib::AngleT::AngleT
AngleT(T s, T c, T num=0, bool normp=false)
Definition Angle.hpp:472
GeographicLib::AngleT::round
AngleT & round()
Definition Angle.hpp:636
GeographicLib::AngleT::DecodeLatLon
static void DecodeLatLon(const std::string &stra, const std::string &strb, AngleT &lat, AngleT &lon, bool longfirst=false)
Definition Angle.cpp:39
GeographicLib::AngleT::LatLonString
static std::string LatLonString(AngleT lat, AngleT lon, int prec, bool dms=false, char dmssep='\0', bool longfirst=false)
Definition Angle.cpp:72
GeographicLib::AngleT::lam
T lam() const
Definition Angle.hpp:561
GeographicLib::AngleT::radians
static AngleT radians(T rad)
Definition Angle.hpp:534
GeographicLib::AngleT::radians0
T radians0() const
Definition Angle.hpp:549
GeographicLib::AngleT::modang
AngleT modang(T m) const
Definition Angle.hpp:711
GeographicLib::AngleT::radians
T radians() const
Definition Angle.hpp:542
GeographicLib::AngleT::ncardinal
T ncardinal() const
Definition Angle.hpp:572
GeographicLib::AngleT::setn
AngleT & setn(T n=0)
Definition Angle.hpp:662
GeographicLib::AngleT::AngleT
AngleT()
Definition Angle.hpp:65
GeographicLib::AngleT::setquadrant
AngleT & setquadrant(unsigned q)
Definition Angle.hpp:682
GeographicLib::AngleT::DecodeAzimuth
static AngleT DecodeAzimuth(const std::string &azistr)
Definition Angle.cpp:62
GeographicLib::AngleT::n
T n() const
Definition Angle.hpp:161
GeographicLib::AngleT::renormalize
AngleT & renormalize()
Definition Angle.hpp:655
GeographicLib::AngleT::zerop
bool zerop(T mult=0) const
Definition Angle.hpp:623
GeographicLib::AngleT::t
T t() const
Definition Angle.hpp:157
GeographicLib::AngleT::degrees
static AngleT degrees(T deg)
Definition Angle.hpp:519
GeographicLib::AngleT::nearest
AngleT nearest(unsigned ind=0U) const
Definition Angle.hpp:743
GeographicLib::AngleT::degrees
T degrees() const
Definition Angle.hpp:524
GeographicLib::AngleT::AzimuthString
static std::string AzimuthString(AngleT azi, int prec, bool dms=false, char dmssep='\0')
Definition Angle.cpp:86
GeographicLib::AngleT::n0
T n0() const
Definition Angle.hpp:669
GeographicLib::AngleT::reflect
AngleT & reflect(bool flips, bool flipc=false, bool swapp=false)
Definition Angle.hpp:696
GeographicLib::AngleT::quadrant
unsigned quadrant() const
Definition Angle.hpp:690
GeographicLib::AngleT::AngleT
AngleT(T deg)
Definition Angle.hpp:505
GeographicLib::AngleT::operator-=
AngleT & operator-=(const AngleT &p)
Definition Angle.hpp:611
GeographicLib::Math::sincosd
static void sincosd(T x, T &sinx, T &cosx)
Definition Math.cpp:104
GeographicLib::Math::atan2d
static T atan2d(T y, T x)
Definition Math.cpp:212
GeographicLib::Math::td
static constexpr int td
degrees per turn
Definition Math.hpp:146
GeographicLib::Math::pi
static T pi()
Definition Math.hpp:187
GeographicLib::Math::NaN
static T NaN()
Definition Math.cpp:301
GeographicLib
Namespace for GeographicLib.
Definition Accumulator.cpp:12
GeographicLib::Angle
AngleT< Math::real > Angle
Definition Angle.hpp:760
std::swap
void swap(GeographicLib::NearestNeighbor< dist_t, pos_t, distfun_t > &a, GeographicLib::NearestNeighbor< dist_t, pos_t, distfun_t > &b)
Definition NearestNeighbor.hpp:819