pygeodesy 24.10.10__py2.py3-none-any.whl → 24.11.11__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 (76) hide show
  1. {PyGeodesy-24.10.10.dist-info → PyGeodesy-24.11.11.dist-info}/METADATA +12 -12
  2. PyGeodesy-24.11.11.dist-info/RECORD +118 -0
  3. {PyGeodesy-24.10.10.dist-info → PyGeodesy-24.11.11.dist-info}/WHEEL +1 -1
  4. pygeodesy/__init__.py +14 -14
  5. pygeodesy/__main__.py +5 -5
  6. pygeodesy/albers.py +12 -17
  7. pygeodesy/azimuthal.py +51 -61
  8. pygeodesy/basics.py +60 -62
  9. pygeodesy/booleans.py +87 -79
  10. pygeodesy/cartesianBase.py +6 -6
  11. pygeodesy/constants.py +23 -19
  12. pygeodesy/css.py +7 -8
  13. pygeodesy/datums.py +3 -3
  14. pygeodesy/deprecated/__init__.py +1 -1
  15. pygeodesy/deprecated/classes.py +9 -9
  16. pygeodesy/deprecated/functions.py +6 -6
  17. pygeodesy/dms.py +250 -270
  18. pygeodesy/ecef.py +11 -14
  19. pygeodesy/ellipsoidalBase.py +106 -121
  20. pygeodesy/ellipsoidalBaseDI.py +114 -118
  21. pygeodesy/ellipsoidalExact.py +35 -37
  22. pygeodesy/ellipsoidalNvector.py +4 -4
  23. pygeodesy/ellipsoidalVincenty.py +2 -2
  24. pygeodesy/ellipsoids.py +10 -51
  25. pygeodesy/elliptic.py +14 -14
  26. pygeodesy/errors.py +28 -28
  27. pygeodesy/etm.py +92 -68
  28. pygeodesy/fmath.py +42 -40
  29. pygeodesy/formy.py +7 -6
  30. pygeodesy/fsums.py +72 -51
  31. pygeodesy/geodesici.py +43 -40
  32. pygeodesy/geodesicw.py +17 -16
  33. pygeodesy/geodesicx/__init__.py +2 -2
  34. pygeodesy/geodesicx/gxarea.py +3 -2
  35. pygeodesy/geodsolve.py +79 -39
  36. pygeodesy/geohash.py +2 -2
  37. pygeodesy/geoids.py +32 -31
  38. pygeodesy/heights.py +2 -2
  39. pygeodesy/internals.py +201 -147
  40. pygeodesy/interns.py +23 -20
  41. pygeodesy/karney.py +62 -13
  42. pygeodesy/ktm.py +11 -13
  43. pygeodesy/latlonBase.py +18 -20
  44. pygeodesy/lazily.py +210 -218
  45. pygeodesy/lcc.py +4 -4
  46. pygeodesy/ltp.py +10 -10
  47. pygeodesy/ltpTuples.py +74 -75
  48. pygeodesy/mgrs.py +20 -21
  49. pygeodesy/named.py +15 -10
  50. pygeodesy/nvectorBase.py +1 -1
  51. pygeodesy/osgr.py +9 -12
  52. pygeodesy/points.py +2 -2
  53. pygeodesy/props.py +35 -14
  54. pygeodesy/resections.py +9 -10
  55. pygeodesy/rhumb/__init__.py +1 -1
  56. pygeodesy/rhumb/bases.py +5 -5
  57. pygeodesy/rhumb/solve.py +9 -10
  58. pygeodesy/simplify.py +5 -5
  59. pygeodesy/solveBase.py +7 -25
  60. pygeodesy/sphericalBase.py +20 -23
  61. pygeodesy/sphericalNvector.py +103 -145
  62. pygeodesy/sphericalTrigonometry.py +68 -73
  63. pygeodesy/streprs.py +5 -5
  64. pygeodesy/trf.py +6 -4
  65. pygeodesy/triaxials.py +46 -9
  66. pygeodesy/units.py +5 -4
  67. pygeodesy/ups.py +6 -6
  68. pygeodesy/utily.py +2 -2
  69. pygeodesy/utm.py +7 -7
  70. pygeodesy/vector2d.py +13 -13
  71. pygeodesy/vector3d.py +19 -21
  72. pygeodesy/vector3dBase.py +21 -19
  73. pygeodesy/webmercator.py +4 -4
  74. pygeodesy/wgrs.py +4 -4
  75. PyGeodesy-24.10.10.dist-info/RECORD +0 -118
  76. {PyGeodesy-24.10.10.dist-info → PyGeodesy-24.11.11.dist-info}/top_level.txt +0 -0
