pygeodesy 24.9.29__py2.py3-none-any.whl → 24.10.24__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 (56) hide show
  1. {PyGeodesy-24.9.29.dist-info → PyGeodesy-24.10.24.dist-info}/METADATA +15 -15
  2. {PyGeodesy-24.9.29.dist-info → PyGeodesy-24.10.24.dist-info}/RECORD +56 -56
  3. pygeodesy/__init__.py +20 -19
  4. pygeodesy/__main__.py +5 -5
  5. pygeodesy/albers.py +12 -17
  6. pygeodesy/basics.py +38 -41
  7. pygeodesy/booleans.py +54 -46
  8. pygeodesy/cartesianBase.py +2 -2
  9. pygeodesy/constants.py +20 -16
  10. pygeodesy/datums.py +3 -3
  11. pygeodesy/dms.py +250 -270
  12. pygeodesy/ellipsoidalBase.py +2 -2
  13. pygeodesy/ellipsoidalBaseDI.py +10 -10
  14. pygeodesy/ellipsoidalNvector.py +4 -4
  15. pygeodesy/ellipsoidalVincenty.py +2 -2
  16. pygeodesy/ellipsoids.py +7 -48
  17. pygeodesy/elliptic.py +14 -14
  18. pygeodesy/errors.py +15 -10
  19. pygeodesy/etm.py +18 -2
  20. pygeodesy/fmath.py +188 -176
  21. pygeodesy/formy.py +4 -4
  22. pygeodesy/fstats.py +54 -56
  23. pygeodesy/fsums.py +304 -266
  24. pygeodesy/geodesici.py +43 -40
  25. pygeodesy/geodesicw.py +3 -3
  26. pygeodesy/geodesicx/gxarea.py +3 -2
  27. pygeodesy/geodsolve.py +73 -24
  28. pygeodesy/geohash.py +2 -2
  29. pygeodesy/geoids.py +28 -27
  30. pygeodesy/internals.py +156 -85
  31. pygeodesy/interns.py +23 -20
  32. pygeodesy/karney.py +61 -12
  33. pygeodesy/latlonBase.py +13 -15
  34. pygeodesy/lazily.py +206 -214
  35. pygeodesy/mgrs.py +13 -13
  36. pygeodesy/named.py +11 -10
  37. pygeodesy/nvectorBase.py +1 -1
  38. pygeodesy/points.py +2 -2
  39. pygeodesy/props.py +34 -13
  40. pygeodesy/rhumb/bases.py +5 -5
  41. pygeodesy/rhumb/solve.py +7 -8
  42. pygeodesy/solveBase.py +7 -25
  43. pygeodesy/sphericalBase.py +20 -23
  44. pygeodesy/sphericalNvector.py +24 -23
  45. pygeodesy/sphericalTrigonometry.py +9 -8
  46. pygeodesy/streprs.py +11 -8
  47. pygeodesy/trf.py +6 -4
  48. pygeodesy/triaxials.py +46 -9
  49. pygeodesy/units.py +4 -3
  50. pygeodesy/ups.py +6 -6
  51. pygeodesy/utily.py +2 -2
  52. pygeodesy/utm.py +2 -2
  53. pygeodesy/vector3d.py +5 -5
  54. pygeodesy/vector3dBase.py +4 -5
  55. {PyGeodesy-24.9.29.dist-info → PyGeodesy-24.10.24.dist-info}/WHEEL +0 -0
  56. {PyGeodesy-24.9.29.dist-info → PyGeodesy-24.10.24.dist-info}/top_level.txt +0 -0
@@ -5,7 +5,7 @@ u'''(INTERNAL) Private ellipsoidal base classes C{CartesianEllipsoidalBase}
5
5
  and C{LatLonEllipsoidalBase}.
6
6
 
7
7
  A pure Python implementation of geodesy tools for ellipsoidal earth models,
8
- transcoded in part from JavaScript originals by I{(C) Chris Veness 2005-2016}
8
+ transcoded in part from JavaScript originals by I{(C) Chris Veness 2005-2024}
9
9
  and published under the same MIT Licence**, see for example U{latlon-ellipsoidal
10
10
  <https://www.Movable-Type.co.UK/scripts/geodesy/docs/latlon-ellipsoidal.js.html>}.
11
11
  '''
@@ -35,7 +35,7 @@ from pygeodesy.units import Epoch, _isDegrees, Radius_, _1mm as _TOL_M
35
35
  # from math import fabs # from .latlonBase
