pygeodesy 25.4.8__py2.py3-none-any.whl → 25.5.5__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (97) hide show
  1. pygeodesy/__init__.py +36 -31
  2. pygeodesy/__main__.py +3 -3
  3. pygeodesy/albers.py +29 -36
  4. pygeodesy/auxilats/_CX_4.py +2 -2
  5. pygeodesy/auxilats/_CX_6.py +2 -2
  6. pygeodesy/auxilats/_CX_8.py +2 -2
  7. pygeodesy/auxilats/_CX_Rs.py +9 -9
  8. pygeodesy/auxilats/__init__.py +3 -3
  9. pygeodesy/auxilats/__main__.py +8 -6
  10. pygeodesy/auxilats/auxAngle.py +2 -2
  11. pygeodesy/auxilats/auxLat.py +5 -5
  12. pygeodesy/auxilats/auxily.py +5 -3
  13. pygeodesy/azimuthal.py +7 -6
  14. pygeodesy/basics.py +32 -18
  15. pygeodesy/booleans.py +18 -16
  16. pygeodesy/cartesianBase.py +26 -24
  17. pygeodesy/clipy.py +11 -10
  18. pygeodesy/constants.py +11 -10
  19. pygeodesy/css.py +14 -11
  20. pygeodesy/datums.py +8 -8
  21. pygeodesy/deprecated/bases.py +2 -2
  22. pygeodesy/deprecated/classes.py +2 -2
  23. pygeodesy/deprecated/consterns.py +4 -4
  24. pygeodesy/dms.py +8 -8
  25. pygeodesy/ecef.py +22 -29
  26. pygeodesy/ecefLocals.py +186 -0
  27. pygeodesy/elevations.py +9 -8
  28. pygeodesy/ellipsoidalBase.py +19 -8
  29. pygeodesy/ellipsoidalBaseDI.py +17 -15
  30. pygeodesy/ellipsoidalNvector.py +6 -3
  31. pygeodesy/ellipsoidalVincenty.py +4 -1
  32. pygeodesy/ellipsoids.py +186 -164
  33. pygeodesy/elliptic.py +9 -9
  34. pygeodesy/errors.py +44 -43
  35. pygeodesy/etm.py +7 -7
  36. pygeodesy/fmath.py +30 -14
  37. pygeodesy/formy.py +11 -12
  38. pygeodesy/frechet.py +216 -109
  39. pygeodesy/fstats.py +5 -4
  40. pygeodesy/fsums.py +79 -78
  41. pygeodesy/gars.py +4 -3
  42. pygeodesy/geodesici.py +15 -14
  43. pygeodesy/geodesicw.py +34 -32
  44. pygeodesy/geodesicx/__init__.py +1 -1
  45. pygeodesy/geodesicx/__main__.py +11 -9
  46. pygeodesy/geodesicx/gx.py +30 -33
  47. pygeodesy/geodesicx/gxarea.py +2 -2
  48. pygeodesy/geodesicx/gxline.py +5 -5
  49. pygeodesy/geodsolve.py +18 -17
  50. pygeodesy/geohash.py +5 -5
  51. pygeodesy/geoids.py +34 -31
  52. pygeodesy/hausdorff.py +17 -13
  53. pygeodesy/heights.py +2 -4
  54. pygeodesy/internals.py +28 -44
  55. pygeodesy/interns.py +10 -7
  56. pygeodesy/iters.py +8 -8
  57. pygeodesy/karney.py +68 -62
  58. pygeodesy/ktm.py +5 -5
  59. pygeodesy/latlonBase.py +20 -21
  60. pygeodesy/lazily.py +104 -78
  61. pygeodesy/lcc.py +11 -9
  62. pygeodesy/ltp.py +56 -58
  63. pygeodesy/ltpTuples.py +35 -36
  64. pygeodesy/mgrs.py +7 -6
  65. pygeodesy/named.py +48 -177
  66. pygeodesy/nvectorBase.py +7 -7
  67. pygeodesy/osgr.py +9 -8
  68. pygeodesy/points.py +12 -10
  69. pygeodesy/props.py +25 -25
  70. pygeodesy/resections.py +83 -80
  71. pygeodesy/rhumb/__init__.py +1 -1
  72. pygeodesy/rhumb/aux_.py +7 -7
  73. pygeodesy/rhumb/bases.py +22 -20
  74. pygeodesy/rhumb/ekx.py +6 -6
  75. pygeodesy/rhumb/solve.py +15 -15
  76. pygeodesy/solveBase.py +3 -3
  77. pygeodesy/sphericalBase.py +6 -6
  78. pygeodesy/sphericalNvector.py +6 -5
  79. pygeodesy/sphericalTrigonometry.py +8 -7
  80. pygeodesy/streprs.py +14 -14
  81. pygeodesy/trf.py +14 -12
  82. pygeodesy/triaxials.py +29 -26
  83. pygeodesy/units.py +5 -4
  84. pygeodesy/unitsBase.py +5 -4
  85. pygeodesy/ups.py +3 -3
  86. pygeodesy/utily.py +4 -4
  87. pygeodesy/utmups.py +4 -4
  88. pygeodesy/utmupsBase.py +110 -18
  89. pygeodesy/vector2d.py +20 -13
  90. pygeodesy/vector3d.py +7 -6
  91. pygeodesy/webmercator.py +6 -5
  92. pygeodesy/wgrs.py +6 -5
  93. {pygeodesy-25.4.8.dist-info → pygeodesy-25.5.5.dist-info}/METADATA +30 -25
  94. pygeodesy-25.5.5.dist-info/RECORD +119 -0
  95. pygeodesy-25.4.8.dist-info/RECORD +0 -118
  96. {pygeodesy-25.4.8.dist-info → pygeodesy-25.5.5.dist-info}/WHEEL +0 -0
  97. {pygeodesy-25.4.8.dist-info → pygeodesy-25.5.5.dist-info}/top_level.txt +0 -0
pygeodesy/ellipsoids.py CHANGED
@@ -64,18 +64,20 @@ Following is the list of predefined L{Ellipsoid}s, all instantiated lazily.
64
64
  # make sure int/int division yields float quotient, see .basics
65
65
  from __future__ import division as _; del _ # PYCHOK semicolon
66
66
 
67
- from pygeodesy.basics import copysign0, isbool, isint
67
+ # from pygeodesy.albers import AlbersEqualAreaCylindrical # _MODS
68
+ from pygeodesy.basics import copysign0, isbool, _isin, isint, typename
68
69
  from pygeodesy.constants import EPS, EPS0, EPS02, EPS1, INF, NINF, PI4, PI_2, PI_3, R_M, R_MA, R_FM, \
69
- _EPSqrt, _EPStol as _TOL, _floatuple as _T, _isfinite, \
70
+ _EPSqrt, _EPStol as _TOL, _floatuple as _T, _isfinite, _over, \
70
71
  _0_0s, _0_0, _0_5, _1_0, _1_EPS, _2_0, _4_0, _90_0, \
71
72
  _0_25, _3_0 # PYCHOK used!
72
73
  from pygeodesy.errors import _AssertionError, IntersectionError, _ValueError, _xattr, _xkwds_not
73
74
  from pygeodesy.fmath import cbrt, cbrt2, fdot, Fhorner, fpowers, hypot, hypot_, \
74
75
  hypot1, hypot2, sqrt3, Fsum
75
76
  # from pygeodesy.fsums import Fsum # from .fmath
77
+ # from pygeodesy.internals import typename # from .basics
76
78
  from pygeodesy.interns import NN, _a_, _Airy1830_, _AiryModified_, _b_, _Bessel1841_, _beta_, \
77
- _Clarke1866_, _Clarke1880IGN_, _DOT_, _f_, _GRS80_, _height_, \
78
- _Intl1924_, _incompatible_, _invalid_, _Krassovski1940_, \
79
+ _Clarke1866_, _Clarke1880IGN_, _DMAIN_, _DOT_, _f_, _GRS80_, \
80
+ _height_, _Intl1924_, _incompatible_, _invalid_, _Krassovski1940_, \
79
81
  _Krassowsky1940_, _lat_, _meridional_, _negative_, _not_finite_, \