pygeodesy/booleans.py CHANGED
@@ -21,9 +21,9 @@ from pygeodesy.basics import isodd, issubclassof, map2, _xscalar
21
21
  from pygeodesy.constants import EPS, EPS2, INT0, _0_0, _0_5, _1_0
22
22
  from pygeodesy.errors import ClipError, _IsnotError, _TypeError, \
23
23
  _ValueError, _xattr, _xkwds_get, _xkwds_pop2
24
- from pygeodesy.fmath import favg, hypot, hypot2
24
+ from pygeodesy.fmath import favg, fdot_, 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,12 +43,12 @@ 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.11.07'
47
47
 
48
- _0_EPS = EPS # near-zero, positive
49
- _EPS_0 = -EPS # near-zero, negative
50
- _1_EPS = _1_0 + EPS # near-one, over
51
- _EPS_1 = _1_0 - EPS # near-one, under
48
+ _0EPS = EPS # near-zero, positive
49
+ _EPS0 = -EPS # near-zero, negative
50
+ _1EPS = _1_0 + EPS # near-one, over
51
+ _EPS1 = _1_0 - EPS # near-one, under
52
52
  _10EPS = EPS * 10 # see ._2Abs, ._10eps
53
53
 
54
54
  _alpha_ = 'alpha'
@@ -162,7 +162,7 @@ class _LatLonBool(_Named):
162
162
  other.x == self.x and
163
163
  other.y == self.y)
164
164
 
165
- def __ne__(self, other): # required for Python 2
165
+ def __ne__(self, other): # required for Python 2 # PYCHOK no cover
166
166
  return not self.__eq__(other)
167
167
 
168
168
  def __repr__(self):
@@ -316,16 +316,31 @@ class LatLonFHP(_LatLonBool):
316
316
 
317
317
  def __mod__(self, other): # cross product
318
318
  _other(self, other)
319
- return self.x * other.y - self.y * other.x
319
+ return fdot_(self.x, other.y, -self.y, other.x)
320
320
 
321
321
  def __mul__(self, other): # dot product
322
322
  _other(self, other)
323
- return self.x * other.x + self.y * other.y
323
+ return fdot_(self.x, other.x, self.y, other.y)
324
324
 
325
325
  def __rmul__(self, other): # scalar product
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)
@@ -409,7 +424,7 @@ class LatLonFHP(_LatLonBool):
409
424
  def _prev_next2(self):
410
425
  # Adjust 2-tuple (._prev, ._next) iff a I{duplicate} intersection
411
426
  p, n = self, self._next
412
- if self._isduplicate:
427
+ if self._isduplicate: # PYCHOK no cover
413
428
  p = self._dupof
414
429
  while p._isduplicate:
415
430
  p = p._dupof
@@ -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):
@@ -580,7 +580,7 @@ class _Clip(_Named):
580
580
  '''
581
581
  return self._bltr4 > _other(self, other)._bltr4
582
582
 
583
- def __hash__(self): # PYCHOK no over
583
+ def __hash__(self): # PYCHOK no cover
584
584
  return hash(self._bltr4)
585
585
 
586
586
  def __iter__(self):
@@ -610,7 +610,7 @@ class _Clip(_Named):
610
610
  '''
611
611
  return self._bltr4 < _other(self, other)._bltr4
612
612
 
613
- def __ne__(self, other): # required for Python 2
613
+ def __ne__(self, other): # required for Python 2 # PYCHOK no cover
614
614
  '''See method C{__eq__}.
615
615
  '''
616
616
  return not self.__eq__(other)
@@ -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,45 +1547,45 @@ 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
1553
- if fabs(ap2_1) > _0_EPS: # non-parallel edges
1554
+ if fabs(ap2_1) > _0EPS: # non-parallel edges
1554
1555
  aq1 = q1._2A(p1, p2)
