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
pygeodesy/booleans.py CHANGED
@@ -23,7 +23,7 @@ from pygeodesy.errors import ClipError, _IsnotError, _TypeError, \
23
23
  _ValueError, _xattr, _xkwds_get, _xkwds_pop2
24
24
  from pygeodesy.fmath import favg, hypot, hypot2
25
25
  # from pygeodesy.fsums import fsum1 # _MODS
26
- from pygeodesy.interns import NN, _BANG_, _clip_, _clipid_, _COMMASPACE_, \
26
+ from pygeodesy.interns import NN, _BANG_, _clipid_, _COMMASPACE_, \
27
27
  _composite_, _DOT_, _duplicate_, _e_, \
28
28
  _ELLIPSIS_, _few_, _height_, _lat_, _LatLon_, \
29
29
  _lon_, _not_, _points_, _SPACE_, _too_, _X_, \
@@ -43,7 +43,7 @@ from pygeodesy.utily import fabs, _unrollon, _Wrap
43
43
  # from math import fabs # from .utily
44
44
 
45
45
  __all__ = _ALL_LAZY.booleans
46
- __version__ = '24.09.28'
46
+ __version__ = '24.10.22'
47
47
 
48
48
  _0_EPS = EPS # near-zero, positive
49
49
  _EPS_0 = -EPS # near-zero, negative
@@ -326,6 +326,21 @@ class LatLonFHP(_LatLonBool):
326
326
  _xscalar(other=other)
327
327
  return self.__class__(self.y * other, self.x * other)
328
328
 
329
+ # def _edge2(self):
330
+ # # Return the start and end point of the
331
+ # # edge containing I{intersection} C{v}.
332
+ # n = p = self
333
+ # while p.isintersection:
334
+ # p = p._prev
335
+ # if p is self:
336
+ # break
337
+ # while n.isintersection:
338
+ # n = n._next
339
+ # if n is self:
340
+ # break
341
+ # # assert p == self or not p._2Abs(self, n)
342
+ # return p, n
343
+
329
344
  def _e_x_str(self, t): # PYCHOK no cover
330
345
  if self._label:
331
346
  t = NN(self._label, t)
@@ -417,21 +432,6 @@ class LatLonFHP(_LatLonBool):
417
432
  n = n._next
418
433
  return p._prev, n
419
434
 
420
- # def _edge2(self):
421
- # # Return the start and end point of the
422
- # # edge containing I{intersection} C{v}.
423
- # n = p = self
424
- # while p.isintersection:
425
- # p = p._prev
426
- # if p is self:
427
- # break
428
- # while n.isintersection:
429
- # n = n._next
430
- # if n is self:
431
- # break
432
- # # assert p == self or not p._2Abs(self, n)
433
- # return p, n
434
-
435
435
  def _RPoracle(self, p1, p2, p3):
436
436
  # Relative Position oracle
437
437
  if p1._linked is self: # or p1._linked2(self):
@@ -729,7 +729,7 @@ class _Clip(_Named):
729
729
  try:
730
730
  i = cp._clips.index(self)
731
731
  if i != self._id:
732
- kwds[_clip_] = i
732
+ kwds.update(clip=i)
733
733
  except ValueError:
734
734
  pass
735
735
  kwds[_clipid_] = self._id
@@ -1201,7 +1201,7 @@ class _CompositeFHP(_CompositeBase):
1201
1201
  def _clip(self, corners, Union=False, Clas=None,
1202
1202
  **closed_inull_raiser_eps):
1203
1203
  # Clip this composite with another one, C{corners},
1204
- # using Foster-Hormann-Popa's algorithm.
1204
+ # using the Foster-Hormann-Popa's algorithm.
1205
1205
  P = self
1206
1206
  Q = self._class(corners, closed_inull_raiser_eps,
1207
1207
  eps=P._eps, raiser=False)
@@ -1442,6 +1442,7 @@ class _CompositeGH(_CompositeBase):
1442
1442
  raiser=False, xtend=False)
1443
1443
  bt = C._bottom_top_eps2
1444
1444
  lr = C._left_right_eps2
1445
+
1445
1446
  # 1. find intersections
1446
1447
  for s1, s2, Sc in S._edges3(**closed_inull_raiser_xtend_eps):
