pygeodesy 25.7.25__py2.py3-none-any.whl → 25.9.9__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/__init__.py +10 -9
- pygeodesy/auxilats/__init__.py +1 -1
- pygeodesy/auxilats/auxAngle.py +4 -3
- pygeodesy/auxilats/auxily.py +1 -1
- pygeodesy/basics.py +4 -4
- pygeodesy/booleans.py +25 -25
- pygeodesy/cartesianBase.py +21 -20
- pygeodesy/constants.py +37 -7
- pygeodesy/deprecated/functions.py +1 -0
- pygeodesy/dms.py +2 -2
- pygeodesy/ecef.py +324 -260
- pygeodesy/ellipsoidalExact.py +4 -4
- pygeodesy/ellipsoidalGeodSolve.py +3 -3
- pygeodesy/ellipsoids.py +79 -52
- pygeodesy/elliptic.py +8 -11
- pygeodesy/errors.py +18 -5
- pygeodesy/etm.py +8 -8
- pygeodesy/fmath.py +1 -1
- pygeodesy/geodesicx/__init__.py +1 -1
- pygeodesy/geodesicx/__main__.py +1 -0
- pygeodesy/geodesicx/gx.py +30 -37
- pygeodesy/geodesicx/gxbases.py +1 -5
- pygeodesy/geodesicx/gxline.py +43 -34
- pygeodesy/geodsolve.py +10 -17
- pygeodesy/internals.py +39 -15
- pygeodesy/karney.py +19 -18
- pygeodesy/ktm.py +3 -3
- pygeodesy/latlonBase.py +4 -4
- pygeodesy/lazily.py +14 -13
- pygeodesy/lcc.py +5 -5
- pygeodesy/named.py +10 -13
- pygeodesy/nvectorBase.py +4 -4
- pygeodesy/rhumb/__init__.py +1 -1
- pygeodesy/rhumb/aux_.py +1 -1
- pygeodesy/rhumb/bases.py +7 -8
- pygeodesy/rhumb/ekx.py +9 -9
- pygeodesy/solveBase.py +14 -3
- pygeodesy/sphericalTrigonometry.py +8 -8
- pygeodesy/utily.py +200 -159
- pygeodesy/vector3dBase.py +10 -8
- {pygeodesy-25.7.25.dist-info → pygeodesy-25.9.9.dist-info}/METADATA +12 -11
- {pygeodesy-25.7.25.dist-info → pygeodesy-25.9.9.dist-info}/RECORD +44 -44
- {pygeodesy-25.7.25.dist-info → pygeodesy-25.9.9.dist-info}/WHEEL +0 -0
- {pygeodesy-25.7.25.dist-info → pygeodesy-25.9.9.dist-info}/top_level.txt +0 -0
pygeodesy/ellipsoidalExact.py
CHANGED
|
@@ -11,20 +11,20 @@ L{GeodesicExact}, L{GeodesicAreaExact} and L{GeodesicLineExact}.
|
|
|
11
11
|
|
|
12
12
|
# from pygeodesy.datums import _WGS84 # from .ellipsoidalBase
|
|
13
13
|
from pygeodesy.ellipsoidalBase import CartesianEllipsoidalBase, \
|
|
14
|
-
_nearestOn, _WGS84
|
|
14
|
+
_nearestOn, Property_RO, _WGS84
|
|
15
15
|
from pygeodesy.ellipsoidalBaseDI import LatLonEllipsoidalBaseDI, \
|
|
16
16
|
_intersection3, _intersections2, \
|
|
17
17
|
_TOL_M, intersecant2
|
|
18
18
|
# from pygeodesy.errors import _xkwds # from .karney
|
|
19
|
-
from pygeodesy.karney import _polygon, fabs,
|
|
19
|
+
from pygeodesy.karney import _polygon, fabs, _xkwds
|
|
20
20
|
from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS, _ALL_OTHER
|
|
21
21
|
from pygeodesy.points import _areaError, ispolar # PYCHOK exported
|
|
22
|
-
# from pygeodesy.props import Property_RO # from .
|
|
22
|
+
# from pygeodesy.props import Property_RO # from .ellipsoidalBase
|
|
23
23
|
|
|
24
24
|
# from math import fabs # from .karney
|
|
25
25
|
|
|
26
26
|
__all__ = _ALL_LAZY.ellipsoidalExact
|
|
27
|
-
__version__ = '25.
|
|
27
|
+
__version__ = '25.08.28'
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
class Cartesian(CartesianEllipsoidalBase):
|
|
@@ -12,11 +12,11 @@ L{geodsolve}, a wrapper invoking I{Karney}'s U{GeodSolve
|
|
|
12
12
|
|
|
13
13
|
# from pygeodesy.datums import _WGS84 # from .ellipsoidalBase
|
|
14
14
|
from pygeodesy.ellipsoidalBase import CartesianEllipsoidalBase, \
|
|
15
|
-
_nearestOn, _WGS84
|
|
15
|
+
_nearestOn, Property_RO, _WGS84
|
|
16
16
|
from pygeodesy.ellipsoidalBaseDI import LatLonEllipsoidalBaseDI, _TOL_M, \
|
|
17
17
|
_intersection3, _intersections2
|
|
18
18
|
# from pygeodesy.errors import _xkwds # from .karney
|
|
19
|
-
from pygeodesy.karney import fabs, _polygon,
|
|
19
|
+
from pygeodesy.karney import fabs, _polygon, _xkwds
|
|
20
20
|
from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS, _ALL_OTHER
|
|
21
21
|
from pygeodesy.points import _areaError, ispolar # PYCHOK exported
|
|
22
22
|
# from pygeodesy.props import Property_RO # from .karney
|
|
@@ -24,7 +24,7 @@ from pygeodesy.points import _areaError, ispolar # PYCHOK exported
|
|
|
24
24
|
# from math import fabs # from .karney
|
|
25
25
|
|
|
26
26
|
__all__ = _ALL_LAZY.ellipsoidalGeodSolve
|
|
27
|
-
__version__ = '25.
|
|
27
|
+
__version__ = '25.08.28'
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
class Cartesian(CartesianEllipsoidalBase):
|
pygeodesy/ellipsoids.py
CHANGED
|
@@ -66,8 +66,9 @@ from __future__ import division as _; del _ # noqa: E702 ;
|
|
|
66
66
|
|
|
67
67
|
# from pygeodesy.albers import AlbersEqualAreaCylindrical # _MODS
|
|
68
68
|
from pygeodesy.basics import copysign0, isbool, _isin, isint, typename
|
|
69
|
-
from pygeodesy.constants import EPS, EPS0, EPS02, EPS1, INF, NINF,
|
|
70
|
-
|
|
69
|
+
from pygeodesy.constants import EPS, EPS_2, EPS0, EPS02, EPS1, INF, NINF, \
|
|
70
|
+
_over, PI_2, PI_3, PI4, R_M, R_MA, R_FM, _EPSqrt, \
|
|
71
|
+
_EPStol as _TOL, _floatuple as _T, _isfinite, \
|
|
71
72
|
_0_0s, _0_0, _0_5, _1_0, _1_EPS, _2_0, _4_0, _90_0, \
|
|
72
73
|
_0_25, _3_0 # PYCHOK used!
|
|
73
74
|
from pygeodesy.errors import _AssertionError, IntersectionError, _ValueError, _xattr, _xkwds_not
|
|
@@ -95,7 +96,7 @@ from pygeodesy.utily import atan1, atan1d, atan2b, degrees90, m2radians, radians
|
|
|
95
96
|
from math import asinh, atan, atanh, cos, degrees, exp, fabs, radians, sin, sinh, sqrt, tan # as _tan
|
|
96
97
|
|
|
97
98
|
__all__ = _ALL_LAZY.ellipsoids
|
|
98
|
-
__version__ = '25.
|
|
99
|
+
__version__ = '25.08.31'
|
|
99
100
|
|
|
100
101
|
_f_0_0 = Float(f =_0_0) # zero flattening
|
|
101
102
|
_f__0_0 = Float(f_=_0_0) # zero inverse flattening
|
|
@@ -442,7 +443,7 @@ class Ellipsoid(_NamedEnumItem):
|
|
|
442
443
|
eps=eps, f0=f0, **name_value))
|
|
443
444
|
|
|
444
445
|
def auxAuthalic(self, lat, inverse=False):
|
|
445
|
-
'''Compute the I{authalic} auxiliary latitude or the I{inverse} thereof.
|
|
446
|
+
'''Compute the I{authalic} auxiliary latitude (Xi) or the I{inverse} thereof.
|
|
446
447
|
|
|
447
448
|
@arg lat: The geodetic (or I{authalic}) latitude (C{degrees90}).
|
|
448
449
|
@kwarg inverse: If C{True}, B{C{lat}} is the I{authalic} and
|
|
@@ -462,7 +463,7 @@ class Ellipsoid(_NamedEnumItem):
|
|
|
462
463
|
return _aux(lat, inverse, Ellipsoid.auxAuthalic)
|
|
463
464
|
|
|
464
465
|
def auxConformal(self, lat, inverse=False):
|
|
465
|
-
'''Compute the I{conformal} auxiliary latitude or the I{inverse} thereof.
|
|
466
|
+
'''Compute the I{conformal} auxiliary latitude (Chi) or the I{inverse} thereof.
|
|
466
467
|
|
|
467
468
|
@arg lat: The geodetic (or I{conformal}) latitude (C{degrees90}).
|
|
468
469
|
@kwarg inverse: If C{True}, B{C{lat}} is the I{conformal} and
|
|
@@ -480,12 +481,13 @@ class Ellipsoid(_NamedEnumItem):
|
|
|
480
481
|
lat = atan1d(f(tan(Phid(lat)))) # PYCHOK attr
|
|
481
482
|
return _aux(lat, inverse, Ellipsoid.auxConformal)
|
|
482
483
|
|
|
483
|
-
def auxGeocentric(self, lat, inverse=False):
|
|
484
|
-
'''Compute the I{geocentric} auxiliary latitude or the I{inverse} thereof.
|
|
484
|
+
def auxGeocentric(self, lat, inverse=False, height=_0_0):
|
|
485
|
+
'''Compute the I{geocentric} auxiliary latitude (Theta) or the I{inverse} thereof.
|
|
485
486
|
|
|
486
487
|
@arg lat: The geodetic (or I{geocentric}) latitude (C{degrees90}).
|
|
487
488
|
@kwarg inverse: If C{True}, B{C{lat}} is the geocentric and
|
|
488
489
|
return the I{geocentric} latitude (C{bool}).
|
|
490
|
+
@kwarg height: Optional, ellipsoidal height (C{meter}).
|
|
489
491
|
|
|
490
492
|
@return: The I{geocentric} (or geodetic) latitude in C{degrees90}.
|
|
491
493
|
|
|
@@ -494,13 +496,24 @@ class Ellipsoid(_NamedEnumItem):
|
|
|
494
496
|
<https://WikiPedia.org/wiki/Latitude#Geocentric_latitude>}, and
|
|
495
497
|
U{Snyder<https://Pubs.USGS.gov/pp/1395/report.pdf>}, pp 17-18.
|
|
496
498
|
'''
|
|
497
|
-
if self.f:
|
|
498
|
-
|
|
499
|
-
|
|
499
|
+
if self.f: # and lat
|
|
500
|
+
t = tan(Phid(lat))
|
|
501
|
+
f = self.b2_a2
|
|
502
|
+
if height:
|
|
503
|
+
if inverse:
|
|
504
|
+
lat = atan1d(t * f) # geodetic n
|
|
505
|
+
d, f = f, _1_0
|
|
506
|
+
else:
|
|
507
|
+
d = _1_0
|
|
508
|
+
n = self.rocPrimeVertical(lat)
|
|
509
|
+
f = _over(n * f + height, n * d + height)
|
|
510
|
+
elif inverse:
|
|
511
|
+
f = self.a2_b2
|
|
512
|
+
lat = atan1d(t * f)
|
|
500
513
|
return _aux(lat, inverse, Ellipsoid.auxGeocentric)
|
|
501
514
|
|
|
502
515
|
def auxIsometric(self, lat, inverse=False):
|
|
503
|
-
'''Compute the I{isometric} auxiliary latitude or the I{inverse} thereof.
|
|
516
|
+
'''Compute the I{isometric} auxiliary latitude (Psi) or the I{inverse} thereof.
|
|
504
517
|
|
|
505
518
|
@arg lat: The geodetic (or I{isometric}) latitude (C{degrees}).
|
|
506
519
|
@kwarg inverse: If C{True}, B{C{lat}} is the I{isometric} and
|
|
@@ -509,8 +522,8 @@ class Ellipsoid(_NamedEnumItem):
|
|
|
509
522
|
@return: The I{isometric} (or geodetic) latitude in C{degrees}.
|
|
510
523
|
|
|
511
524
|
@note: The I{isometric} latitude for geodetic C{+/-90} is far
|
|
512
|
-
outside the C{[-90..+90]} range but the inverse
|
|
513
|
-
|
|
525
|
+
outside the C{[-90..+90]} range but the inverse thereof
|
|
526
|
+
is the original geodetic latitude.
|
|
514
527
|
|
|
515
528
|
@see: U{Inverse-/IsometricLatitude<https://GeographicLib.SourceForge.io/
|
|
516
529
|
C++/doc/classGeographicLib_1_1Ellipsoid.html>}, U{Isometric latitude
|
|
@@ -525,7 +538,7 @@ class Ellipsoid(_NamedEnumItem):
|
|
|
525
538
|
return _aux(lat, inverse, Ellipsoid.auxIsometric, clip=0)
|
|
526
539
|
|
|
527
540
|
def auxParametric(self, lat, inverse=False):
|
|
528
|
-
'''Compute the I{parametric} auxiliary latitude or the I{inverse} thereof.
|
|
541
|
+
'''Compute the I{parametric} auxiliary latitude (Beta) or the I{inverse} thereof.
|
|
529
542
|
|
|
530
543
|
@arg lat: The geodetic (or I{parametric}) latitude (C{degrees90}).
|
|
531
544
|
@kwarg inverse: If C{True}, B{C{lat}} is the I{parametric} and
|
|
@@ -545,7 +558,7 @@ class Ellipsoid(_NamedEnumItem):
|
|
|
545
558
|
auxReduced = auxParametric # synonymous
|
|
546
559
|
|
|
547
560
|
def auxRectifying(self, lat, inverse=False):
|
|
548
|
-
'''Compute the I{rectifying} auxiliary latitude or the I{inverse} thereof.
|
|
561
|
+
'''Compute the I{rectifying} auxiliary latitude (Mu) or the I{inverse} thereof.
|
|
549
562
|
|
|
550
563
|
@arg lat: The geodetic (or I{rectifying}) latitude (C{degrees90}).
|
|
551
564
|
@kwarg inverse: If C{True}, B{C{lat}} is the I{rectifying} and
|
|
@@ -691,23 +704,23 @@ class Ellipsoid(_NamedEnumItem):
|
|
|
691
704
|
'''
|
|
692
705
|
lat = Lat(lat)
|
|
693
706
|
if lat:
|
|
694
|
-
|
|
707
|
+
B = lat # beta
|
|
695
708
|
if fabs(lat) < _90_0:
|
|
696
709
|
if self.f:
|
|
697
|
-
|
|
698
|
-
z, r = sincos2d(
|
|
710
|
+
B = self._beta(lat)
|
|
711
|
+
z, r = sincos2d(B)
|
|
699
712
|
r *= self.a
|
|
700
713
|
z *= self.b
|
|
701
714
|
else: # near-polar
|
|
702
715
|
r, z = _0_0, copysign0(self.b, lat)
|
|
703
716
|
else: # equator
|
|
704
717
|
r = self.a
|
|
705
|
-
z = lat =
|
|
706
|
-
return Circle4Tuple(r, z, lat,
|
|
718
|
+
z = lat = B = _0_0
|
|
719
|
+
return Circle4Tuple(r, z, lat, B)
|
|
707
720
|
|
|
708
721
|
def degrees2m(self, deg, lat=0):
|
|
709
|
-
'''Convert an angle
|
|
710
|
-
|
|
722
|
+
'''Convert an angle along the equator or along a parallel
|
|
723
|
+
of (geodetic) latitude to the distance.
|
|
711
724
|
|
|
712
725
|
@arg deg: The angle (C{degrees}).
|
|
713
726
|
@kwarg lat: Parallel latitude (C{degrees90}, C{str}).
|
|
@@ -877,10 +890,10 @@ class Ellipsoid(_NamedEnumItem):
|
|
|
877
890
|
|
|
878
891
|
@raise ValueError: Invalid B{C{s}}.
|
|
879
892
|
'''
|
|
880
|
-
r = _1_0
|
|
881
|
-
if
|
|
893
|
+
r, e2 = _1_0, self.e2
|
|
894
|
+
if e2: # and s
|
|
882
895
|
try:
|
|
883
|
-
r -=
|
|
896
|
+
r -= e2 * Scalar(s=s)**2
|
|
884
897
|
if r < 0:
|
|
885
898
|
raise ValueError(_negative_)
|
|
886
899
|
except (TypeError, ValueError) as x:
|
|
@@ -1186,6 +1199,22 @@ class Ellipsoid(_NamedEnumItem):
|
|
|
1186
1199
|
|
|
1187
1200
|
return Vector4Tuple(v.x, v.y, v.z, h, iteration=i, name__=self.height4)
|
|
1188
1201
|
|
|
1202
|
+
def _heightB(self, sa, ca, z, p): # in ecef.EcefSudano, ecec.EcefVeness
|
|
1203
|
+
'''(INTERNAL) Height above ellipsoid (Bowring eqn 7) at C{lat}.
|
|
1204
|
+
'''
|
|
1205
|
+
# sa, ca = sincos2d(lat)
|
|
1206
|
+
# p = hypot(x, y) # distance to polar axis
|
|
1207
|
+
|
|
1208
|
+
# r = a / self.e2s(sa) # length of normal terminated by polar axis
|
|
1209
|
+
# h = p * ca + z * sa - (a * a / r)
|
|
1210
|
+
return (p * ca + fabs(z * sa) - self.a * self.e2s(sa)) if sa else (p - self.a)
|
|
1211
|
+
|
|
1212
|
+
@Property_RO
|
|
1213
|
+
def _heightMax(self):
|
|
1214
|
+
'''(INTERNAL) Get the height limit (C{meter}, conventionally).
|
|
1215
|
+
'''
|
|
1216
|
+
return self.a / EPS_2 # self.a * _2_EPS, about 12M lightyears
|
|
1217
|
+
|
|
1189
1218
|
def _hubeny_2(self, phi2, phi1, lam21, scaled=True, squared=True):
|
|
1190
1219
|
'''(INTERNAL) like function C{pygeodesy.flatLocal_}/C{pygeodesy.hubeny_},
|
|
1191
1220
|
returning the I{angular} distance in C{radians squared} or C{radians}
|
|
@@ -1451,19 +1480,18 @@ class Ellipsoid(_NamedEnumItem):
|
|
|
1451
1480
|
@see: U{Geocentric Radius
|
|
1452
1481
|
<https://WikiPedia.org/wiki/Earth_radius#Geocentric_radius>}
|
|
1453
1482
|
'''
|
|
1454
|
-
r,
|
|
1455
|
-
if
|
|
1456
|
-
if fabs(
|
|
1457
|
-
s2, c2 = _s2_c2(
|
|
1458
|
-
b2_a2_s2 = self.b2_a2 * s2
|
|
1483
|
+
r, p = self.a, Phid(lat)
|
|
1484
|
+
if p and self.f:
|
|
1485
|
+
if fabs(p) < PI_2:
|
|
1486
|
+
s2, c2 = _s2_c2(p)
|
|
1459
1487
|
# R == sqrt((a2**2 * c2 + b2**2 * s2) / (a2 * c2 + b2 * s2))
|
|
1460
1488
|
# == sqrt(a2**2 * (c2 + (b2 / a2)**2 * s2) / (a2 * (c2 + b2 / a2 * s2)))
|
|
1461
1489
|
# == sqrt(a2 * (c2 + (b2 / a2)**2 * s2) / (c2 + (b2 / a2) * s2))
|
|
1462
1490
|
# == a * sqrt((c2 + b2_a2 * b2_a2 * s2) / (c2 + b2_a2 * s2))
|
|
1463
|
-
|
|
1464
|
-
r
|
|
1491
|
+
s2 *= self.b2_a2
|
|
1492
|
+
r *= sqrt((c2 + self.b2_a2 * s2) / (c2 + s2))
|
|
1465
1493
|
else:
|
|
1466
|
-
r
|
|
1494
|
+
r = self.b
|
|
1467
1495
|
return Radius(Rgeocentric=r)
|
|
1468
1496
|
|
|
1469
1497
|
@Property_RO
|
|
@@ -1542,7 +1570,7 @@ class Ellipsoid(_NamedEnumItem):
|
|
|
1542
1570
|
|
|
1543
1571
|
@deprecated_property_RO
|
|
1544
1572
|
def rhumbx(self):
|
|
1545
|
-
'''DEPRECATED on 2023.11.28, use property C{rhumbekx}.
|
|
1573
|
+
'''DEPRECATED on 2023.11.28, use property C{rhumbekx}.'''
|
|
1546
1574
|
return self.rhumbekx
|
|
1547
1575
|
|
|
1548
1576
|
def Rlat(self, lat):
|
|
@@ -1587,16 +1615,15 @@ class Ellipsoid(_NamedEnumItem):
|
|
|
1587
1615
|
|
|
1588
1616
|
@see: Method L{roc2_} and class L{EcefYou}.
|
|
1589
1617
|
'''
|
|
1590
|
-
if
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
n = self.a2_b / fabs(sa)
|
|
1618
|
+
if sa and self.f: # .isEllipsoidal
|
|
1619
|
+
if ca is None:
|
|
1620
|
+
r = self.e2s2(sa) # see .roc2_ and _EcefBase._forward
|
|
1621
|
+
n = sqrt(self.a2 / r) if r > EPS02 else _0_0
|
|
1622
|
+
elif ca: # derived from EcefYou.forward
|
|
1623
|
+
h = hypot(ca, self.b_a * sa)
|
|
1624
|
+
n = self.a / h
|
|
1625
|
+
else:
|
|
1626
|
+
n = self.a2_b / fabs(sa)
|
|
1600
1627
|
else:
|
|
1601
1628
|
n = self.a
|
|
1602
1629
|
return n
|
|
@@ -1637,18 +1664,18 @@ class Ellipsoid(_NamedEnumItem):
|
|
|
1637
1664
|
and the meridional and prime vertical U{Radii of Curvature
|
|
1638
1665
|
<https://WikiPedia.org/wiki/Earth_radius#Radii_of_curvature>}.
|
|
1639
1666
|
'''
|
|
1640
|
-
|
|
1667
|
+
p = fabs(Phi(phi))
|
|
1641
1668
|
if self.f:
|
|
1642
|
-
r = self.e2s2(sin(
|
|
1669
|
+
r = self.e2s2(sin(p))
|
|
1643
1670
|
if r > EPS02:
|
|
1644
|
-
n = self.
|
|
1645
|
-
m = n *
|
|
1671
|
+
n = sqrt(self.a2 / r)
|
|
1672
|
+
m = n * self.e21 / r
|
|
1646
1673
|
else:
|
|
1647
1674
|
m = n = _0_0
|
|
1648
1675
|
else:
|
|
1649
1676
|
m = n = self.a
|
|
1650
|
-
if scaled and
|
|
1651
|
-
n *= cos(
|
|
1677
|
+
if scaled and p:
|
|
1678
|
+
n *= cos(p) if p < PI_2 else _0_0
|
|
1652
1679
|
return Curvature2Tuple(m, n)
|
|
1653
1680
|
|
|
1654
1681
|
def rocAzimuth(self, lat, azimuth):
|
|
@@ -1779,8 +1806,8 @@ class Ellipsoid(_NamedEnumItem):
|
|
|
1779
1806
|
U{Radii of Curvature<https://WikiPedia.org/wiki/
|
|
1780
1807
|
Earth_radius#Radii_of_curvature>}.
|
|
1781
1808
|
'''
|
|
1782
|
-
r = self.
|
|
1783
|
-
return Radius(rocPrimeVertical=r
|
|
1809
|
+
r = self.roc1_(sin(Phid(lat))) if lat else self.a
|
|
1810
|
+
return Radius(rocPrimeVertical=r)
|
|
1784
1811
|
|
|
1785
1812
|
rocTransverse = rocPrimeVertical # synonymous
|
|
1786
1813
|
|
pygeodesy/elliptic.py
CHANGED
|
@@ -75,7 +75,7 @@ U{22<https://DLMF.NIST.gov/22>}.
|
|
|
75
75
|
# make sure int/int division yields float quotient, see .basics
|
|
76
76
|
from __future__ import division as _; del _ # noqa: E702 ;
|
|
77
77
|
|
|
78
|
-
from pygeodesy.basics import copysign0, map2, neg, neg_
|
|
78
|
+
from pygeodesy.basics import copysign0, map2, neg, neg_
|
|
79
79
|
from pygeodesy.constants import EPS, INF, NAN, PI, PI_2, PI_4, \
|
|
80
80
|
_EPStol as _TolJAC, _0_0, _0_25, \
|
|
81
81
|
_0_5, _1_0, _2_0, _N_2_0, _3_0, \
|
|
@@ -85,7 +85,7 @@ from pygeodesy.constants import _EPSjam as _TolJAM # PYCHOK used!
|
|
|
85
85
|
# from pygeodesy.errors import _ValueError # from .fsums
|
|
86
86
|
from pygeodesy.fmath import favg, Fdot_, fma, hypot1, zqrt
|
|
87
87
|
from pygeodesy.fsums import Fsum, _fsum, _ValueError
|
|
88
|
-
|
|
88
|
+
from pygeodesy.internals import _Enum, typename
|
|
89
89
|
from pygeodesy.interns import NN, _delta_, _DOT_, _f_, _invalid_, \
|
|
90
90
|
_invokation_, _negative_, _SPACE_
|
|
91
91
|
from pygeodesy.karney import _K_2_0, _norm180, _signBit, _sincos2
|
|
@@ -100,7 +100,7 @@ from math import asin, asinh, atan, ceil, cosh, fabs, floor, radians, \
|
|
|
100
100
|
sin, sinh, sqrt, tan, tanh # tan as _tan
|
|
101
101
|
|
|
102
102
|
__all__ = _ALL_LAZY.elliptic
|
|
103
|
-
__version__ = '25.
|
|
103
|
+
__version__ = '25.09.04'
|
|
104
104
|
|
|
105
105
|
_TolRD = zqrt(EPS * 0.002)
|
|
106
106
|
_TolRF = zqrt(EPS * 0.030)
|
|
@@ -108,13 +108,10 @@ _TolRG0 = _TolJAC * 2.7
|
|
|
108
108
|
_TRIPS = 28 # Max depth, 6-18 might be sufficient
|
|
109
109
|
|
|
110
110
|
|
|
111
|
-
class _Cs(
|
|
112
|
-
'''(INTERAL) Complete
|
|
111
|
+
class _Cs(_Enum):
|
|
112
|
+
'''(INTERAL) Complete Integrals cache.
|
|
113
113
|
'''
|
|
114
|
-
|
|
115
|
-
# for n,v in kwds.items():
|
|
116
|
-
# setattr(self, n, v)
|
|
117
|
-
self.__dict__ = kwds
|
|
114
|
+
pass
|
|
118
115
|
|
|
119
116
|
|
|
120
117
|
class Elliptic(_Named):
|
|
@@ -773,8 +770,8 @@ class Elliptic(_Named):
|
|
|
773
770
|
def _S(**kwds):
|
|
774
771
|
return Scalar_(Error=EllipticError, **kwds)
|
|
775
772
|
|
|
776
|
-
self._k2
|
|
777
|
-
self._kp2
|
|
773
|
+
self._k2 = _S(k2 = k2, low=None, high=_1_0)
|
|
774
|
+
self._kp2 = _S(kp2=_1p2(kp2, k2)) # low=_0_0
|
|
778
775
|
|
|
779
776
|
self._alpha2 = _S(alpha2 = alpha2, low=None, high=_1_0)
|
|
780
777
|
self._alphap2 = _S(alphap2=_1p2(alphap2, alpha2)) # low=_0_0
|
pygeodesy/errors.py
CHANGED
|
@@ -16,9 +16,10 @@ C{PYGEODESY_EXCEPTION_CHAINING=std} or to any non-empty string.
|
|
|
16
16
|
# from pygeodesy import errors # _MODS, _MODS.getattr
|
|
17
17
|
from pygeodesy.internals import _envPYGEODESY, _plural, _tailof, typename
|
|
18
18
|
from pygeodesy.interns import MISSING, NN, _a_, _an_, _and_, _clip_, _COLON_, _COLONSPACE_, \
|
|
19
|
-
_COMMASPACE_, _datum_, _ELLIPSIS_, _ellipsoidal_,
|
|
20
|
-
|
|
21
|
-
_specified_, _UNDER_,
|
|
19
|
+
_COMMASPACE_, _datum_, _DOT_, _ELLIPSIS_, _ellipsoidal_, \
|
|
20
|
+
_EQUALSPACED_, _immutable_, _incompatible_, _invalid_, _keyword_, \
|
|
21
|
+
_LatLon_, _len_, _not_, _or_, _SPACE_, _specified_, _UNDER_, \
|
|
22
|
+
_vs_, _with_
|
|
22
23
|
from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS, _PYTHON_X_DEV
|
|
23
24
|
# from pygeodesy import streprs as _streprs # _MODS.into
|
|
24
25
|
# from pygeodesy.unitsBase import Str # _MODS
|
|
@@ -27,11 +28,12 @@ from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS, _PYTHON_X_DEV
|
|
|
27
28
|
from copy import copy as _copy
|
|
28
29
|
|
|
29
30
|
__all__ = _ALL_LAZY.errors # _ALL_DOCS('_InvalidError', '_IsnotError') _under
|
|
30
|
-
__version__ = '25.
|
|
31
|
+
__version__ = '25.09.04'
|
|
31
32
|
|
|
32
33
|
_argument_ = 'argument'
|
|
33
34
|
_basics = _MODS.into(basics=__name__)
|
|
34
35
|
_box_ = 'box'
|
|
36
|
+
_del_ = 'del'
|
|
35
37
|
_expected_ = 'expected'
|
|
36
38
|
_limiterrors = True # in .formy
|
|
37
39
|
_name_value_ = repr('name=value')
|
|
@@ -224,7 +226,8 @@ class IntersectionError(_ValueError): # in .ellipsoidalBaseDI, .formy, ...
|
|
|
224
226
|
'''New L{IntersectionError}.
|
|
225
227
|
'''
|
|
226
228
|
if args:
|
|
227
|
-
|
|
229
|
+
t = _COMMASPACE_(*map(repr, args))
|
|
230
|
+
_ValueError.__init__(self, t, **kwds)
|
|
228
231
|
else:
|
|
229
232
|
_ValueError.__init__(self, **kwds)
|
|
230
233
|
|
|
@@ -474,6 +477,16 @@ def exception_chaining(exc=None):
|
|
|
474
477
|
getattr(exc, '__cause__', None) # _DCAUSE_
|
|
475
478
|
|
|
476
479
|
|
|
480
|
+
def _ImmutableError(inst, attr, value=_del_, Error=_TypeError): # PYCHOK self
|
|
481
|
+
'''(INTERNAL) Format an C{immutable _TypeError}.
|
|
482
|
+
'''
|
|
483
|
+
n = typename(inst)
|
|
484
|
+
n = _DOT_(_xattr(inst, name=n), attr)
|
|
485
|
+
t = _SPACE_(_del_, n) if value is _del_ else \
|
|
486
|
+
_EQUALSPACED_(n, repr(value))
|
|
487
|
+
return Error(_immutable_, txt=t)
|
|
488
|
+
|
|
489
|
+
|
|
477
490
|
def _incompatible(this):
|
|
478
491
|
'''(INTERNAL) Format an C{"incompatible with ..."} text.
|
|
479
492
|
'''
|
pygeodesy/etm.py
CHANGED
|
@@ -75,8 +75,8 @@ from pygeodesy.datums import _ellipsoidal_datum, _WGS84, _EWGS84
|
|
|
75
75
|
# from pygeodesy.fsums import Fsum # from .fmath
|
|
76
76
|
from pygeodesy.fmath import cbrt, hypot, hypot1, hypot2, Fsum
|
|
77
77
|
from pygeodesy.interns import _COMMASPACE_, _DMAIN_, _near_, _SPACE_, _spherical_
|
|
78
|
-
from pygeodesy.karney import _K_2_4,
|
|
79
|
-
|
|
78
|
+
from pygeodesy.karney import _K_2_4, _diff182, _fix90, _norm2, _norm180, \
|
|
79
|
+
_signBit, _tand, _unsigned2
|
|
80
80
|
# from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS # from .named
|
|
81
81
|
from pygeodesy.named import callername, _incompatible, _NamedBase, \
|
|
82
82
|
_ALL_LAZY, _MODS
|
|
@@ -93,7 +93,7 @@ from pygeodesy.utm import _cmlon, _LLEB, _parseUTM5, _toBand, _toXtm8, \
|
|
|
93
93
|
from math import asinh, degrees, radians, sinh, sqrt
|
|
94
94
|
|
|
95
95
|
__all__ = _ALL_LAZY.etm
|
|
96
|
-
__version__ = '25.
|
|
96
|
+
__version__ = '25.08.31'
|
|
97
97
|
|
|
98
98
|
_OVERFLOW = _1_EPS**2 # ~2e+31
|
|
99
99
|
_TAYTOL = pow(EPS, 0.6)
|
|
@@ -790,7 +790,7 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
790
790
|
mu = mu / d2
|
|
791
791
|
mv = mv / d2
|
|
792
792
|
else:
|
|
793
|
-
mu, mv = map1(
|
|
793
|
+
mu, mv = map1(_copysignOVERFLOW, mu, mv)
|
|
794
794
|
xi = self._Eu.fE(snu, cnu, dnu) - mu
|
|
795
795
|
v -= self._Ev.fE(snv, cnv, dnv) - mv
|
|
796
796
|
return xi, v, d2
|
|
@@ -910,12 +910,12 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
910
910
|
if d1 > EPS02: # _EPSmin
|
|
911
911
|
t1 = snu * dnv / sqrt(d1)
|
|
912
912
|
else: # like atan(overflow) = pi/2
|
|
913
|
-
t1, d1 =
|
|
913
|
+
t1, d1 = _copysignOVERFLOW(snu), 0
|
|
914
914
|
d2 = cnu2 * self._mu + cnv**2 * mv
|
|
915
915
|
if d2 > EPS02: # _EPSmin
|
|
916
916
|
t2 = sinh(e * asinh(e * snu / sqrt(d2)))
|
|
917
917
|
else:
|
|
918
|
-
t2, d2 =
|
|
918
|
+
t2, d2 = _copysignOVERFLOW(snu), 0
|
|
919
919
|
# psi = asinh(t1) - asinh(t2)
|
|
920
920
|
# taup = sinh(psi)
|
|
921
921
|
taup = t1 * hypot1(t2) - t2 * hypot1(t1)
|
|
@@ -1026,10 +1026,10 @@ _allPropertiesOf_n(22, ExactTransverseMercator, Property_RO) # PYCHOK assert _R
|
|
|
1026
1026
|
del _0_1, _allPropertiesOf_n, EPS, _1_EPS, _EWGS84
|
|
1027
1027
|
|
|
1028
1028
|
|
|
1029
|
-
def
|
|
1029
|
+
def _copysignOVERFLOW(x):
|
|
1030
1030
|
'''(INTERNAL) Like C{copysign0(OVERFLOW, B{x})}.
|
|
1031
1031
|
'''
|
|
1032
|
-
return
|
|
1032
|
+
return (-_OVERFLOW) if _signBit(x) else _OVERFLOW
|
|
1033
1033
|
|
|
1034
1034
|
|
|
1035
1035
|
def parseETM5(strUTM, datum=_WGS84, Etm=Etm, falsed=True, **name):
|
pygeodesy/fmath.py
CHANGED
|
@@ -25,7 +25,7 @@ from math import fabs, sqrt # pow
|
|
|
25
25
|
import operator as _operator # in .datums, .trf, .utm
|
|
26
26
|
|
|
27
27
|
__all__ = _ALL_LAZY.fmath
|
|
28
|
-
__version__ = '25.
|
|
28
|
+
__version__ = '25.08.31'
|
|
29
29
|
|
|
30
30
|
# sqrt(2) - 1 <https://WikiPedia.org/wiki/Square_root_of_2>
|
|
31
31
|
_0_4142 = 0.41421356237309504880 # ~ 3_730_904_090_310_553 / 9_007_199_254_740_992
|
pygeodesy/geodesicx/__init__.py
CHANGED
pygeodesy/geodesicx/__main__.py
CHANGED
|
@@ -46,6 +46,7 @@ def _main(**C4order): # PYCHOK no cover
|
|
|
46
46
|
from sys import argv # .internals._isPyChOK
|
|
47
47
|
_main(C4order=int(argv[1])) if len(argv) == 2 and argv[1].isdigit() else _main()
|
|
48
48
|
|
|
49
|
+
|
|
49
50
|
# % python3.13 -m pygeodesy.geodesicx
|
|
50
51
|
# pygeodesy.geodesicx 25.06.01: C4order=30, C4n=5425, C4u=5107, C4u_n=94.1%, C4x=465, C4t=tuple, C4z=166008, geographiclib 2.0 (pygeodesy 25.5.28 Python 3.13.3 64bit arm64 macOS 15.5)
|
|
51
52
|
|