1555
1556
  aq2_1 = q2._2A(p1, p2) - aq1
1556
- if fabs(aq2_1) > _0_EPS:
1557
+ if fabs(aq2_1) > _0EPS:
1557
1558
  # compute and classify alpha and beta
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
- elif fabs(ap1) < _0_EPS: # parallel or colinear edges
1567
+ elif fabs(ap1) < _0EPS: # parallel or colinear edges
1567
1568
  dp = self._dp
1568
1569
  d1 = q1 - p1
1569
1570
  # compute and classify alpha and beta
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
 
@@ -1609,8 +1610,8 @@ class _EdgeGH(object):
1609
1610
 
1610
1611
  def _alpha2(self, x, y, dx, dy):
1611
1612
  # Return C{(alpha)}, see .points.nearestOn5
1612
- a = (y * dy + x * dx) / self._hypot2
1613
- d = (y * dx - x * dy) / self._hypot0
1613
+ a = fdot_(y, dy, x, dx) / self._hypot2
1614
+ d = fdot_(y, dx, -x, dy) / self._hypot0
1614
1615
  return a, fabs(d)
1615
1616
 
1616
1617
  def _Error(self, n, *args, **kwds): # PYCHOK no cover
@@ -1621,7 +1622,7 @@ class _EdgeGH(object):
1621
1622
  @Property_RO
1622
1623
  def _hypot0(self):
1623
1624
  _, sx, _, sy = self._x_sx_y_sy
1624
- return hypot(sx, sy) * _0_EPS
1625
+ return hypot(sx, sy) * _0EPS
1625
1626
 
1626
1627
  @Property_RO
1627
1628
  def _hypot2(self):
@@ -1649,33 +1650,33 @@ class _EdgeGH(object):
1649
1650
  cy = c2.y - c1_y
1650
1651
  d = cy * sx - cx * sy
1651
1652
 
1652
- if fabs(d) > _0_EPS: # non-parallel edges
1653
+ if fabs(d) > _0EPS: # non-parallel edges
1653
1654
  dx = x - c1_x
1654
1655
  dy = y - c1_y
1655
- ca = (sx * dy - sy * dx) / d
1656
- if _0_EPS < ca < _EPS_1 or (self._xtend and
1657
- _EPS_0 < ca < _1_EPS):
1658
- sa = (cx * dy - cy * dx) / d
1659
- if _0_EPS < sa < _EPS_1 or (self._xtend and
1660
- _EPS_0 < sa < _1_EPS):
1656
+ ca = fdot_(sx, dy, -sy, dx) / d
1657
+ if _0EPS < ca < _EPS1 or (self._xtend and
1658
+ _EPS0 < ca < _1EPS):
1659
+ sa = fdot_(cx, dy, -cy, dx) / d
1660
+ if _0EPS < sa < _EPS1 or (self._xtend and
1661
+ _EPS0 < sa < _1EPS):
1661
1662
  yield (y + sa * sy), (x + sa * sx), sa, ca
1662
1663
 
1663
1664
  # unhandled, "degenerate" cases 1, 2 or 3
1664
- elif self._raiser and not (sa < _EPS_0 or sa > _1_EPS): # PYCHOK no cover
1665
+ elif self._raiser and not (sa < _EPS0 or sa > _1EPS): # PYCHOK no cover
1665
1666
  raise self._Error(1, c1, c2, sa=sa) # intersection at s1 or s2
1666
1667
 
1667
- elif self._raiser and not (ca < _EPS_0 or ca > _1_EPS): # PYCHOK no cover
1668
+ elif self._raiser and not (ca < _EPS0 or ca > _1EPS): # PYCHOK no cover
1668
1669
  # intersection at c1 or c2 or at c1 or c2 and s1 or s2
1669
- sa = (cx * dy - cy * dx) / d
1670
- e = 2 if sa < _EPS_0 or sa > _1_EPS else 3
1670
+ sa = fdot_(cx, dy, -cy, dx) / d
1671
+ e = 2 if sa < _EPS0 or sa > _1EPS else 3
1671
1672
  raise self._Error(e, c1, c2, ca=ca)
1672
1673
 
1673
1674
  elif parallel and (sx or sy) and (cx or cy): # PYCHOK no cover
1674
1675
  # non-null, parallel or colinear edges