80
82
  _prime_vertical_, _radius_, _Sphere_, _SPACE_, _vs_, _WGS72_, _WGS84_
81
83
  # from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS # from .named
@@ -86,25 +88,25 @@ from pygeodesy.props import deprecated_Property_RO, Property_RO, property_doc_,
86
88
  deprecated_property_RO, property_RO, property_ROver
87
89
  from pygeodesy.streprs import Fmt, fstr, instr, strs, unstr
88
90
  # from pygeodesy.triaxials import _hartzell3 # _MODS
89
- from pygeodesy.units import Bearing_, Distance, Float, Float_, Height, Lamd, Lat, Meter, \
90
- Meter2, Meter3, Phi, Phid, Radius, Radius_, Scalar
91
+ from pygeodesy.units import Azimuth, Bearing, Distance, Float, Float_, Height, Lamd, Lat, \
92
+ Meter, Meter2, Meter3, Phi, Phid, Radius, Radius_, Scalar
91
93
  from pygeodesy.utily import atan1, atan1d, atan2b, degrees90, m2radians, radians2m, sincos2d
92
94
 
93
95
  from math import asinh, atan, atanh, cos, degrees, exp, fabs, radians, sin, sinh, sqrt, tan # as _tan
94
96
 
95
97
  __all__ = _ALL_LAZY.ellipsoids
96
- __version__ = '24.11.26'
98
+ __version__ = '25.04.28'
97
99
 
98
100
  _f_0_0 = Float(f =_0_0) # zero flattening
99
101
  _f__0_0 = Float(f_=_0_0) # zero inverse flattening
100
102
  # see U{WGS84_f<https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1Constants.html>}
101
- _f__WGS84 = Float(f_=_1_0 / (1000000000 / 298257223563)) # 298.25722356299997 vs 298.257223563
103
+ _f__WGS84 = Float(f_=_1_0 / (1000000000 / 298257223563)) # 298.257223562_999_97 vs 298.257223563
102
104
 
103
105
 
104
106
  def _aux(lat, inverse, auxLat, clip=90):
105
107
  '''Return a named auxiliary latitude in C{degrees}.
106
108
  '''
107
- return Lat(lat, clip=clip, name=_lat_ if inverse else auxLat.__name__)
109
+ return Lat(lat, clip=clip, name=_lat_ if inverse else typename(auxLat))
108
110
 
109
111
 
110
112
  def _s2_c2(phi):
@@ -138,12 +140,14 @@ class a_f2Tuple(_NamedTuple):
138
140
  @arg f: Flattening (C{scalar} < 1, negative for I{prolate}).
139
141
  @kwarg name: Optional C{B{name}=NN} (C{str}).
140
142
 
141
- @return: An L{a_f2Tuple}C{(a, f)} instance.
143
+ @return: An L{a_f2Tuple}C{(a, f)}.
142
144
 
143
145
  @raise UnitError: Invalid B{C{a}} or B{C{f}}.
144
146
 
145
- @note: C{abs(B{f}) < EPS} is forced to C{B{f}=0}, I{spherical}.
146
- Negative C{B{f}} produces a I{prolate} ellipsoid.
147
+ @note: C{abs(B{f}) < }L{EPS<pygeodesy.constants.EPS>} is
148
+ forced to C{B{f}=0}, I{spherical}.
149
+
150
+ @note: Negative C{B{f}} produces a I{prolate} ellipsoid.
147
151
  '''
148
152
  a = Radius_(a=a) # low=EPS, high=None
149
153
  f = Float_( f=f, low=None, high=EPS1)
@@ -243,7 +247,7 @@ class Ellipsoid(_NamedEnumItem):
243
247
  if not _isfinite(a):
244
248
  raise ValueError(_SPACE_(_a_, _not_finite_))
245
249
 
246
- if b: # not in (_0_0, None)
250
+ if b: # not _isin(b, None, _0_0)
247
251
  b = Radius_(b=b) # low=EPS
248
252
  f = a_b2f(a, b) if f is None else Float(f=f)
249
253
  f_ = f2f_(f) if f_ is None else Float(f_=f_)
@@ -357,11 +361,16 @@ class Ellipsoid(_NamedEnumItem):
357
361
  '''
358
362
  return a_f2Tuple(self.a, self.f, name=self.name)
359
363
 
364
+ a_f2 = a_f # synonym
365
+
360
366
  @Property_RO
361
367
  def A(self):
362
368
  '''Get the UTM I{meridional (or rectifying)} radius (C{meter}).
363
369
 
364
- @see: I{Meridian arc unit} U{Q<https://StudyLib.net/doc/7443565/>}.
370
+ @note: C{A * PI / 2} ≈= L{L<Ellipsoid.L>}, the I{quarter meridian}.
371
+
372
+ @see: I{Meridian arc unit} U{Q<https://StudyLib.net/doc/7443565/>},
373
+ the mean, meridional length I{per radian}.
365
374
  '''
366
375
  A, n = self.a, self.n
367
376
  if n:
@@ -373,6 +382,11 @@ class Ellipsoid(_NamedEnumItem):
373
382
  # A *= fhorner(n**2, 1048576, 262144, 16384, 4096, 1600, 784, 441) / 1048576) / (1 + n)
374
383
  A = Radius(A=Fhorner(n**2, 1048576, 262144, 16384, 4096, 1600, 784, 441).fover(d))
375
384
  return A
385
+ # # Moritz, H. <https://Geodesy.Geology.Ohio-State.EDU/course/refpapers/00740128.pdf>
386
+ # # q = 4 / self.rocPolar
387
+ # # Q = (1 - 3 / 4 * e'2 + 45 / 64 * e'4 - 175 / 256 * e'6 + 11025 / 16384 * e'8) * rocPolar
388
+ # # = (4 + e'2 * (-3 + e'2 * (45 / 16 + e'2 * (-175 / 64 + e'2 * 11025 / 4096)))) / q
389
+ # return Radius(Q=Fhorner(self.e22, 4, -3, 45 / 16, -175 / 64, 11025 / 4096).fover(q))
376
390
 
377
391
  @Property_RO
378
392
  def _albersCyl(self):
@@ -424,7 +438,7 @@ class Ellipsoid(_NamedEnumItem):
424
438
  t = Fmt.EQUAL(self._DOT_(n), t)
425
439
  raise Error(t, txt=txt or Fmt.exceeds_eps(eps))
426
440
  return Float(v if self.f else f0, name=n)