1447
1448
  if not (_outside(s1.x, s2.x, *lr) or
@@ -1546,7 +1547,7 @@ class _EdgeFHP(object):
1546
1547
  dq = q2 - q1
1547
1548
  dq2 = dq * dq # dot product, hypot2
1548
1549
  if dq2 > EPS2: # like ._clip
1549
- T, E = None, _EdgeFHP # self.__class__
1550
+ T, _E = None, _EdgeFHP # self.__class__
1550
1551
  p1, p2 = self._p1_p2
1551
1552
  ap1 = p1._2A(q1, q2)
1552
1553
  ap2_1 = p2._2A(q1, q2) - ap1
@@ -1558,10 +1559,10 @@ class _EdgeFHP(object):
1558
1559
  a, a_0, a_0_1, _ = _alpha4(-ap1 / ap2_1)
1559
1560
  b, b_0, b_0_1, _ = _alpha4(-aq1 / aq2_1)
1560
1561
  # distinguish intersection types
1561
- T = E.X_INTERSECT if a_0_1 and b_0_1 else (
1562
- E.P_INTERSECT if a_0_1 and b_0 else (
1563
- E.Q_INTERSECT if a_0 and b_0_1 else (
1564
- E.V_INTERSECT if a_0 and b_0 else None)))
1562
+ T = _E.X_INTERSECT if a_0_1 and b_0_1 else (
1563
+ _E.P_INTERSECT if a_0_1 and b_0 else (
1564
+ _E.Q_INTERSECT if a_0 and b_0_1 else (
1565
+ _E.V_INTERSECT if a_0 and b_0 else None)))
1565
1566
 
1566
1567
  elif fabs(ap1) < _0_EPS: # parallel or colinear edges
1567
1568
  dp = self._dp
@@ -1570,21 +1571,21 @@ class _EdgeFHP(object):
1570
1571
  a, a_0, a_0_1, _a_0_1 = _alpha4((d1 * dp) / self._dp2)
1571
1572
  b, b_0, b_0_1, _b_0_1 = _alpha4((d1 * dq) / (-dq2))
1572
1573
  # distinguish overlap type
1573
- T = E.X_OVERLAP if a_0_1 and b_0_1 else (
1574
- E.P_OVERLAP if a_0_1 and _b_0_1 else (
1575
- E.Q_OVERLAP if _a_0_1 and b_0_1 else (
1576
- E.V_OVERLAP if a_0 and b_0 else None)))
1574
+ T = _E.X_OVERLAP if a_0_1 and b_0_1 else (
1575
+ _E.P_OVERLAP if a_0_1 and _b_0_1 else (
1576
+ _E.Q_OVERLAP if _a_0_1 and b_0_1 else (
1577
+ _E.V_OVERLAP if a_0 and b_0 else None)))
1577
1578
 
1578
1579
  if T:
1579
- if T is E.X_INTERSECT:
1580
+ if T is _E.X_INTERSECT:
1580
1581
  v = p1 + a * self._dp
1581
1582
  yield T, (v, p1, p2, a), (v, q1, q2, b)
1582
- elif T in E.Vs:
1583
+ elif T in _E.Vs:
1583
1584
  yield T, (p1,), (q1,)
1584
1585
  else:
1585
- if T in E.Qs:
1586
+ if T in _E.Qs:
1586
1587
  yield T, (p1,), (p1, q1, q2, b)
1587
- if T in E.Ps:
1588
+ if T in _E.Ps:
1588
1589
  yield T, (q1, p1, p2, a), (q1,)
1589
1590
 
1590
1591
 
@@ -1898,9 +1899,9 @@ def _alpha4(a):
1898
1899
  # Return 4-tuple (alpha, -EPS < alpha < EPS,
1899
1900
  # 0 < alpha < 1,
1900
1901
  # not 0 < alpha < 1)
1901
- return (a, False, True, False) if _0_EPS < a < _EPS_1 else (
1902
- (a, False, False, True) if _0_EPS < fabs(a) else
1903
- (a, True, False, False))
1902
+ a_EPS = bool(_EPS_0 < a < _0_EPS)
1903
+ a_0_1 = bool(_0_EPS < a < _EPS_1)
1904
+ return a, a_EPS, a_0_1, (not a_0_1)
1904
1905
 
1905
1906
 
1906
1907
  def _Cps(Cp, composites_points, where):
@@ -1914,7 +1915,7 @@ def _Cps(Cp, composites_points, where):
1914
1915
 
1915
1916
 
1916
1917
  def _eps0(eps):
1917
- # Adjust C{eps} or C{None}.
1918
+ # Adjust C{eps} or C{0}.
1918
1919
  return eps if eps and eps > EPS else 0
1919
1920
 
1920
1921
 
@@ -1930,7 +1931,7 @@ def isBoolean(obj):
1930
1931
 
1931
1932
 
1932
1933
  def _left_right_bottom_top_eps2(p1, p2):
1933
- '''(INTERNAL) Return 2-tuple C{(left, right), (bottom, top)}, oversized.
1934
+ '''(INTERNAL) Return 2-tuple C{((left, right), (bottom, top))}, both oversized.
1934
1935
  '''
1935
1936
  return (_min_max_eps2(p1.x, p2.x),
1936
1937
  _min_max_eps2(p1.y, p2.y))
@@ -1939,18 +1940,23 @@ def _left_right_bottom_top_eps2(p1, p2):
1939
1940
  def _low_high_eps2(lo, hi, eps):
1940
1941
  '''(INTERNAL) Return 2-tuple C{(lo, hi)}, oversized.
1941
1942
  '''
1942
- lo *= (_1_0 + eps) if lo < 0 else (_1_0 - eps)
1943
- hi *= (_1_0 - eps) if hi < 0 else (_1_0 + eps)
1944
- return (lo or -eps), (hi or eps)
1943
+ # assert eps > 0
1944
+ lo -= fabs(eps * lo)
1945
+ hi += fabs(eps * hi)
1946
+ if lo < hi:
1947
+ pass
1948
+ elif lo > hi:
1949
+ lo, hi = hi, lo
1950
+ else:
1951
+ lo -= eps
1952
+ hi += eps
1953
+ return lo, hi
1945
1954
 
1946
1955
 
1947
1956
  def _min_max_eps2(*xs):
1948
1957
  '''(INTERNAL) Return 2-tuple C{(min, max)}, oversized.
1949
1958
  '''
1950
- lo, hi = min(xs), max(xs)
1951
- lo *= _1_EPS if lo < 0 else _EPS_1
1952
- hi *= _EPS_1 if hi < 0 else _1_EPS
1953
- return (lo or _EPS_0), (hi or _0_EPS)
1959
+ return _low_high_eps2(min(xs), max(xs), EPS)
1954
1960
 
1955
1961
 
1956
1962
  def _other(this, other):
@@ -1963,9 +1969,11 @@ def _other(this, other):
1963
1969
 
1964
1970
 
1965
1971
  def _outside(x1, x2, lo, hi):
1966
- '''(INTERNAL) Is C{(x1, x2)} outside C{(lo, hi)}?
1972
+ '''(INTERNAL) Are C{x1} and C{x2} outside C{(lo, hi)}?
1967
1973
  '''
1968
- return max(x1, x2) < lo or min(x1, x2) > hi
1974
+ # assert lo <= hi
1975
+ return (x1 < lo or x2 > hi) if x1 > x2 else \
1976
+ (x2 < lo or x1 > hi)
1969
1977
 
1970
1978
 
1971
1979
  __all__ += _ALL_DOCS(_BooleanBase, _Clip,
@@ -4,7 +4,7 @@
4
4
  u'''(INTERNAL) Private C{CartesianBase} class for elliposiodal, spherical and N-/vectorial
5
5
  C{Cartesian}s and public functions L{rtp2xyz}, L{rtp2xyz_}, L{xyz2rtp} and L{xyz2rtp_}.
6
6
 
7
- After I{(C) Chris Veness 2011-2015} published under the same MIT Licence**, see
7
+ After I{(C) Chris Veness 2011-2024} published under the same MIT Licence**, see
8
8
  U{https://www.Movable-Type.co.UK/scripts/latlong.html},
9
9
  U{https://www.Movable-Type.co.UK/scripts/latlong-vectors.html} and
10
10
  U{https://www.Movable-Type.co.UK/scripts/geodesy/docs/latlon-ellipsoidal.js.html}.
@@ -43,7 +43,7 @@ from pygeodesy.vector3d import Vector3d, _xyzhdlln4
43
43
  # from math import atan2, degrees, fabs, radians, sqrt # from .fmath, .utily
44
44
 
45
45
  __all__ = _ALL_LAZY.cartesianBase
46
- __version__ = '24.08.18'
46
+ __version__ = '24.10.12'
47
47
 
48
48
  _r_ = 'r'
49
49
  _theta_ = 'theta'
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__ = '24.09.28'
29
+ __version__ = '24.10.15'
30
30
 
31
31
 
32
32
  def _copysign_0_0(y):
@@ -256,7 +256,8 @@ _K0_UTM = _Float(_K0_UTM = 0.9996) # PYCHOK in .etm, .ktm, .utm, UTM scale at
256
256
  # sqrt(2) <https://WikiPedia.org/wiki/Square_root_of_2>
257
257
  # 1.414213562373095_048_801_688_724_209_698_078_569_671_875_376_948_073_176_679_737_99
258
258
  # _1SQRT2= _Float(_1SQRT2 =sqrt(_2_0) + 1)
259
- _SQRT2_2 = _Float(_SQRT2_2=sqrt(_0_5)) # PYCHOK = 0.707106781186547_6 == sqrt(2) / 2
259
+ # 0.707106781186547_524_400_844_362_104_849_039_284_835_937_688_474_036_588_339_868_99
260
+ _SQRT2_2 = _Float(_SQRT2_2=sqrt(_0_5)) # PYCHOK = 0.707106781186547_5 == sqrt(2) / 2
260
261
 
261
262
  INF = Float(INF =_inf) # PYCHOK INFinity, see function L{isinf}, L{isfinite}, NOT _Float!
262
263
  INT0 = Int( INT0= 0) # PYCHOK unique int(0) instance, see .fsums, useZ=False
@@ -494,20 +495,23 @@ def _umod_PI2(rad):
494
495
 
495
496
  if __name__ == '__main__':
496
497
 
497
- from pygeodesy import itemsorted, printf
498
-
499
- t = n = v = []
500
- for n, v in itemsorted(locals()):
501
- if isinstance(v, (Float, Int, Radius)):
502
- printf('%9s: %r', n, v.toRepr(std=False))
503
- if v.name != n:
504
- raise AssertionError('%r != %r' % (n, v))
505
- if v.name is not n:
506
- raise AssertionError('%r is not %r' % (n, v))
507
- if not n.startswith(_UNDER_):
508
- t.append(n)
509
- t.append(float_.__name__)
510
- printf('__all__ = %r', tuple(t))
498
+ def _main():
499
+ from pygeodesy import itemsorted, printf
500
+
501
+ t = n = v = []
502
+ for n, v in itemsorted(locals()):
503
+ if isinstance(v, (Float, Int, Radius)):
504
+ printf('%9s: %r', n, v.toRepr(std=False))
505
+ if v.name != n:
506
+ raise AssertionError('%r != %r' % (n, v))
507
+ if v.name is not n:
508
+ raise AssertionError('%r is not %r' % (n, v))
509
+ if not n.startswith(_UNDER_):
510
+ t.append(n)
511
+ t.append(float_.__name__)
512
+ printf('__all__ = %r', tuple(t))
513
+
514
+ _main()
511
515
 
512
516
  # **) MIT License
513
517
  #
pygeodesy/datums.py CHANGED
@@ -8,7 +8,7 @@ Classes L{Datum} and L{Transform} and registries L{Datums} and L{Transforms}, re
8
8
  Pure Python implementation of geodesy tools for ellipsoidal earth models, including datums
9
9
  and ellipsoid parameters for different geographic coordinate systems and methods for
10
10
  converting between them and to cartesian coordinates. Transcoded from JavaScript originals by
11
- I{(C) Chris Veness 2005-2016} and published under the same MIT Licence**, see U{latlon-ellipsoidal.js
11
+ I{(C) Chris Veness 2005-2024} and published under the same MIT Licence**, see U{latlon-ellipsoidal.js
12
12
  <https://www.Movable-Type.co.UK/scripts/geodesy/docs/latlon-ellipsoidal.js.html>}.
13
13
 
14
14
  Historical geodetic datums: a latitude/longitude point defines a geographic location on, above
@@ -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__ = '24.06.24'
97
+ __version__ = '24.10.12'
98
98
 
99
99
  _a_ellipsoid_ = _UNDER_(_a_, _ellipsoid_)
100
100
  _BD72_ = 'BD72'
@@ -610,7 +610,7 @@ def _mean_radius(radius, *lats):
610
610
  return r
611
611
 
612
612
 
613
- def _negastr(name): # in .trf
613
+ def _negastr(name): # in .trf, test/testTrf
614
614
  '''(INTERNAL) Negate a C{Transform/-Xform} name.
615
615
  '''
616
616
  b, m, p = _BAR_, _MINUS_, _PLUS_