pygeodesy 25.4.8__py2.py3-none-any.whl → 25.4.25__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 (96) hide show
  1. pygeodesy/__init__.py +30 -27
  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 +31 -17
  15. pygeodesy/booleans.py +12 -10
  16. pygeodesy/cartesianBase.py +21 -20
  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 +10 -7
  26. pygeodesy/elevations.py +9 -8
  27. pygeodesy/ellipsoidalBase.py +19 -8
  28. pygeodesy/ellipsoidalBaseDI.py +17 -15
  29. pygeodesy/ellipsoidalNvector.py +6 -3
  30. pygeodesy/ellipsoidalVincenty.py +4 -1
  31. pygeodesy/ellipsoids.py +167 -138
  32. pygeodesy/elliptic.py +9 -9
  33. pygeodesy/errors.py +44 -43
  34. pygeodesy/etm.py +7 -7
  35. pygeodesy/fmath.py +10 -9
  36. pygeodesy/formy.py +11 -12
  37. pygeodesy/frechet.py +216 -109
  38. pygeodesy/fstats.py +5 -4
  39. pygeodesy/fsums.py +78 -77
  40. pygeodesy/gars.py +4 -3
  41. pygeodesy/geodesici.py +15 -14
  42. pygeodesy/geodesicw.py +34 -32
  43. pygeodesy/geodesicx/__init__.py +1 -1
  44. pygeodesy/geodesicx/__main__.py +11 -9
  45. pygeodesy/geodesicx/gx.py +30 -33
  46. pygeodesy/geodesicx/gxarea.py +2 -2
  47. pygeodesy/geodesicx/gxline.py +5 -5
  48. pygeodesy/geodsolve.py +18 -17
  49. pygeodesy/geohash.py +5 -5
  50. pygeodesy/geoids.py +34 -31
  51. pygeodesy/hausdorff.py +17 -13
  52. pygeodesy/heights.py +2 -4
  53. pygeodesy/internals.py +28 -44
  54. pygeodesy/interns.py +10 -7
  55. pygeodesy/iters.py +8 -8
  56. pygeodesy/karney.py +68 -62
  57. pygeodesy/ktm.py +5 -5
  58. pygeodesy/latlonBase.py +14 -18
  59. pygeodesy/lazily.py +65 -63
  60. pygeodesy/lcc.py +11 -9
  61. pygeodesy/ltp.py +8 -7
  62. pygeodesy/ltpTuples.py +2 -2
  63. pygeodesy/mgrs.py +7 -6
  64. pygeodesy/named.py +47 -31
  65. pygeodesy/nvectorBase.py +7 -7
  66. pygeodesy/osgr.py +9 -8
  67. pygeodesy/points.py +12 -10
  68. pygeodesy/props.py +25 -25
  69. pygeodesy/resections.py +11 -10
  70. pygeodesy/rhumb/__init__.py +1 -1
  71. pygeodesy/rhumb/aux_.py +7 -7
  72. pygeodesy/rhumb/bases.py +22 -20
  73. pygeodesy/rhumb/ekx.py +6 -6
  74. pygeodesy/rhumb/solve.py +15 -15
  75. pygeodesy/solveBase.py +3 -3
  76. pygeodesy/sphericalBase.py +6 -6
  77. pygeodesy/sphericalNvector.py +6 -5
  78. pygeodesy/sphericalTrigonometry.py +8 -7
  79. pygeodesy/streprs.py +14 -14
  80. pygeodesy/trf.py +14 -12
  81. pygeodesy/triaxials.py +29 -26
  82. pygeodesy/units.py +5 -4
  83. pygeodesy/unitsBase.py +5 -4
  84. pygeodesy/ups.py +3 -3
  85. pygeodesy/utily.py +4 -4
  86. pygeodesy/utmups.py +4 -4
  87. pygeodesy/utmupsBase.py +88 -18
  88. pygeodesy/vector2d.py +18 -11
  89. pygeodesy/vector3d.py +7 -6
  90. pygeodesy/webmercator.py +6 -5
  91. pygeodesy/wgrs.py +6 -5
  92. {pygeodesy-25.4.8.dist-info → pygeodesy-25.4.25.dist-info}/METADATA +27 -23
  93. pygeodesy-25.4.25.dist-info/RECORD +118 -0
  94. pygeodesy-25.4.8.dist-info/RECORD +0 -118
  95. {pygeodesy-25.4.8.dist-info → pygeodesy-25.4.25.dist-info}/WHEEL +0 -0
  96. {pygeodesy-25.4.8.dist-info → pygeodesy-25.4.25.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.23'
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):
@@ -243,7 +245,7 @@ class Ellipsoid(_NamedEnumItem):
243
245
  if not _isfinite(a):
244
246
  raise ValueError(_SPACE_(_a_, _not_finite_))
245
247
 
246
- if b: # not in (_0_0, None)
248
+ if b: # not _isin(b, None, _0_0)
247
249
  b = Radius_(b=b) # low=EPS
248
250
  f = a_b2f(a, b) if f is None else Float(f=f)
249
251
  f_ = f2f_(f) if f_ is None else Float(f_=f_)
@@ -424,7 +426,7 @@ class Ellipsoid(_NamedEnumItem):
424
426
  t = Fmt.EQUAL(self._DOT_(n), t)
425
427
  raise Error(t, txt=txt or Fmt.exceeds_eps(eps))
426
428
  return Float(v if self.f else f0, name=n)