36
36
 
37
37
  __all__ = _ALL_LAZY.ellipsoidalBase
38
- __version__ = '24.08.14'
38
+ __version__ = '24.10.12'
39
39
 
40
40
 
41
41
  class CartesianEllipsoidalBase(CartesianBase):
@@ -34,7 +34,7 @@ from pygeodesy.utily import m2km, unroll180, _unrollon, _unrollon3, \
34
34
  from math import degrees, radians
35
35
 
36
36
  __all__ = _ALL_LAZY.ellipsoidalBaseDI
37
- __version__ = '24.09.26'
37
+ __version__ = '24.10.19'
38
38
 
39
39
  _polar__ = 'polar?'
40
40
  _B2END = _1_5 # _intersect3 bearing to pseudo-end point factor
@@ -279,9 +279,9 @@ class LatLonEllipsoidalBaseDI(LatLonEllipsoidalBase):
279
279
  two points or as a point and bearing.
280
280
 
281
281
  @arg circle: Radius of the circle centered at this location (C{meter},
282
- conventionally) or a point on the circle (this C{LatLon}).
283
- @arg point: A location on the geodesic (this C{LatLon}).
284
- @arg other: An other point on the geodesic (this C{LatLon}) or the
282
+ conventionally) or a point on the circle (same C{LatLon} class).
283
+ @arg point: A location on the geodesic (same C{LatLon} class).
284
+ @arg other: An other point on the geodesic (same C{LatLon} class) or the
285
285
  (forward) bearing at the B{C{point}} (compass C{degrees}).
286
286
  @kwarg exact: Exact C{geodesic...} to use (C{bool} or C{Geodesic...}), see
287
287
  method L{Ellipsoid.geodesic_}.
@@ -292,12 +292,12 @@ class LatLonEllipsoidalBaseDI(LatLonEllipsoidalBase):
292
292
  @kwarg tol: Convergence tolerance (C{scalar}).
293
293
 
294
294
  @return: 2-Tuple of the intersection points (representing a geodesic chord),
295
- each an instance of this C{LatLon}. Both points are the same
295
+ each an instance of same C{LatLon} class. Both points are the same
296
296
  instance if the geodesic (line) is tangential to the circle.
297
297
 
298
298
  @raise IntersectionError: The circle and geodesic do not intersect.
299
299
 
300
- @raise TypeError: If B{C{point}} is not this C{LatLon} or B{C{circle}}
300
+ @raise TypeError: If B{C{point}} is not same C{LatLon} class or B{C{circle}}
301
301
  or B{C{other}} invalid.
302
302
 
303
303
  @raise UnitError: Invalid B{C{circle}}, B{C{other}}, B{C{exact}} or
@@ -345,7 +345,7 @@ class LatLonEllipsoidalBaseDI(LatLonEllipsoidalBase):
345
345
  @return: A L{NearestOn8Tuple}C{(closest, distance, fi, j, start, end,
346
346
  initial, final)} with C{distance} in C{meter}, conventionally
347
347
  and with the C{closest}, the C{start} the C{end} point each
348
- an instance of this C{LatLon}.
348
+ an instance of same C{LatLon} class.
349
349
 
350
350
  @raise PointsError: Insufficient number of B{C{points}}.
351
351
 
@@ -397,7 +397,7 @@ class LatLonEllipsoidalBaseDI(LatLonEllipsoidalBase):
397
397
 
398
398
  f, j = _fi_j2(f, len(Ps)) # like .vector3d.nearestOn6
399
399
 
400
- n = self.nearestOn8.__name__ # _dunder_nameof
400
+ n = self.nearestOn8.__name__ # _DUNDER_nameof
401
401
  c.rename(n)
402
402
  if s is not c:
403
403
  s = s.copy(name=n)
@@ -422,9 +422,9 @@ class LatLonEllipsoidalBaseDI(LatLonEllipsoidalBase):
422
422
  and/or B{C{other}} (C{bool}).
423
423
  @kwarg tol: Convergence tolerance (C{meter}).
424
424
 
425
- @return: The intersection point, an instance of this C{LatLon}.
425
+ @return: The intersection point, an instance of same C{LatLon} class.
426
426
 
427
- @raise TypeError: If B{C{point}} or B{C{other}} not this C{LatLon}.
427
+ @raise TypeError: If B{C{point}} or B{C{other}} not same C{LatLon} class.
428
428
 