1675
1676
  sa1, d1 = self._alpha2(c1_x - x, c1_y - y, sx, sy)
1676
1677
  sa2, d2 = self._alpha2(c2.x - x, c2.y - y, sx, sy)
1677
- if max(d1, d2) < _0_EPS:
1678
- if self._xtend and not _outside(sa1, sa2, _EPS_0, _1_EPS):
1678
+ if max(d1, d2) < _0EPS:
1679
+ if self._xtend and not _outside(sa1, sa2, _EPS0, _1EPS):
1679
1680
  if sa1 > sa2: # anti-parallel
1680
1681
  sa1, sa2 = sa2, sa1
1681
1682
  ca1, ca2 = _1_0, _0_0
@@ -1693,7 +1694,7 @@ class _EdgeGH(object):
1693
1694
  yield (y + sy), (x + sx), ca2, _alpha1(ca2 - ca)
1694
1695
  else: # c2 is between s1 and s2
1695
1696
  yield (y + sa2 * sy), (x + sa2 * sx), sa2, ca2
1696
- elif self._raiser and not _outside(sa1, sa2, _0_0, _1_EPS):
1697
+ elif self._raiser and not _outside(sa1, sa2, _0_0, _1EPS):
1697
1698
  raise self._Error(4, c1, c2, d1=d1, d2=d2)
1698
1699
 
1699
1700
 
@@ -1886,9 +1887,9 @@ class BooleanGH(_CompositeGH, _BooleanBase):
1886
1887
  return self._boolean(other, True, False, self.__sub__)
1887
1888
 
1888
1889
 
1889
- def _alpha1(alpha):
1890
+ def _alpha1(alpha): # PYCHOK no cover
1890
1891
  # Return C{alpha} in C{[0..1]} range
1891
- if _EPS_0 < alpha < _1_EPS:
1892
+ if _EPS0 < alpha < _1EPS:
1892
1893
  return max(_0_0, min(alpha, _1_0))
1893
1894
  t = _not_(Fmt.SQUARE(_ELLIPSIS_(0, 1)))
1894
1895
  raise ClipError(_alpha_, alpha, txt=t)
@@ -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(_EPS0 < a < _0EPS)
1903
+ a_0_1 = bool(_0EPS < a < _EPS1)
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.11.06'
47
47
 
48
48
  _r_ = 'r'
49
49
  _theta_ = 'theta'
@@ -186,7 +186,7 @@ class CartesianBase(Vector3d):
186
186
  or L{Local9Tuple}).
187
187
  @kwarg Cartesian: Optional (geocentric) class to return the destination
188
188
  or C{None}.
189
- @kwarg name_Cartesian_kwds: Optional C{B{name}=NN} (C{str}) and optional,
189
+ @kwarg name_Cartesian_kwds: Optional C{B{name}=NN} (C{str}) and optionally,
190
190
  additional B{C{Cartesian}} keyword arguments, ignored if
191
191
  C{B{Cartesian} is None}.
192
192
 
@@ -768,7 +768,7 @@ class CartesianBase(Vector3d):
768
768
  (C{Nvector}) or C{None}.
769
769
  @kwarg datum: Optional datum (L{Datum}, L{Ellipsoid}, L{Ellipsoid2}
770
770
  or L{a_f2Tuple}) overriding this cartesian's datum.
771
- @kwarg name_Nvector_kwds: Optional C{B{name}=NN} (C{str}) and optional,
771
+ @kwarg name_Nvector_kwds: Optional C{B{name}=NN} (C{str}) and optionally,
772
772
  additional B{C{Nvector}} keyword arguments, ignored if
773
773
  C{B{Nvector} is None}.
774
774
 
@@ -940,8 +940,8 @@ def rtp2xyz_(r_rtp, theta=0, phi=0, **name_Cartesian_and_kwds):
940
940
  @arg theta: Inclination B{C{theta}} (C{radians} with respect to the positive z-axis),
941
941
  required if C{B{r_rtp}} is C{scalar}, ignored otherwise.
942
942
  @arg phi: Azimuthal angle B{C{phi}} (C{radians}), like B{C{theta}}.