427
- raise Error(unstr(self._DOT_(self._assert.__name__), val,
429
+ raise Error(unstr(self._DOT_(typename(self._assert)), val,
428
430
  eps=eps, f0=f0, **name_value))
429
431
 
430
432
  def auxAuthalic(self, lat, inverse=False):
@@ -442,7 +444,8 @@ class Ellipsoid(_NamedEnumItem):
442
444
  U{Snyder<https://Pubs.USGS.gov/pp/1395/report.pdf>}, p 16.
443
445
  '''
444
446
  if self.f:
445
- f = self._albersCyl._tanf if inverse else self._albersCyl._txif # PYCHOK attr
447
+ f = self._albersCyl._tanf if inverse else \
448
+ self._albersCyl._txif # PYCHOK attr
446
449
  lat = atan1d(f(tan(Phid(lat)))) # PYCHOK attr
447
450
  return _aux(lat, inverse, Ellipsoid.auxAuthalic)
448
451
 
@@ -461,7 +464,7 @@ class Ellipsoid(_NamedEnumItem):
461
464
  U{Snyder<https://Pubs.USGS.gov/pp/1395/report.pdf>}, pp 15-16.
462
465
  '''
463
466
  if self.f:
464
- f = self.es_tauf if inverse else self.es_taupf # PYCHOK attr
467
+ f = self.es_tauf if inverse else self.es_taupf # PYCHOK attr
465
468
  lat = atan1d(f(tan(Phid(lat)))) # PYCHOK attr
466
469
  return _aux(lat, inverse, Ellipsoid.auxConformal)
467
470
 
@@ -480,8 +483,8 @@ class Ellipsoid(_NamedEnumItem):
480
483
  U{Snyder<https://Pubs.USGS.gov/pp/1395/report.pdf>}, pp 17-18.
481
484
  '''
482
485
  if self.f:
483
- f = self.a2_b2 if inverse else self.b2_a2
484
- lat = atan1d(f * tan(Phid(lat)))
486
+ f = self.a2_b2 if inverse else self.b2_a2
487
+ lat = atan1d(tan(Phid(lat)) * f)
485
488
  return _aux(lat, inverse, Ellipsoid.auxGeocentric)
486
489
 
487
490
  def auxIsometric(self, lat, inverse=False):
@@ -503,7 +506,7 @@ class Ellipsoid(_NamedEnumItem):
503
506
  U{Snyder<https://Pubs.USGS.gov/pp/1395/report.pdf>}, pp 15-16.
504
507
  '''
505
508
  if self.f:
506
- r = Phid(lat, clip=0)
509
+ r = Phid(lat, clip=0)
507
510
  lat = degrees(atan1(self.es_tauf(sinh(r))) if inverse else
508
511
  asinh(self.es_taupf(tan(r))))
509
512
  # clip=0, since auxIsometric(+/-90) is far outside [-90..+90]
@@ -549,9 +552,9 @@ class Ellipsoid(_NamedEnumItem):
549
552
  if inverse:
550
553
  e = self._elliptic_e22
551
554
  d = degrees90(e.fEinv(e.cE * lat / _90_0))
552
- lat = self.auxParametric(d, inverse=True)
555
+ lat = self.auxParametric(d, inverse=True)
553
556
  else:
554
- lat = _90_0 * self.Llat(lat) / self.L
557
+ lat = _over(self.Llat(lat), self.L) * _90_0
555
558
  return _aux(lat, inverse, Ellipsoid.auxRectifying)
556
559
 
557
560
  @Property_RO
@@ -582,7 +585,7 @@ class Ellipsoid(_NamedEnumItem):
582
585
 
583
586
  @see: U{Radii of Curvature<https://WikiPedia.org/wiki/Earth_radius#Radii_of_curvature>}.
584
587
  '''
585
- return Radius(b2_a=self.b2 / self.a if self.f else self.b)
588
+ return Radius(b2_a=_over(self.b2, self.a) if self.f else self.b)
586
589
 
587
590
  @Property_RO
588
591
  def b2_a2(self):
@@ -831,7 +834,7 @@ class Ellipsoid(_NamedEnumItem):
831
834
  def _elliptic_e12(self): # see I{Karney}'s Ellipsoid._e12
832
835
  '''(INTERNAL) Elliptic helper for C{Rhumb}.
833
836
  '''
834
- e12 = self.e2 / (self.e2 - _1_0) # NOT DEPRECATED .e12!
837
+ e12 = _over(self.e2, self.e2 - _1_0) # NOT DEPRECATED .e12!
835
838
  return _MODS.elliptic.Elliptic(e12)
836
839
 
837
840
  @Property_RO
@@ -869,7 +872,7 @@ class Ellipsoid(_NamedEnumItem):
869
872
  if r < 0:
870
873
  raise ValueError(_negative_)
871
874
  except (TypeError, ValueError) as x:
872
- t = self._DOT_(Ellipsoid.e2s2.__name__)
875
+ t = self._DOT_(typename(Ellipsoid.e2s2))
873
876
  raise _ValueError(t, s, cause=x)
874
877
  return r
875
878
 
@@ -919,8 +922,8 @@ class Ellipsoid(_NamedEnumItem):
919
922
  '''
920
923
  t = Scalar(taup=taup)
921
924
  if self.f: # .isEllipsoidal
922
- a = fabs(t)
923
- T = t * (self._exp_es_atanh_1 if a > 70 else self._1_e21)
925
+ a = fabs(t)
926
+ T = (self._exp_es_atanh_1 if a > 70 else self._1_e21) * t
924
927
  if fabs(T * _EPSqrt) < _2_0: # handles +/- INF and NAN
925
928
  s = (a * _TOL) if a > _1_0 else _TOL
926
929
  for T, _, d in self._es_tauf3(t, T): # max 2
@@ -939,8 +942,8 @@ class Ellipsoid(_NamedEnumItem):
939
942
  _tf2 = self._es_taupf2
940
943
  for i in range(1, N + 1):
941
944
  a, h = _tf2(T)
942
- d = (taup - a) * (e + T**2) / (hypot1(a) * h)
943
945
  # = (taup - a) / hypot1(a) / ((e + T**2) / h)
946
+ d = _over((taup - a) * (T**2 + e), hypot1(a) * h)
944
947
  T, d = _F2_(d) # τi, (τi - τi-1)
945
948
  yield T, i, d
946
949
 
@@ -1085,8 +1088,9 @@ class Ellipsoid(_NamedEnumItem):
1085
1088
 
1086
1089
  @arg pov: Point-Of-View outside this ellipsoid (C{Cartesian}, L{Ecef9Tuple}
1087
1090
  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.
1091
+ @kwarg los: Line-Of-Sight, I{direction} to this ellipsoid (L{Los}, L{Vector3d})
1092
+ or C{True} for the I{normal, perpendicular, plumb} to the surface
1093
+ of this ellipsoid or C{False} or C{None} to point to its center.
1090
1094
 
1091
1095
  @return: L{Vector4Tuple}C{(x, y, z, h)} with the cartesian coordinates C{x},
1092
1096
  C{y} and C{z} of the projection on or the intersection with this
@@ -1095,8 +1099,7 @@ class Ellipsoid(_NamedEnumItem):
1095
1099
 
1096
1100
  @raise IntersectionError: Null B{C{pov}} or B{C{los}} vector, or B{C{pov}}
1097
1101
  is inside this ellipsoid or B{C{los}} points
1098
- outside this ellipsoid or points in an opposite
1099
- direction.
1102
+ outside this ellipsoid or in opposite direction.
1100
1103
 
1101
1104
  @raise TypeError: Invalid B{C{pov}} or B{C{los}}.
1102
1105
 
@@ -1105,10 +1108,10 @@ class Ellipsoid(_NamedEnumItem):
1105
1108
  methods L{Ellipsoid.height4} and L{Triaxial.hartzell4}.
1106
1109
  '''
1107
1110
  try:
1108
- v, d, _ = _MODS.triaxials._hartzell3(pov, los, self._triaxial)
1111
+ v, d, i = _MODS.triaxials._hartzell3(pov, los, self._triaxial)
1109
1112
  except Exception as x:
1110
1113
  raise IntersectionError(pov=pov, los=los, cause=x)
1111
- return Vector4Tuple(v.x, v.y, v.z, d, name__=self.hartzell4)
1114
+ return Vector4Tuple(v.x, v.y, v.z, d, iteration=i, name__=self.hartzell4)
1112
1115
 
1113
1116
  @Property_RO
1114
1117
  def _hash(self):
@@ -1164,10 +1167,10 @@ class Ellipsoid(_NamedEnumItem):
1164
1167
  h = t.minus(v).length
1165
1168
 
1166
1169
  else: # radial to ellipsoid's center
1167
- h = hypot_(a * v.z, b * v.x, b * v.y)
1170
+ h = hypot_(a * v.z, b * v.x, b * v.y)
1168
1171
  t = (a * b / h) if h > EPS0 else _0_0 # EPS
1169
- v = v.times(t)
1170
- h = r * (_1_0 - t)
1172
+ v = v.times(t)
1173
+ h = r * (_1_0 - t)
1171
1174
 
1172
1175
  return Vector4Tuple(v.x, v.y, v.z, h, iteration=i, name__=self.height4)
1173
1176
 
@@ -1238,7 +1241,7 @@ class Ellipsoid(_NamedEnumItem):
1238
1241
 
1239
1242
  @raise ValueError: Invalid B{C{order}}.
1240
1243
  '''
1241
- if not (isint(order) and order in (4, 6, 8)):
1244
+ if not (isint(order) and _isin(order, 4, 6, 8)):
1242
1245
  raise _ValueError(order=order)
1243
1246
  if self._KsOrder != order:
1244
1247
  Ellipsoid.AlphaKs._update(self)
@@ -1302,8 +1305,8 @@ class Ellipsoid(_NamedEnumItem):
1302
1305
  return degrees(self.m2radians(distance, lat=lat))
1303
1306
 
1304
1307
  def m2radians(self, distance, lat=0):
1305
- '''Convert a distance to an angle along the equator or
1306
- along a parallel of (geodetic) latitude.
1308
+ '''Convert a distance to an angle along the equator or along
1309
+ a parallel of (geodetic) latitude.
1307
1310
 
1308
1311
  @arg distance: Distance (C{meter}).
1309
1312
  @kwarg lat: Parallel latitude (C{degrees90}, C{str}).
@@ -1646,19 +1649,26 @@ class Ellipsoid(_NamedEnumItem):
1646
1649
  r = self.e2s2(sin(a))
1647
1650
  if r > EPS02:
1648
1651
  n = self.a / sqrt(r)
1649
- m = n * self.e21 / r
1652
+ m = n * self.e21 / r
1650
1653
  else:
1651
1654
  m = n = _0_0
1652
1655
  else:
1653
1656
  m = n = self.a
1654
1657
  if scaled and a:
1655
1658
  n *= cos(a) if a < PI_2 else _0_0
1656
- return Curvature2Tuple(Radius(rocMeridional=m),
1657
- Radius(rocPrimeVertical=n))
1659
+ return Curvature2Tuple(m, n)
1660
+
1661
+ def rocAzimuth(self, lat, azimuth):
1662
+ '''Compute the I{directional} radius of curvature of (geodetic) latitude
1663
+ and C{azimuth} compass direction.
1664
+
1665
+ @see: Method L{rocBearing<Ellipsoid.rocBearing>} for details, using C{azimuth} for C{bearing}.
1666
+ '''
1667
+ return Radius(rocAzimuth=self._rocDirectional(lat, Azimuth(azimuth)))
1658
1668
 
1659
1669
  def rocBearing(self, lat, bearing):
1660
- '''Compute the I{directional} radius of curvature of (geodetic)
1661
- latitude and compass direction.
1670
+ '''Compute the I{directional} radius of curvature of (geodetic) latitude
1671
+ and C{bearing} compass direction.
1662
1672
 
1663
1673
  @arg lat: Latitude (C{degrees90}).
1664
1674
  @arg bearing: Direction (compass C{degrees360}).
@@ -1672,18 +1682,23 @@ class Ellipsoid(_NamedEnumItem):
1672
1682
 
1673
1683
  @see: U{Radii of Curvature<https://WikiPedia.org/wiki/Earth_radius#Radii_of_curvature>}
1674
1684
  '''
1685
+ return Radius(rocBearing=self._rocDirectional(lat, Bearing(bearing)))
1686
+
1687
+ def _rocDirectional(self, lat, deg):
1688
+ '''(INTERNAL) Helper for C{rocAzimuth} and C{rocBearing}.
1689
+ '''
1675
1690
  if self.f:
1676
- s2, c2 = _s2_c2(Bearing_(bearing))
1691
+ s2, c2 = _s2_c2(radians(deg))
1677
1692
  m, n = self.roc2_(Phid(lat))
1678
1693
  if n < m: # == n / (c2 * n / m + s2)
1679
1694
  c2 *= n / m
1680
1695
  elif m < n: # == m / (c2 + s2 * m / n)
1681
1696
  s2 *= m / n
1682
- n = m
1683
- b = n / (c2 + s2) # == 1 / (c2 / m + s2 / n)
1697
+ n = m
1698
+ r = _over(n, c2 + s2) # == 1 / (c2 / m + s2 / n)
1684
1699
  else:
1685
- b = self.b # == self.a
1686
- return Radius(rocBearing=b)
1700
+ r = self.b # == self.a
1701
+ return r
1687
1702
 
1688
1703
  @Property_RO
1689
1704
  def rocEquatorial2(self):
@@ -1694,8 +1709,8 @@ class Ellipsoid(_NamedEnumItem):
1694
1709
  L{a2_b}, C{rocPolar} and polar and equatorial U{Radii of Curvature
1695
1710
  <https://WikiPedia.org/wiki/Earth_radius#Radii_of_curvature>}.
1696
1711
  '''
1697
- return Curvature2Tuple(Radius(rocMeridional0=self.b2_a if self.f else self.a),
1698
- Radius(rocPrimeVertical0=self.a))
1712
+ m = self.b2_a if self.f else self.a
1713
+ return Curvature2Tuple(m, self.a)
1699
1714
 
1700
1715
  def rocGauss(self, lat):
1701
1716
  '''Compute the I{Gaussian} radius of curvature of (geodetic) latitude.
@@ -1716,7 +1731,7 @@ class Ellipsoid(_NamedEnumItem):
1716
1731
  g = self.b
1717
1732
  if self.f:
1718
1733
  s2, c2 = _s2_c2(Phid(lat))
1719
- g = g / (c2 + self.b2_a2 * s2)
1734
+ g = _over(g, c2 + self.b2_a2 * s2)
1720
1735
  return Radius(rocGauss=g)
1721
1736
 
1722
1737
  def rocMean(self, lat):
@@ -1733,9 +1748,9 @@ class Ellipsoid(_NamedEnumItem):
1733
1748
  '''
1734
1749
  if self.f:
1735
1750
  m, n = self.roc2_(Phid(lat))
1736
- m *= n * _2_0 / (m + n) # == 2 / (1 / m + 1 / n)
1751
+ m *= _over(n * _2_0, m + n) # == 2 / (1 / m + 1 / n)
1737
1752
  else:
1738
- m = self.a
1753
+ m = self.a
1739
1754
  return Radius(rocMean=m)
1740
1755
 
1741
1756
  def rocMeridional(self, lat):
@@ -1751,8 +1766,8 @@ class Ellipsoid(_NamedEnumItem):
1751
1766
  <https://www.EdWilliams.org/avform.htm#flat>} and U{Radii of
1752
1767
  Curvature<https://WikiPedia.org/wiki/Earth_radius#Radii_of_curvature>}.
1753
1768
  '''
1754
- return self.roc2_(Phid(lat)).meridional if lat else \
1755
- self.rocEquatorial2.meridional
1769
+ r = self.roc2_(Phid(lat)) if lat else self.rocEquatorial2
1770
+ return Radius(rocMeridional=r.meridional)
1756
1771
 
1757
1772
  rocPolar = a2_b # synonymous
1758
1773
 
@@ -1771,8 +1786,8 @@ class Ellipsoid(_NamedEnumItem):
1771
1786
  U{Radii of Curvature<https://WikiPedia.org/wiki/
1772
1787
  Earth_radius#Radii_of_curvature>}.
1773
1788
  '''
1774
- return self.roc2_(Phid(lat)).prime_vertical if lat else \
1775
- self.rocEquatorial2.prime_vertical
1789
+ r = self.roc2_(Phid(lat)) if lat else self.rocEquatorial2
1790
+ return Radius(rocPrimeVertical=r.prime_vertical)
1776
1791
 
1777
1792
  rocTransverse = rocPrimeVertical # synonymous
1778
1793
 
@@ -1792,7 +1807,9 @@ class Ellipsoid(_NamedEnumItem):
1792
1807
 
1793
1808
  @see: U{Earth radius<https://WikiPedia.org/wiki/Earth_radius>}.
1794
1809
  '''
1795
- r = (cbrt2((_1_0 + sqrt3(self.b_a)) * _0_5) * self.a) if self.f else self.a
1810
+ r = self.a
1811
+ if self.f:
1812
+ r *= cbrt2((sqrt3(self.b_a) + _1_0) * _0_5)
1796
1813
  return Radius(Rrectifying=r)
1797
1814
 
1798
1815
  @deprecated_Property_RO
@@ -1806,9 +1823,11 @@ class Ellipsoid(_NamedEnumItem):
1806
1823
 
1807
1824
  @see: C{Rbiaxial}
1808
1825
  '''
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)
1826
+ q, b = self.a, self.b
1827
+ if b < q:
1828
+ q *= sqrt((self.b2_a2 + _3_0) * _0_25)
1829
+ elif b > q:
1830
+ q = sqrt((self.a2_b2 * _3_0 + _1_0) * _0_25) * b
1812
1831
  return Radius(Rtriaxial=q)
1813
1832
 
1814
1833
  def toEllipsoid2(self, **name):
@@ -1897,22 +1916,23 @@ class Ellipsoid2(Ellipsoid):
1897
1916
  Ellipsoid.__init__(self, a, f=f, **name)
1898
1917
 
1899
1918
 
1900
- def _spherical_a_b(a, b):
1919
+ def _ispherical_a_b(a, b):
1901
1920
  '''(INTERNAL) C{True} for spherical or invalid C{a} or C{b}.
1902
1921
  '''
1903
1922
  return a < EPS0 or b < EPS0 or fabs(a - b) < EPS0
1904
1923
 
1905
1924
 
1906
- def _spherical_f(f):
1925
+ def _ispherical_f(f):
1907
1926
  '''(INTERNAL) C{True} for spherical or invalid C{f}.
1908
1927
  '''
1909
- return fabs(f) < EPS or f > EPS1
1928
+ return f > EPS1 or fabs(f) < EPS
1910
1929
 
1911
1930
 
1912
- def _spherical_f_(f_):
1931
+ def _ispherical_f_(f_):
1913
1932
  '''(INTERNAL) C{True} for spherical or invalid C{f_}.
1914
1933
  '''
1915
- return fabs(f_) < EPS or fabs(f_) > _1_EPS
1934
+ f_ = fabs(f_)
1935
+ return f_ < EPS or f_ > _1_EPS
1916
1936
 
1917
1937
 
1918
1938
  def a_b2e(a, b):
@@ -1921,12 +1941,12 @@ def a_b2e(a, b):
1921
1941
  @arg a: Equatorial radius (C{scalar} > 0).
1922
1942
  @arg b: Polar radius (C{scalar} > 0).
1923
1943
 
1924
- @return: The I{unsigned}, (1st) eccentricity (C{float} or C{0}),
1925
- M{sqrt(1 - (b / a)**2)}.
1944
+ @return: The I{unsigned}, (1st) eccentricity (C{float} or C{0}), M{sqrt(1 - (b / a)**2)}.
1926
1945
 
1927
1946
  @note: The result is always I{non-negative} and C{0} for I{near-spherical} ellipsoids.
1928
1947
  '''
1929
- return Float(e=sqrt(fabs(a_b2e2(a, b)))) # == sqrt(fabs(a - b) * (a + b)) / a)
1948
+ e2 = _a2b2e2(a, b, b2=False)
1949
+ return Float(e=sqrt(fabs(e2)) if e2 else _0_0) # == sqrt(fabs((a - b) * (a + b))) / a
1930
1950
 
1931
1951
 
1932
1952
  def a_b2e2(a, b):
@@ -1935,13 +1955,12 @@ def a_b2e2(a, b):
1935
1955
  @arg a: Equatorial radius (C{scalar} > 0).
1936
1956
  @arg b: Polar radius (C{scalar} > 0).
1937
1957
 
1938
- @return: The I{signed}, (1st) eccentricity I{squared} (C{float} or C{0}),
1939
- M{1 - (b / a)**2}.
1958
+ @return: The I{signed}, (1st) eccentricity I{squared} (C{float} or C{0}), M{1 - (b / a)**2}.
1940
1959
 
1941
- @note: The result is positive for I{oblate}, negative for I{prolate}
1942
- or C{0} for I{near-spherical} ellipsoids.
1960
+ @note: The result is positive for I{oblate}, negative for I{prolate} or C{0}
1961
+ for I{near-spherical} ellipsoids.
1943
1962
  '''
1944
- return Float(e2=_0_0 if _spherical_a_b(a, b) else ((a - b) * (a + b) / a**2))
1963
+ return Float(e2=_a2b2e2(a, b, b2=False))
1945
1964
 
1946
1965
 
1947
1966
  def a_b2e22(a, b):
@@ -1950,13 +1969,12 @@ def a_b2e22(a, b):
1950
1969
  @arg a: Equatorial radius (C{scalar} > 0).
1951
1970
  @arg b: Polar radius (C{scalar} > 0).
1952
1971
 
1953
- @return: The I{signed}, 2nd eccentricity I{squared} (C{float} or C{0}),
1954
- M{(a / b)**2 - 1}.
1972
+ @return: The I{signed}, 2nd eccentricity I{squared} (C{float} or C{0}), M{(a / b)**2 - 1}.
1955
1973
 
1956
- @note: The result is positive for I{oblate}, negative for I{prolate}
1957
- or C{0} for I{near-spherical} ellipsoids.
1974
+ @note: The result is positive for I{oblate}, negative for I{prolate} or C{0}
1975
+ for I{near-spherical} ellipsoids.
1958
1976
  '''
1959
- return Float(e22=_0_0 if _spherical_a_b(a, b) else ((a - b) * (a + b) / b**2))
1977
+ return Float(e22=_a2b2e2(a, b, a2=False))
1960
1978
 
1961
1979
 
1962
1980
  def a_b2e32(a, b):
@@ -1968,11 +1986,23 @@ def a_b2e32(a, b):
1968
1986
  @return: The I{signed}, 3rd eccentricity I{squared} (C{float} or C{0}),
1969
1987
  M{(a**2 - b**2) / (a**2 + b**2)}.
1970
1988
 
1971
- @note: The result is positive for I{oblate}, negative for I{prolate}
1972
- or C{0} for I{near-spherical} ellipsoids.
1989
+ @note: The result is positive for I{oblate}, negative for I{prolate} or C{0}
1990
+ for I{near-spherical} ellipsoids.
1991
+ '''
1992
+ return Float(e32=_a2b2e2(a, b))
1993
+
1994
+
1995
+ def _a2b2e2(a, b, a2=True, b2=True):
1996
+ '''(INTERNAL) Helper for C{a_b2e}, C{a_b2e2}, C{a_b2e22} and C{a_b2e32}.
1973
1997
  '''
1974
- a2, b2 = a**2, b**2
1975
- return Float(e32=_0_0 if _spherical_a_b(a2, b2) else ((a2 - b2) / (a2 + b2)))
1998
+ if _ispherical_a_b(a, b):
1999
+ e2 = _0_0
2000
+ else: # a > 0, b > 0
2001
+ a, b = (_1_0, b / a) if a > b else (a / b, _1_0)
2002
+ a2b2 = float(a - b) * (a + b)
2003
+ e2 = _over(a2b2, (a**2 if a2 else _0_0) +
2004
+ (b**2 if b2 else _0_0)) if a2b2 else _0_0
2005
+ return e2
1976
2006
 
1977
2007
 
1978
2008
  def a_b2f(a, b):
@@ -1986,8 +2016,8 @@ def a_b2f(a, b):
1986
2016
  @note: The result is positive for I{oblate}, negative for I{prolate} or C{0}
1987
2017
  for I{near-spherical} ellipsoids.
1988
2018
  '''
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)
2019
+ f = 0 if _ispherical_a_b(a, b) else _over(float(a - b), a)
2020
+ return _f_0_0 if _ispherical_f(f) else Float(f=f)
1991
2021
 
1992
2022
 
1993
2023
  def a_b2f_(a, b):
@@ -2001,8 +2031,8 @@ def a_b2f_(a, b):
2001
2031
  @note: The result is positive for I{oblate}, negative for I{prolate} or C{0}
2002
2032
  for I{near-spherical} ellipsoids.
2003
2033
  '''
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_)
2034
+ f_ = 0 if _ispherical_a_b(a, b) else _over(a, float(a - b))
2035
+ return _f__0_0 if _ispherical_f_(f_) else Float(f_=f_)
2006
2036
 
2007
2037
 
2008
2038
  def a_b2f2(a, b):
@@ -2016,8 +2046,8 @@ def a_b2f2(a, b):
2016
2046
  @note: The result is positive for I{oblate}, negative for I{prolate} or C{0}
2017
2047
  for I{near-spherical} ellipsoids.
2018
2048
  '''
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))
2049
+ t = 0 if _ispherical_a_b(a, b) else float(a - b)
2050
+ return Float(f2=_0_0 if fabs(t) < EPS0 else _over(t, b))
2021
2051
 
2022
2052
 
2023
2053
  def a_b2n(a, b):
@@ -2028,11 +2058,11 @@ def a_b2n(a, b):
2028
2058
 
2029
2059
  @return: The I{signed}, 3rd flattening (C{scalar} or C{0}), M{(a - b) / (a + b)}.
2030
2060
 
2031
- @note: The result is positive for I{oblate}, negative for I{prolate}
2032
- or C{0} for I{near-spherical} ellipsoids.
2061
+ @note: The result is positive for I{oblate}, negative for I{prolate} or C{0}
2062
+ for I{near-spherical} ellipsoids.
2033
2063
  '''
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)))
2064
+ t = 0 if _ispherical_a_b(a, b) else float(a - b)
2065
+ return Float(n=_0_0 if fabs(t) < EPS0 else _over(t, a + b))
2036
2066
 
2037
2067
 
2038
2068
  def a_f2b(a, f):
@@ -2043,8 +2073,8 @@ def a_f2b(a, f):
2043
2073
 
2044
2074
  @return: The polar radius (C{float}), M{a * (1 - f)}.
2045
2075
  '''
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)
2076
+ b = a if _ispherical_f(f) else (a * (_1_0 - f))
2077
+ return Radius_(b=a if _ispherical_a_b(a, b) else b)
2048
2078
 
2049
2079
 
2050
2080
  def a_f_2b(a, f_):
@@ -2055,8 +2085,8 @@ def a_f_2b(a, f_):
2055
2085
 
2056
2086
  @return: The polar radius (C{float}), M{a * (f_ - 1) / f_}.
2057
2087
  '''
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)
2088
+ b = a if _ispherical_f_(f_) else _over(a * (f_ - _1_0), f_)
2089
+ return Radius_(b=a if _ispherical_a_b(a, b) else b)
2060
2090
 
2061
2091
 
2062
2092
  def b_f2a(b, f):
@@ -2068,8 +2098,8 @@ def b_f2a(b, f):
2068
2098
  @return: The equatorial radius (C{float}), M{b / (1 - f)}.
2069
2099
  '''
2070
2100
  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)
2101
+ a = b if fabs(t) < EPS0 else _over(b, t)
2102
+ return Radius_(a=b if _ispherical_a_b(a, b) else a)
2073
2103
 
2074
2104
 
2075
2105
  def b_f_2a(b, f_):
@@ -2081,9 +2111,9 @@ def b_f_2a(b, f_):
2081
2111
  @return: The equatorial radius (C{float}), M{b * f_ / (f_ - 1)}.
2082
2112
  '''
2083
2113
  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)
2114
+ a = b if _ispherical_f_(f_) or fabs(t) < EPS0 \
2115
+ or fabs(t - f_) < EPS0 else _over(b * f_, t)
2116
+ return Radius_(a=b if _ispherical_a_b(a, b) else a)
2087
2117
 
2088
2118
 
2089
2119
  def e2f(e):
@@ -2103,9 +2133,9 @@ def e22f(e2):
2103
2133
 
2104
2134
  @arg e2: The (1st) eccentricity I{squared}, I{signed} (L{NINF} < C{float} < 1)
2105
2135
 
2106
- @return: The flattening (C{float} or C{0}), M{e2 / (sqrt(e2 - 1) + 1)}.
2136
+ @return: The flattening (C{float} or C{0}), M{e2 / (sqrt(1 - e2) + 1)}.
2107
2137
  '''
2108
- return Float(f=e2 / (sqrt(_1_0 - e2) + _1_0)) if e2 else _f_0_0
2138
+ return Float(f=_over(e2, sqrt(_1_0 - e2) + _1_0)) if e2 and e2 < _1_0 else _f_0_0
2109
2139
 
2110
2140
 
2111
2141
  def f2e2(f):
@@ -2113,17 +2143,16 @@ def f2e2(f):
2113
2143
 
2114
2144
  @arg f: Flattening (C{scalar} < 1, negative for I{prolate}).
2115
2145
 
2116
- @return: The I{signed}, (1st) eccentricity I{squared} (C{float} < 1),
2117
- M{f * (2 - f)}.
2146
+ @return: The I{signed}, (1st) eccentricity I{squared} (C{float} < 1), M{f * (2 - f)}.
2118
2147
 
2119
- @note: The result is positive for I{oblate}, negative for I{prolate}
2120
- or C{0} for I{near-spherical} ellipsoids.
2148
+ @note: The result is positive for I{oblate}, negative for I{prolate} or C{0}
2149
+ for I{near-spherical} ellipsoids.
2121
2150
 
2122
2151
  @see: U{Eccentricity conversions<https://GeographicLib.SourceForge.io/
2123
2152
  C++/doc/classGeographicLib_1_1Ellipsoid.html>} and U{Flattening
2124
2153
  <https://WikiPedia.org/wiki/Flattening>}.
2125
2154
  '''
2126
- return Float(e2=_0_0 if _spherical_f(f) else (f * (_2_0 - f)))
2155
+ return Float(e2=_0_0 if _ispherical_f(f) else (f * (_2_0 - f)))
2127
2156
 
2128
2157
 
2129
2158
  def f2e22(f):
@@ -2131,18 +2160,18 @@ def f2e22(f):
2131
2160
 
2132
2161
  @arg f: Flattening (C{scalar} < 1, negative for I{prolate}).
2133
2162
 
2134
- @return: The I{signed}, 2nd eccentricity I{squared} (C{float} > -1 or
2135
- C{INF}), M{f * (2 - f) / (1 - f)**2}.
2163
+ @return: The I{signed}, 2nd eccentricity I{squared} (C{float} > -1 or C{INF}),
2164
+ M{f * (2 - f) / (1 - f)**2}.
2136
2165
 
2137
- @note: The result is positive for I{oblate}, negative for I{prolate}
2138
- or C{0} for near-spherical ellipsoids.
2166
+ @note: The result is positive for I{oblate}, negative for I{prolate} or C{0}
2167
+ for near-spherical ellipsoids.
2139
2168
 
2140
2169
  @see: U{Eccentricity conversions<https://GeographicLib.SourceForge.io/
2141
2170
  C++/doc/classGeographicLib_1_1Ellipsoid.html>}.
2142
2171
  '''
2143
2172
  # e2 / (1 - e2) == f * (2 - f) / (1 - f)**2
2144
2173
  t = (_1_0 - f)**2
2145
- return Float(e22=INF if t < EPS0 else (f2e2(f) / t)) # PYCHOK type
2174
+ return Float(e22=INF if t < EPS0 else _over(f2e2(f), t)) # PYCHOK type
2146
2175
 
2147
2176
 
2148
2177
  def f2e32(f):
@@ -2153,15 +2182,15 @@ def f2e32(f):
2153
2182
  @return: The I{signed}, 3rd eccentricity I{squared} (C{float}),
2154
2183
  M{f * (2 - f) / (1 + (1 - f)**2)}.
2155
2184
 
2156
- @note: The result is positive for I{oblate}, negative for I{prolate}
2157
- or C{0} for I{near-spherical} ellipsoids.
2185
+ @note: The result is positive for I{oblate}, negative for I{prolate} or C{0}
2186
+ for I{near-spherical} ellipsoids.
2158
2187
 
2159
2188
  @see: U{Eccentricity conversions<https://GeographicLib.SourceForge.io/
2160
2189
  C++/doc/classGeographicLib_1_1Ellipsoid.html>}.
2161
2190
  '''
2162
2191
  # e2 / (2 - e2) == f * (2 - f) / (1 + (1 - f)**2)
2163
2192
  e2 = f2e2(f)
2164
- return Float(e32=e2 / (_2_0 - e2))
2193
+ return Float(e32=_over(e2, _2_0 - e2))
2165
2194
 
2166
2195
 
2167
2196
  def f_2f(f_):
@@ -2171,11 +2200,11 @@ def f_2f(f_):
2171
2200
 
2172
2201
  @return: The flattening (C{scalar} or C{0}), M{1 / f_}.
2173
2202
 
2174
- @note: The result is positive for I{oblate}, negative for I{prolate}
2175
- or C{0} for I{near-spherical} ellipsoids.
2203
+ @note: The result is positive for I{oblate}, negative for I{prolate} or C{0}
2204
+ for I{near-spherical} ellipsoids.
2176
2205
  '''
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
2206
+ f = 0 if _ispherical_f_(f_) else _over(_1_0, f_)
2207
+ return _f_0_0 if _ispherical_f(f) else Float(f=f) # PYCHOK type
2179
2208
 
2180
2209
 
2181
2210
  def f2f_(f):
@@ -2185,11 +2214,11 @@ def f2f_(f):
2185
2214
 
2186
2215
  @return: The inverse flattening (C{scalar} or C{0}), M{1 / f}.
2187
2216
 
2188
- @note: The result is positive for I{oblate}, negative for I{prolate}
2189
- or C{0} for I{near-spherical} ellipsoids.
2217
+ @note: The result is positive for I{oblate}, negative for I{prolate} or C{0}
2218
+ for I{near-spherical} ellipsoids.
2190
2219
  '''
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
2220
+ f_ = 0 if _ispherical_f(f) else _over(_1_0, f)
2221
+ return _f__0_0 if _ispherical_f_(f_) else Float(f_=f_) # PYCHOK type
2193
2222
 
2194
2223
 
2195
2224
  def f2f2(f):
@@ -2199,16 +2228,16 @@ def f2f2(f):
2199
2228
 
2200
2229
  @return: The I{signed}, 2nd flattening (C{scalar} or C{INF}), M{f / (1 - f)}.
2201
2230
 
2202
- @note: The result is positive for I{oblate}, negative for I{prolate}
2203
- or C{0} for I{near-spherical} ellipsoids.
2231
+ @note: The result is positive for I{oblate}, negative for I{prolate} or C{0}
2232
+ for I{near-spherical} ellipsoids.
2204
2233
 
2205
2234
  @see: U{Eccentricity conversions<https://GeographicLib.SourceForge.io/
2206
2235
  C++/doc/classGeographicLib_1_1Ellipsoid.html>} and U{Flattening
2207
2236
  <https://WikiPedia.org/wiki/Flattening>}.
2208
2237
  '''
2209
2238
  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
2239
+ return Float(f2=_0_0 if _ispherical_f(f) else
2240
+ (INF if fabs(t) < EPS else _over(f, t))) # PYCHOK type
2212
2241
 
2213
2242
 
2214
2243
  def f2n(f):
@@ -2219,14 +2248,14 @@ def f2n(f):
2219
2248
  @return: The I{signed}, 3rd flattening (-1 <= C{float} < 1),
2220
2249
  M{f / (2 - f)}.
2221
2250
 
2222
- @note: The result is positive for I{oblate}, negative for I{prolate}
2223
- or C{0} for I{near-spherical} ellipsoids.
2251
+ @note: The result is positive for I{oblate}, negative for I{prolate} or C{0}
2252
+ for I{near-spherical} ellipsoids.
2224
2253
 
2225
2254
  @see: U{Eccentricity conversions<https://GeographicLib.SourceForge.io/
2226
2255
  C++/doc/classGeographicLib_1_1Ellipsoid.html>} and U{Flattening
2227
2256
  <https://WikiPedia.org/wiki/Flattening>}.
2228
2257
  '''
2229
- return Float(n=_0_0 if _spherical_f(f) else (f / float(_2_0 - f)))
2258
+ return Float(n=_0_0 if _ispherical_f(f) else _over(f, float(_2_0 - f)))
2230
2259
 
2231
2260
 
2232
2261
  def n2e2(n):
@@ -2237,14 +2266,14 @@ def n2e2(n):
2237
2266
  @return: The I{signed}, (1st) eccentricity I{squared} (C{float} or NINF),
2238
2267
  M{4 * n / (1 + n)**2}.
2239
2268
 
2240
- @note: The result is positive for I{oblate}, negative for I{prolate}
2241
- or C{0} for I{near-spherical} ellipsoids.
2269
+ @note: The result is positive for I{oblate}, negative for I{prolate} or C{0}
2270
+ for I{near-spherical} ellipsoids.
2242
2271
 
2243
2272
  @see: U{Flattening<https://WikiPedia.org/wiki/Flattening>}.
2244
2273
  '''
2245
2274
  t = (n + _1_0)**2
2246
2275
  return Float(e2=_0_0 if fabs(n) < EPS0 else
2247
- (NINF if t < EPS0 else (_4_0 * n / t)))
2276
+ (NINF if t < EPS0 else _over(_4_0 * n, t)))
2248
2277
 
2249
2278
 
2250
2279
  def n2f(n):
@@ -2259,8 +2288,8 @@ def n2f(n):
2259
2288
  <https://WikiPedia.org/wiki/Flattening>}.
2260
2289
  '''
2261
2290
  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)
2291
+ f = 0 if fabs(n) < EPS0 else (NINF if t < EPS0 else _over(_2_0 * n, t))
2292
+ return _f_0_0 if _ispherical_f(f) else Float(f=f)
2264
2293
 
2265
2294
 
2266
2295
  def n2f_(n):
@@ -2369,7 +2398,7 @@ Ellipsoids._assert( # <https://WikiPedia.org/wiki/Earth_ellipsoid>
2369
2398
 
2370
2399
  _EWGS84 = Ellipsoids.WGS84 # (INTERNAL) shared
2371
2400
 
2372
- if __name__ == '__main__':
2401
+ if __name__ == _DMAIN_:
2373
2402
 
2374
2403
  from pygeodesy.interns import _COMMA_, _NL_, _NLATvar_
2375
2404
  from pygeodesy import nameof, printf
@@ -2392,7 +2421,7 @@ if __name__ == '__main__':
2392
2421
  t = [NN] + Ellipsoids.toRepr(all=True, asorted=True).split(_NL_)
2393
2422
  printf(_NLATvar_.join(i.strip(_COMMA_) for i in t))
2394
2423
 
2395
- # % python3 -m pygeodesy.ellipsoids
2424
+ # % python3.13 -m pygeodesy.ellipsoids
2396
2425
 
2397
2426
  # 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
2427
  # e=8.1819190842622e-02, f_=2.98257223563e+02, f=3.3528106647475e-03, n=1.6792203863837e-03 (0.0e+00)
@@ -2418,7 +2447,7 @@ if __name__ == '__main__':
2418
2447
  # BetaKs 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
2419
2448
  # KsOrder 8
2420
2449
 
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
2450
+ # 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
2451
  # e=8.2094437949696e-02, f_=-2.97257223563e+02, f=-3.3640898209765e-03, n=-1.6792203863837e-03 (0.0e+00)
2423
2452
  # AlphaKs -0.00084149152514366627, 0.00000076653480614871, -0.00000000120934503389, 0.0000000000024576225, -0.00000000000000578863, 0.00000000000000001502, -0.00000000000000000004, 0.0
2424
2453
  # BetaKs -0.00084149187224351817, 0.00000005842735196773, -0.0000000001680487236, 0.00000000000021706261, -0.00000000000000038002, 0.00000000000000000073, -0.0, 0.0