429
429
  @raise UnitError: Invalid B{C{other}}, B{C{exact}} or B{C{height}}.
430
430
  '''
@@ -8,7 +8,7 @@ and C{Nvector} and DEPRECATED L{Ned} and functions L{meanOf}, L{sumOf}
8
8
  and DEPRECATED L{toNed}.
9
9
 
10
10
  Pure Python implementation of n-vector-based geodetic (lat-/longitude)
11
- methods by I{(C) Chris Veness 2011-2016} published under the same MIT
11
+ methods by I{(C) Chris Veness 2011-2024} published under the same MIT
12
12
  Licence**, see U{Vector-based geodesy
13
13
  <https://www.Movable-Type.co.UK/scripts/latlong-vectors.html>}.
14
14
 
@@ -48,7 +48,7 @@ from pygeodesy.units import Bearing, Distance, Height, Scalar
48
48
  # from math import fabs # from .nvectorBase
49
49
 
50
50
  __all__ = _ALL_LAZY.ellipsoidalNvector
51
- __version__ = '24.08.13'
51
+ __version__ = '24.10.19'
52
52
 
53
53
 
54
54
  class Ned(_Ned):
@@ -417,7 +417,7 @@ class LatLon(LatLonNvectorBase, LatLonEllipsoidalBase):
417
417
  return LatLonNvectorBase.toNvector(self, **kwds)
418
418
 
419
419
 
420
- _Nvll = LatLon(0, 0, name=_Nv00_) # reference instance (L{LatLon})
420
+ _Nv00 = LatLon(0, 0, name=_Nv00_) # reference instance (L{LatLon})
421
421
 
422
422
 
423
423
  class Nvector(NvectorBase):
@@ -541,7 +541,7 @@ def meanOf(points, datum=_WGS84, height=None, wrap=False,
541
541
 
542
542
  @raise ValueError: Insufficient number of B{C{points}}.
543
543
  '''
544
- Ps = _Nvll.PointsIter(points, wrap=wrap)
544
+ Ps = _Nv00.PointsIter(points, wrap=wrap)
545
545
  n = sumOf(p._N_vector for p in Ps.iterate(closed=False))
546
546
  return n.toLatLon(**_xkwds(LatLon_and_kwds, height=height, datum=datum,
547
547
  LatLon=LatLon, name__=meanOf))
@@ -8,7 +8,7 @@ I{Thaddeus Vincenty}'s geodetic (lat-/longitude) L{LatLon}, geocentric
8
8
  L{intersections2}, L{nearestOn} and L{perimeterOf}.
9
9
 
10
10
  Pure Python implementation of geodesy tools for ellipsoidal earth models,