943
- @kwarg name_Cartesian_and_kwds: Optional C{B{name}=NN} (C{str}), a C{B{Cartesian}=None}
944
- class to return the coordinates and optional, additional C{B{Cartesian}}
943
+ @kwarg name_Cartesian_and_kwds: Optional C{B{name}=NN} (C{str}), C{B{Cartesian}=None}
944
+ class to return the coordinates and optionally, additional C{B{Cartesian}}
945
945
  keyword arguments.
946
946
 
947
947
  @return: A C{B{Cartesian}(x, y, z)} instance or if no C{B{Cartesian}} keyword argument
pygeodesy/constants.py CHANGED
@@ -10,10 +10,10 @@ L{pygeodesy.isnon0} and L{pygeodesy.remainder}.
10
10
  # make sure int/int division yields float quotient, see .basics
11
11
  from __future__ import division as _; del _ # PYCHOK semicolon
12
12
 
13
- from pygeodesy.basics import _copysign, isbool, iscomplex, isint, _0_0
13
+ from pygeodesy.basics import _copysign, isbool, iscomplex, isint
14
14
  from pygeodesy.errors import _xError, _xError2, _xkwds_get1, _xkwds_item2
15
15
  # from pygeodesy.fsums import _isFsum_2Tuple # _MODS
16
- # from pygeodesy.internals import _0_0 # from .basics
16
+ from pygeodesy.internals import _0_0, _100_0
17
17
  from pygeodesy.interns import _INF_, _NAN_, _UNDER_
18
18
  from pygeodesy.lazily import _ALL_MODS as _MODS, _ALL_LAZY
19
19
  # from pygeodesy.streprs import Fmt # from .unitsBase
@@ -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.11.06'
30
30
 
31
31
 
32
32
  def _copysign_0_0(y):
@@ -185,7 +185,7 @@ _32_0 = _float( 32) # PYCHOK expected
185
185
  _60_0 = _float( 60) # PYCHOK expected
186
186
  _64_0 = _float( 64) # PYCHOK expected
187
187
  _90_0 = _float( 90) # PYCHOK expected
188
- _100_0 = _float( 100) # PYCHOK expected
188
+ _100_0 = _float(_100_0) # PYCHOK expected
189
189
  _180_0 = _float( 180) # PYCHOK expected
190
190
  _270_0 = _float( 270) # PYCHOK expected
191
191
  _360_0 = _float( 360) # PYCHOK expected
@@ -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/css.py CHANGED
@@ -33,7 +33,7 @@ from pygeodesy.units import Azimuth, Degrees, Easting, Height, _heigHt, \
33
33
  # from math import fabs # from .karney
34
34
 
35
35
  __all__ = _ALL_LAZY.css
36
- __version__ = '24.07.25'
36
+ __version__ = '24.11.06'
37
37
 
38
38
 
39
39
  def _CS0(cs0):
@@ -313,16 +313,15 @@ class CassiniSoldner(_NamedBase):
313
313
  self._sb0, self._cb0 = _norm2(s * g.f1, c)
314
314
 
315
315
  def reverse(self, easting, northing, LatLon=None, **name_LatLon_kwds):
316
- '''Convert a Cassini-Soldner location to (ellipsoidal) geodetic
317
- lat- and longitude.
316
+ '''Convert a Cassini-Soldner location to (ellipsoidal) geodetic lat- and longitude.
318
317
 
319
318
  @arg easting: Easting of the location (C{meter}).
320
319
  @arg northing: Northing of the location (C{meter}).
321
- @kwarg LatLon: Optional, ellipsoidal class to return the geodetic
322
- location as (C{LatLon}) or C{None}.
323
- @kwarg name_LatLon_kwds: Optional name C{B{name}=NN} (C{str}) and
324
- optional, additional B{C{LatLon}} keyword arguments,
325
- ignored if C{B{LatLon} is None}.
320
+ @kwarg LatLon: Optional, ellipsoidal class to return the geodetic location as
321
+ (C{LatLon}) or C{None}.
322
+ @kwarg name_LatLon_kwds: Optional name C{B{name}=NN} (C{str}) and optionally,
323
+ additional B{C{LatLon}} keyword arguments, ignored if C{B{LatLon}
324
+ is None}.
326
325
 
327
326
  @return: Geodetic location B{C{LatLon}} or if C{B{LatLon} is None},
