pygeodesy 24.8.4__py2.py3-none-any.whl → 24.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-24.8.4.dist-info → PyGeodesy-24.9.9.dist-info}/METADATA +17 -16
- PyGeodesy-24.9.9.dist-info/RECORD +118 -0
- {PyGeodesy-24.8.4.dist-info → PyGeodesy-24.9.9.dist-info}/WHEEL +1 -1
- pygeodesy/__init__.py +23 -23
- pygeodesy/__main__.py +46 -47
- pygeodesy/auxilats/_CX_4.py +104 -181
- pygeodesy/auxilats/_CX_6.py +152 -277
- pygeodesy/auxilats/_CX_8.py +211 -438
- pygeodesy/auxilats/_CX_Rs.py +222 -0
- pygeodesy/auxilats/__init__.py +2 -2
- pygeodesy/auxilats/__main__.py +30 -38
- pygeodesy/auxilats/auxDST.py +2 -2
- pygeodesy/auxilats/auxLat.py +28 -36
- pygeodesy/auxilats/auxily.py +30 -50
- pygeodesy/basics.py +18 -7
- pygeodesy/booleans.py +10 -11
- pygeodesy/cartesianBase.py +5 -5
- pygeodesy/constants.py +35 -34
- pygeodesy/ellipsoidalBase.py +18 -15
- pygeodesy/ellipsoidalExact.py +2 -2
- pygeodesy/ellipsoidalGeodSolve.py +2 -2
- pygeodesy/ellipsoidalKarney.py +2 -2
- pygeodesy/ellipsoidalNvector.py +2 -2
- pygeodesy/ellipsoidalVincenty.py +7 -6
- pygeodesy/elliptic.py +154 -88
- pygeodesy/epsg.py +3 -3
- pygeodesy/etm.py +71 -59
- pygeodesy/fmath.py +99 -90
- pygeodesy/fsums.py +201 -14
- pygeodesy/gars.py +9 -8
- pygeodesy/geodesici.py +6 -5
- pygeodesy/geodesicx/_C4_24.py +1 -3
- pygeodesy/geodesicx/_C4_27.py +1 -3
- pygeodesy/geodesicx/_C4_30.py +1 -3
- pygeodesy/geodesicx/__init__.py +1 -1
- pygeodesy/geodesicx/__main__.py +44 -46
- pygeodesy/geodesicx/gx.py +3 -3
- pygeodesy/geodesicx/gxarea.py +5 -5
- pygeodesy/geodesicx/gxbases.py +32 -18
- pygeodesy/geodsolve.py +3 -3
- pygeodesy/geohash.py +18 -11
- pygeodesy/geoids.py +293 -315
- pygeodesy/heights.py +150 -158
- pygeodesy/internals.py +70 -9
- pygeodesy/interns.py +4 -4
- pygeodesy/karney.py +83 -60
- pygeodesy/ktm.py +4 -4
- pygeodesy/latlonBase.py +13 -7
- pygeodesy/lazily.py +13 -8
- pygeodesy/ltp.py +5 -6
- pygeodesy/ltpTuples.py +7 -1
- pygeodesy/mgrs.py +47 -42
- pygeodesy/named.py +8 -4
- pygeodesy/namedTuples.py +14 -1
- pygeodesy/osgr.py +7 -7
- pygeodesy/points.py +2 -2
- pygeodesy/props.py +7 -6
- pygeodesy/resections.py +7 -7
- pygeodesy/rhumb/__init__.py +1 -1
- pygeodesy/rhumb/aux_.py +42 -60
- pygeodesy/rhumb/solve.py +3 -3
- pygeodesy/simplify.py +10 -10
- pygeodesy/sphericalBase.py +3 -3
- pygeodesy/sphericalTrigonometry.py +2 -2
- pygeodesy/streprs.py +3 -3
- pygeodesy/triaxials.py +207 -201
- pygeodesy/units.py +3 -3
- pygeodesy/unitsBase.py +4 -4
- pygeodesy/utmupsBase.py +3 -3
- pygeodesy/vector2d.py +158 -51
- pygeodesy/vector3d.py +13 -52
- pygeodesy/vector3dBase.py +81 -63
- pygeodesy/webmercator.py +3 -3
- pygeodesy/wgrs.py +20 -22
- PyGeodesy-24.8.4.dist-info/RECORD +0 -117
- {PyGeodesy-24.8.4.dist-info → PyGeodesy-24.9.9.dist-info}/top_level.txt +0 -0
pygeodesy/elliptic.py
CHANGED
|
@@ -65,7 +65,8 @@ in U{B. C. Carlson, Computation of real or complex elliptic integrals
|
|
|
65
65
|
The computation of the Jacobi elliptic functions uses the algorithm
|
|
66
66
|
given in U{R. Bulirsch, Numerical Calculation of Elliptic Integrals
|
|
67
67
|
and Elliptic Functions<https://DOI.org/10.1007/BF01397975>},
|
|
68
|
-
Numerische Mathematik 7, 78--90 (1965)
|
|
68
|
+
Numerische Mathematik 7, 78--90 (1965) or optionally the C{Jacobi
|
|
69
|
+
amplitude} in method L{Elliptic.sncndn<pygeodesy.Elliptic.sncndn>}.
|
|
69
70
|
|
|
70
71
|
The notation follows U{NIST Digital Library of Mathematical Functions
|
|
71
72
|
<https://DLMF.NIST.gov>} chapters U{19<https://DLMF.NIST.gov/19>} and
|
|
@@ -75,13 +76,13 @@ U{22<https://DLMF.NIST.gov/22>}.
|
|
|
75
76
|
from __future__ import division as _; del _ # PYCHOK semicolon
|
|
76
77
|
|
|
77
78
|
from pygeodesy.basics import copysign0, map2, neg, neg_
|
|
78
|
-
from pygeodesy.constants import EPS, INF, NAN, PI, PI_2, PI_4, \
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
79
|
+
from pygeodesy.constants import EPS, INF, NAN, PI, PI_2, PI_4, _0_0, \
|
|
80
|
+
_0_25, _0_5, _1_0, _2_0, _N_2_0, _3_0, \
|
|
81
|
+
_4_0, _6_0, _8_0, _64_0, _180_0, _360_0, \
|
|
82
|
+
_EPStol as _TolJAC, _over, \
|
|
83
|
+
_EPSjam as _TolJAM # PYCHOK used!
|
|
83
84
|
# from pygeodesy.errors import _ValueError # from .fmath
|
|
84
|
-
from pygeodesy.fmath import
|
|
85
|
+
from pygeodesy.fmath import favg, hypot1, zqrt, _ValueError
|
|
85
86
|
from pygeodesy.fsums import Fsum, _sum
|
|
86
87
|
# from pygeodesy.internals import _dunder_nameof # from .lazily
|
|
87
88
|
from pygeodesy.interns import NN, _delta_, _DOT_, _f_, _invalid_, \
|
|
@@ -94,16 +95,16 @@ from pygeodesy.props import _allPropertiesOf_n, Property_RO, _update_all
|
|
|
94
95
|
from pygeodesy.units import Scalar, Scalar_
|
|
95
96
|
# from pygeodesy.utily import sincos2 as _sincos2 # from .karney
|
|
96
97
|
|
|
97
|
-
from math import asinh, atan, atan2, ceil, cosh, fabs, floor, \
|
|
98
|
-
radians, sin, sqrt, tanh
|
|
98
|
+
from math import asin, asinh, atan, atan2, ceil, cosh, fabs, floor, \
|
|
99
|
+
radians, sin, sinh, sqrt, tan, tanh
|
|
99
100
|
|
|
100
101
|
__all__ = _ALL_LAZY.elliptic
|
|
101
|
-
__version__ = '24.
|
|
102
|
+
__version__ = '24.09.06'
|
|
102
103
|
|
|
103
104
|
_TolRD = zqrt(EPS * 0.002)
|
|
104
105
|
_TolRF = zqrt(EPS * 0.030)
|
|
105
106
|
_TolRG0 = _TolJAC * 2.7
|
|
106
|
-
_TRIPS =
|
|
107
|
+
_TRIPS = 25 # Max depth, 6-7 might be sufficient
|
|
107
108
|
|
|
108
109
|
|
|
109
110
|
class _Cs(object):
|
|
@@ -127,6 +128,19 @@ class _Dsum(list):
|
|
|
127
128
|
return self
|
|
128
129
|
|
|
129
130
|
|
|
131
|
+
class _Dadd(_Dsum):
|
|
132
|
+
'''(INTERNAL) Deferred C{Fsum} for C{_List.amrs4}.
|
|
133
|
+
'''
|
|
134
|
+
def __init__(self, mul):
|
|
135
|
+
self._mul = mul
|
|
136
|
+
|
|
137
|
+
def __add__(self, x):
|
|
138
|
+
self += x
|
|
139
|
+
r = self(self._mul)
|
|
140
|
+
_ = self.pop()
|
|
141
|
+
return r # Fsum or float
|
|
142
|
+
|
|
143
|
+
|
|
130
144
|
class Elliptic(_Named):
|
|
131
145
|
'''Elliptic integrals and functions.
|
|
132
146
|
|
|
@@ -407,7 +421,6 @@ class Elliptic(_Named):
|
|
|
407
421
|
# Applied Math. and Computation 218, 7005-7013 (2012)
|
|
408
422
|
# <https://DOI.org/10.1016/j.amc.2011.12.021>
|
|
409
423
|
_Phi2 = Phi.fsum2f_ # aggregate
|
|
410
|
-
_abs = fabs
|
|
411
424
|
for i in range(1, _TRIPS): # GEOGRAPHICLIB_PANIC
|
|
412
425
|
sn, cn, dn = self._sncndn3(phi)
|
|
413
426
|
if dn:
|
|
@@ -415,7 +428,7 @@ class Elliptic(_Named):
|
|
|
415
428
|
phi, d = _Phi2((r - sn) / dn)
|
|
416
429
|
else: # PYCHOK no cover
|
|
417
430
|
d = _0_0 # XXX continue?
|
|
418
|
-
if
|
|
431
|
+
if fabs(d) < _TolJAC: # 3-4 trips
|
|
419
432
|
_iterations(self, i)
|
|
420
433
|
break
|
|
421
434
|
else: # PYCHOK no cover
|
|
@@ -505,7 +518,8 @@ class Elliptic(_Named):
|
|
|
505
518
|
return ei
|
|
506
519
|
|
|
507
520
|
return self._fXf(phi_or_sn, cn, dn, self.cE,
|
|
508
|
-
self.deltaE, _fE
|
|
521
|
+
self.deltaE, _fE,
|
|
522
|
+
k2_0=self.k2==0)
|
|
509
523
|
|
|
510
524
|
def fEd(self, deg):
|
|
511
525
|
'''The incomplete integral of the second kind with
|
|
@@ -561,7 +575,8 @@ class Elliptic(_Named):
|
|
|
561
575
|
return r
|
|
562
576
|
|
|
563
577
|
return self._fXf(phi_or_sn, cn, dn, self.cK,
|
|
564
|
-
self.deltaF, _fF
|
|
578
|
+
self.deltaF, _fF,
|
|
579
|
+
k2_0=self.k2==0, kp2_0=self.kp2==0)
|
|
565
580
|
|
|
566
581
|
def fG(self, phi_or_sn, cn=None, dn=None):
|
|
567
582
|
'''Legendre's geodesic longitude integral in terms of
|
|
@@ -648,12 +663,16 @@ class Elliptic(_Named):
|
|
|
648
663
|
|
|
649
664
|
return self._fXf(phi_or_sn, cn, dn, cX, deltaX, _fX)
|
|
650
665
|
|
|
651
|
-
def _fXf(self, phi_or_sn, cn, dn, cX, deltaX, fX):
|
|
666
|
+
def _fXf(self, phi_or_sn, cn, dn, cX, deltaX, fX, k2_0=False, kp2_0=False):
|
|
652
667
|
'''(INTERNAL) Helper for C{.fD}, C{.fE}, C{.fF} and C{._fXa}.
|
|
653
668
|
'''
|
|
654
669
|
self._iteration = 0 # aggregate
|
|
655
670
|
phi = sn = phi_or_sn
|
|
656
671
|
if cn is dn is None: # fX(phi) call
|
|
672
|
+
if k2_0: # C++ version 2.4
|
|
673
|
+
return phi
|
|
674
|
+
elif kp2_0:
|
|
675
|
+
return asinh(tan(phi))
|
|
657
676
|
sn, cn, dn = self._sncndn3(phi)
|
|
658
677
|
if fabs(phi) >= PI:
|
|
659
678
|
return (deltaX(sn, cn, dn) + phi) * cX / PI_2
|
|
@@ -668,6 +687,51 @@ class Elliptic(_Named):
|
|
|
668
687
|
xi = fX(sn, cn, dn) if cn > 0 else cX
|
|
669
688
|
return copysign0(xi, sn)
|
|
670
689
|
|
|
690
|
+
def _jam(self, x):
|
|
691
|
+
'''Jacobi amplitude function.
|
|
692
|
+
|
|
693
|
+
@return: C{phi} (C{float}).
|
|
694
|
+
'''
|
|
695
|
+
# implements DLMF Sec 22.20(ii), see also U{Sala
|
|
696
|
+
# (1989)<https://doi.org/10.1137/0520100>}, Sec 5
|
|
697
|
+
if self.k2:
|
|
698
|
+
if self.kp2:
|
|
699
|
+
r, ac = self._jamac2
|
|
700
|
+
x *= r # phi
|
|
701
|
+
for a, c in ac:
|
|
702
|
+
p = x
|
|
703
|
+
x = favg(asin(c * sin(x) / a), x)
|
|
704
|
+
if self.k2 < 0: # Sala Eq. 5.8
|
|
705
|
+
x = p - x
|
|
706
|
+
else: # PYCHOK no cover
|
|
707
|
+
x = atan(sinh(x)) # gd(x)
|
|
708
|
+
return x
|
|
709
|
+
|
|
710
|
+
@Property_RO
|
|
711
|
+
def _jamac2(self):
|
|
712
|
+
'''(INTERNAL) Get Jacobi amplitude 2-tuple C{(r, ac)}.
|
|
713
|
+
'''
|
|
714
|
+
a = r = _1_0
|
|
715
|
+
b, c = self.kp2, self.k2
|
|
716
|
+
# assert b and c
|
|
717
|
+
if c < 0: # Sala Eq. 5.8
|
|
718
|
+
r = sqrt(b)
|
|
719
|
+
b = _1_0 / b
|
|
720
|
+
# c *= b # unused
|
|
721
|
+
ac = [] # [(a, sqrt(c))] unused
|
|
722
|
+
for i in range(1, _TRIPS): # GEOGRAPHICLIB_PANIC
|
|
723
|
+
b = sqrt(a * b)
|
|
724
|
+
c = favg(a, -b)
|
|
725
|
+
a = favg(a, b) # == PI_2 / K
|
|
726
|
+
ac.append((a, c))
|
|
727
|
+
if c <= (a * _TolJAM): # 7 trips, quadratic
|
|
728
|
+
_iterations(self, i)
|
|
729
|
+
break
|
|
730
|
+
else: # PYCHOK no cover
|
|
731
|
+
raise _convergenceError(c / a, _TolJAM)
|
|
732
|
+
r *= a * float(1 << i) # 2**i == 2**len(ac)
|
|
733
|
+
return r, tuple(reversed(ac))
|
|
734
|
+
|
|
671
735
|
@Property_RO
|
|
672
736
|
def k2(self):
|
|
673
737
|
'''Get k^2, the square of the modulus (C{float}).
|
|
@@ -723,38 +787,46 @@ class Elliptic(_Named):
|
|
|
723
787
|
# Pi(alpha2, 1) = inf
|
|
724
788
|
# G( alpha2, 1) = H(alpha2, 1) = RC(1, alphap2)
|
|
725
789
|
|
|
726
|
-
def sncndn(self, x):
|
|
727
|
-
'''The Jacobi elliptic function.
|
|
790
|
+
def sncndn(self, x, jam=False):
|
|
791
|
+
'''The Jacobi amplitude and elliptic function.
|
|
728
792
|
|
|
729
793
|
@arg x: The argument (C{float}).
|
|
794
|
+
@kwarg jam: If C{True}, use the Jacobi amplitude otherwise the
|
|
795
|
+
Bulirsch' function (C{bool}).
|
|
730
796
|
|
|
731
|
-
@return: An L{Elliptic3Tuple}C{(sn, cn, dn)} with
|
|
732
|
-
C{*n(B{x}, k)}.
|
|
797
|
+
@return: An L{Elliptic3Tuple}C{(sn, cn, dn)} with C{*n(B{x}, k)}.
|
|
733
798
|
|
|
734
799
|
@raise EllipticError: No convergence.
|
|
735
800
|
'''
|
|
736
801
|
self._iteration = 0 # reset
|
|
737
|
-
try:
|
|
802
|
+
try:
|
|
738
803
|
if self.kp2:
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
for
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
804
|
+
if jam: # Jacobi amplitude, C++ version 2.4
|
|
805
|
+
sn, cn, dn = self._sncndn3(self._jam(x))
|
|
806
|
+
|
|
807
|
+
else: # Bulirsch's sncndn routine, p 89 of
|
|
808
|
+
# Numerische Mathematik 7, 78-90 (1965).
|
|
809
|
+
# Implements DLMF Eqs 22.17.2 - 22.17.4,
|
|
810
|
+
# but only good for .k2 > 1 or .kp2 < 0
|
|
811
|
+
c, d, cd, mn = self._sncndn4
|
|
812
|
+
dn = _1_0
|
|
813
|
+
sn, cn = _sincos2(x * cd)
|
|
814
|
+
if sn:
|
|
815
|
+
a = cn / sn
|
|
816
|
+
c *= a
|
|
817
|
+
for m, n in mn:
|
|
818
|
+
a *= c
|
|
819
|
+
c *= dn
|
|
820
|
+
dn = (n + a) / (m + a)
|
|
821
|
+
a = c / m
|
|
822
|
+
a = _1_0 / hypot1(c)
|
|
823
|
+
sn = neg(a) if _signBit(sn) else a
|
|
824
|
+
cn = sn * c
|
|
825
|
+
if d: # and _signBit(self.kp2): # implied
|
|
826
|
+
cn, dn = dn, cn
|
|
827
|
+
sn = sn / d # /= chokes PyChecker
|
|
756
828
|
else:
|
|
757
|
-
sn = tanh(x)
|
|
829
|
+
sn = tanh(x) # accurate for large abs(x)
|
|
758
830
|
cn = dn = _1_0 / cosh(x)
|
|
759
831
|
|
|
760
832
|
except Exception as e:
|
|
@@ -763,7 +835,7 @@ class Elliptic(_Named):
|
|
|
763
835
|
return Elliptic3Tuple(sn, cn, dn, iteration=self._iteration)
|
|
764
836
|
|
|
765
837
|
def _sncndn3(self, phi):
|
|
766
|
-
'''(INTERNAL) Helper for C{.fEinv} and C{.
|
|
838
|
+
'''(INTERNAL) Helper for C{.fEinv}, C{._fXf} and C{.sncndn}.
|
|
767
839
|
'''
|
|
768
840
|
sn, cn = _sincos2(phi)
|
|
769
841
|
return sn, cn, self.fDelta(sn, cn)
|
|
@@ -772,29 +844,27 @@ class Elliptic(_Named):
|
|
|
772
844
|
def _sncndn4(self):
|
|
773
845
|
'''(INTERNAL) Get Bulirsch' 4-tuple C{(c, d, cd, mn)}.
|
|
774
846
|
'''
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
mn, a = [], _1_0
|
|
847
|
+
d, b = 0, self.kp2
|
|
848
|
+
if _signBit(b):
|
|
849
|
+
d = _1_0 - b
|
|
850
|
+
b = neg(b / d)
|
|
851
|
+
d = sqrt(d)
|
|
852
|
+
ab, a = [], _1_0
|
|
783
853
|
for i in range(1, _TRIPS): # GEOGRAPHICLIB_PANIC
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
c = (a
|
|
787
|
-
r =
|
|
788
|
-
|
|
789
|
-
if r <= t: # 6 trips, quadratic
|
|
854
|
+
b = sqrt(b)
|
|
855
|
+
ab.append((a, b))
|
|
856
|
+
c = favg(a, b)
|
|
857
|
+
r = fabs(a - b)
|
|
858
|
+
if r <= (a * _TolJAC): # 6 trips, quadratic
|
|
790
859
|
_iterations(self, i)
|
|
791
860
|
break
|
|
792
|
-
|
|
793
|
-
a
|
|
861
|
+
t = a
|
|
862
|
+
b *= a
|
|
863
|
+
a = c
|
|
794
864
|
else: # PYCHOK no cover
|
|
795
|
-
raise _convergenceError(r,
|
|
865
|
+
raise _convergenceError(r / t, _TolJAC)
|
|
796
866
|
cd = (c * d) if d else c
|
|
797
|
-
return c, d, cd,
|
|
867
|
+
return c, d, cd, tuple(reversed(ab))
|
|
798
868
|
|
|
799
869
|
@staticmethod
|
|
800
870
|
def fRC(x, y):
|
|
@@ -882,7 +952,7 @@ class Elliptic(_Named):
|
|
|
882
952
|
raise _ellipticError(Elliptic._RFRD, x, y, z, m, cause=e)
|
|
883
953
|
return float(R)
|
|
884
954
|
|
|
885
|
-
_allPropertiesOf_n(
|
|
955
|
+
_allPropertiesOf_n(16, Elliptic) # # PYCHOK assert, see Elliptic.reset
|
|
886
956
|
|
|
887
957
|
|
|
888
958
|
class EllipticError(_ValueError):
|
|
@@ -901,25 +971,18 @@ class Elliptic3Tuple(_NamedTuple):
|
|
|
901
971
|
class _List(list):
|
|
902
972
|
'''(INTERNAL) Helper for C{_RD}, C{_RF3} and C{_RJ}.
|
|
903
973
|
'''
|
|
904
|
-
_a0
|
|
905
|
-
# _xyzp = ()
|
|
974
|
+
_a0 = None
|
|
906
975
|
|
|
907
976
|
def __init__(self, *xyzp): # x, y, z [, p]
|
|
908
977
|
list.__init__(self, xyzp)
|
|
909
|
-
self._xyzp = xyzp
|
|
910
978
|
|
|
911
979
|
def a0(self, n):
|
|
912
980
|
'''Compute the initial C{a}.
|
|
913
981
|
'''
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
try:
|
|
919
|
-
a = Fsum(*t).fover(n)
|
|
920
|
-
except ValueError: # Fsum(NAN) exception
|
|
921
|
-
a = _sum(t) / n
|
|
922
|
-
self._a0 = a
|
|
982
|
+
A = _Dsum(self)
|
|
983
|
+
while len(A) < n:
|
|
984
|
+
A += A[-1]
|
|
985
|
+
self._a0 = a = float(A(_1_0 / n))
|
|
923
986
|
return a
|
|
924
987
|
|
|
925
988
|
def amrs4(self, inst, y, Tol):
|
|
@@ -929,20 +992,22 @@ class _List(list):
|
|
|
929
992
|
L = self
|
|
930
993
|
a = L.a0(5 if y else 3)
|
|
931
994
|
m = 1
|
|
932
|
-
t = max(fabs(a - _) for _ in L) / Tol
|
|
995
|
+
t = max(fabs(a - _) for _ in L) / Tol # thresh
|
|
933
996
|
for i in range(_TRIPS):
|
|
934
997
|
d = fabs(a * m)
|
|
935
998
|
if d > t: # 3-6 trips
|
|
936
999
|
_iterations(inst, i)
|
|
937
1000
|
break
|
|
938
1001
|
s = map2(sqrt, L) # sqrt(x), srqt(y), sqrt(z) [, sqrt(p)]
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
1002
|
+
# Deferred fdot(s[:3], s[1], s[2], s[0]) + ...
|
|
1003
|
+
Q = _Dadd(_0_25)
|
|
1004
|
+
Q += s[0] * s[1]
|
|
1005
|
+
Q += s[1] * s[2]
|
|
1006
|
+
Q += s[2] * s[0]
|
|
1007
|
+
L[:] = (float(Q + _) for _ in L)
|
|
1008
|
+
a = float(Q + a)
|
|
945
1009
|
if y: # yield only if used
|
|
1010
|
+
r = _sum(Q) # fdot
|
|
946
1011
|
yield a, m, r, s # L[2] is next z
|
|
947
1012
|
m *= 4
|
|
948
1013
|
else: # PYCHOK no cover
|
|
@@ -967,14 +1032,15 @@ def _ab2(inst, x, y):
|
|
|
967
1032
|
b, a = a, b
|
|
968
1033
|
for i in range(_TRIPS):
|
|
969
1034
|
yield a, b # xi, yi
|
|
970
|
-
d =
|
|
971
|
-
|
|
972
|
-
if d <= t: # 3-4 trips
|
|
1035
|
+
d = fabs(a - b)
|
|
1036
|
+
if d <= (a * _TolRG0): # 3-4 trips
|
|
973
1037
|
_iterations(inst, i)
|
|
974
1038
|
break
|
|
975
|
-
|
|
1039
|
+
t = a
|
|
1040
|
+
a = favg(t, b)
|
|
1041
|
+
b = sqrt(t * b)
|
|
976
1042
|
else: # PYCHOK no cover
|
|
977
|
-
raise _convergenceError(d,
|
|
1043
|
+
raise _convergenceError(d / t, _TolRG0)
|
|
978
1044
|
|
|
979
1045
|
|
|
980
1046
|
def _convergenceError(d, tol, **thresh):
|
|
@@ -1083,10 +1149,10 @@ def _RD(inst, x, y, z, *over):
|
|
|
1083
1149
|
z = (x + y) / _3_0
|
|
1084
1150
|
z2 = z**2
|
|
1085
1151
|
return _Horner(S(_1_0), sqrt(a) * a * m,
|
|
1086
|
-
|
|
1087
|
-
(xy * _3_0 -
|
|
1088
|
-
(xy -
|
|
1089
|
-
|
|
1152
|
+
(xy - z2 * _6_0),
|
|
1153
|
+
(xy * _3_0 - z2 * _8_0) * z,
|
|
1154
|
+
(xy - z2) * z2 * _3_0,
|
|
1155
|
+
(xy * z2 * z), *over) # Fsum
|
|
1090
1156
|
|
|
1091
1157
|
|
|
1092
1158
|
def _rF2(inst, x, y): # 2-arg version, z=0
|
|
@@ -1160,7 +1226,7 @@ def _RJ(inst, x, y, z, p, *over):
|
|
|
1160
1226
|
if d:
|
|
1161
1227
|
if n:
|
|
1162
1228
|
rc = _rC(inst, _1_0, n / d**2 + _1_0)
|
|
1163
|
-
n
|
|
1229
|
+
n = n / _64_0 # /= chokes PyChecker
|
|
1164
1230
|
else:
|
|
1165
1231
|
rc = _1_0 # == _rC(None, _1_0, _1_0)
|
|
1166
1232
|
S += rc / (d * m)
|
pygeodesy/epsg.py
CHANGED
|
@@ -17,7 +17,7 @@ including coverage of UPS as zone C{0}.
|
|
|
17
17
|
from pygeodesy.basics import isint, isstr, _xinstanceof
|
|
18
18
|
from pygeodesy.errors import _ValueError
|
|
19
19
|
from pygeodesy.interns import NN, _N_, _NS_, _S_, _SPACE_
|
|
20
|
-
from pygeodesy.lazily import
|
|
20
|
+
from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY
|
|
21
21
|
from pygeodesy.namedTuples import UtmUps2Tuple
|
|
22
22
|
from pygeodesy.props import Property_RO
|
|
23
23
|
from pygeodesy.streprs import Fmt
|
|
@@ -28,7 +28,7 @@ from pygeodesy.utmupsBase import _to3zBhp, _UPS_ZONE, _UTM_ZONE_MIN, \
|
|
|
28
28
|
_UTM_ZONE_MAX, _UTMUPS_ZONE_INVALID
|
|
29
29
|
|
|
30
30
|
__all__ = _ALL_LAZY.epsg
|
|
31
|
-
__version__ = '24.05
|
|
31
|
+
__version__ = '24.08.05'
|
|
32
32
|
|
|
33
33
|
# _EPSG_INVALID = _UTMUPS_ZONE_INVALID
|
|
34
34
|
_EPSG_N_01 = 32601 # EPSG code for UTM zone 01 N
|
|
@@ -219,7 +219,7 @@ def encode(zone, hemipole=NN, band=NN):
|
|
|
219
219
|
return e
|
|
220
220
|
|
|
221
221
|
|
|
222
|
-
__all__ +=
|
|
222
|
+
__all__ += _ALL_DOCS(decode2, encode)
|
|
223
223
|
|
|
224
224
|
# **) MIT License
|
|
225
225
|
#
|
pygeodesy/etm.py
CHANGED
|
@@ -73,10 +73,9 @@ from pygeodesy.elliptic import _ALL_LAZY, Elliptic
|
|
|
73
73
|
# from pygeodesy.errors import _incompatible # from .named
|
|
74
74
|
# from pygeodesy.fsums import Fsum # from .fmath
|
|
75
75
|
from pygeodesy.fmath import cbrt, hypot, hypot1, hypot2, Fsum
|
|
76
|
-
from pygeodesy.interns import _COMMASPACE_,
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
_tand, _unsigned2
|
|
76
|
+
from pygeodesy.interns import _COMMASPACE_, _near_, _SPACE_, _spherical_
|
|
77
|
+
from pygeodesy.karney import _K_2_4, _copyBit, _diff182, _fix90, \
|
|
78
|
+
_norm2, _norm180, _tand, _unsigned2
|
|
80
79
|
# from pygeodesy.lazily import _ALL_LAZY # from .elliptic
|
|
81
80
|
from pygeodesy.named import callername, _incompatible, _NamedBase
|
|
82
81
|
from pygeodesy.namedTuples import Forward4Tuple, Reverse4Tuple
|
|
@@ -92,7 +91,7 @@ from pygeodesy.utm import _cmlon, _LLEB, _parseUTM5, _toBand, _toXtm8, \
|
|
|
92
91
|
from math import asinh, atan2, degrees, radians, sinh, sqrt
|
|
93
92
|
|
|
94
93
|
__all__ = _ALL_LAZY.etm
|
|
95
|
-
__version__ = '24.06
|
|
94
|
+
__version__ = '24.09.06'
|
|
96
95
|
|
|
97
96
|
_OVERFLOW = _1_EPS**2 # about 2e+31
|
|
98
97
|
_TAYTOL = pow(EPS, 0.6)
|
|
@@ -431,13 +430,15 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
431
430
|
|
|
432
431
|
f = flattening
|
|
433
432
|
|
|
434
|
-
def forward(self, lat, lon, lon0=None, **name): # MCCABE 13
|
|
433
|
+
def forward(self, lat, lon, lon0=None, jam=_K_2_4, **name): # MCCABE 13
|
|
435
434
|
'''Forward projection, from geographic to transverse Mercator.
|
|
436
435
|
|
|
437
436
|
@arg lat: Latitude of point (C{degrees}).
|
|
438
437
|
@arg lon: Longitude of point (C{degrees}).
|
|
439
438
|
@kwarg lon0: Central meridian (C{degrees180}), overriding
|
|
440
439
|
the default if not C{None}.
|
|
440
|
+
@kwarg jam: If C{True}, use the C{Jacobi amplitude}
|
|
441
|
+
otherwise C{Bulirsch}' function (C{bool}).
|
|
441
442
|
@kwarg name: Optional C{B{name}=NN} (C{str}).
|
|
442
443
|
|
|
443
444
|
@return: L{Forward4Tuple}C{(easting, northing, gamma, scale)}.
|
|
@@ -473,7 +474,7 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
473
474
|
tau, lam = _tand(lat), radians(lon)
|
|
474
475
|
u, v = self._zetaInv2(self._E.es_taupf(tau), lam)
|
|
475
476
|
|
|
476
|
-
sncndn6 = self._sncndn6(u, v)
|
|
477
|
+
sncndn6 = self._sncndn6(u, v, jam=jam)
|
|
477
478
|
y, x, _ = self._sigma3(v, *sncndn6)
|
|
478
479
|
g, k = (lon, self.k0) if isnear90(lat) else \
|
|
479
480
|
self._zetaScaled(sncndn6, ll=False)
|
|
@@ -668,13 +669,15 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
668
669
|
self._mu = mu
|
|
669
670
|
self._mv = mv
|
|
670
671
|
|
|
671
|
-
def reverse(self, x, y, lon0=None, **name):
|
|
672
|
+
def reverse(self, x, y, lon0=None, jam=_K_2_4, **name):
|
|
672
673
|
'''Reverse projection, from Transverse Mercator to geographic.
|
|
673
674
|
|
|
674
675
|
@arg x: Easting of point (C{meters}).
|
|
675
676
|
@arg y: Northing of point (C{meters}).
|
|
676
677
|
@kwarg lon0: Optional central meridian (C{degrees180}),
|
|
677
678
|
overriding the default (C{iff not None}).
|
|
679
|
+
@kwarg jam: If C{True}, use the C{Jacobi amplitude}
|
|
680
|
+
otherwise C{Bulirsch}' function (C{bool}).
|
|
678
681
|
@kwarg name: Optional C{B{name}=NN} (C{str}).
|
|
679
682
|
|
|
680
683
|
@return: L{Reverse4Tuple}C{(lat, lon, gamma, scale)}.
|
|
@@ -706,7 +709,7 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
706
709
|
v = self._Ev_cK
|
|
707
710
|
|
|
708
711
|
if v or u != self._Eu_cK:
|
|
709
|
-
g, k, lat, lon = self._zetaScaled(self._sncndn6(u, v))
|
|
712
|
+
g, k, lat, lon = self._zetaScaled(self._sncndn6(u, v, jam=jam))
|
|
710
713
|
else: # PYCHOK no cover
|
|
711
714
|
g, k, lat, lon = _0_0, self.k0, _90_0, _0_0
|
|
712
715
|
|
|
@@ -866,12 +869,12 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
866
869
|
|
|
867
870
|
return u, v, t, C
|
|
868
871
|
|
|
869
|
-
def _sncndn6(self, u, v):
|
|
872
|
+
def _sncndn6(self, u, v, **jam):
|
|
870
873
|
'''(INTERNAL) Get 6-tuple C{(snu, cnu, dnu, snv, cnv, dnv)}.
|
|
871
874
|
'''
|
|
872
875
|
# snu, cnu, dnu = self._Eu.sncndn(u)
|
|
873
876
|
# snv, cnv, dnv = self._Ev.sncndn(v)
|
|
874
|
-
return self._Eu.sncndn(u) + self._Ev.sncndn(v)
|
|
877
|
+
return self._Eu.sncndn(u, **jam) + self._Ev.sncndn(v, **jam)
|
|
875
878
|
|
|
876
879
|
def toStr(self, joined=_COMMASPACE_, **kwds): # PYCHOK signature
|
|
877
880
|
'''Return a C{str} representation.
|
|
@@ -1094,67 +1097,76 @@ def toEtm8(latlon, lon=None, datum=None, Etm=Etm, falsed=True,
|
|
|
1094
1097
|
n, latlon, d.exactTM, Error=ETMError)
|
|
1095
1098
|
|
|
1096
1099
|
|
|
1097
|
-
if __name__ == '__main__': # MCCABE
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
while _as and _as[0].startswith(_DASH_):
|
|
1108
|
-
_a = _as.pop(0)
|
|
1109
|
-
if len(_a) < 2:
|
|
1110
|
-
_exit('%s: option %r invalid' % (_usage(*argv), _a))
|
|
1111
|
-
elif '-forward'.startswith(_a):
|
|
1112
|
-
_f, _r = True, False
|
|
1113
|
-
elif '-reverse'.startswith(_a):
|
|
1114
|
-
_f, _r = False, True
|
|
1115
|
-
elif '-precision'.startswith(_a):
|
|
1116
|
-
_p = int(_as.pop(0))
|
|
1117
|
-
elif '-series'.startswith(_a):
|
|
1118
|
-
_s, _t = True, False
|
|
1119
|
-
elif _a == '-t':
|
|
1120
|
-
_s, _t = False, True
|
|
1121
|
-
elif '-help'.startswith(_a):
|
|
1100
|
+
if __name__ == '__main__': # MCCABE 16
|
|
1101
|
+
|
|
1102
|
+
def _main():
|
|
1103
|
+
|
|
1104
|
+
from pygeodesy import fstr, KTransverseMercator
|
|
1105
|
+
# from pygeodesy.interns import _DASH_ # from internals
|
|
1106
|
+
from pygeodesy.internals import printf, _usage, _DASH_
|
|
1107
|
+
from sys import argv, exit as _exit
|
|
1108
|
+
|
|
1109
|
+
def _help():
|
|
1122
1110
|
_exit(_usage(argv[0], '[-s | -t ]',
|
|
1123
1111
|
'[-p[recision] <ndigits>',
|
|
1124
1112
|
'[-f[orward] <lat> <lon>',
|
|
1125
1113
|
'|-r[everse] <easting> <northing>',
|
|
1126
1114
|
'|<lat> <lon>]',
|
|
1127
1115
|
'|-h[elp]'))
|
|
1116
|
+
|
|
1117
|
+
# mimick some of I{Karney}'s utility C{TransverseMercatorProj}
|
|
1118
|
+
_f = _r = _s = _t = False
|
|
1119
|
+
_p = -6
|
|
1120
|
+
_as = argv[1:]
|
|
1121
|
+
while _as and _as[0].startswith(_DASH_):
|
|
1122
|
+
_a = _as.pop(0)
|
|
1123
|
+
if len(_a) < 2:
|
|
1124
|
+
_exit('%s: option %r invalid' % (_usage(*argv), _a))
|
|
1125
|
+
elif '-forward'.startswith(_a):
|
|
1126
|
+
_f, _r = True, False
|
|
1127
|
+
elif '-reverse'.startswith(_a):
|
|
1128
|
+
_f, _r = False, True
|
|
1129
|
+
elif '-precision'.startswith(_a):
|
|
1130
|
+
_p = int(_as.pop(0))
|
|
1131
|
+
elif '-series'.startswith(_a):
|
|
1132
|
+
_s, _t = True, False
|
|
1133
|
+
elif _a == '-t':
|
|
1134
|
+
_s, _t = False, True
|
|
1135
|
+
elif '-help'.startswith(_a):
|
|
1136
|
+
_help()
|
|
1137
|
+
else:
|
|
1138
|
+
_exit('%s: option %r not supported' % (_usage(*argv), _a))
|
|
1139
|
+
|
|
1140
|
+
if len(_as) > 1:
|
|
1141
|
+
f2 = map1(float, *_as[:2])
|
|
1142
|
+
else:
|
|
1143
|
+
printf('%s ...: incomplete', _usage(*argv))
|
|
1144
|
+
_help()
|
|
1145
|
+
|
|
1146
|
+
if _s: # -series
|
|
1147
|
+
tm = KTransverseMercator()
|
|
1148
|
+
else:
|
|
1149
|
+
tm = ExactTransverseMercator(extendp=_t)
|
|
1150
|
+
|
|
1151
|
+
if _f:
|
|
1152
|
+
t = tm.forward(*f2)
|
|
1153
|
+
elif _r:
|
|
1154
|
+
t = tm.reverse(*f2)
|
|
1128
1155
|
else:
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
else:
|
|
1133
|
-
_exit('%s ...: incomplete' % (_usage(*argv),))
|
|
1134
|
-
|
|
1135
|
-
if _s: # -series
|
|
1136
|
-
tm = KTransverseMercator()
|
|
1137
|
-
else:
|
|
1138
|
-
tm = ExactTransverseMercator(extendp=_t)
|
|
1139
|
-
|
|
1140
|
-
if _f:
|
|
1141
|
-
t = tm.forward(*f2)
|
|
1142
|
-
elif _r:
|
|
1143
|
-
t = tm.reverse(*f2)
|
|
1144
|
-
else:
|
|
1145
|
-
t = tm.forward(*f2)
|
|
1156
|
+
t = tm.forward(*f2)
|
|
1157
|
+
printf('%s: %s', tm.classname, fstr(t, prec=_p, sep=_SPACE_))
|
|
1158
|
+
t = tm.reverse(t.easting, t.northing)
|
|
1146
1159
|
printf('%s: %s', tm.classname, fstr(t, prec=_p, sep=_SPACE_))
|
|
1147
|
-
t = tm.reverse(t.easting, t.northing)
|
|
1148
|
-
printf('%s: %s', tm.classname, fstr(t, prec=_p, sep=_SPACE_))
|
|
1149
1160
|
|
|
1161
|
+
_main()
|
|
1150
1162
|
|
|
1151
|
-
# % python3 -m pygeodesy.etm -p 12 33.33 44.44
|
|
1163
|
+
# % python3.12 -m pygeodesy.etm -p 12 33.33 44.44
|
|
1152
1164
|
# ExactTransverseMercator: 4276926.11480390653 4727193.767015309073 28.375536563148 1.233325101778
|
|
1153
1165
|
# ExactTransverseMercator: 33.33 44.44 28.375536563148 1.233325101778
|
|
1154
1166
|
|
|
1155
|
-
# % python3 -m pygeodesy.etm -
|
|
1156
|
-
#
|
|
1157
|
-
#
|
|
1167
|
+
# % python3.12 -s -m pygeodesy.etm -p 12 33.33 44.44
|
|
1168
|
+
# ExactTransverseMercator: 4276926.11480390653 4727193.767015309073 28.375536563148 1.233325101778
|
|
1169
|
+
# ExactTransverseMercator: 33.33 44.44 28.375536563148 1.233325101778
|
|
1158
1170
|
|
|
1159
1171
|
# % echo 33.33 44.44 | .../bin/TransverseMercatorProj
|
|
1160
1172
|
# 4276926.114804 4727193.767015 28.375536563148 1.233325101778
|