pygeodesy 24.10.10__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 (54) hide show
  1. {PyGeodesy-24.10.10.dist-info → PyGeodesy-24.10.24.dist-info}/METADATA +10 -10
  2. {PyGeodesy-24.10.10.dist-info → PyGeodesy-24.10.24.dist-info}/RECORD +54 -54
  3. pygeodesy/__init__.py +13 -13
  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 +5 -5
  19. pygeodesy/etm.py +18 -2
  20. pygeodesy/fmath.py +4 -4
  21. pygeodesy/formy.py +4 -4
  22. pygeodesy/fsums.py +22 -12
  23. pygeodesy/geodesici.py +43 -40
  24. pygeodesy/geodesicw.py +3 -3
  25. pygeodesy/geodesicx/gxarea.py +3 -2
  26. pygeodesy/geodsolve.py +73 -24
  27. pygeodesy/geohash.py +2 -2
  28. pygeodesy/geoids.py +28 -27
  29. pygeodesy/internals.py +155 -85
  30. pygeodesy/interns.py +23 -20
  31. pygeodesy/karney.py +61 -12
  32. pygeodesy/latlonBase.py +13 -15
  33. pygeodesy/lazily.py +206 -214
  34. pygeodesy/mgrs.py +13 -13
  35. pygeodesy/named.py +11 -10
  36. pygeodesy/nvectorBase.py +1 -1
  37. pygeodesy/points.py +2 -2
  38. pygeodesy/props.py +34 -13
  39. pygeodesy/rhumb/bases.py +5 -5
  40. pygeodesy/rhumb/solve.py +7 -8
  41. pygeodesy/solveBase.py +7 -25
  42. pygeodesy/sphericalBase.py +20 -23
  43. pygeodesy/sphericalNvector.py +24 -23
  44. pygeodesy/sphericalTrigonometry.py +9 -8
  45. pygeodesy/streprs.py +5 -5
  46. pygeodesy/trf.py +6 -4
  47. pygeodesy/triaxials.py +46 -9
  48. pygeodesy/units.py +4 -3
  49. pygeodesy/ups.py +6 -6
  50. pygeodesy/utily.py +2 -2
  51. pygeodesy/utm.py +2 -2
  52. pygeodesy/vector3dBase.py +4 -5
  53. {PyGeodesy-24.10.10.dist-info → PyGeodesy-24.10.24.dist-info}/WHEEL +0 -0
  54. {PyGeodesy-24.10.10.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
19
  _COMMASPACE_, _datum_, _ELLIPSIS_, _ellipsoidal_, _incompatible_, \
20
20
  _invalid_, _keyword_, _LatLon_, _len_, _not_, _or_, _SPACE_, \
21
21
  _specified_, _UNDER_, _vs_, _with_
22
- from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS, _getenv, _PYTHON_X_DEV
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.10.01'
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
 
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
 
pygeodesy/fmath.py CHANGED
@@ -16,7 +16,7 @@ from pygeodesy.errors import _IsnotError, LenError, _TypeError, _ValueError, \
16
16
  from pygeodesy.fsums import _2float, Fsum, fsum, _isFsum_2Tuple, _1primed, \
17
17
  Fmt, unstr
18
18
  from pygeodesy.interns import MISSING, _negative_, _not_scalar_
19
- from pygeodesy.lazily import _ALL_LAZY, _sys_version_info2
19
+ from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS
20
20
  # from pygeodesy.streprs import Fmt, unstr # from .fsums
21
21
  from pygeodesy.units import Int_, _isHeight, _isRadius, Float_ # PYCHOK for .heights
22
22
 
@@ -24,7 +24,7 @@ from math import fabs, sqrt # pow
24
24
  import operator as _operator # in .datums, .trf, .utm
25
25
 
26
26
  __all__ = _ALL_LAZY.fmath
27
- __version__ = '24.10.04'
27
+ __version__ = '24.10.11'
28
28
 
29
29
  # sqrt(2) - 1 <https://WikiPedia.org/wiki/Square_root_of_2>
30
30
  _0_4142 = 0.41421356237309504880 # ... ~ 3730904090310553 / 9007199254740992
@@ -804,7 +804,7 @@ def fremainder(x, y):
804
804
  return r
805
805
 
806
806
 
807
- if _sys_version_info2 < (3, 8): # PYCHOK no cover
807
+ if _MODS.sys_version_info2 < (3, 8): # PYCHOK no cover
808
808
  from math import hypot # OK in Python 3.7-
809
809
 
810
810
  def hypot_(*xs):
@@ -831,7 +831,7 @@ if _sys_version_info2 < (3, 8): # PYCHOK no cover
831
831
  '''
832
832
  return float(_Hypot(*xs))
833
833
 
834
- elif _sys_version_info2 < (3, 10):
834
+ elif _MODS.sys_version_info2 < (3, 10):
835
835
  # In Python 3.8 and 3.9 C{math.hypot} is inaccurate, see
836
836
  # U{agdhruv<https://GitHub.com/geopy/geopy/issues/466>},
837
837
  # U{cffk<https://Bugs.Python.org/issue43088>} and module
pygeodesy/formy.py CHANGED
@@ -20,11 +20,11 @@ from pygeodesy.errors import IntersectionError, LimitError, limiterrors, \
20
20
  _xcallable,_xkwds, _xkwds_pop2
21
21
  from pygeodesy.fmath import euclid, hypot, hypot2, sqrt0
22
22
  from pygeodesy.fsums import fsumf_, Fmt, unstr
23
- # from pygeodesy.internals import _dunder_nameof # from .named
23
+ # from pygeodesy.internals import _DUNDER_nameof # from .named
24
24
  from pygeodesy.interns import _delta_, _distant_, _inside_, _SPACE_, _too_
25
25
  from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS
26
26
  from pygeodesy.named import _name__, _name2__, _NamedTuple, _xnamed, \
27
- _dunder_nameof
27
+ _DUNDER_nameof
28
28
  from pygeodesy.namedTuples import Bearing2Tuple, Distance4Tuple, LatLon2Tuple, \
29
29
  Intersection3Tuple, PhiLam2Tuple, Vector3Tuple
30
30
  # from pygeodesy.streprs import Fmt, unstr # from .fsums
@@ -43,7 +43,7 @@ from contextlib import contextmanager
43
43
  from math import asin, atan, atan2, cos, degrees, fabs, radians, sin, sqrt # pow
44
44
 
45
45
  __all__ = _ALL_LAZY.formy
46
- __version__ = '24.09.27'
46
+ __version__ = '24.10.14'
47
47
 
48
48
  _RADIANS2 = (PI / _180_0)**2 # degrees- to radians-squared
49
49
  _ratio_ = 'ratio'
@@ -1136,7 +1136,7 @@ class _idllmn6(object): # see also .geodesicw._wargs, .latlonBase._toCartesian3
1136
1136
  _, lat2, lon2 = _Wrap.latlon3(lon1, lat2, lon2, wrap)
1137
1137
  kwds = _xkwds(kwds, wrap=wrap) # for _xError
1138
1138
  m = small if small is _100km else Meter_(small=small)
1139
- n = _dunder_nameof(intersections2 if s else intersection2)
1139
+ n = _DUNDER_nameof(intersections2 if s else intersection2)
1140
1140
  if datum is None or euclidean(lat1, lon1, lat2, lon2) < m:
1141
1141
  d, m = None, _MODS.vector3d
1142
1142
  _i = m._intersects2 if s else m._intersect3d3
pygeodesy/fsums.py CHANGED
@@ -48,12 +48,12 @@ from pygeodesy.errors import _AssertionError, _OverflowError, _TypeError, \
48
48
  _ValueError, _xError, _xError2, _xkwds, \
49
49
  _xkwds_get, _xkwds_get1, _xkwds_not, \
50
50
  _xkwds_pop, _xsError
51
- from pygeodesy.internals import _enquote, _passarg
51
+ from pygeodesy.internals import _enquote, _getPYGEODESY, _MODS, _passarg
52
52
  from pygeodesy.interns import NN, _arg_, _COMMASPACE_, _DOT_, _from_, \
53
53
  _not_finite_, _SPACE_, _std_, _UNDER_
54
- from pygeodesy.lazily import _ALL_LAZY, _getenv, _sys_version_info2
54
+ # from pygeodesy.lazily import _ALL_LAZY # from .named
55
55
  from pygeodesy.named import _name__, _name2__, _Named, _NamedTuple, \
56
- _NotImplemented
56
+ _NotImplemented, _ALL_LAZY
57
57
  from pygeodesy.props import _allPropertiesOf_n, deprecated_method, \
58
58
  deprecated_property_RO, Property, \
59
59
  Property_RO, property_RO
@@ -64,7 +64,7 @@ from math import fabs, isinf, isnan, \
64
64
  ceil as _ceil, floor as _floor # PYCHOK used! .ltp
65
65
 
66
66
  __all__ = _ALL_LAZY.fsums
67
- __version__ = '24.10.09'
67
+ __version__ = '24.10.22'
68
68
 
69
69
  from pygeodesy.interns import (
70
70
  _PLUS_ as _add_op_, # in .auxilats.auxAngle
@@ -79,15 +79,15 @@ from pygeodesy.interns import (
79
79
  )
80
80
  _floordiv_op_ = _truediv_op_ * 2 # _DSLASH_
81
81
  _divmod_op_ = _floordiv_op_ + _mod_op_
82
- _F2PRODUCT = _getenv('PYGEODESY_FSUM_F2PRODUCT', NN)
82
+ _F2PRODUCT = _getPYGEODESY('FSUM_F2PRODUCT')
83
83
  _iadd_op_ = _add_op_ + _fset_op_ # in .auxilats.auxAngle, .fstats
84
84
  _integer_ = 'integer'
85
85
  _isub_op_ = _sub_op_ + _fset_op_ # in .auxilats.auxAngle
86
86
  _NONFINITEr = _0_0 # NOT INT0!
87
- _NONFINITES = _getenv('PYGEODESY_FSUM_NONFINITES', NN)
87
+ _NONFINITES = _getPYGEODESY('FSUM_NONFINITES')
88
88
  _non_zero_ = 'non-zero'
89
89
  _pow_op_ = _mul_op_ * 2 # _DSTAR_
90
- _RESIDUAL_0_0 = _getenv('PYGEODESY_FSUM_RESIDUAL', _0_0)
90
+ _RESIDUAL_0_0 = _getPYGEODESY('FSUM_RESIDUAL', _0_0)
91
91
  _significant_ = 'significant'
92
92
  _threshold_ = 'threshold'
93
93
 
@@ -516,7 +516,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
516
516
  @see: Module L{fsums<pygeodesy.fsums>} for env variables C{PYGEODESY_FSUM_F2PRODUCT},
517
517
  C{PYGEODESY_FSUM_NONFINITES} and C{PYGEODESY_FSUM_RESIDUAL}.
518
518
  '''
519
- _f2product = _sys_version_info2 > (3, 12) or bool(_F2PRODUCT)
519
+ _f2product = _MODS.sys_version_info2 > (3, 12) or bool(_F2PRODUCT)
520
520
  _isfine = {} # == _isfinite, see nonfiniterrors()
521
521
  _n = 0
522
522
  # _ps = [] # partial sums
@@ -913,6 +913,14 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
913
913
  f = self._copy_2r(other, self.__rdivmod__)
914
914
  return f._fdivmod2(self, _divmod_op_)
915
915
 
916
+ # turned off, called by _deepcopy and _copy
917
+ # def __reduce__(self): # Python 3.8+
918
+ # ''' Pickle, like std C{fractions.Fraction}, see U{__reduce__
919
+ # <https://docs.Python.org/3/library/pickle.html#object.__reduce__>}
920
+ # '''
921
+ # dict_ = self._Fsum_as().__dict__ # no __setstate__
922
+ # return (self.__class__, self.partials, dict_)
923
+
916
924
  # def __repr__(self):
917
925
  # '''Return the default C{repr(this)}.
918
926
  # '''
@@ -926,7 +934,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
926
934
  f = self._copy_2r(other, self.__rfloordiv__)
927
935
  return f._floordiv(self, _floordiv_op_)
928
936
 
929
- def __rmatmul__(self, other): # PYCHOK no cover
937
+ def __rmatmul__(self, other): # PYCHOK no coveS
930
938
  '''Not implemented.'''
931
939
  return _NotImplemented(self, other)
932
940
 
@@ -1015,7 +1023,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1015
1023
 
1016
1024
  __trunc__ = __int__
1017
1025
 
1018
- if _sys_version_info2 < (3, 0): # PYCHOK no cover
1026
+ if _MODS.sys_version_info2 < (3, 0): # PYCHOK no cover
1019
1027
  # <https://docs.Python.org/2/library/operator.html#mapping-operators-to-functions>
1020
1028
  __div__ = __truediv__
1021
1029
  __idiv__ = __itruediv__
@@ -1101,7 +1109,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1101
1109
  def _copy_2(self, which, name=NN):
1102
1110
  '''(INTERNAL) Copy for I{dyadic} operators.
1103
1111
  '''
1104
- n = name or which.__name__ # _dunder_nameof
1112
+ n = name or which.__name__ # _DUNDER_nameof
1105
1113
  # NOT .classof due to .Fdot(a, *b) args, etc.
1106
1114
  f = _Named.copy(self, deep=False, name=n)
1107
1115
  f._ps = list(self._ps) # separate list
@@ -1152,6 +1160,8 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
1152
1160
  fs = _xs(xs, **kwds) # PYCHOK yield
1153
1161
  ps = self._ps
1154
1162
  ps[:] = self._ps_acc(list(ps), fs, up=up)
1163
+ # if len(ps) > 16:
1164
+ # _ = _psum(ps, **self._isfine)
1155
1165
  return self
1156
1166
 
1157
1167
  def _facc_args(self, xs, **up):
@@ -2803,7 +2813,7 @@ def _xsum(which, xs, nonfinites=None, primed=0, **floats): # origin=0
2803
2813
  # delete all decorators, etc.
2804
2814
  del _allPropertiesOf_n, deprecated_method, deprecated_property_RO, \
2805
2815
  Property, Property_RO, property_RO, _ALL_LAZY, _F2PRODUCT, \
2806
- MANT_DIG, _NONFINITES, _RESIDUAL_0_0, _getenv, _std_
2816
+ MANT_DIG, _NONFINITES, _RESIDUAL_0_0, _getPYGEODESY, _std_
2807
2817
 
2808
2818
  if __name__ == '__main__':
2809
2819