328
327
  a L{LatLon2Tuple}C{(lat, lon)}.
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_
@@ -27,7 +27,7 @@ __all__ = (_ALL_DEPRECATED.deprecated_bases +
27
27
  _ALL_DEPRECATED.deprecated_classes +
28
28
  _ALL_DEPRECATED.deprecated_consterns +
29
29
  _ALL_DEPRECATED.deprecated_functions)
30
- __version__ = '24.09.19'
30
+ __version__ = '24.11.07'
31
31
 
32
32
  if _unLazy0:
33
33
  from pygeodesy.deprecated import bases, datum, nvector, rhumbBase, \
@@ -22,7 +22,7 @@ from pygeodesy.trf import TRFXform7Tuple as _TRFXform7Tuple
22
22
  from pygeodesy.units import Bearing, Int, Lamd, Lat, Lon, Meter, Phid
23
23
 
24
24
  __all__ = _ALL_DEPRECATED.deprecated_classes
25
- __version__ = '24.07.02'
25
+ __version__ = '24.11.07'
26
26
 
27
27
 
28
28
  class _Deprecated_NamedTuple(_NamedTuple):
@@ -153,7 +153,7 @@ def HeightIDW3(knots, **kwds): # PYCHOK no cover
153
153
 
154
154
  class Lam_(Lamd):
155
155
  '''DEPRECATED on 2024.06.15, use class L{Lamd}.'''
156
- def __init__(self, *args, **kwds): # PYCHOK signature
156
+ def __init__(self, *args, **kwds): # PYCHOK no cover
157
157
  deprecated_class(self.__class__)
158
158
  Lamd.__init__(self, *args, **kwds)
159
159
 
@@ -172,7 +172,7 @@ class NearestOn4Tuple(_Deprecated_NamedTuple): # PYCHOK no cover
172
172
 
173
173
  class Phi_(Phid):
174
174
  '''DEPRECATED on 2024.06.15, use class L{Phid}.'''
175
- def __init__(self, *args, **kwds): # PYCHOK signature
175
+ def __init__(self, *args, **kwds): # PYCHOK no cover
176
176
  deprecated_class(self.__class__)
177
177
  Phid.__init__(self, *args, **kwds)
178
178
 
@@ -205,22 +205,22 @@ class Rhumb7Tuple(_Deprecated_NamedTuple):
205
205
  _Units_ = _Rhumb8Tuple._Units_[:7]
206
206
 
207
207
  @deprecated_method
208
- def toDirect9Tuple(self, **kwds):
208
+ def toDirect9Tuple(self, **kwds): # PYCHOK no cover
209
209
  return self.toRhumb8Tuple().toDirect9Tuple(self, **kwds)
210
210
 
211
211
  @deprecated_method
212
- def toGDict(self, **kwds):
212
+ def toGDict(self, **kwds): # PYCHOK no cover
213
213
  return self.toRhumb8Tuple().toGDict(**kwds)
214
214
 
215
215
  @deprecated_method
216
- def toInverse10Tuple(self, **kwds):
216
+ def toInverse10Tuple(self, **kwds): # PYCHOK no cover
217
217
  return self.toRhumb8Tuple().toInverse10Tuple(self, **kwds)
218
218
 
219
219
  @deprecated_method
220
- def toRhumb8Tuple(self, dflt=NAN):
220
+ def toRhumb8Tuple(self, dflt=NAN): # PYCHOK no cover
221
221
  return _Rhumb8Tuple(self + (dflt,), name=self.name)
222
222
 
223
- def _to7Tuple(self):
223
+ def _to7Tuple(self): # PYCHOK no cover
224
224
  '''(INTERNAL) see L{Rhumb8Tuple._to7Tuple}.
225
225
  '''
226
226
  return self
@@ -266,7 +266,7 @@ class UtmUps4Tuple(_Deprecated_NamedTuple): # PYCHOK no cover
266
266
 
267
267
  class XDist(ADict):
268
268
  '''DEPRECATED on 2024.07.02, use class L{XDict}.'''
269
- def __init__(self, *args, **kwds): # PYCHOK signature
269
+ def __init__(self, *args, **kwds): # PYCHOK no cover
270
270
  deprecated_class(self.__class__)
271
271
  ADict.__init__(self, *args, **kwds)
272
272