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.
- {PyGeodesy-24.10.10.dist-info → PyGeodesy-24.11.11.dist-info}/METADATA +12 -12
- PyGeodesy-24.11.11.dist-info/RECORD +118 -0
- {PyGeodesy-24.10.10.dist-info → PyGeodesy-24.11.11.dist-info}/WHEEL +1 -1
- pygeodesy/__init__.py +14 -14
- pygeodesy/__main__.py +5 -5
- pygeodesy/albers.py +12 -17
- pygeodesy/azimuthal.py +51 -61
- pygeodesy/basics.py +60 -62
- pygeodesy/booleans.py +87 -79
- pygeodesy/cartesianBase.py +6 -6
- pygeodesy/constants.py +23 -19
- pygeodesy/css.py +7 -8
- pygeodesy/datums.py +3 -3
- pygeodesy/deprecated/__init__.py +1 -1
- pygeodesy/deprecated/classes.py +9 -9
- pygeodesy/deprecated/functions.py +6 -6
- pygeodesy/dms.py +250 -270
- pygeodesy/ecef.py +11 -14
- pygeodesy/ellipsoidalBase.py +106 -121
- pygeodesy/ellipsoidalBaseDI.py +114 -118
- pygeodesy/ellipsoidalExact.py +35 -37
- pygeodesy/ellipsoidalNvector.py +4 -4
- pygeodesy/ellipsoidalVincenty.py +2 -2
- pygeodesy/ellipsoids.py +10 -51
- pygeodesy/elliptic.py +14 -14
- pygeodesy/errors.py +28 -28
- pygeodesy/etm.py +92 -68
- pygeodesy/fmath.py +42 -40
- pygeodesy/formy.py +7 -6
- pygeodesy/fsums.py +72 -51
- pygeodesy/geodesici.py +43 -40
- pygeodesy/geodesicw.py +17 -16
- pygeodesy/geodesicx/__init__.py +2 -2
- pygeodesy/geodesicx/gxarea.py +3 -2
- pygeodesy/geodsolve.py +79 -39
- pygeodesy/geohash.py +2 -2
- pygeodesy/geoids.py +32 -31
- pygeodesy/heights.py +2 -2
- pygeodesy/internals.py +201 -147
- pygeodesy/interns.py +23 -20
- pygeodesy/karney.py +62 -13
- pygeodesy/ktm.py +11 -13
- pygeodesy/latlonBase.py +18 -20
- pygeodesy/lazily.py +210 -218
- pygeodesy/lcc.py +4 -4
- pygeodesy/ltp.py +10 -10
- pygeodesy/ltpTuples.py +74 -75
- pygeodesy/mgrs.py +20 -21
- pygeodesy/named.py +15 -10
- pygeodesy/nvectorBase.py +1 -1
- pygeodesy/osgr.py +9 -12
- pygeodesy/points.py +2 -2
- pygeodesy/props.py +35 -14
- pygeodesy/resections.py +9 -10
- pygeodesy/rhumb/__init__.py +1 -1
- pygeodesy/rhumb/bases.py +5 -5
- pygeodesy/rhumb/solve.py +9 -10
- pygeodesy/simplify.py +5 -5
- pygeodesy/solveBase.py +7 -25
- pygeodesy/sphericalBase.py +20 -23
- pygeodesy/sphericalNvector.py +103 -145
- pygeodesy/sphericalTrigonometry.py +68 -73
- pygeodesy/streprs.py +5 -5
- pygeodesy/trf.py +6 -4
- pygeodesy/triaxials.py +46 -9
- pygeodesy/units.py +5 -4
- pygeodesy/ups.py +6 -6
- pygeodesy/utily.py +2 -2
- pygeodesy/utm.py +7 -7
- pygeodesy/vector2d.py +13 -13
- pygeodesy/vector3d.py +19 -21
- pygeodesy/vector3dBase.py +21 -19
- pygeodesy/webmercator.py +4 -4
- pygeodesy/wgrs.py +4 -4
- PyGeodesy-24.10.10.dist-info/RECORD +0 -118
- {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_,
|
|
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.
|
|
46
|
+
__version__ = '24.11.07'
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
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) >
|
|
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) >
|
|
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 =
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
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) <
|
|
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 =
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
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
|
|
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
|
|
1583
|
+
elif T in _E.Vs:
|
|
1583
1584
|
yield T, (p1,), (q1,)
|
|
1584
1585
|
else:
|
|
1585
|
-
if T in
|
|
1586
|
+
if T in _E.Qs:
|
|
1586
1587
|
yield T, (p1,), (p1, q1, q2, b)
|
|
1587
|
-
if T in
|
|
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
|
|
1613
|
-
d = (y
|
|
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) *
|
|
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) >
|
|
1653
|
+
if fabs(d) > _0EPS: # non-parallel edges
|
|
1653
1654
|
dx = x - c1_x
|
|
1654
1655
|
dy = y - c1_y
|
|
1655
|
-
ca = (sx
|
|
1656
|
-
if
|
|
1657
|
-
|
|
1658
|
-
sa = (cx
|
|
1659
|
-
if
|
|
1660
|
-
|
|
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 <
|
|
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 <
|
|
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
|
|
1670
|
-
e
|
|
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) <
|
|
1678
|
-
if self._xtend and not _outside(sa1, sa2,
|
|
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,
|
|
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
|
|
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
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
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{
|
|
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
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
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
|
-
|
|
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)
|
|
1972
|
+
'''(INTERNAL) Are C{x1} and C{x2} outside C{(lo, hi)}?
|
|
1967
1973
|
'''
|
|
1968
|
-
|
|
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,
|
pygeodesy/cartesianBase.py
CHANGED
|
@@ -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-
|
|
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.
|
|
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
|
|
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
|
|
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}),
|
|
944
|
-
class to return the coordinates and
|
|
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
|
|
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
|
-
|
|
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.
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
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.
|
|
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
|
-
|
|
323
|
-
@kwarg name_LatLon_kwds: Optional name C{B{name}=NN} (C{str}) and
|
|
324
|
-
|
|
325
|
-
|
|
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-
|
|
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.
|
|
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_
|
pygeodesy/deprecated/__init__.py
CHANGED
|
@@ -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.
|
|
30
|
+
__version__ = '24.11.07'
|
|
31
31
|
|
|
32
32
|
if _unLazy0:
|
|
33
33
|
from pygeodesy.deprecated import bases, datum, nvector, rhumbBase, \
|
pygeodesy/deprecated/classes.py
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
269
|
+
def __init__(self, *args, **kwds): # PYCHOK no cover
|
|
270
270
|
deprecated_class(self.__class__)
|
|
271
271
|
ADict.__init__(self, *args, **kwds)
|
|
272
272
|
|