pygeodesy 25.12.12__py2.py3-none-any.whl → 26.1.16__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.
pygeodesy/__init__.py CHANGED
@@ -8,8 +8,8 @@ geodetic (lat-/longitude), geocentric (U{ECEF<https://WikiPedia.org/wiki/ECEF>}
8
8
  <https://GeographicLib.SourceForge.io/1.44/triaxial.html>} coordinates.
9
9
 
10
10
  Transcoded in part from U{JavaScript originals<https://GitHub.com/ChrisVeness/geodesy>} by I{Chris Veness (C)
11
- 2005-2024} and from several U{C++ classes<https://GeographicLib.SourceForge.io/C++/doc/annotated.html>} by I{Charles
12
- F. F. Karney (C) 2008-2024} and published under the same U{MIT License<https://OpenSource.org/licenses/MIT>}**.
11
+ 2005-2025} and from several U{C++ classes<https://GeographicLib.SourceForge.io/C++/doc/annotated.html>} by I{Charles
12
+ F. F. Karney (C) 2008-2025} and published under the same U{MIT License<https://OpenSource.org/licenses/MIT>}**.
13
13
 
14
14
  There are four modules for ellipsoidal earth models, C{ellipsoidalExact}, C{-Karney}, C{-Vincenty} and C{-Nvector}
15
15
  and two for spherical ones, C{sphericalTrigonometry} and C{-Nvector}. Each module provides a geodetic B{C{LatLon}}
@@ -101,9 +101,15 @@ and L{GnomonicGeodSolve} depend on I{Karney}'s C++ utility U{GeodSolve
101
101
  <https://GeographicLib.SourceForge.io/C++/doc/GeodSolve.1.html>} to be executable and set with
102
102
  env variable C{PYGEODESY_GEODSOLVE} or with property L{Ellipsoid.geodsolve}.
103
103
 
104
+ Triaxial geodesic classes L{Geodesic3Solve} and L{GeodesicLine3Solve} in module L{geod3solve} need
105
+ I{Karney}'s C++ utility U{Geod3Solve<https://GeographicLib.SourceForge.io/C++/doc/Geod3Solve.1.html>}
106
+ to be executable and set with env variable C{PYGEODESY_GEOD3SOLVE} or with property
107
+ L{Geodesic3Solve.Geod3Solve<geod3solve._Geodesic3SolveBase.Geod3Solve>}.
108
+
104
109
  Class L{Intersectool} in module L{geodesici} needs I{Karney}'s C++ utility U{IntersectTool
105
110
  <https://GeographicLib.SourceForge.io/C++/doc/IntersectTool.1.html>} to be executable and set with
106
- env variable C{PYGEODESY_INTERSECTTOOL}.
111
+ env variable C{PYGEODESY_INTERSECTTOOL} or with property L{Intersectool.IntersectTool
112
+ <geodesici.Intersectool.IntersectTool>}.
107
113
 
108
114
  To compare C{MGRS} results from modules L{mgrs} and C{testMgrs} with I{Karney}'s C++ utility
109
115
  U{GeoConvert<https://GeographicLib.SourceForge.io/C++/doc/GeoConvert.1.html>}, the latter must
@@ -126,38 +132,40 @@ Tests
126
132
  =====
127
133
 
128
134
  The tests ran with Python 3.14.2 (with U{geographiclib<https://PyPI.org/project/geographiclib>} 2.1),
129
- Python 3.13.9 (with U{geographiclib<https://PyPI.org/project/geographiclib>} 2.1),
135
+ Python 3.13.11 (with U{geographiclib<https://PyPI.org/project/geographiclib>} 2.1),
130
136
  U{numpy<https://PyPI.org/project/numpy>} 2.3.3, U{scipy<https://PyPI.org/project/scipy>} 1.16.2,
131
- U{GeoConvert<https://GeographicLib.SourceForge.io/C++/doc/utilities.html>} 2.5 and
132
- U{GeodSolve<https://GeographicLib.SourceForge.io/C++/doc/utilities.html>} 2.5),
133
- Python 3.12.7 (with U{geographiclib<https://PyPI.org/project/geographiclib>} 2.0,
137
+ U{GeoConvert<https://GeographicLib.SourceForge.io/C++/doc/utilities.html>} 2.7 and
138
+ U{GeodSolve<https://GeographicLib.SourceForge.io/C++/doc/utilities.html>} 2.7),
139
+ Python 3.12.10 (with U{geographiclib<https://PyPI.org/project/geographiclib>} 2.0,
134
140
  U{numpy<https://PyPI.org/project/numpy>} 2.1.0, U{scipy<https://PyPI.org/project/scipy>} 1.14.1,
135
- U{GeodSolve<https://GeographicLib.SourceForge.io/C++/doc/utilities.html>} 2.5,
136
- U{IntersectTool<https://GeographicLib.SourceForge.io/C++/doc/utilities.html>} 2.5 and
137
- U{RhumbSolve<https://GeographicLib.SourceForge.io/C++/doc/utilities.html>} 2.5),
138
- Python 3.11.5 (with U{geographiclib<https://PyPI.org/project/geographiclib>} 2.0,
141
+ U{GeodSolve<https://GeographicLib.SourceForge.io/C++/doc/utilities.html>} 2.7,
142
+ U{GeodS3olve<https://GeographicLib.SourceForge.io/C++/doc/utilities.html>} 2.7,
143
+ U{IntersectTool<https://GeographicLib.SourceForge.io/C++/doc/utilities.html>} 2.7 and
144
+ U{RhumbSolve<https://GeographicLib.SourceForge.io/C++/doc/utilities.html>} 2.7),
145
+ Python 3.11.9 (with U{geographiclib<https://PyPI.org/project/geographiclib>} 2.0,
139
146
  U{numpy<https://PyPI.org/project/numpy>} 1.24.2 and U{scipy<https://PyPI.org/project/scipy>} 1.10.1),
140
147
  and with Python 2.7.18 (with U{geographiclib<https://PyPI.org/project/geographiclib>} 1.50,
141
148
  U{numpy<https://PyPI.org/project/numpy>} 1.16.6, U{scipy<https://PyPI.org/project/scipy>} 1.2.2,
142
- U{GeoConvert<https://GeographicLib.SourceForge.io/C++/doc/utilities.html>} 2.5,
143
- U{GeodSolve<https://GeographicLib.SourceForge.io/C++/doc/utilities.html>} 2.5,
144
- U{IntersectTool<https://GeographicLib.SourceForge.io/C++/doc/utilities.html>} 2.5 and
145
- U{RhumbSolve<https://GeographicLib.SourceForge.io/C++/doc/utilities.html>} 2.5), all in 64-bit on
146
- macOS 26.1 Tahoe.
149
+ U{GeoConvert<https://GeographicLib.SourceForge.io/C++/doc/utilities.html>} 2.7,
150
+ U{GeodSolve<https://GeographicLib.SourceForge.io/C++/doc/utilities.html>} 2.7,
151
+ U{Geod3Solve<https://GeographicLib.SourceForge.io/C++/doc/utilities.html>} 2.7,
152
+ U{IntersectTool<https://GeographicLib.SourceForge.io/C++/doc/utilities.html>} 2.7 and
153
+ U{RhumbSolve<https://GeographicLib.SourceForge.io/C++/doc/utilities.html>} 2.7), all in 64-bit on
154
+ macOS 26.2 Tahoe.
147
155
 
148
156
  All tests ran with and without C{lazy import} for Python 3 and with command line option C{-W default} and
149
157
  env variable C{PYGEODESY_WARNINGS=on} for all Python versions. The results of those tests are included in
150
158
  the distribution files.
151
159
 
152
160
  Test coverage has been measured with U{coverage<https://PyPI.org/project/coverage>} 7.10.7 using Python
153
- 3.14.2, 3.13.9 and 3.12.7. The complete coverage report in HTML and a PDF summary are included in the
161
+ 3.14.2, 3.13.11 and 3.12.10. The complete coverage report in HTML and a PDF summary are included in the
154
162
  distribution files.
155
163
 
156
- Python 3.14.2, 3.13.9, 3.12.7 and 3.11.5 run on Apple M4 Si (C{arm64}), I{natively}. Python 2.7.18 runs
164
+ Python 3.14.2, 3.13.11, 3.12.10 and 3.11.9 run on Apple Si M4 (C{arm64}), I{natively}. Python 2.7.18 runs
157
165
  on Intel (C{x86_64}) or Intel I{emulation} ("C{arm64_x86_64}", see function L{machine<pygeodesy.machine>}).
158
166
 
159
- The tests also ran with Python 3.13.9 (and U{geographiclib<https://PyPI.org/project/geographiclib>} 2.1) on
160
- U{Debian 12<https://Cirrus-CI.com/github/mrJean1/PyGeodesy/master>} in 64-bit only, with Python 3.12.8 (and
167
+ The tests also ran with Python 3.14.2 (and U{geographiclib<https://PyPI.org/project/geographiclib>} 2.1) on
168
+ U{Debian 12<https://Cirrus-CI.com/github/mrJean1/PyGeodesy/master>} in 64-bit only, with Python 3.13.11 (and
161
169
  U{geographiclib<https://PyPI.org/project/geographiclib>} 2.0) on U{Windows 2019Server
162
170
  <https://CI.AppVeyor.com/project/mrJean1/pygeodesy>} in 64-bit only and with Python 2.7.18 (and U{geographiclib
163
171
  <https://PyPI.org/project/geographiclib>} 1.52) on U{Windows 10<https://CI.AppVeyor.com/project/mrJean1/pygeodesy>}
@@ -166,7 +174,7 @@ in 64- and 32-bit.
166
174
  A single-File and single-Directory application with C{pygeodesy} has been bundled using U{PyInstaller
167
175
  <https://PyPI.org/project/pyinstaller>} 3.4 and 64-bit Python 3.7.3 on macOS 10.13.6 High Sierra.
168
176
 
169
- Previously, the tests were run with Python 3.13.0-7, 3.12.0-6, 3.11.2-4, 3.10.1-7, 3.9.6, 3.9.1, 3.8.7, 3.7.1, 2.7.15,
177
+ Previously, the tests were run with Python 3.13.0-9, 3.12.0-7, 3.11.2-5, 3.10.1-7, 3.9.6, 3.9.1, 3.8.7, 3.7.1, 2.7.15,
170
178
  U{PyPy<https://PyPy.org>} 7.3.12 (Python 3.10.12), 7.3.1 (Python 3.6.9) and U{PyPy<https://PyPy.org>} 7.1.1 (Python
171
179
  2.7.13) (and U{geographiclib <https://PyPI.org/project/geographiclib>} 1.52, U{numpy<https://PyPI.org/project/numpy>}
172
180
  1.16.3, 1.16.4, 1.16.6, 1.19.0, 1.19.4, 1.19.5 or 1.22.4 and U{scipy<https://PyPI.org/project/scipy>} 1.2.1, 1.4.1,
@@ -187,10 +195,10 @@ Notes
187
195
  =====
188
196
 
189
197
  All Python source code has been statically U{checked<https://GitHub.com/ActiveState/code/tree/master/recipes/Python/
190
- 546532_PyChecker_postprocessor>} with U{Ruff<https://GitHub.com/astral-sh/ruff>} using Python 3.13.9 and with
198
+ 546532_PyChecker_postprocessor>} with U{Ruff<https://GitHub.com/astral-sh/ruff>} using Python 3.13.11 and with
191
199
  U{PyChecker<https://PyPI.org/project/pychecker>}, U{PyFlakes<https://PyPI.org/project/pyflakes>}, U{PyCodeStyle
192
200
  <https://PyPI.org/project/pycodestyle>} (formerly Pep8) and U{McCabe<https://PyPI.org/project/mccabe>} using Python
193
- 2.7.18, both in 64-bit on macOS 26.1 Tahoe.
201
+ 2.7.18, both in 64-bit on macOS 26.2 Tahoe.
194
202
 
195
203
  For a summary of all I{Karney}-based functionality in C{pygeodesy}, see module U{karney
196
204
  <https://mrJean1.GitHub.io/PyGeodesy/docs/pygeodesy.karney-module.html>}.
@@ -210,7 +218,7 @@ The following environment variables are observed by C{pygeodesy}:
210
218
  - C{PYGEODESY_FSUM_RESIDUAL} - see module L{fsums<pygeodesy.fsums>} and method L{RESIDUAL<pygeodesy.Fsum.RESIDUAL>}.
211
219
  - C{PYGEODESY_GEOCONVERT} - see module L{mgrs<pygeodesy.mgrs>}.
212
220
  - C{PYGEODESY_GEODSOLVE} - see module L{geodsolve<pygeodesy.geodsolve>}.
213
- - C{PYGEODESY_GEOD3SOLVE} - see module L{geodsolve<pygeodesy.geod3solve>}.
221
+ - C{PYGEODESY_GEOD3SOLVE} - see module L{geod3solve<pygeodesy.geod3solve>}.
214
222
  - C{PYGEODESY_INTERSECTTOOL} - see module L{geodesici<pygeodesy.geodesici>}.
215
223
  - C{PYGEODESY_LAZY_IMPORT} - see module L{lazily<pygeodesy.lazily>} and variable L{isLazy<pygeodesy.isLazy>}.
216
224
  - C{PYGEODESY_NOTIMPLEMENTED} - C{__special__} methods return C{NotImplemented} if set to "std".
@@ -618,7 +626,7 @@ else:
618
626
 
619
627
  from pygeodesy.internals import _version2, _DOT_ # noqa: E402
620
628
  # from pygeodesy.interns import _DOT_ # from .internals
621
- __version__ = '25.12.12'
629
+ __version__ = '26.01.16'
622
630
  # see setup.py for similar logic
623
631
  version = _DOT_(*_version2(__version__, n=3))
624
632
 
pygeodesy/albers.py CHANGED
@@ -38,11 +38,11 @@ from pygeodesy.utily import atan1, atan1d, atan2, degrees360, sincos2, \
38
38
  from math import atanh, degrees, fabs, radians, sqrt
39
39
 
40
40
  __all__ = _ALL_LAZY.albers
41
- __version__ = '25.05.12'
41
+ __version__ = '26.01.06'
42
42
 
43
43
  _k1_ = 'k1'
44
- _NUMIT = 9 # XXX 4?
45
- _NUMIT0 = 41 # XXX 21?
44
+ _MAXIT = 9 # XXX 4?
45
+ _MAXIT0 = 41 # XXX 21?
46
46
  _TERMS = 31 # XXX 16?
47
47
  _TOL0 = sqrt3(_TOL)
48
48
 
@@ -425,7 +425,7 @@ class _AlbersBase(_NamedBase):
425
425
  _Ta02 = Fsum(ta0).fsum2f_
426
426
  _1, _2 = _1_0, _2_0
427
427
  _4, _6 = _4_0, _6_0
428
- for self._iteration in range(1, _NUMIT0): # 4 trips
428
+ for self._iteration in range(1, _MAXIT0): # 4 trips
429
429
  ta02 = ta0**2
430
430
  sca02 = ta02 + _1
431
431
  sca0 = sqrt(sca02)
@@ -492,7 +492,7 @@ class _AlbersBase(_NamedBase):
492
492
  ta = txi
493
493
  tol = _tol(_TOL, ta)
494
494
  _Ta2 = Fsum(ta).fsum2f_
495
- for self._iteration in range(1, _NUMIT): # max 2, mean 1.99
495
+ for self._iteration in range(1, _MAXIT): # max 2, mean 1.99
496
496
  # dtxi / dta = (scxi / sca)^3 * 2 * (1 - e^2)
497
497
  # / (qZ * (1 - e^2 * sa^2)^2)
498
498
  ta2 = ta**2
@@ -43,7 +43,7 @@ from pygeodesy.vector3d import Vector3d, _xyzhdlln4
43
43
  # from math import degrees, fabs, radians, sqrt # from .fmath, .utily
44
44
 
45
45
  __all__ = _ALL_LAZY.cartesianBase
46
- __version__ = '25.11.07'
46
+ __version__ = '26.01.06'
47
47
 
48
48
  _r_ = 'r'
49
49
  _resections = _MODS.into(resections=__name__)
@@ -361,7 +361,7 @@ class CartesianBase(Vector3d, _EcefLocal):
361
361
  d = self.datum if earth is None else earth
362
362
  if normal and d is self.datum:
363
363
  r = self._height4
364
- elif isinstance(d, _MODS.triaxials.triaxial5.Triaxial_):
364
+ elif isinstance(d, _MODS.triaxials.Triaxial_):
365
365
  r = d.height4(self, normal=normal)
366
366
  try:
367
367
  d = d.toEllipsoid(name=n)
pygeodesy/constants.py CHANGED
@@ -26,7 +26,7 @@ except ImportError: # Python 2-
26
26
  _inf, _nan = float(_INF_), float(_NAN_)
27
27
 
28
28
  __all__ = _ALL_LAZY.constants
29
- __version__ = '25.12.06'
29
+ __version__ = '26.01.14'
30
30
 
31
31
 
32
32
  def _copysign_0_0(y):
@@ -295,6 +295,11 @@ OVERFLOW = _Float(OVERFLOW=_1_0 / EPS0) # PYCHOK = 2.028240960365e+31
295
295
  # _1SQRT2= _Float(_1SQRT2 =sqrt(_2_0) + 1)
296
296
  # 0.707106781186547_524_400_844_362_104_849_039_284_835_937_688_474_036_588_339_868_99
297
297
  _SQRT2_2 = _Float(_SQRT2_2=sqrt(_0_5)) # PYCHOK = 0.707106781186547_5 == sqrt(2) / 2
298
+ # sqrt(3) <https://WikiPedia.org/wiki/Square_root_of_3>
299
+ # 1.732050807568877_293_527_446_341_505_872_366_942_805_253_810_380_628_055_806
300
+ _SQRT3 = _Float(_SQRT3 =sqrt(_3_0)) # PYCHOK = 1.732050807568877_2 == sqrt(3)
301
+ # 0.866025403784438_646_763_723_170_752_936_183_471_402_626_905_190_314_027_903
302
+ _SQRT3_2 = _Float(_SQRT3_2=sqrt(_0_75)) # PYCHOK = 0.866025403784438_6 == sqrt(3) / 2
298
303
 
299
304
  INF = Float(INF =_inf) # PYCHOK INFinity, see function L{isinf}, L{isfinite}, NOT _Float!
300
305
  INT0 = Int( INT0= 0) # PYCHOK unique int(0) instance, see .fsums, useZ=False
@@ -332,6 +337,8 @@ R_VM = _Radius(R_VM=6366707.0194937) # PYCHOK aViation/naVigation earth radius
332
337
 
333
338
  _INF_NAN_NINF = {INF, NAN, NINF, _inf, _nan}
334
339
  _pos_self = _1_0.__pos__() is _1_0 # PYCHOK in .fsums, .vector3dBase
340
+ _1_3rd = 1 / 3 # in .fmath
341
+ _2_3rd = 2 / 3 # in .fmath, .formy
335
342
 
336
343
 
337
344
  def _0_0s(n):
pygeodesy/datums.py CHANGED
@@ -94,7 +94,7 @@ from pygeodesy.units import _isRadius, Radius_, radians
94
94
  # import operator as _operator # from .fmath
95
95
 
96
96
  __all__ = _ALL_LAZY.datums
97
- __version__ = '25.05.12'
97
+ __version__ = '26.01.13'
98
98
 
99
99
  _a_ellipsoid_ = _UNDER_(_a_, _ellipsoid_)
100
100
  _BD72_ = 'BD72'
@@ -723,13 +723,10 @@ assert _WGS84.ellipsoid is _EWGS84
723
723
 
724
724
  if __name__ == _DMAIN_:
725
725
 
726
- from pygeodesy.interns import _COMMA_, _NL_, _NLATvar_
727
- from pygeodesy import printf
728
-
729
- # __doc__ of this file, force all into registery
730
- for r in (Datums, Transforms):
731
- t = [NN] + r.toRepr(all=True, asorted=True).split(_NL_)
732
- printf(_NLATvar_.join(i.strip(_COMMA_) for i in t))
726
+ from pygeodesy.internals import _pregistry
727
+ # __doc__ of this file, force all into registry
728
+ _pregistry(Datums)
729
+ _pregistry(Transforms)
733
730
 
734
731
  # **) MIT License
735
732
  #
pygeodesy/ellipsoids.py CHANGED
@@ -67,10 +67,10 @@ from __future__ import division as _; del _ # noqa: E702 ;
67
67
  # from pygeodesy.albers import AlbersEqualAreaCylindrical # _MODS
68
68
  from pygeodesy.basics import copysign0, isbool, _isin, isint, typename
69
69
  from pygeodesy.constants import EPS, EPS_2, EPS0, EPS02, EPS1, INF, NINF, \
70
- _over, PI_2, PI_3, PI4, R_M, R_MA, R_FM, _EPSqrt, \
70
+ _EPSqrt, PI_2, PI_3, PI2, PI4, R_M, R_MA, R_FM, \
71
71
  _EPStol as _TOL, _floatuple as _T, _isfinite, \
72
- _0_0s, _0_0, _0_5, _1_0, _1_EPS, _2_0, _4_0, _90_0, \
73
- _0_25, _3_0 # PYCHOK used!
72
+ _over, _0_0s, _0_0, _0_5, _1_0, _1_EPS, _2_0, \
73
+ _4_0, _90_0, _0_25, _3_0 # PYCHOK used!
74
74
  from pygeodesy.errors import _AssertionError, IntersectionError, _ValueError, _xattr, _xkwds_not
75
75
  from pygeodesy.fmath import cbrt, cbrt2, fdot, Fhorner, fpowers, hypot, hypot_, \
76
76
  hypot1, hypot2, sqrt3, Fsum
@@ -96,7 +96,7 @@ from pygeodesy.utily import atan1, atan1d, atan2b, degrees90, m2radians, radians
96
96
  from math import asinh, atan, atanh, cos, degrees, exp, fabs, radians, sin, sinh, sqrt, tan # as _tan
97
97
 
98
98
  __all__ = _ALL_LAZY.ellipsoids
99
- __version__ = '25.11.26'
99
+ __version__ = '26.01.13'
100
100
 
101
101
  _f_0_0 = Float(f =_0_0) # zero flattening
102
102
  _f__0_0 = Float(f_=_0_0) # zero inverse flattening
@@ -111,19 +111,19 @@ def _aux(lat, inverse, auxLat, clip=90):
111
111
  return Lat(lat, clip=clip, name=_lat_ if inverse else typename(auxLat))
112
112
 
113
113
 
114
- def _s2_c2(phi):
114
+ def _sin2cos2(rad):
115
115
  '''(INTERNAL) Return 2-tuple C{(sin(B{phi})**2, cos(B{phi})**2)}.
116
116
  '''
117
- if phi:
118
- s2 = sin(phi)**2
117
+ if rad:
118
+ s2 = sin(rad)**2
119
119
  if s2 > EPS:
120
120
  c2 = _1_0 - s2
121
121
  if c2 > EPS:
122
122
  if c2 < EPS1:
123
123
  return s2, c2
124
124
  else:
125
- return _1_0, _0_0 # phi == PI_2
126
- return _0_0, _1_0 # phi == 0
125
+ return _1_0, _0_0 # rad == PI_2
126
+ return _0_0, _1_0 # rad == 0
127
127
 
128
128
 
129
129
  class a_f2Tuple(_NamedTuple):
@@ -871,6 +871,12 @@ class Ellipsoid(_NamedEnumItem):
871
871
 
872
872
  equatoradius = a # Requatorial
873
873
 
874
+ @Property_RO
875
+ def equatorimeter(self):
876
+ '''Get the ellipsoid's I{equatorial} perimeter (C{meter}).
877
+ '''
878
+ return Meter(equatorimeter=self.a * PI2)
879
+
874
880
  def e2s(self, s):
875
881
  '''Compute norm M{sqrt(1 - e2 * s**2)}.
876
882
 
@@ -1134,7 +1140,8 @@ class Ellipsoid(_NamedEnumItem):
1134
1140
  methods L{Ellipsoid.height4} and L{Triaxial.hartzell4}.
1135
1141
  '''
1136
1142
  try:
1137
- v, d, i = _MODS.triaxials.triaxial5._hartzell3(pov, los, self._triaxial)
1143
+ m = _MODS._triaxials_triaxial5
1144
+ v, d, i = m._hartzell3(pov, los, self._triaxial)
1138
1145
  except Exception as x:
1139
1146
  raise IntersectionError(pov=pov, los=los, cause=x)
1140
1147
  return Vector4Tuple(v.x, v.y, v.z, d, iteration=i, name__=self.hartzell4)
@@ -1188,7 +1195,8 @@ class Ellipsoid(_NamedEnumItem):
1188
1195
  v = v.times_(t, t, 0) # force z=0.0
1189
1196
  h = x - a # equatorial
1190
1197
  else: # normal in 1st quadrant
1191
- x, y, i = _MODS.triaxials.triaxial5._plumbTo3(x, y, self)
1198
+ m = _MODS._triaxials_triaxial5
1199
+ x, y, i = m._plumbTo3(x, y, self)
1192
1200
  t, v = v, v.times_(x, x, y)
1193
1201
  h = t.minus(v).length
1194
1202
 
@@ -1381,6 +1389,12 @@ class Ellipsoid(_NamedEnumItem):
1381
1389
 
1382
1390
  polaradius = b # Rpolar
1383
1391
 
1392
+ @property_RO
1393
+ def polarimeter(self):
1394
+ '''Get the ellipsoid's I{polar}, meridional perimeter (C{meter}).
1395
+ '''
1396
+ return Meter(polarimeter=self.L * _4_0)
1397
+
1384
1398
  # Q = A # I{meridian arc unit} C{Q}, the mean, meridional length I{per radian}
1385
1399
 
1386
1400
  @deprecated_Property_RO
@@ -1484,7 +1498,7 @@ class Ellipsoid(_NamedEnumItem):
1484
1498
  r, p = self.a, Phid(lat)
1485
1499
  if p and self.f:
1486
1500
  if fabs(p) < PI_2:
1487
- s2, c2 = _s2_c2(p)
1501
+ s2, c2 = _sin2cos2(p)
1488
1502
  # R == sqrt((a2**2 * c2 + b2**2 * s2) / (a2 * c2 + b2 * s2))
1489
1503
  # == sqrt(a2**2 * (c2 + (b2 / a2)**2 * s2) / (a2 * (c2 + b2 / a2 * s2)))
1490
1504
  # == sqrt(a2 * (c2 + (b2 / a2)**2 * s2) / (c2 + (b2 / a2) * s2))
@@ -1709,7 +1723,7 @@ class Ellipsoid(_NamedEnumItem):
1709
1723
  '''(INTERNAL) Helper for C{rocAzimuth} and C{rocBearing}.
1710
1724
  '''
1711
1725
  if self.f:
1712
- s2, c2 = _s2_c2(radians(deg))
1726
+ s2, c2 = _sin2cos2(radians(deg))
1713
1727
  m, n = self.roc2_(Phid(lat))
1714
1728
  if n < m: # == n / (c2 * n / m + s2)
1715
1729
  c2 *= n / m
@@ -1751,7 +1765,7 @@ class Ellipsoid(_NamedEnumItem):
1751
1765
  # ... requires 1 or 2 sqrt
1752
1766
  g = self.b
1753
1767
  if self.f:
1754
- s2, c2 = _s2_c2(Phid(lat))
1768
+ s2, c2 = _sin2cos2(Phid(lat))
1755
1769
  g = _over(g, c2 + self.b2_a2 * s2)
1756
1770
  return Radius(rocGauss=g)
1757
1771
 
@@ -1898,8 +1912,8 @@ class Ellipsoid(_NamedEnumItem):
1898
1912
  def _triaxial(self):
1899
1913
  '''(INTERNAL) Get this ellipsoid's un-/ordered C{Triaxial/_}.
1900
1914
  '''
1901
- a, b, m = self.a, self.b, _MODS.triaxials
1902
- T = m.Triaxial if a > b else m.Triaxial_
1915
+ a, b, t = self.a, self.b, _MODS.triaxials
1916
+ T = t.Triaxial if a > b else t.Triaxial_
1903
1917
  return T(a, a, b, name=self.name)
1904
1918
 
1905
1919
  @Property_RO
@@ -2421,7 +2435,6 @@ _EWGS84 = Ellipsoids.WGS84 # (INTERNAL) shared
2421
2435
 
2422
2436
  if __name__ == _DMAIN_:
2423
2437
 
2424
- from pygeodesy.interns import _COMMA_, _NL_, _NLATvar_
2425
2438
  from pygeodesy import nameof, printf
2426
2439
 
2427
2440
  for E in (_EWGS84, Ellipsoids.GRS80, # NAD83,
@@ -2438,9 +2451,9 @@ if __name__ == _DMAIN_:
2438
2451
  printf('# %s %s', Ellipsoid.BetaKs.name, fstr(E.BetaKs, prec=20))
2439
2452
  printf('# %s %s', nameof(Ellipsoid.KsOrder), E.KsOrder) # property
2440
2453
 
2454
+ from pygeodesy.internals import _pregistry
2441
2455
  # __doc__ of this file, force all into registry
2442
- t = [NN] + Ellipsoids.toRepr(all=True, asorted=True).split(_NL_)
2443
- printf(_NLATvar_.join(i.strip(_COMMA_) for i in t))
2456
+ _pregistry(Ellipsoids)
2444
2457
 
2445
2458
  # % python3.13 -m pygeodesy.ellipsoids
2446
2459