11
- transcoded from JavaScript originals by I{(C) Chris Veness 2005-2016}
11
+ transcoded from JavaScript originals by I{(C) Chris Veness 2005-2024}
12
12
  and published under the same MIT Licence**, see U{Vincenty geodesics
13
13
  <https://www.Movable-Type.co.UK/scripts/LatLongVincenty.html>}. More
14
14
  at U{geographiclib<https://PyPI.org/project/geographiclib>} and
@@ -72,7 +72,7 @@ from pygeodesy.utily import atan2b, atan2d, sincos2, sincos2d, unroll180, wrap18
72
72
  from math import atan2, cos, degrees, fabs, radians, tan
73
73
 
74
74
  __all__ = _ALL_LAZY.ellipsoidalVincenty
75
- __version__ = '24.08.13'
75
+ __version__ = '24.10.12'
76
76
 
77
77
  _antipodal_to_ = _SPACE_(_antipodal_, _to_)
78
78
 
pygeodesy/ellipsoids.py CHANGED
@@ -66,7 +66,7 @@ from __future__ import division as _; del _ # PYCHOK semicolon
66
66
 
67
67
  from pygeodesy.basics import copysign0, isbool, isint
68
68
  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, _SQRT2_2, \
69
+ _EPSqrt, _EPStol as _TOL, _floatuple as _T, _isfinite, \
70
70
  _0_0s, _0_0, _0_5, _1_0, _1_EPS, _2_0, _4_0, _90_0, \
71
71
  _0_25, _3_0 # PYCHOK used!
72
72
  from pygeodesy.errors import _AssertionError, IntersectionError, _ValueError, _xattr, _xkwds_not
@@ -93,7 +93,7 @@ from pygeodesy.utily import atan1, atan1d, atan2b, degrees90, m2radians, radians
93
93
  from math import asinh, atan, atanh, cos, degrees, exp, fabs, radians, sin, sinh, sqrt, tan
94
94
 
95
95
  __all__ = _ALL_LAZY.ellipsoids
96
- __version__ = '24.07.25'
96
+ __version__ = '24.10.15'
97
97
 
98
98
  _f_0_0 = Float(f =_0_0) # zero flattening
99
99
  _f__0_0 = Float(f_=_0_0) # zero inverse flattening
@@ -281,7 +281,7 @@ class Ellipsoid(_NamedEnumItem):
281
281
 
282
282
  self._register(Ellipsoids, n)
283
283
 
284
- if f and f_: # see .test/testEllipsoidal.py
284
+ if f and f_: # see test/testEllipsoidal
285
285
  d = dict(eps=_TOL)
286
286
  if None in ff_: # both f_ and f given
287
287
  d.update(Error=_ValueError, txt=_incompatible_)
@@ -1160,7 +1160,7 @@ class Ellipsoid(_NamedEnumItem):
1160
1160
  v = v.times_(t, t, 0) # force z=0.0
1161
1161
  h = x - a # equatorial
1162
1162
  else: # normal in 1st quadrant
1163
- x, y, i = _plumbTo3(x, y, self)
1163
+ x, y, i = _MODS.triaxials._plumbTo3(x, y, self)
1164
1164
  t, v = v, v.times_(x, x, y)
1165
1165
  h = t.minus(v).length
1166
1166
 
@@ -1522,9 +1522,9 @@ class Ellipsoid(_NamedEnumItem):
1522
1522
  def _Rhumbs(self):
1523
1523
  '''(INTERNAL) Get all C{Rhumb...} classes, I{once}.
1524
1524
  '''
1525
- p = _MODS.rhumb
1526
- return (p.aux_.RhumbAux, # overwrite property_ROver
1527
- p.ekx.Rhumb, p.solve.RhumbSolve)
1525
+ r = _MODS.rhumb
1526
+ return (r.aux_.RhumbAux, # overwrite property_ROver
1527
+ r.ekx.Rhumb, r.solve.RhumbSolve)
1528
1528
 
1529
1529
  @property
1530
1530
  def rhumbsolve(self):
@@ -2276,47 +2276,6 @@ def n2f_(n):
2276
2276
  return f2f_(n2f(n))
2277
2277
 
2278
2278
 
2279
- def _plumbTo3(px, py, E, eps=EPS): # in .height4 above
2280
- '''(INTERNAL) Nearest point on a 2-D ellipse in 1st quadrant.
2281
-
2282
- @see: Functions C{pygeodesy.triaxial._plumbTo4} and C{-._plumbTo5}.
2283
- '''
2284
- a, b, e0 = E.a, E.b, EPS0
2285
- if min(px, py, a, b) < e0:
2286
- raise _AssertionError(px=px, py=py, a=a, b=b, E=E)
2287
-
2288
- a2 = a - b * E.b_a
2289
- b2 = b - a * E.a_b
2290
- tx = ty = _SQRT2_2
2291
- _a, _h = fabs, hypot
2292
- for i in range(16): # max 5
2293
- ex = a2 * tx**3
2294
- ey = b2 * ty**3
2295
-
2296
- qx = px - ex
2297
- qy = py - ey
2298
- q = _h(qx, qy)
2299
- if q < e0: # PYCHOK no cover
2300
- break
2301
- r = _h(ex - tx * a,
2302
- ey - ty * b) / q
2303
-
2304
- sx, tx = tx, min(_1_0, max(0, (ex + qx * r) / a))
2305
- sy, ty = ty, min(_1_0, max(0, (ey + qy * r) / b))
2306
- t = _h(ty, tx)
2307
- if t < e0: # PYCHOK no cover
2308
- break
2309
- tx = tx / t # /= chokes PyChecker
2310
- ty = ty / t
2311
- if _a(sx - tx) < eps and \
2312
- _a(sy - ty) < eps:
2313
- break
2314
-
2315
- tx *= a / px
2316
- ty *= b / py
2317
- return tx, ty, i # x and y as fractions
2318
-
2319
-
2320
2279
  class Ellipsoids(_NamedEnum):
2321
2280
  '''(INTERNAL) L{Ellipsoid} registry, I{must} be a sub-class
2322
2281
  to accommodate the L{_LazyNamedEnumItem} properties.
pygeodesy/elliptic.py CHANGED
@@ -84,12 +84,12 @@ from pygeodesy.constants import EPS, INF, NAN, PI, PI_2, PI_4, _0_0, \
84
84
  # from pygeodesy.errors import _ValueError # from .fmath
85
85
  from pygeodesy.fmath import favg, hypot1, zqrt, _ValueError
86
86
  from pygeodesy.fsums import Fsum, _sum
87
- # from pygeodesy.internals import _dunder_nameof # from .lazily
87
+ from pygeodesy.internals import _DUNDER_nameof
88
88
  from pygeodesy.interns import NN, _delta_, _DOT_, _f_, _invalid_, \
89
89
  _invokation_, _negative_, _SPACE_
90
90
  from pygeodesy.karney import _K_2_0, _norm180, _signBit, _sincos2
91
- from pygeodesy.lazily import _ALL_LAZY, _dunder_nameof
92
- from pygeodesy.named import _Named, _NamedTuple, Fmt, unstr
91
+ # from pygeodesy.lazily import _ALL_LAZY # from .named
92
+ from pygeodesy.named import _Named, _NamedTuple, _ALL_LAZY, Fmt, unstr
93
93
  from pygeodesy.props import _allPropertiesOf_n, Property_RO, _update_all
94
94
  # from pygeodesy.streprs import Fmt, unstr # from .named
95
95
  from pygeodesy.units import Scalar, Scalar_
@@ -99,7 +99,7 @@ from math import asin, asinh, atan, atan2, ceil, cosh, fabs, floor, \
99
99
  radians, sin, sinh, sqrt, tan, tanh
100
100
 
101
101
  __all__ = _ALL_LAZY.elliptic
102
- __version__ = '24.09.06'
102
+ __version__ = '24.10.14'
103
103
 
104
104
  _TolRD = zqrt(EPS * 0.002)
105
105
  _TolRF = zqrt(EPS * 0.030)
@@ -408,9 +408,9 @@ class Elliptic(_Named):
408
408
  def _Einv(self, x):
409
409
  '''(INTERNAL) Helper for C{.deltaEinv} and C{.fEinv}.
410
410
  '''
411
- E2 = self.cE * _2_0
412
- n = floor(x / E2 + _0_5)
413
- r = x - E2 * n # r in [-cE, cE)
411
+ E2 = self.cE * _2_0
412
+ n = floor(x / E2 + _0_5)
413
+ r = x - E2 * n # r in [-cE, cE)
414
414
  # linear approximation
415
415
  phi = PI * r / E2 # phi in [-PI_2, PI_2)
416
416
  Phi = Fsum(phi)
@@ -427,7 +427,7 @@ class Elliptic(_Named):
427
427
  sn = self.fE(sn, cn, dn)
428
428
  phi, d = _Phi2((r - sn) / dn)
429
429
  else: # PYCHOK no cover
430
- d = _0_0 # XXX continue?
430
+ d = _0_0 # XXX or continue?
431
431
  if fabs(d) < _TolJAC: # 3-4 trips
432
432
  _iterations(self, i)
433
433
  break
@@ -497,20 +497,20 @@ class Elliptic(_Named):
497
497
  '''(INTERNAL) Core of C{.fE}.
498
498
  '''
499
499
  if sn:
500
- sn2, cn2, dn2 = sn**2, cn**2, dn**2
501
- kp2, k2 = self.kp2, self.k2
500
+ cn2, dn2 = cn**2, dn**2
501
+ kp2, k2 = self.kp2, self.k2
502
502
  if k2 <= 0: # Carlson, eq. 4.6, <https://DLMF.NIST.gov/19.25.E9>
503
503
  Ei = _RF3(self, cn2, dn2, _1_0)
504
504
  if k2:
505
- Ei -= _RD(self, cn2, dn2, _1_0, _3over(k2, sn2))
505
+ Ei -= _RD(self, cn2, dn2, _1_0, _3over(k2, sn**2))
506
506
  elif kp2 >= 0: # k2 > 0, <https://DLMF.NIST.gov/19.25.E10>
507
507
  Ei = _over(k2 * fabs(cn), dn) # float
508
508
  if kp2:
509
- Ei += (_RD( self, cn2, _1_0, dn2, _3over(k2, sn2)) +
509
+ Ei += (_RD( self, cn2, _1_0, dn2, _3over(k2, sn**2)) +
510
510
  _RF3(self, cn2, dn2, _1_0)) * kp2
511
511
  else: # kp2 < 0, <https://DLMF.NIST.gov/19.25.E11>
512
512
  Ei = _over(dn, fabs(cn))
513
- Ei -= _RD(self, dn2, _1_0, cn2, _3over(kp2, sn2))
513
+ Ei -= _RD(self, dn2, _1_0, cn2, _3over(kp2, sn**2))
514
514
  Ei *= fabs(sn)
515
515
  ei = float(Ei)
516
516
  else: # PYCHOK no cover
@@ -1075,7 +1075,7 @@ def _ellipticError(where, *args, **kwds_cause_txt):
1075
1075
 
1076
1076
  x, t, kwds = _x_t_kwds(**kwds_cause_txt)
1077
1077
 
1078
- n = _dunder_nameof(where, where)
1078
+ n = _DUNDER_nameof(where, where)
1079
1079
  n = _DOT_(Elliptic.__name__, n)
1080
1080
  n = _SPACE_(_invokation_, n)
1081
1081
  u = unstr(n, *args, **kwds)
pygeodesy/errors.py CHANGED
@@ -14,12 +14,12 @@ C{PYGEODESY_EXCEPTION_CHAINING=std} or to any non-empty string.
14
14
  # from pygeodesy.basics import isint, isodd, issubclassof, itemsorted, _xinstanceof, _zip # _MODS
15
15
  # from pygeodesy.ellipsoidalBase import CartesianEllipsoidalBase, LatLonEllipsoidalBase # _MODS
16
16
  # from pygeodesy import errors # _MODS, _MODS.getattr
17
- from pygeodesy.internals import _dunder_nameof_, _plural, _tailof
17
+ from pygeodesy.internals import _DUNDER_nameof_, _getPYGEODESY, _plural, _tailof
18
18
  from pygeodesy.interns import MISSING, NN, _a_, _an_, _and_, _clip_, _COLON_, _COLONSPACE_, \
19
- _COMMASPACE_, _datum_, _ellipsoidal_, _incompatible_, _invalid_, \
20
- _keyword_, _LatLon_, _len_, _not_, _or_, _SPACE_, _specified_, \
21
- _UNDER_, _vs_, _with_
22
- from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS, _getenv, _PYTHON_X_DEV
19
+ _COMMASPACE_, _datum_, _ELLIPSIS_, _ellipsoidal_, _incompatible_, \
20
+ _invalid_, _keyword_, _LatLon_, _len_, _not_, _or_, _SPACE_, \
21
+ _specified_, _UNDER_, _vs_, _with_
22
+ from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS, _PYTHON_X_DEV
23
23
  # from pygeodesy import streprs as _streprs # _MODS
24
24
  # from pygeodesy.unitsBase import Str # _MODS
25
25
  # from pygeodesy.vector3dBase import Vector3dBase # _MODS
@@ -27,7 +27,7 @@ from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS, _getenv, _PYTHON_X_D
27
27
  from copy import copy as _copy
28
28
 
29
29
  __all__ = _ALL_LAZY.errors # _ALL_DOCS('_InvalidError', '_IsnotError') _under
30
- __version__ = '24.09.26'
30
+ __version__ = '24.10.14'
31
31
 
32
32
  _argument_ = 'argument'
33
33
  _box_ = 'box'
@@ -43,7 +43,7 @@ try:
43
43
  _exception_chaining = None # not available
44
44
  _ = Exception().__cause__ # Python 3.9+ exception chaining
45
45
 
46
- if _PYTHON_X_DEV or _getenv('PYGEODESY_EXCEPTION_CHAINING', NN): # == _std_
46
+ if _PYTHON_X_DEV or _getPYGEODESY('EXCEPTION_CHAINING'): # == _std_
47
47
  _exception_chaining = True # turned on, std
48
48
  raise AttributeError() # allow exception chaining
49
49
 
@@ -527,7 +527,7 @@ def _IsnotError(*types__, **name_value_Error_cause): # name=value [, Error=Type
527
527
  n, v = _xkwds_item2(kwds)
528
528
 
529
529
  n = _streprs.Fmt.PARENSPACED(n, repr(v))
530
- t = _not_(_an(_or(*_dunder_nameof_(*types__))) if types__ else _specified_)
530
+ t = _not_(_an(_or(*_DUNDER_nameof_(*types__))) if types__ else _specified_)
531
531
  return _XError(E, n, txt=t, cause=x)
532
532
 
533
533
 
@@ -895,8 +895,13 @@ def _Xorder(_Coeffs, Error, **Xorder): # in .auxLat, .ktm, .rhumb.bases, .rhumb
895
895
  def _xsError(X, xs, i, x, *n, **kwds): # in .fmath, ._fstats, .fsums
896
896
  '''(INTERNAL) Error for C{xs} or C{x}, item C{xs[i]}.
897
897
  '''
898
- return ((_xError(X, n[0], xs, **kwds) if n else
899
- _xError(X, xs=xs, **kwds)) if x is xs else
898
+ def _xs(*xs):
899
+ if len(xs) > 4:
900
+ xs = xs[:3] + (_ELLIPSIS_,) + xs[-1:]
901
+ return xs
902
+
903
+ return ((_xError(X, n[0], _xs(*xs), **kwds) if n else
904
+ _xError(X, xs=_xs(*xs), **kwds)) if x is xs else
900
905
  _xError(X, _streprs.Fmt.INDEX(xs=i), x, **kwds))
901
906
 
902
907
 
pygeodesy/etm.py CHANGED
@@ -91,7 +91,7 @@ from pygeodesy.utm import _cmlon, _LLEB, _parseUTM5, _toBand, _toXtm8, \
91
91
  from math import asinh, atan2, degrees, radians, sinh, sqrt
92
92
 
93
93
  __all__ = _ALL_LAZY.etm
94
- __version__ = '24.09.06'
94
+ __version__ = '24.10.21'
95
95
 
96
96
  _OVERFLOW = _1_EPS**2 # about 2e+31
97
97
  _TAYTOL = pow(EPS, 0.6)
@@ -1160,14 +1160,30 @@ if __name__ == '__main__': # MCCABE 16
1160
1160
 
1161
1161
  _main()
1162
1162
 
1163
+ # % python3.13 -m pygeodesy.etm -p 12 33.33 44.44
1164
+ # ExactTransverseMercator: 4276926.114803905599 4727193.767015309073 28.375536563148 1.233325101778
1165
+ # ExactTransverseMercator: 33.33 44.44 28.375536563148 1.233325101778
1166
+
1167
+ # % python3.13 -m pygeodesy.etm -s -p 12 33.33 44.44
1168
+ # KTransverseMercator: 4276926.114803904667 4727193.767015310004 28.375536563148 1.233325101778
1169
+ # KTransverseMercator: 33.33 44.44 28.375536563148 1.233325101778
1170
+
1163
1171
  # % python3.12 -m pygeodesy.etm -p 12 33.33 44.44
1164
1172
  # ExactTransverseMercator: 4276926.11480390653 4727193.767015309073 28.375536563148 1.233325101778
1165
1173
  # ExactTransverseMercator: 33.33 44.44 28.375536563148 1.233325101778
1166
1174
 
1167
- # % python3.12 -s -m pygeodesy.etm -p 12 33.33 44.44
1175
+ # % python3.12 -m pygeodesy.etm -s -p 12 33.33 44.44
1176
+ # KTransverseMercator: 4276926.114803904667 4727193.767015310004 28.375536563148 1.233325101778
1177
+ # KTransverseMercator: 33.33 44.44 28.375536563148 1.233325101778
1178
+
1179
+ # % python2 -m pygeodesy.etm -p 12 33.33 44.44
1168
1180
  # ExactTransverseMercator: 4276926.11480390653 4727193.767015309073 28.375536563148 1.233325101778
1169
1181
  # ExactTransverseMercator: 33.33 44.44 28.375536563148 1.233325101778
1170
1182
 
1183
+ # % python2 -m pygeodesy.etm -s -p 12 33.33 44.44
1184
+ # KTransverseMercator: 4276926.114803904667 4727193.767015310004 28.375536563148 1.233325101778
1185
+ # KTransverseMercator: 33.33 44.44 28.375536563148 1.233325101778
1186
+
1171
1187
  # % echo 33.33 44.44 | .../bin/TransverseMercatorProj
1172
1188
  # 4276926.114804 4727193.767015 28.375536563148 1.233325101778
1173
1189