427
- raise Error(unstr(self._DOT_(self._assert.__name__), val,
441
+ raise Error(unstr(self._DOT_(typename(self._assert)), val,
428
442
  eps=eps, f0=f0, **name_value))
429
443
 
430
444
  def auxAuthalic(self, lat, inverse=False):
@@ -442,7 +456,8 @@ class Ellipsoid(_NamedEnumItem):
442
456
  U{Snyder<https://Pubs.USGS.gov/pp/1395/report.pdf>}, p 16.
443
457
  '''
444
458
  if self.f:
445
- f = self._albersCyl._tanf if inverse else self._albersCyl._txif # PYCHOK attr
459
+ f = self._albersCyl._tanf if inverse else \
460
+ self._albersCyl._txif # PYCHOK attr
446
461
  lat = atan1d(f(tan(Phid(lat)))) # PYCHOK attr
447
462
  return _aux(lat, inverse, Ellipsoid.auxAuthalic)
448
463
 
@@ -461,7 +476,7 @@ class Ellipsoid(_NamedEnumItem):
461
476
  U{Snyder<https://Pubs.USGS.gov/pp/1395/report.pdf>}, pp 15-16.
462
477
  '''
463
478
  if self.f:
464
- f = self.es_tauf if inverse else self.es_taupf # PYCHOK attr
479
+ f = self.es_tauf if inverse else self.es_taupf # PYCHOK attr
465
480
  lat = atan1d(f(tan(Phid(lat)))) # PYCHOK attr
466
481
  return _aux(lat, inverse, Ellipsoid.auxConformal)
467
482
 
@@ -480,8 +495,8 @@ class Ellipsoid(_NamedEnumItem):
480
495
  U{Snyder<https://Pubs.USGS.gov/pp/1395/report.pdf>}, pp 17-18.
481
496
  '''
482
497
  if self.f:
483
- f = self.a2_b2 if inverse else self.b2_a2
484
- lat = atan1d(f * tan(Phid(lat)))
498
+ f = self.a2_b2 if inverse else self.b2_a2
499
+ lat = atan1d(tan(Phid(lat)) * f)
485
500
  return _aux(lat, inverse, Ellipsoid.auxGeocentric)
486
501
 
487
502
  def auxIsometric(self, lat, inverse=False):
@@ -503,7 +518,7 @@ class Ellipsoid(_NamedEnumItem):
503
518
  U{Snyder<https://Pubs.USGS.gov/pp/1395/report.pdf>}, pp 15-16.
504
519
  '''
505
520
  if self.f:
506
- r = Phid(lat, clip=0)
521
+ r = Phid(lat, clip=0)
507
522
  lat = degrees(atan1(self.es_tauf(sinh(r))) if inverse else
508
523
  asinh(self.es_taupf(tan(r))))
509
524
  # clip=0, since auxIsometric(+/-90) is far outside [-90..+90]
@@ -549,9 +564,9 @@ class Ellipsoid(_NamedEnumItem):
549
564
  if inverse:
550
565
  e = self._elliptic_e22
551
566
  d = degrees90(e.fEinv(e.cE * lat / _90_0))
552
- lat = self.auxParametric(d, inverse=True)
567
+ lat = self.auxParametric(d, inverse=True)
553
568
  else:
554
- lat = _90_0 * self.Llat(lat) / self.L
569
+ lat = _over(self.Llat(lat), self.L) * _90_0
555
570
  return _aux(lat, inverse, Ellipsoid.auxRectifying)
556
571
 
557
572
  @Property_RO
@@ -582,7 +597,7 @@ class Ellipsoid(_NamedEnumItem):
582
597
 
583
598
  @see: U{Radii of Curvature<https://WikiPedia.org/wiki/Earth_radius#Radii_of_curvature>}.
584
599
  '''
585
- return Radius(b2_a=self.b2 / self.a if self.f else self.b)
600
+ return Radius(b2_a=_over(self.b2, self.a) if self.f else self.b)
586
601
 
587
602
  @Property_RO
588
603
  def b2_a2(self):
@@ -831,7 +846,7 @@ class Ellipsoid(_NamedEnumItem):
831
846
  def _elliptic_e12(self): # see I{Karney}'s Ellipsoid._e12
832
847
  '''(INTERNAL) Elliptic helper for C{Rhumb}.
833
848
  '''
834
- e12 = self.e2 / (self.e2 - _1_0) # NOT DEPRECATED .e12!
849
+ e12 = _over(self.e2, self.e2 - _1_0) # NOT DEPRECATED .e12!
835
850
  return _MODS.elliptic.Elliptic(e12)
836
851
 
837
852
  @Property_RO
@@ -869,7 +884,7 @@ class Ellipsoid(_NamedEnumItem):
869
884
  if r < 0:
870
885
  raise ValueError(_negative_)
871
886
  except (TypeError, ValueError) as x:
872
- t = self._DOT_(Ellipsoid.e2s2.__name__)
887
+ t = self._DOT_(typename(Ellipsoid.e2s2))
873
888
  raise _ValueError(t, s, cause=x)
874
889
  return r
875
890
 
@@ -919,8 +934,8 @@ class Ellipsoid(_NamedEnumItem):
919
934
  '''
920
935
  t = Scalar(taup=taup)
921
936
  if self.f: # .isEllipsoidal
922
- a = fabs(t)
923
- T = t * (self._exp_es_atanh_1 if a > 70 else self._1_e21)
937
+ a = fabs(t)
938
+ T = (self._exp_es_atanh_1 if a > 70 else self._1_e21) * t
924
939
  if fabs(T * _EPSqrt) < _2_0: # handles +/- INF and NAN
925
940
  s = (a * _TOL) if a > _1_0 else _TOL
926
941
  for T, _, d in self._es_tauf3(t, T): # max 2
@@ -939,8 +954,8 @@ class Ellipsoid(_NamedEnumItem):
939
954
  _tf2 = self._es_taupf2
940
955
  for i in range(1, N + 1):
941
956
  a, h = _tf2(T)
942
- d = (taup - a) * (e + T**2) / (hypot1(a) * h)
943
957
  # = (taup - a) / hypot1(a) / ((e + T**2) / h)
958
+ d = _over((taup - a) * (T**2 + e), hypot1(a) * h)
944
959
  T, d = _F2_(d) # τi, (τi - τi-1)
945
960
  yield T, i, d
946
961
 
@@ -1085,8 +1100,9 @@ class Ellipsoid(_NamedEnumItem):
1085
1100
 
1086
1101
  @arg pov: Point-Of-View outside this ellipsoid (C{Cartesian}, L{Ecef9Tuple}
1087
1102
  or L{Vector3d}).
1088
- @kwarg los: Line-Of-Sight, I{direction} to this ellipsoid (L{Vector3d}) or
1089
- C{None} to point to this ellipsoid's center.
1103
+ @kwarg los: Line-Of-Sight, I{direction} to this ellipsoid (L{Los}, L{Vector3d})
1104
+ or C{True} for the I{normal, perpendicular, plumb} to the surface
1105
+ of this ellipsoid or C{False} or C{None} to point to its center.
1090
1106
 
1091
1107
  @return: L{Vector4Tuple}C{(x, y, z, h)} with the cartesian coordinates C{x},
1092
1108
  C{y} and C{z} of the projection on or the intersection with this
@@ -1095,8 +1111,7 @@ class Ellipsoid(_NamedEnumItem):
1095
1111
 
1096
1112
  @raise IntersectionError: Null B{C{pov}} or B{C{los}} vector, or B{C{pov}}
1097
1113
  is inside this ellipsoid or B{C{los}} points
1098
- outside this ellipsoid or points in an opposite
1099
- direction.
1114
+ outside this ellipsoid or in opposite direction.
1100
1115
 
1101
1116
  @raise TypeError: Invalid B{C{pov}} or B{C{los}}.
1102
1117
 
@@ -1105,10 +1120,10 @@ class Ellipsoid(_NamedEnumItem):
1105
1120
  methods L{Ellipsoid.height4} and L{Triaxial.hartzell4}.
1106
1121
  '''
1107
1122
  try:
1108
- v, d, _ = _MODS.triaxials._hartzell3(pov, los, self._triaxial)
1123
+ v, d, i = _MODS.triaxials._hartzell3(pov, los, self._triaxial)
1109
1124
  except Exception as x:
1110
1125
  raise IntersectionError(pov=pov, los=los, cause=x)
1111
- return Vector4Tuple(v.x, v.y, v.z, d, name__=self.hartzell4)
1126
+ return Vector4Tuple(v.x, v.y, v.z, d, iteration=i, name__=self.hartzell4)
1112
1127
 
1113
1128
  @Property_RO
1114
1129
  def _hash(self):
@@ -1164,10 +1179,10 @@ class Ellipsoid(_NamedEnumItem):
1164
1179
  h = t.minus(v).length
1165
1180
 
1166
1181
  else: # radial to ellipsoid's center
1167
- h = hypot_(a * v.z, b * v.x, b * v.y)
1182
+ h = hypot_(a * v.z, b * v.x, b * v.y)
1168
1183
  t = (a * b / h) if h > EPS0 else _0_0 # EPS
1169
- v = v.times(t)
1170
- h = r * (_1_0 - t)
1184
+ v = v.times(t)
1185
+ h = r * (_1_0 - t)
1171
1186
 
1172
1187
  return Vector4Tuple(v.x, v.y, v.z, h, iteration=i, name__=self.height4)
1173
1188
 
@@ -1238,7 +1253,7 @@ class Ellipsoid(_NamedEnumItem):
1238
1253
 
1239
1254
  @raise ValueError: Invalid B{C{order}}.
1240
1255
  '''
1241
- if not (isint(order) and order in (4, 6, 8)):
1256
+ if not (isint(order) and _isin(order, 4, 6, 8)):
1242
1257
  raise _ValueError(order=order)
1243
1258
  if self._KsOrder != order:
1244
1259
  Ellipsoid.AlphaKs._update(self)
@@ -1302,8 +1317,8 @@ class Ellipsoid(_NamedEnumItem):
1302
1317
  return degrees(self.m2radians(distance, lat=lat))
1303
1318
 
1304
1319
  def m2radians(self, distance, lat=0):
1305
- '''Convert a distance to an angle along the equator or
1306
- along a parallel of (geodetic) latitude.
1320
+ '''Convert a distance to an angle along the equator or along
1321
+ a parallel of (geodetic) latitude.
1307
1322
 
1308
1323
  @arg distance: Distance (C{meter}).
1309
1324
  @kwarg lat: Parallel latitude (C{degrees90}, C{str}).
@@ -1336,23 +1351,7 @@ class Ellipsoid(_NamedEnumItem):
1336
1351
 
1337
1352
  polaradius = b # Rpolar
1338
1353
 
1339
- # @Property_RO
1340
- # def Q(self):
1341
- # '''Get the I{meridian arc unit} C{Q}, the mean, meridional length I{per radian} C({float}).
1342
- #
1343
- # @note: C{Q * PI / 2} ≈ C{L}, the I{quarter meridian}.
1344
- #
1345
- # @see: Property C{A} and U{Engsager, K., Poder, K.<https://StudyLib.net/doc/7443565/
1346
- # a-highly-accurate-world-wide-algorithm-for-the-transverse...>}.
1347
- # '''
1348
- # n = self.n
1349
- # d = (n + _1_0) / self.a
1350
- # return Float(Q=Fhorner(n**2, _1_0, _0_25, _1_16th, _0_25).fover(d) if d else self.b)
1351
-
1352
- # # Moritz, H. <https://Geodesy.Geology.Ohio-State.EDU/course/refpapers/00740128.pdf>
1353
- # # Q = (1 - 3/4 * e'2 + 45/64 * e'4 - 175/256 * e'6 + 11025/16384 * e'8) * rocPolar
1354
- # # = (4 + e'2 * (-3 + e'2 * (45/16 + e'2 * (-175/64 + e'2 * 11025/4096)))) * rocPolar / 4
1355
- # return Fhorner(self.e22, 4, -3, 45 / 16, -175 / 64, 11025 / 4096).fover(4 / self.rocPolar)
1354
+ # Q = A # I{meridian arc unit} C{Q}, the mean, meridional length I{per radian}
1356
1355
 
1357
1356
  @deprecated_Property_RO
1358
1357
  def quarteradius(self): # PYCHOK no cover
@@ -1379,16 +1378,13 @@ class Ellipsoid(_NamedEnumItem):
1379
1378
  <https://WikiPedia.org/wiki/Earth_radius>}.
1380
1379
  '''
1381
1380
  return Radius(R2=sqrt(self.c2) if self.f else self.a)
1382
-
1383
- Rauthalic = R2
1384
-
1385
- # @Property_RO
1386
- # def R2(self):
1387
1381
  # # Moritz, H. <https://Geodesy.Geology.Ohio-State.EDU/course/refpapers/00740128.pdf>
1388
1382
  # # R2 = (1 - 2/3 * e'2 + 26/45 * e'4 - 100/189 * e'6 + 7034/14175 * e'8) * rocPolar
1389
1383
  # # = (3 + e'2 * (-2 + e'2 * (26/15 + e'2 * (-100/63 + e'2 * 7034/4725)))) * rocPolar / 3
1390
1384
  # return Fhorner(self.e22, 3, -2, 26 / 15, -100 / 63, 7034 / 4725).fover(3 / self.rocPolar)
1391
1385
 
1386
+ Rauthalic = R2
1387
+
1392
1388
  @Property_RO
1393
1389
  def R2x(self):
1394
1390
  '''Get the I{authalic} earth radius (C{meter}), M{sqrt(c2x)}.
@@ -1646,19 +1642,26 @@ class Ellipsoid(_NamedEnumItem):
1646
1642
  r = self.e2s2(sin(a))
1647
1643
  if r > EPS02:
1648
1644
  n = self.a / sqrt(r)
1649
- m = n * self.e21 / r
1645
+ m = n * self.e21 / r
1650
1646
  else:
1651
1647
  m = n = _0_0
1652
1648
  else:
1653
1649
  m = n = self.a
1654
1650
  if scaled and a:
1655
1651
  n *= cos(a) if a < PI_2 else _0_0
1656
- return Curvature2Tuple(Radius(rocMeridional=m),
1657
- Radius(rocPrimeVertical=n))
1652
+ return Curvature2Tuple(m, n)
1653
+
1654
+ def rocAzimuth(self, lat, azimuth):
1655
+ '''Compute the I{directional} radius of curvature of (geodetic) latitude
1656
+ and C{azimuth} compass direction.
1657
+
1658
+ @see: Method L{rocBearing<Ellipsoid.rocBearing>} for details, using C{azimuth} for C{bearing}.
1659
+ '''
1660
+ return Radius(rocAzimuth=self._rocDirectional(lat, Azimuth(azimuth)))
1658
1661
 
1659
1662
  def rocBearing(self, lat, bearing):
1660
- '''Compute the I{directional} radius of curvature of (geodetic)
1661
- latitude and compass direction.
1663
+ '''Compute the I{directional} radius of curvature of (geodetic) latitude
1664
+ and C{bearing} compass direction.
1662
1665
 
1663
1666
  @arg lat: Latitude (C{degrees90}).
1664
1667
  @arg bearing: Direction (compass C{degrees360}).
@@ -1672,18 +1675,23 @@ class Ellipsoid(_NamedEnumItem):
1672
1675
 
1673
1676
  @see: U{Radii of Curvature<https://WikiPedia.org/wiki/Earth_radius#Radii_of_curvature>}
1674
1677
  '''
1678
+ return Radius(rocBearing=self._rocDirectional(lat, Bearing(bearing)))
1679
+
1680
+ def _rocDirectional(self, lat, deg):
1681
+ '''(INTERNAL) Helper for C{rocAzimuth} and C{rocBearing}.
1682
+ '''
1675
1683
  if self.f:
1676
- s2, c2 = _s2_c2(Bearing_(bearing))
1684
+ s2, c2 = _s2_c2(radians(deg))
1677
1685
  m, n = self.roc2_(Phid(lat))
1678
1686
  if n < m: # == n / (c2 * n / m + s2)
1679
1687
  c2 *= n / m
1680
1688
  elif m < n: # == m / (c2 + s2 * m / n)
1681
1689
  s2 *= m / n
1682
- n = m
1683
- b = n / (c2 + s2) # == 1 / (c2 / m + s2 / n)
1690
+ n = m
1691
+ r = _over(n, c2 + s2) # == 1 / (c2 / m + s2 / n)
1684
1692
  else:
1685
- b = self.b # == self.a
1686
- return Radius(rocBearing=b)
1693
+ r = self.b # == self.a
1694
+ return r
1687
1695
 
1688
1696
  @Property_RO
1689
1697
  def rocEquatorial2(self):
@@ -1694,8 +1702,8 @@ class Ellipsoid(_NamedEnumItem):
1694
1702
  L{a2_b}, C{rocPolar} and polar and equatorial U{Radii of Curvature
1695
1703
  <https://WikiPedia.org/wiki/Earth_radius#Radii_of_curvature>}.
1696
1704
  '''
1697
- return Curvature2Tuple(Radius(rocMeridional0=self.b2_a if self.f else self.a),
1698
- Radius(rocPrimeVertical0=self.a))
1705
+ m = self.b2_a if self.f else self.a
1706
+ return Curvature2Tuple(m, self.a)
1699
1707
 
1700
1708
  def rocGauss(self, lat):
1701
1709
  '''Compute the I{Gaussian} radius of curvature of (geodetic) latitude.
@@ -1716,7 +1724,7 @@ class Ellipsoid(_NamedEnumItem):
1716
1724
  g = self.b
1717
1725
  if self.f:
1718
1726
  s2, c2 = _s2_c2(Phid(lat))
1719
- g = g / (c2 + self.b2_a2 * s2)
1727
+ g = _over(g, c2 + self.b2_a2 * s2)
1720
1728
  return Radius(rocGauss=g)
1721
1729
 
1722
1730
  def rocMean(self, lat):
@@ -1733,9 +1741,9 @@ class Ellipsoid(_NamedEnumItem):
1733
1741
  '''
1734
1742
  if self.f:
1735
1743
  m, n = self.roc2_(Phid(lat))
1736
- m *= n * _2_0 / (m + n) # == 2 / (1 / m + 1 / n)
1744
+ m *= _over(n * _2_0, m + n) # == 2 / (1 / m + 1 / n)
1737
1745
  else:
1738
- m = self.a
1746
+ m = self.a
1739
1747
  return Radius(rocMean=m)
1740
1748
 
1741
1749
  def rocMeridional(self, lat):
@@ -1751,8 +1759,8 @@ class Ellipsoid(_NamedEnumItem):
1751
1759
  <https://www.EdWilliams.org/avform.htm#flat>} and U{Radii of
1752
1760
  Curvature<https://WikiPedia.org/wiki/Earth_radius#Radii_of_curvature>}.
1753
1761
  '''
1754
- return self.roc2_(Phid(lat)).meridional if lat else \
1755
- self.rocEquatorial2.meridional
1762
+ r = self.roc2_(Phid(lat)) if lat else self.rocEquatorial2
1763
+ return Radius(rocMeridional=r.meridional)
1756
1764
 
1757
1765
  rocPolar = a2_b # synonymous
1758
1766
 
@@ -1771,8 +1779,8 @@ class Ellipsoid(_NamedEnumItem):
1771
1779
  U{Radii of Curvature<https://WikiPedia.org/wiki/
1772
1780
  Earth_radius#Radii_of_curvature>}.
1773
1781
  '''
1774
- return self.roc2_(Phid(lat)).prime_vertical if lat else \
1775
- self.rocEquatorial2.prime_vertical
1782
+ r = self.roc2_(Phid(lat)) if lat else self.rocEquatorial2
1783
+ return Radius(rocPrimeVertical=r.prime_vertical)
1776
1784
 
1777
1785
  rocTransverse = rocPrimeVertical # synonymous
1778
1786
 
@@ -1792,7 +1800,9 @@ class Ellipsoid(_NamedEnumItem):
1792
1800
 
1793
1801
  @see: U{Earth radius<https://WikiPedia.org/wiki/Earth_radius>}.
1794
1802
  '''
1795
- r = (cbrt2((_1_0 + sqrt3(self.b_a)) * _0_5) * self.a) if self.f else self.a
1803
+ r = self.a
1804
+ if self.f:
1805
+ r *= cbrt2((sqrt3(self.b_a) + _1_0) * _0_5)
1796
1806
  return Radius(Rrectifying=r)
1797
1807
 
1798
1808
  @deprecated_Property_RO
@@ -1806,9 +1816,11 @@ class Ellipsoid(_NamedEnumItem):
1806
1816
 
1807
1817
  @see: C{Rbiaxial}
1808
1818
  '''
1809
- a, b = self.a, self.b
1810
- q = (sqrt((_3_0 + self.b2_a2) * _0_25) * a) if a > b else (
1811
- (sqrt((_3_0 * self.a2_b2 + _1_0) * _0_25) * b) if a < b else a)
1819
+ q, b = self.a, self.b
1820
+ if b < q:
1821
+ q *= sqrt((self.b2_a2 + _3_0) * _0_25)
1822
+ elif b > q:
1823
+ q = sqrt((self.a2_b2 * _3_0 + _1_0) * _0_25) * b
1812
1824
  return Radius(Rtriaxial=q)
1813
1825
 
1814
1826
  def toEllipsoid2(self, **name):
@@ -1897,22 +1909,23 @@ class Ellipsoid2(Ellipsoid):
1897
1909
  Ellipsoid.__init__(self, a, f=f, **name)
1898
1910
 
1899
1911
 
1900
- def _spherical_a_b(a, b):
1912
+ def _ispherical_a_b(a, b):
1901
1913
  '''(INTERNAL) C{True} for spherical or invalid C{a} or C{b}.
1902
1914
  '''
1903
1915
  return a < EPS0 or b < EPS0 or fabs(a - b) < EPS0
1904
1916
 
1905
1917
 
1906
- def _spherical_f(f):
1918
+ def _ispherical_f(f):
1907
1919
  '''(INTERNAL) C{True} for spherical or invalid C{f}.
1908
1920
  '''
1909
- return fabs(f) < EPS or f > EPS1
1921
+ return f > EPS1 or fabs(f) < EPS
1910
1922
 
1911
1923
 
1912
- def _spherical_f_(f_):
1924
+ def _ispherical_f_(f_):
1913
1925
  '''(INTERNAL) C{True} for spherical or invalid C{f_}.
1914
1926
  '''
1915
- return fabs(f_) < EPS or fabs(f_) > _1_EPS
1927
+ f_ = fabs(f_)
1928
+ return f_ < EPS or f_ > _1_EPS
1916
1929
 
1917
1930
 
1918
1931
  def a_b2e(a, b):
@@ -1921,12 +1934,12 @@ def a_b2e(a, b):
1921
1934
  @arg a: Equatorial radius (C{scalar} > 0).
1922
1935
  @arg b: Polar radius (C{scalar} > 0).
1923
1936
 
1924
- @return: The I{unsigned}, (1st) eccentricity (C{float} or C{0}),
1925
- M{sqrt(1 - (b / a)**2)}.
1937
+ @return: The I{unsigned}, (1st) eccentricity (C{float} or C{0}), M{sqrt(1 - (b / a)**2)}.
1926
1938
 
1927
1939
  @note: The result is always I{non-negative} and C{0} for I{near-spherical} ellipsoids.
1928
1940
  '''
1929
- return Float(e=sqrt(fabs(a_b2e2(a, b)))) # == sqrt(fabs(a - b) * (a + b)) / a)
1941
+ e2 = _a2b2e2(a, b, b2=False)
1942
+ return Float(e=sqrt(fabs(e2)) if e2 else _0_0) # == sqrt(fabs((a - b) * (a + b))) / a
1930
1943
 
1931
1944
 
1932
1945
  def a_b2e2(a, b):
@@ -1935,13 +1948,12 @@ def a_b2e2(a, b):
1935
1948
  @arg a: Equatorial radius (C{scalar} > 0).
1936
1949
  @arg b: Polar radius (C{scalar} > 0).
1937
1950
 
1938
- @return: The I{signed}, (1st) eccentricity I{squared} (C{float} or C{0}),
1939
- M{1 - (b / a)**2}.
1951
+ @return: The I{signed}, (1st) eccentricity I{squared} (C{float} or C{0}), M{1 - (b / a)**2}.
1940
1952
 
1941
- @note: The result is positive for I{oblate}, negative for I{prolate}
1942
- or C{0} for I{near-spherical} ellipsoids.
1953
+ @note: The result is positive for I{oblate}, negative for I{prolate} or C{0}
1954
+ for I{near-spherical} ellipsoids.
1943
1955
  '''
1944
- return Float(e2=_0_0 if _spherical_a_b(a, b) else ((a - b) * (a + b) / a**2))
1956
+ return Float(e2=_a2b2e2(a, b, b2=False))
1945
1957
 
1946
1958
 
1947
1959
  def a_b2e22(a, b):
@@ -1950,13 +1962,12 @@ def a_b2e22(a, b):
1950
1962
  @arg a: Equatorial radius (C{scalar} > 0).
1951
1963
  @arg b: Polar radius (C{scalar} > 0).
1952
1964
 
1953
- @return: The I{signed}, 2nd eccentricity I{squared} (C{float} or C{0}),
1954
- M{(a / b)**2 - 1}.
1965
+ @return: The I{signed}, 2nd eccentricity I{squared} (C{float} or C{0}), M{(a / b)**2 - 1}.
1955
1966
 
1956
- @note: The result is positive for I{oblate}, negative for I{prolate}
1957
- or C{0} for I{near-spherical} ellipsoids.
1967
+ @note: The result is positive for I{oblate}, negative for I{prolate} or C{0}
1968
+ for I{near-spherical} ellipsoids.
1958
1969
  '''
1959
- return Float(e22=_0_0 if _spherical_a_b(a, b) else ((a - b) * (a + b) / b**2))
1970
+ return Float(e22=_a2b2e2(a, b, a2=False))
1960
1971
 
1961
1972
 
1962
1973
  def a_b2e32(a, b):
@@ -1968,11 +1979,23 @@ def a_b2e32(a, b):
1968
1979
  @return: The I{signed}, 3rd eccentricity I{squared} (C{float} or C{0}),
1969
1980
  M{(a**2 - b**2) / (a**2 + b**2)}.
1970
1981
 
1971
- @note: The result is positive for I{oblate}, negative for I{prolate}
1972
- or C{0} for I{near-spherical} ellipsoids.
1982
+ @note: The result is positive for I{oblate}, negative for I{prolate} or C{0}
1983
+ for I{near-spherical} ellipsoids.
1984
+ '''
1985
+ return Float(e32=_a2b2e2(a, b))
1986
+
1987
+
1988
+ def _a2b2e2(a, b, a2=True, b2=True):
1989
+ '''(INTERNAL) Helper for C{a_b2e}, C{a_b2e2}, C{a_b2e22} and C{a_b2e32}.
1973
1990
  '''
1974
- a2, b2 = a**2, b**2
1975
- return Float(e32=_0_0 if _spherical_a_b(a2, b2) else ((a2 - b2) / (a2 + b2)))
1991
+ if _ispherical_a_b(a, b):
1992
+ e2 = _0_0
1993
+ else: # a > 0, b > 0
1994
+ a, b = (_1_0, b / a) if a > b else (a / b, _1_0)
1995
+ a2b2 = float(a - b) * (a + b)
1996
+ e2 = _over(a2b2, (a**2 if a2 else _0_0) +
1997
+ (b**2 if b2 else _0_0)) if a2b2 else _0_0
1998
+ return e2
1976
1999
 
1977
2000
 
1978
2001
  def a_b2f(a, b):
@@ -1986,8 +2009,8 @@ def a_b2f(a, b):
1986
2009
  @note: The result is positive for I{oblate}, negative for I{prolate} or C{0}
1987
2010
  for I{near-spherical} ellipsoids.
1988
2011
  '''
1989
- f = 0 if _spherical_a_b(a, b) else ((a - b) / a)
1990
- return _f_0_0 if _spherical_f(f) else Float(f=f)
2012
+ f = 0 if _ispherical_a_b(a, b) else _over(float(a - b), a)
2013
+ return _f_0_0 if _ispherical_f(f) else Float(f=f)
1991
2014
 
1992
2015
 
1993
2016
  def a_b2f_(a, b):
@@ -2001,8 +2024,8 @@ def a_b2f_(a, b):
2001
2024
  @note: The result is positive for I{oblate}, negative for I{prolate} or C{0}
2002
2025
  for I{near-spherical} ellipsoids.
2003
2026
  '''
2004
- f_ = 0 if _spherical_a_b(a, b) else (a / float(a - b))
2005
- return _f__0_0 if _spherical_f_(f_) else Float(f_=f_)
2027
+ f_ = 0 if _ispherical_a_b(a, b) else _over(a, float(a - b))
2028
+ return _f__0_0 if _ispherical_f_(f_) else Float(f_=f_)
2006
2029
 
2007
2030
 
2008
2031
  def a_b2f2(a, b):
@@ -2016,8 +2039,8 @@ def a_b2f2(a, b):
2016
2039
  @note: The result is positive for I{oblate}, negative for I{prolate} or C{0}
2017
2040
  for I{near-spherical} ellipsoids.
2018
2041
  '''
2019
- t = 0 if _spherical_a_b(a, b) else float(a - b)
2020
- return Float(f2=_0_0 if fabs(t) < EPS0 else (t / b))
2042
+ t = 0 if _ispherical_a_b(a, b) else float(a - b)
2043
+ return Float(f2=_0_0 if fabs(t) < EPS0 else _over(t, b))
2021
2044
 
2022
2045
 
2023
2046
  def a_b2n(a, b):
@@ -2028,11 +2051,11 @@ def a_b2n(a, b):
2028
2051
 
2029
2052
  @return: The I{signed}, 3rd flattening (C{scalar} or C{0}), M{(a - b) / (a + b)}.
2030
2053
 
2031
- @note: The result is positive for I{oblate}, negative for I{prolate}
2032
- or C{0} for I{near-spherical} ellipsoids.
2054
+ @note: The result is positive for I{oblate}, negative for I{prolate} or C{0}
2055
+ for I{near-spherical} ellipsoids.
2033
2056
  '''
2034
- t = 0 if _spherical_a_b(a, b) else float(a - b)
2035
- return Float(n=_0_0 if fabs(t) < EPS0 else (t / (a + b)))
2057
+ t = 0 if _ispherical_a_b(a, b) else float(a - b)
2058
+ return Float(n=_0_0 if fabs(t) < EPS0 else _over(t, a + b))
2036
2059
 
2037
2060
 
2038
2061
  def a_f2b(a, f):
@@ -2043,8 +2066,8 @@ def a_f2b(a, f):
2043
2066
 
2044
2067
  @return: The polar radius (C{float}), M{a * (1 - f)}.
2045
2068
  '''
2046
- b = a if _spherical_f(f) else (a * (_1_0 - f))
2047
- return Radius_(b=a if _spherical_a_b(a, b) else b)
2069
+ b = a if _ispherical_f(f) else (a * (_1_0 - f))
2070
+ return Radius_(b=a if _ispherical_a_b(a, b) else b)
2048
2071
 
2049
2072
 
2050
2073
  def a_f_2b(a, f_):
@@ -2055,8 +2078,8 @@ def a_f_2b(a, f_):
2055
2078
 
2056
2079
  @return: The polar radius (C{float}), M{a * (f_ - 1) / f_}.
2057
2080
  '''
2058
- b = a if _spherical_f_(f_) else (a * (f_ - _1_0) / f_)
2059
- return Radius_(b=a if _spherical_a_b(a, b) else b)
2081
+ b = a if _ispherical_f_(f_) else _over(a * (f_ - _1_0), f_)
2082
+ return Radius_(b=a if _ispherical_a_b(a, b) else b)
2060
2083
 
2061
2084
 
2062
2085
  def b_f2a(b, f):
@@ -2068,8 +2091,8 @@ def b_f2a(b, f):
2068
2091
  @return: The equatorial radius (C{float}), M{b / (1 - f)}.
2069
2092
  '''
2070
2093
  t = _1_0 - f
2071
- a = b if fabs(t) < EPS0 else (b / t)
2072
- return Radius_(a=b if _spherical_a_b(a, b) else a)
2094
+ a = b if fabs(t) < EPS0 else _over(b, t)
2095
+ return Radius_(a=b if _ispherical_a_b(a, b) else a)
2073
2096
 
2074
2097
 
2075
2098
  def b_f_2a(b, f_):
@@ -2081,9 +2104,9 @@ def b_f_2a(b, f_):
2081
2104
  @return: The equatorial radius (C{float}), M{b * f_ / (f_ - 1)}.
2082
2105
  '''
2083
2106
  t = f_ - _1_0
2084
- a = b if _spherical_f_(f_) or fabs(t - f_) < EPS0 \
2085
- or fabs(t) < EPS0 else (b * f_ / t)
2086
- return Radius_(a=b if _spherical_a_b(a, b) else a)
2107
+ a = b if _ispherical_f_(f_) or fabs(t) < EPS0 \
2108
+ or fabs(t - f_) < EPS0 else _over(b * f_, t)
2109
+ return Radius_(a=b if _ispherical_a_b(a, b) else a)
2087
2110
 
2088
2111
 
2089
2112
  def e2f(e):
@@ -2103,9 +2126,9 @@ def e22f(e2):
2103
2126
 
2104
2127
  @arg e2: The (1st) eccentricity I{squared}, I{signed} (L{NINF} < C{float} < 1)
2105
2128
 
2106
- @return: The flattening (C{float} or C{0}), M{e2 / (sqrt(e2 - 1) + 1)}.
2129
+ @return: The flattening (C{float} or C{0}), M{e2 / (sqrt(1 - e2) + 1)}.
2107
2130
  '''
2108
- return Float(f=e2 / (sqrt(_1_0 - e2) + _1_0)) if e2 else _f_0_0
2131
+ return Float(f=_over(e2, sqrt(_1_0 - e2) + _1_0)) if e2 and e2 < _1_0 else _f_0_0
2109
2132
 
2110
2133
 
2111
2134
  def f2e2(f):
@@ -2113,17 +2136,16 @@ def f2e2(f):
2113
2136
 
2114
2137
  @arg f: Flattening (C{scalar} < 1, negative for I{prolate}).
2115
2138
 
2116
- @return: The I{signed}, (1st) eccentricity I{squared} (C{float} < 1),
2117
- M{f * (2 - f)}.
2139
+ @return: The I{signed}, (1st) eccentricity I{squared} (C{float} < 1), M{f * (2 - f)}.
2118
2140
 
2119
- @note: The result is positive for I{oblate}, negative for I{prolate}
2120
- or C{0} for I{near-spherical} ellipsoids.
2141
+ @note: The result is positive for I{oblate}, negative for I{prolate} or C{0}
2142
+ for I{near-spherical} ellipsoids.
2121
2143
 
2122
2144
  @see: U{Eccentricity conversions<https://GeographicLib.SourceForge.io/
2123
2145
  C++/doc/classGeographicLib_1_1Ellipsoid.html>} and U{Flattening
2124
2146
  <https://WikiPedia.org/wiki/Flattening>}.
2125
2147
  '''
2126
- return Float(e2=_0_0 if _spherical_f(f) else (f * (_2_0 - f)))
2148
+ return Float(e2=_0_0 if _ispherical_f(f) else (f * (_2_0 - f)))
2127
2149
 
2128
2150
 
2129
2151
  def f2e22(f):
@@ -2131,18 +2153,18 @@ def f2e22(f):
2131
2153
 
2132
2154
  @arg f: Flattening (C{scalar} < 1, negative for I{prolate}).
2133
2155
 
2134
- @return: The I{signed}, 2nd eccentricity I{squared} (C{float} > -1 or
2135
- C{INF}), M{f * (2 - f) / (1 - f)**2}.
2156
+ @return: The I{signed}, 2nd eccentricity I{squared} (C{float} > -1 or C{INF}),
2157
+ M{f * (2 - f) / (1 - f)**2}.
2136
2158
 
2137
- @note: The result is positive for I{oblate}, negative for I{prolate}
2138
- or C{0} for near-spherical ellipsoids.
2159
+ @note: The result is positive for I{oblate}, negative for I{prolate} or C{0}
2160
+ for near-spherical ellipsoids.
2139
2161
 
2140
2162
  @see: U{Eccentricity conversions<https://GeographicLib.SourceForge.io/
2141
2163
  C++/doc/classGeographicLib_1_1Ellipsoid.html>}.
2142
2164
  '''
2143
2165
  # e2 / (1 - e2) == f * (2 - f) / (1 - f)**2
2144
2166
  t = (_1_0 - f)**2
2145
- return Float(e22=INF if t < EPS0 else (f2e2(f) / t)) # PYCHOK type
2167
+ return Float(e22=INF if t < EPS0 else _over(f2e2(f), t)) # PYCHOK type
2146
2168
 
2147
2169
 
2148
2170
  def f2e32(f):
@@ -2153,15 +2175,15 @@ def f2e32(f):
2153
2175
  @return: The I{signed}, 3rd eccentricity I{squared} (C{float}),
2154
2176
  M{f * (2 - f) / (1 + (1 - f)**2)}.
2155
2177
 
2156
- @note: The result is positive for I{oblate}, negative for I{prolate}
2157
- or C{0} for I{near-spherical} ellipsoids.
2178
+ @note: The result is positive for I{oblate}, negative for I{prolate} or C{0}
2179
+ for I{near-spherical} ellipsoids.
2158
2180
 
2159
2181
  @see: U{Eccentricity conversions<https://GeographicLib.SourceForge.io/
2160
2182
  C++/doc/classGeographicLib_1_1Ellipsoid.html>}.
2161
2183
  '''
2162
2184
  # e2 / (2 - e2) == f * (2 - f) / (1 + (1 - f)**2)
2163
2185
  e2 = f2e2(f)
2164
- return Float(e32=e2 / (_2_0 - e2))
2186
+ return Float(e32=_over(e2, _2_0 - e2))
2165
2187
 
2166
2188
 
2167
2189
  def f_2f(f_):
@@ -2171,11 +2193,11 @@ def f_2f(f_):
2171
2193
 
2172
2194
  @return: The flattening (C{scalar} or C{0}), M{1 / f_}.
2173
2195
 
2174
- @note: The result is positive for I{oblate}, negative for I{prolate}
2175
- or C{0} for I{near-spherical} ellipsoids.
2196
+ @note: The result is positive for I{oblate}, negative for I{prolate} or C{0}
2197
+ for I{near-spherical} ellipsoids.
2176
2198
  '''
2177
- f = 0 if _spherical_f_(f_) else _1_0 / f_
2178
- return _f_0_0 if _spherical_f(f) else Float(f=f) # PYCHOK type
2199
+ f = 0 if _ispherical_f_(f_) else _over(_1_0, f_)
2200
+ return _f_0_0 if _ispherical_f(f) else Float(f=f) # PYCHOK type
2179
2201
 
2180
2202
 
2181
2203
  def f2f_(f):
@@ -2185,11 +2207,11 @@ def f2f_(f):
2185
2207
 
2186
2208
  @return: The inverse flattening (C{scalar} or C{0}), M{1 / f}.
2187
2209
 
2188
- @note: The result is positive for I{oblate}, negative for I{prolate}
2189
- or C{0} for I{near-spherical} ellipsoids.
2210
+ @note: The result is positive for I{oblate}, negative for I{prolate} or C{0}
2211
+ for I{near-spherical} ellipsoids.
2190
2212
  '''
2191
- f_ = 0 if _spherical_f(f) else _1_0 / f
2192
- return _f__0_0 if _spherical_f_(f_) else Float(f_=f_) # PYCHOK type
2213
+ f_ = 0 if _ispherical_f(f) else _over(_1_0, f)
2214
+ return _f__0_0 if _ispherical_f_(f_) else Float(f_=f_) # PYCHOK type
2193
2215
 
2194
2216
 
2195
2217
  def f2f2(f):
@@ -2199,16 +2221,16 @@ def f2f2(f):
2199
2221
 
2200
2222
  @return: The I{signed}, 2nd flattening (C{scalar} or C{INF}), M{f / (1 - f)}.
2201
2223
 
2202
- @note: The result is positive for I{oblate}, negative for I{prolate}
2203
- or C{0} for I{near-spherical} ellipsoids.
2224
+ @note: The result is positive for I{oblate}, negative for I{prolate} or C{0}
2225
+ for I{near-spherical} ellipsoids.
2204
2226
 
2205
2227
  @see: U{Eccentricity conversions<https://GeographicLib.SourceForge.io/
2206
2228
  C++/doc/classGeographicLib_1_1Ellipsoid.html>} and U{Flattening
2207
2229
  <https://WikiPedia.org/wiki/Flattening>}.
2208
2230
  '''
2209
2231
  t = _1_0 - f
2210
- return Float(f2=_0_0 if _spherical_f(f) else (INF if fabs(t) < EPS
2211
- else (f / t))) # PYCHOK type
2232
+ return Float(f2=_0_0 if _ispherical_f(f) else
2233
+ (INF if fabs(t) < EPS else _over(f, t))) # PYCHOK type
2212
2234
 
2213
2235
 
2214
2236
  def f2n(f):
@@ -2219,14 +2241,14 @@ def f2n(f):
2219
2241
  @return: The I{signed}, 3rd flattening (-1 <= C{float} < 1),
2220
2242
  M{f / (2 - f)}.
2221
2243
 
2222
- @note: The result is positive for I{oblate}, negative for I{prolate}
2223
- or C{0} for I{near-spherical} ellipsoids.
2244
+ @note: The result is positive for I{oblate}, negative for I{prolate} or C{0}
2245
+ for I{near-spherical} ellipsoids.
2224
2246
 
2225
2247
  @see: U{Eccentricity conversions<https://GeographicLib.SourceForge.io/
2226
2248
  C++/doc/classGeographicLib_1_1Ellipsoid.html>} and U{Flattening
2227
2249
  <https://WikiPedia.org/wiki/Flattening>}.
2228
2250
  '''
2229
- return Float(n=_0_0 if _spherical_f(f) else (f / float(_2_0 - f)))
2251
+ return Float(n=_0_0 if _ispherical_f(f) else _over(f, float(_2_0 - f)))
2230
2252
 
2231
2253
 
2232
2254
  def n2e2(n):
@@ -2237,14 +2259,14 @@ def n2e2(n):
2237
2259
  @return: The I{signed}, (1st) eccentricity I{squared} (C{float} or NINF),
2238
2260
  M{4 * n / (1 + n)**2}.
2239
2261
 
2240
- @note: The result is positive for I{oblate}, negative for I{prolate}
2241
- or C{0} for I{near-spherical} ellipsoids.
2262
+ @note: The result is positive for I{oblate}, negative for I{prolate} or C{0}
2263
+ for I{near-spherical} ellipsoids.
2242
2264
 
2243
2265
  @see: U{Flattening<https://WikiPedia.org/wiki/Flattening>}.
2244
2266
  '''
2245
2267
  t = (n + _1_0)**2
2246
2268
  return Float(e2=_0_0 if fabs(n) < EPS0 else
2247
- (NINF if t < EPS0 else (_4_0 * n / t)))
2269
+ (NINF if t < EPS0 else _over(_4_0 * n, t)))
2248
2270
 
2249
2271
 
2250
2272
  def n2f(n):
@@ -2259,8 +2281,8 @@ def n2f(n):
2259
2281
  <https://WikiPedia.org/wiki/Flattening>}.
2260
2282
  '''
2261
2283
  t = n + _1_0
2262
- f = 0 if fabs(n) < EPS0 else (NINF if t < EPS0 else (_2_0 * n / t))
2263
- return _f_0_0 if _spherical_f(f) else Float(f=f)
2284
+ f = 0 if fabs(n) < EPS0 else (NINF if t < EPS0 else _over(_2_0 * n, t))
2285
+ return _f_0_0 if _ispherical_f(f) else Float(f=f)
2264
2286
 
2265
2287
 
2266
2288
  def n2f_(n):
@@ -2369,7 +2391,7 @@ Ellipsoids._assert( # <https://WikiPedia.org/wiki/Earth_ellipsoid>
2369
2391
 
2370
2392
  _EWGS84 = Ellipsoids.WGS84 # (INTERNAL) shared
2371
2393
 
2372
- if __name__ == '__main__':
2394
+ if __name__ == _DMAIN_:
2373
2395
 
2374
2396
  from pygeodesy.interns import _COMMA_, _NL_, _NLATvar_
2375
2397
  from pygeodesy import nameof, printf
@@ -2392,7 +2414,7 @@ if __name__ == '__main__':
2392
2414
  t = [NN] + Ellipsoids.toRepr(all=True, asorted=True).split(_NL_)
2393
2415
  printf(_NLATvar_.join(i.strip(_COMMA_) for i in t))
2394
2416
 
2395
- # % python3 -m pygeodesy.ellipsoids
2417
+ # % python3.13 -m pygeodesy.ellipsoids
2396
2418
 
2397
2419
  # Ellipsoids.WGS84: name='WGS84', a=6378137, f=0.0033528107, f_=298.257223563, b=6356752.3142451793, f2=0.0033640898, n=0.0016792204, e=0.0818191908, e2=0.00669438, e21=0.99330562, e22=0.0067394967, e32=0.0033584313, A=6367449.1458234144, L=10001965.7293127235, R1=6371008.7714150595, R2=6371007.1809184738, R3=6371000.7900091587, Rbiaxial=6367453.6345163295, Rtriaxial=6372797.5559594007
2398
2420
  # e=8.1819190842622e-02, f_=2.98257223563e+02, f=3.3528106647475e-03, n=1.6792203863837e-03 (0.0e+00)
@@ -2418,7 +2440,7 @@ if __name__ == '__main__':
2418
2440
  # BetaKs 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
2419
2441
  # KsOrder 8
2420
2442
 
2421
- # Ellipsoids._Prolate: name='_Prolate', a=6356752.3142451793, f=-0.0033640898, f_=-297.257223563, b=6378137, f2=-0.0033528107, n=-0.0016792204, e=0.0820944379, e2=-0.0067394967, e21=1.0067394967, e22=-0.00669438, e32=-0.0033584313, A=6367449.1458234144, L=10035500.5204500314, R1=6363880.5428301189, R2=6363878.9413582645, R3=6363872.5644020075, Rbiaxial=6367453.6345163295, Rtriaxial=6362105.2243882557
2443
+ # Ellipsoids._Prolate: name='_Prolate', a=6356752.3142451793, f=-0.0033640898, f_=-297.257223563, b=6378137, f2=-0.0033528107, n=-0.0016792204, e=0.0820944379, e2=-0.0067394967, e21=1.0067394967, e22=-0.00669438, e32=-0.0033584313, A=6367449.1458234144, L=10035500.5204500332, R1=6363880.5428301189, R2=6363878.9413582645, R3=6363872.5644020075, Rbiaxial=6367453.6345163295, Rtriaxial=6362105.2243882557
2422
2444
  # e=8.2094437949696e-02, f_=-2.97257223563e+02, f=-3.3640898209765e-03, n=-1.6792203863837e-03 (0.0e+00)
2423
2445
  # AlphaKs -0.00084149152514366627, 0.00000076653480614871, -0.00000000120934503389, 0.0000000000024576225, -0.00000000000000578863, 0.00000000000000001502, -0.00000000000000000004, 0.0
2424
2446
  # BetaKs -0.00084149187224351817, 0.00000005842735196773, -0.0000000001680487236, 0.00000000000021706261, -0.00000000000000038002, 0.00000000000000000073, -0.0, 0.0