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/etm.py
CHANGED
|
@@ -11,7 +11,7 @@ Class L{ExactTransverseMercator} provides C{Exact Transverse Mercator} projectio
|
|
|
11
11
|
instances of class L{Etm} represent ETM C{(easting, northing)} locations. See also
|
|
12
12
|
I{Karney}'s utility U{TransverseMercatorProj<https://GeographicLib.SourceForge.io/C++/doc/
|
|
13
13
|
TransverseMercatorProj.1.html>} and use C{"python[3] -m pygeodesy.etm ..."} to compare
|
|
14
|
-
the results.
|
|
14
|
+
the results, see usage C{"python[3] -m pygeodesy.etm -h"}.
|
|
15
15
|
|
|
16
16
|
Following is a copy of I{Karney}'s U{TransverseMercatorExact.hpp
|
|
17
17
|
<https://GeographicLib.SourceForge.io/C++/doc/TransverseMercatorExact_8hpp_source.html>}
|
|
@@ -65,23 +65,25 @@ from __future__ import division as _; del _ # PYCHOK semicolon
|
|
|
65
65
|
|
|
66
66
|
from pygeodesy.basics import map1, neg, neg_, _xinstanceof
|
|
67
67
|
from pygeodesy.constants import EPS, EPS02, PI_2, PI_4, _K0_UTM, \
|
|
68
|
-
|
|
69
|
-
|
|
68
|
+
_1_EPS, _0_0, _0_1, _0_5, _1_0, _2_0, \
|
|
69
|
+
_3_0, _90_0, isnear0, isnear90
|
|
70
|
+
from pygeodesy.constants import _4_0 # PYCHOK used!
|
|
70
71
|
from pygeodesy.datums import _ellipsoidal_datum, _WGS84, _EWGS84
|
|
71
72
|
# from pygeodesy.ellipsoids import _EWGS84 # from .datums
|
|
72
|
-
from pygeodesy.elliptic import
|
|
73
|
+
# from pygeodesy.elliptic import Elliptic # _MODS
|
|
73
74
|
# from pygeodesy.errors import _incompatible # from .named
|
|
74
75
|
# from pygeodesy.fsums import Fsum # from .fmath
|
|
75
76
|
from pygeodesy.fmath import cbrt, hypot, hypot1, hypot2, Fsum
|
|
76
77
|
from pygeodesy.interns import _COMMASPACE_, _near_, _SPACE_, _spherical_
|
|
77
78
|
from pygeodesy.karney import _K_2_4, _copyBit, _diff182, _fix90, \
|
|
78
79
|
_norm2, _norm180, _tand, _unsigned2
|
|
79
|
-
# from pygeodesy.lazily import _ALL_LAZY # from .
|
|
80
|
-
from pygeodesy.named import callername, _incompatible, _NamedBase
|
|
80
|
+
# from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS # from .named
|
|
81
|
+
from pygeodesy.named import callername, _incompatible, _NamedBase, \
|
|
82
|
+
_ALL_LAZY, _MODS
|
|
81
83
|
from pygeodesy.namedTuples import Forward4Tuple, Reverse4Tuple
|
|
82
84
|
from pygeodesy.props import deprecated_method, deprecated_property_RO, \
|
|
83
85
|
Property_RO, property_RO, _update_all, \
|
|
84
|
-
property_doc_
|
|
86
|
+
property_doc_, _allPropertiesOf_n
|
|
85
87
|
from pygeodesy.streprs import Fmt, pairs, unstr
|
|
86
88
|
from pygeodesy.units import Degrees, Scalar_
|
|
87
89
|
from pygeodesy.utily import atan1d, atan2d, _loneg, sincos2
|
|
@@ -91,12 +93,12 @@ from pygeodesy.utm import _cmlon, _LLEB, _parseUTM5, _toBand, _toXtm8, \
|
|
|
91
93
|
from math import asinh, atan2, degrees, radians, sinh, sqrt
|
|
92
94
|
|
|
93
95
|
__all__ = _ALL_LAZY.etm
|
|
94
|
-
__version__ = '24.
|
|
96
|
+
__version__ = '24.11.04'
|
|
95
97
|
|
|
96
|
-
_OVERFLOW = _1_EPS**2 #
|
|
97
|
-
_TAYTOL = pow(EPS,
|
|
98
|
+
_OVERFLOW = _1_EPS**2 # ~2e+31
|
|
99
|
+
_TAYTOL = pow(EPS, 0.6)
|
|
98
100
|
_TAYTOL2 = _TAYTOL * _2_0
|
|
99
|
-
_TOL_10 = EPS
|
|
101
|
+
_TOL_10 = EPS * _0_1
|
|
100
102
|
_TRIPS = 21 # C++ 10
|
|
101
103
|
|
|
102
104
|
|
|
@@ -218,12 +220,12 @@ class Etm(Utm):
|
|
|
218
220
|
class ExactTransverseMercator(_NamedBase):
|
|
219
221
|
'''Pure Python version of Karney's C++ class U{TransverseMercatorExact
|
|
220
222
|
<https://GeographicLib.SourceForge.io/C++/doc/TransverseMercatorExact_8cpp_source.html>},
|
|
221
|
-
a numerically exact transverse Mercator projection,
|
|
223
|
+
a numerically exact transverse Mercator projection, abbreviated as C{TMExact}.
|
|
222
224
|
'''
|
|
223
225
|
_datum = _WGS84 # Datum
|
|
224
226
|
_E = _EWGS84 # Ellipsoid
|
|
225
227
|
_extendp = False # use extended domain
|
|
226
|
-
# _iteration = None # ._sigmaInv2 and ._zetaInv2
|
|
228
|
+
# _iteration = None # _NameBase, ._sigmaInv2 and ._zetaInv2
|
|
227
229
|
_k0 = _K0_UTM # central scale factor
|
|
228
230
|
_lat0 = _0_0 # central parallel
|
|
229
231
|
_lon0 = _0_0 # central meridian
|
|
@@ -240,7 +242,7 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
240
242
|
L{Ellipsoid}, L{Ellipsoid2} or L{a_f2Tuple}).
|
|
241
243
|
@kwarg lon0: Central meridian, default (C{degrees180}).
|
|
242
244
|
@kwarg k0: Central scale factor (C{float}).
|
|
243
|
-
@kwarg extendp:
|
|
245
|
+
@kwarg extendp: If C{True}, use the I{extended} domain, I{standard} otherwise (C{bool}).
|
|
244
246
|
@kwarg raiser: If C{True}, throw an L{ETMError} for convergence failures (C{bool}).
|
|
245
247
|
@kwarg name: Optional C{B{name}=NN} for the projection (C{str}).
|
|
246
248
|
|
|
@@ -349,7 +351,7 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
349
351
|
def _Eu(self):
|
|
350
352
|
'''(INTERNAL) Get and cache C{Elliptic(_mu)}.
|
|
351
353
|
'''
|
|
352
|
-
return Elliptic(self._mu)
|
|
354
|
+
return _MODS.elliptic.Elliptic(self._mu)
|
|
353
355
|
|
|
354
356
|
@Property_RO
|
|
355
357
|
def _Eu_cE(self):
|
|
@@ -390,7 +392,7 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
390
392
|
def _Ev(self):
|
|
391
393
|
'''(INTERNAL) Get and cache C{Elliptic(_mv)}.
|
|
392
394
|
'''
|
|
393
|
-
return Elliptic(self._mv)
|
|
395
|
+
return _MODS.elliptic.Elliptic(self._mv)
|
|
394
396
|
|
|
395
397
|
@Property_RO
|
|
396
398
|
def _Ev_cK(self):
|
|
@@ -416,7 +418,7 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
416
418
|
'''
|
|
417
419
|
return self._Ev_cKE * 1.25 # _1_25
|
|
418
420
|
|
|
419
|
-
@
|
|
421
|
+
@property_RO
|
|
420
422
|
def extendp(self):
|
|
421
423
|
'''Get the domain (C{bool}), I{extended} or I{standard}.
|
|
422
424
|
'''
|
|
@@ -635,7 +637,7 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
635
637
|
'''Set the central parallel and meridian.
|
|
636
638
|
|
|
637
639
|
@arg lat0: Latitude of the central parallel (C{degrees90}).
|
|
638
|
-
@arg lon0: Longitude of the central
|
|
640
|
+
@arg lon0: Longitude of the central meridian (C{degrees180}).
|
|
639
641
|
|
|
640
642
|
@return: 2-Tuple C{(lat0, lon0)} of the previous central
|
|
641
643
|
parallel and meridian.
|
|
@@ -644,7 +646,7 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
644
646
|
'''
|
|
645
647
|
t = self._lat0, self.lon0
|
|
646
648
|
self._lat0 = _fix90(Degrees(lat0=lat0, Error=ETMError))
|
|
647
|
-
self. lon0 = lon0
|
|
649
|
+
self. lon0 = lon0 # lon0.setter
|
|
648
650
|
return t
|
|
649
651
|
|
|
650
652
|
def _resets(self, datum):
|
|
@@ -655,15 +657,15 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
655
657
|
@raise ETMError: Near-spherical B{C{datum}} or C{ellipsoid}.
|
|
656
658
|
'''
|
|
657
659
|
E = datum.ellipsoid
|
|
658
|
-
mu = E.e2 # .eccentricity1st2
|
|
660
|
+
mu = E.e2 # E.eccentricity1st2
|
|
659
661
|
mv = E.e21 # _1_0 - mu
|
|
660
662
|
if isnear0(E.e) or isnear0(mu, eps0=EPS02) \
|
|
661
663
|
or isnear0(mv, eps0=EPS02): # or sqrt(mu) != E.e
|
|
662
664
|
raise ETMError(ellipsoid=E, txt=_near_(_spherical_))
|
|
663
665
|
|
|
664
666
|
if self._datum or self._E:
|
|
665
|
-
_i = ExactTransverseMercator.iteration._uname
|
|
666
|
-
_update_all(self, _i, '_sigmaC', '_zetaC') # _under
|
|
667
|
+
_i = ExactTransverseMercator.iteration._uname # property_RO
|
|
668
|
+
_update_all(self, _i, '_sigmaC', '_zetaC', Base=Property_RO) # _under
|
|
667
669
|
|
|
668
670
|
self._E = E
|
|
669
671
|
self._mu = mu
|
|
@@ -757,7 +759,7 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
757
759
|
# k = sqrt(mv + mu / sec2) * sqrt(sec2) * sqrt(q2)
|
|
758
760
|
# = sqrt(mv * sec2 + mu) * sqrt(q2)
|
|
759
761
|
# = sqrt(mv + mv * tau**2 + mu) * sqrt(q2)
|
|
760
|
-
k, q2 = _0_0, (
|
|
762
|
+
k, q2 = _0_0, (snv**2 * mv + cnudnv**2)
|
|
761
763
|
if q2 > 0:
|
|
762
764
|
k2 = (tau**2 + _1_0) * mv + mu
|
|
763
765
|
if k2 > 0:
|
|
@@ -809,9 +811,9 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
809
811
|
d = (cnv**2 + snuv**2 * mu)**2 * self._mv
|
|
810
812
|
r = cnv * dnu * dnv
|
|
811
813
|
i = cnu * snuv * mu
|
|
812
|
-
du = (r
|
|
813
|
-
dv =
|
|
814
|
-
return du, dv
|
|
814
|
+
du = (r + i) * (r - i) / d # (r**2 - i**2) / d
|
|
815
|
+
dv = r * i * _2_0 / d
|
|
816
|
+
return du, neg(dv)
|
|
815
817
|
|
|
816
818
|
def _sigmaInv2(self, xi, eta):
|
|
817
819
|
'''(INTERNAL) Invert C{sigma} using Newton's method.
|
|
@@ -874,7 +876,8 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
874
876
|
'''
|
|
875
877
|
# snu, cnu, dnu = self._Eu.sncndn(u)
|
|
876
878
|
# snv, cnv, dnv = self._Ev.sncndn(v)
|
|
877
|
-
return self._Eu.sncndn(u, **jam) +
|
|
879
|
+
return self._Eu.sncndn(u, **jam) + \
|
|
880
|
+
self._Ev.sncndn(v, **jam)
|
|
878
881
|
|
|
879
882
|
def toStr(self, joined=_COMMASPACE_, **kwds): # PYCHOK signature
|
|
880
883
|
'''Return a C{str} representation.
|
|
@@ -900,21 +903,19 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
900
903
|
real &taup, real &lam)}
|
|
901
904
|
'''
|
|
902
905
|
e, cnu2, mv = self._e, cnu**2, self._mv
|
|
903
|
-
# Overflow value like atan(overflow) = pi/2
|
|
904
|
-
t1 = t2 = _overflow(snu)
|
|
905
906
|
# Lee 54.17 but write
|
|
906
907
|
# atanh(snu * dnv) = asinh(snu * dnv / sqrt(cnu^2 + _mv * snu^2 * snv^2))
|
|
907
908
|
# atanh(_e * snu / dnv) = asinh(_e * snu / sqrt(_mu * cnu^2 + _mv * cnv^2))
|
|
908
|
-
d1 = cnu2 +
|
|
909
|
+
d1 = cnu2 + (snu * snv)**2 * mv
|
|
909
910
|
if d1 > EPS02: # _EPSmin
|
|
910
911
|
t1 = snu * dnv / sqrt(d1)
|
|
911
|
-
else:
|
|
912
|
-
d1 = 0
|
|
913
|
-
d2 = self._mu
|
|
912
|
+
else: # like atan(overflow) = pi/2
|
|
913
|
+
t1, d1 = _overflow(snu), 0
|
|
914
|
+
d2 = cnu2 * self._mu + cnv**2 * mv
|
|
914
915
|
if d2 > EPS02: # _EPSmin
|
|
915
916
|
t2 = sinh(e * asinh(e * snu / sqrt(d2)))
|
|
916
917
|
else:
|
|
917
|
-
d2 = 0
|
|
918
|
+
t2, d2 = _overflow(snu), 0
|
|
918
919
|
# psi = asinh(t1) - asinh(t2)
|
|
919
920
|
# taup = sinh(psi)
|
|
920
921
|
taup = t1 * hypot1(t2) - t2 * hypot1(t1)
|
|
@@ -939,9 +940,9 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
939
940
|
snuv2 = snuv**2 * self._mu
|
|
940
941
|
# Lee 54.21 but write (see A+S 16.21.4)
|
|
941
942
|
# (1 - dnu^2 * snv^2) = (cnv^2 + _mu * snu^2 * snv^2)
|
|
942
|
-
d =
|
|
943
|
-
du =
|
|
944
|
-
dv =
|
|
943
|
+
d = (cnv2 + snuv2)**2 * self._mv # max(d, EPS02)?
|
|
944
|
+
du = (cnv2 - snuv2) * cnu * dnuv / d
|
|
945
|
+
dv = (cnu2 + dnuv2) * cnv * snuv / d
|
|
945
946
|
return du, neg(dv)
|
|
946
947
|
|
|
947
948
|
def _zetaInv2(self, taup, lam):
|
|
@@ -1021,6 +1022,9 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
1021
1022
|
g_k += atan1d(tau), degrees(lam)
|
|
1022
1023
|
return g_k # or (g, k, lat, lon)
|
|
1023
1024
|
|
|
1025
|
+
_allPropertiesOf_n(22, ExactTransverseMercator, Property_RO) # PYCHOK assert
|
|
1026
|
+
del _0_1, _allPropertiesOf_n, EPS, _1_EPS, _EWGS84
|
|
1027
|
+
|
|
1024
1028
|
|
|
1025
1029
|
def _overflow(x):
|
|
1026
1030
|
'''(INTERNAL) Like C{copysign0(OVERFLOW, B{x})}.
|
|
@@ -1102,32 +1106,42 @@ if __name__ == '__main__': # MCCABE 16
|
|
|
1102
1106
|
def _main():
|
|
1103
1107
|
|
|
1104
1108
|
from pygeodesy import fstr, KTransverseMercator
|
|
1105
|
-
|
|
1106
|
-
from pygeodesy.internals import printf, _usage
|
|
1109
|
+
from pygeodesy.interns import _BAR_, _COLONSPACE_, _DASH_, NN
|
|
1110
|
+
from pygeodesy.internals import printf, _usage
|
|
1107
1111
|
from sys import argv, exit as _exit
|
|
1108
1112
|
|
|
1109
|
-
def
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1113
|
+
def _error(why, _a=NN):
|
|
1114
|
+
if _a:
|
|
1115
|
+
why = 'option %r %s' % (_a, why)
|
|
1116
|
+
_exit(_COLONSPACE_(_usage(*argv), why))
|
|
1117
|
+
|
|
1118
|
+
def _help(*why):
|
|
1119
|
+
if why:
|
|
1120
|
+
printf(_COLONSPACE_(_usage(*argv), *why))
|
|
1121
|
+
_exit(_usage(argv[0], '[-s[eries]', _BAR_, '-t]',
|
|
1122
|
+
'[-p[recision] <ndigits>]',
|
|
1123
|
+
'[-f[orward] <lat> <lon>', _BAR_,
|
|
1124
|
+
'-r[everse] <easting> <northing>', _BAR_,
|
|
1125
|
+
'<lat> <lon>]', _BAR_,
|
|
1126
|
+
'-h[elp]'))
|
|
1127
|
+
|
|
1128
|
+
def _result(t4):
|
|
1129
|
+
printf(_COLONSPACE_(tm.classname, fstr(t4, prec=_p, sep=_SPACE_)))
|
|
1116
1130
|
|
|
1117
1131
|
# mimick some of I{Karney}'s utility C{TransverseMercatorProj}
|
|
1118
1132
|
_f = _r = _s = _t = False
|
|
1119
1133
|
_p = -6
|
|
1120
|
-
|
|
1121
|
-
while
|
|
1122
|
-
_a =
|
|
1134
|
+
args = argv[1:]
|
|
1135
|
+
while args and args[0].startswith(_DASH_):
|
|
1136
|
+
_a = args.pop(0)
|
|
1123
1137
|
if len(_a) < 2:
|
|
1124
|
-
|
|
1138
|
+
_error('invalid', _a)
|
|
1125
1139
|
elif '-forward'.startswith(_a):
|
|
1126
1140
|
_f, _r = True, False
|
|
1127
1141
|
elif '-reverse'.startswith(_a):
|
|
1128
1142
|
_f, _r = False, True
|
|
1129
|
-
elif '-precision'.startswith(_a):
|
|
1130
|
-
_p = int(
|
|
1143
|
+
elif '-precision'.startswith(_a) and args:
|
|
1144
|
+
_p = int(args.pop(0))
|
|
1131
1145
|
elif '-series'.startswith(_a):
|
|
1132
1146
|
_s, _t = True, False
|
|
1133
1147
|
elif _a == '-t':
|
|
@@ -1135,39 +1149,49 @@ if __name__ == '__main__': # MCCABE 16
|
|
|
1135
1149
|
elif '-help'.startswith(_a):
|
|
1136
1150
|
_help()
|
|
1137
1151
|
else:
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
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)
|
|
1152
|
+
_error('not supported', _a)
|
|
1153
|
+
if len(args) < 2:
|
|
1154
|
+
_help('incomplete')
|
|
1150
1155
|
|
|
1156
|
+
f2 = map1(float, *args[:2])
|
|
1157
|
+
tm = KTransverseMercator() if _s else \
|
|
1158
|
+
ExactTransverseMercator(extendp=_t)
|
|
1151
1159
|
if _f:
|
|
1152
1160
|
t = tm.forward(*f2)
|
|
1153
1161
|
elif _r:
|
|
1154
1162
|
t = tm.reverse(*f2)
|
|
1155
1163
|
else:
|
|
1156
1164
|
t = tm.forward(*f2)
|
|
1157
|
-
|
|
1165
|
+
_result(t)
|
|
1158
1166
|
t = tm.reverse(t.easting, t.northing)
|
|
1159
|
-
|
|
1167
|
+
_result(t)
|
|
1160
1168
|
|
|
1161
1169
|
_main()
|
|
1162
1170
|
|
|
1163
|
-
# % python3.
|
|
1171
|
+
# % python3.13 -m pygeodesy.etm -p 12 33.33 44.44
|
|
1172
|
+
# ExactTransverseMercator: 4276926.114803905599 4727193.767015309073 28.375536563148 1.233325101778
|
|
1173
|
+
# ExactTransverseMercator: 33.33 44.44 28.375536563148 1.233325101778
|
|
1174
|
+
|
|
1175
|
+
# % python3.13 -m pygeodesy.etm -s -p 12 33.33 44.44
|
|
1176
|
+
# KTransverseMercator: 4276926.114803904667 4727193.767015310004 28.375536563148 1.233325101778
|
|
1177
|
+
# KTransverseMercator: 33.33 44.44 28.375536563148 1.233325101778
|
|
1178
|
+
|
|
1179
|
+
# % python3.12 -m pygeodesy.etm -p 12 33.33 44.44
|
|
1164
1180
|
# ExactTransverseMercator: 4276926.11480390653 4727193.767015309073 28.375536563148 1.233325101778
|
|
1165
1181
|
# ExactTransverseMercator: 33.33 44.44 28.375536563148 1.233325101778
|
|
1166
1182
|
|
|
1167
|
-
# % python3.12 -
|
|
1183
|
+
# % python3.12 -m pygeodesy.etm -s -p 12 33.33 44.44
|
|
1184
|
+
# KTransverseMercator: 4276926.114803904667 4727193.767015310004 28.375536563148 1.233325101778
|
|
1185
|
+
# KTransverseMercator: 33.33 44.44 28.375536563148 1.233325101778
|
|
1186
|
+
|
|
1187
|
+
# % python2 -m pygeodesy.etm -p 12 33.33 44.44
|
|
1168
1188
|
# ExactTransverseMercator: 4276926.11480390653 4727193.767015309073 28.375536563148 1.233325101778
|
|
1169
1189
|
# ExactTransverseMercator: 33.33 44.44 28.375536563148 1.233325101778
|
|
1170
1190
|
|
|
1191
|
+
# % python2 -m pygeodesy.etm -s -p 12 33.33 44.44
|
|
1192
|
+
# KTransverseMercator: 4276926.114803904667 4727193.767015310004 28.375536563148 1.233325101778
|
|
1193
|
+
# KTransverseMercator: 33.33 44.44 28.375536563148 1.233325101778
|
|
1194
|
+
|
|
1171
1195
|
# % echo 33.33 44.44 | .../bin/TransverseMercatorProj
|
|
1172
1196
|
# 4276926.114804 4727193.767015 28.375536563148 1.233325101778
|
|
1173
1197
|
|
pygeodesy/fmath.py
CHANGED
|
@@ -12,11 +12,10 @@ from pygeodesy.constants import EPS0, EPS02, EPS1, NAN, PI, PI_2, PI_4, \
|
|
|
12
12
|
_0_0, _0_125, _1_6th, _0_25, _1_3rd, _0_5, _1_0, \
|
|
13
13
|
_1_5, _copysign_0_0, isfinite, remainder
|
|
14
14
|
from pygeodesy.errors import _IsnotError, LenError, _TypeError, _ValueError, \
|
|
15
|
-
_xError, _xkwds_pop2, _xsError
|
|
16
|
-
from pygeodesy.fsums import _2float, Fsum, fsum, _isFsum_2Tuple,
|
|
17
|
-
Fmt, unstr
|
|
15
|
+
_xError, _xkwds, _xkwds_pop2, _xsError
|
|
16
|
+
from pygeodesy.fsums import _2float, Fsum, fsum, _isFsum_2Tuple, Fmt, unstr
|
|
18
17
|
from pygeodesy.interns import MISSING, _negative_, _not_scalar_
|
|
19
|
-
from pygeodesy.lazily import _ALL_LAZY,
|
|
18
|
+
from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS
|
|
20
19
|
# from pygeodesy.streprs import Fmt, unstr # from .fsums
|
|
21
20
|
from pygeodesy.units import Int_, _isHeight, _isRadius, Float_ # PYCHOK for .heights
|
|
22
21
|
|
|
@@ -24,7 +23,7 @@ from math import fabs, sqrt # pow
|
|
|
24
23
|
import operator as _operator # in .datums, .trf, .utm
|
|
25
24
|
|
|
26
25
|
__all__ = _ALL_LAZY.fmath
|
|
27
|
-
__version__ = '24.
|
|
26
|
+
__version__ = '24.11.08'
|
|
28
27
|
|
|
29
28
|
# sqrt(2) - 1 <https://WikiPedia.org/wiki/Square_root_of_2>
|
|
30
29
|
_0_4142 = 0.41421356237309504880 # ... ~ 3730904090310553 / 9007199254740992
|
|
@@ -62,14 +61,7 @@ class Fdot(Fsum):
|
|
|
62
61
|
n = len(b)
|
|
63
62
|
if len(a) != n: # PYCHOK no cover
|
|
64
63
|
raise LenError(Fdot, a=len(a), b=n)
|
|
65
|
-
self.
|
|
66
|
-
|
|
67
|
-
def _faddot(self, n, xs, ys, **kwds):
|
|
68
|
-
if n > 0:
|
|
69
|
-
_f = Fsum(**kwds)
|
|
70
|
-
r = (_f(x).fmul(y) for x, y in zip(xs, ys)) # PYCHOK attr?
|
|
71
|
-
self.fadd(_1primed(r) if n < 4 else r) # PYCHOK attr?
|
|
72
|
-
return self
|
|
64
|
+
self._facc_dot(n, a, b, **kwds)
|
|
73
65
|
|
|
74
66
|
|
|
75
67
|
class Fhorner(Fsum):
|
|
@@ -129,7 +121,7 @@ class Fhypot(Fsum):
|
|
|
129
121
|
raise self._ErrorXs(X, xs, root=r)
|
|
130
122
|
|
|
131
123
|
|
|
132
|
-
class Fpolynomial(
|
|
124
|
+
class Fpolynomial(Fsum):
|
|
133
125
|
'''Precision polynomial evaluation.
|
|
134
126
|
'''
|
|
135
127
|
def __init__(self, x, *cs, **name_f2product_nonfinites_RESIDUAL):
|
|
@@ -150,12 +142,10 @@ class Fpolynomial(Fdot):
|
|
|
150
142
|
|
|
151
143
|
@see: Class L{Fhorner}, function L{fpolynomial} and method L{Fsum.fadd}.
|
|
152
144
|
'''
|
|
153
|
-
Fsum.__init__(self,
|
|
145
|
+
Fsum.__init__(self, **name_f2product_nonfinites_RESIDUAL)
|
|
154
146
|
n = len(cs) - 1
|
|
155
|
-
if n
|
|
156
|
-
|
|
157
|
-
elif n < 0:
|
|
158
|
-
self(_0_0)
|
|
147
|
+
self(_0_0 if n < 0 else cs[0])
|
|
148
|
+
self._facc_dot(n, cs[1:], _powers(x, n), **name_f2product_nonfinites_RESIDUAL)
|
|
159
149
|
|
|
160
150
|
|
|
161
151
|
class Fpowers(Fsum):
|
|
@@ -431,35 +421,48 @@ def favg(a, b, f=_0_5, nonfinites=True):
|
|
|
431
421
|
return float(F)
|
|
432
422
|
|
|
433
423
|
|
|
434
|
-
def fdot(
|
|
435
|
-
'''Return the precision dot product M{sum(
|
|
424
|
+
def fdot(xs, *ys, **start_f2product_nonfinites):
|
|
425
|
+
'''Return the precision dot product M{sum(xs[i] * ys[i] for i in range(len(xs)))}.
|
|
436
426
|
|
|
437
|
-
@arg
|
|
438
|
-
@arg
|
|
427
|
+
@arg xs: Iterable of values (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
|
|
428
|
+
@arg ys: Other values (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}), all
|
|
439
429
|
positional.
|
|
440
|
-
@kwarg
|
|
441
|
-
|
|
430
|
+
@kwarg start_f2product_nonfinites: Optional bias C{B{start}=0} (C{scalar}, an
|
|
431
|
+
L{Fsum} or L{Fsum2Tuple}) and settings C{B{f2product}=None} (C{bool})
|
|
432
|
+
and C{B{nonfinites=True}} (C{bool}), see class L{Fsum<Fsum.__init__>}.
|
|
442
433
|
|
|
443
434
|
@return: Dot product (C{float}).
|
|
444
435
|
|
|
445
|
-
@raise LenError: Unequal C{len(B{
|
|
436
|
+
@raise LenError: Unequal C{len(B{xs})} and C{len(B{ys})}.
|
|
446
437
|
|
|
447
438
|
@see: Class L{Fdot}, U{Algorithm 5.10 B{DotK}
|
|
448
439
|
<https://www.TUHH.De/ti3/paper/rump/OgRuOi05.pdf>} and function
|
|
449
440
|
C{math.sumprod} in Python 3.12 and later.
|
|
450
441
|
'''
|
|
451
|
-
D = Fdot(
|
|
442
|
+
D = Fdot(xs, *ys, **_xkwds(start_f2product_nonfinites, nonfinites=True))
|
|
452
443
|
return float(D)
|
|
453
444
|
|
|
454
445
|
|
|
455
|
-
def
|
|
456
|
-
'''Return the precision dot product M{
|
|
457
|
-
|
|
446
|
+
def fdot_(*xys, **start_f2product_nonfinites):
|
|
447
|
+
'''Return the (precision) dot product M{sum(xys[i] * xys[i+1] for i in range(0, len(xys), B{2}))}.
|
|
448
|
+
|
|
449
|
+
@arg xys: Pairwise values (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}), all positional.
|
|
450
|
+
|
|
451
|
+
@see: Function L{fdot} for further details.
|
|
452
|
+
|
|
453
|
+
@return: Dot product (C{float}).
|
|
454
|
+
'''
|
|
455
|
+
return fdot(xys[0::2], *xys[1::2], **start_f2product_nonfinites)
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
def fdot3(xs, ys, zs, **start_f2product_nonfinites):
|
|
459
|
+
'''Return the (precision) dot product M{start + sum(xs[i] * ys[i] * zs[i] for i in range(len(xs)))}.
|
|
458
460
|
|
|
459
461
|
@arg xs: Iterable (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
|
|
460
462
|
@arg ys: Iterable (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
|
|
461
463
|
@arg zs: Iterable (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
|
|
462
|
-
|
|
464
|
+
|
|
465
|
+
@see: Function L{fdot} for further details.
|
|
463
466
|
|
|
464
467
|
@return: Dot product (C{float}).
|
|
465
468
|
|
|
@@ -469,17 +472,16 @@ def fdot3(xs, ys, zs, start=0):
|
|
|
469
472
|
if not n == len(ys) == len(zs):
|
|
470
473
|
raise LenError(fdot3, xs=n, ys=len(ys), zs=len(zs))
|
|
471
474
|
|
|
472
|
-
D = Fdot((), nonfinites=True
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
D = D.
|
|
475
|
+
D = Fdot((), **_xkwds(start_f2product_nonfinites, nonfinites=True))
|
|
476
|
+
kwds = dict(f2product=D.f2product(), nonfinites=D.nonfinites())
|
|
477
|
+
_f = Fsum(**kwds)
|
|
478
|
+
D = D._facc(_f(x).f2mul_(y, z, **kwds) for x, y, z in zip(xs, ys, zs))
|
|
476
479
|
return float(D)
|
|
477
480
|
|
|
478
481
|
|
|
479
482
|
def fhorner(x, *cs, **incx):
|
|
480
|
-
'''Horner form evaluation of polynomial M{sum(cs[i] * x**i for
|
|
481
|
-
|
|
482
|
-
where C{n = len(cs) - 1}.
|
|
483
|
+
'''Horner form evaluation of polynomial M{sum(cs[i] * x**i for i=0..n)} as
|
|
484
|
+
in- or decreasing exponent M{sum(... i=n..0)}, where C{n = len(cs) - 1}.
|
|
483
485
|
|
|
484
486
|
@return: Horner sum (C{float}).
|
|
485
487
|
|
|
@@ -804,7 +806,7 @@ def fremainder(x, y):
|
|
|
804
806
|
return r
|
|
805
807
|
|
|
806
808
|
|
|
807
|
-
if
|
|
809
|
+
if _MODS.sys_version_info2 < (3, 8): # PYCHOK no cover
|
|
808
810
|
from math import hypot # OK in Python 3.7-
|
|
809
811
|
|
|
810
812
|
def hypot_(*xs):
|
|
@@ -831,7 +833,7 @@ if _sys_version_info2 < (3, 8): # PYCHOK no cover
|
|
|
831
833
|
'''
|
|
832
834
|
return float(_Hypot(*xs))
|
|
833
835
|
|
|
834
|
-
elif
|
|
836
|
+
elif _MODS.sys_version_info2 < (3, 10):
|
|
835
837
|
# In Python 3.8 and 3.9 C{math.hypot} is inaccurate, see
|
|
836
838
|
# U{agdhruv<https://GitHub.com/geopy/geopy/issues/466>},
|
|
837
839
|
# U{cffk<https://Bugs.Python.org/issue43088>} and module
|
pygeodesy/formy.py
CHANGED
|
@@ -20,11 +20,11 @@ from pygeodesy.errors import IntersectionError, LimitError, limiterrors, \
|
|
|
20
20
|
_xcallable,_xkwds, _xkwds_pop2
|
|
21
21
|
from pygeodesy.fmath import euclid, hypot, hypot2, sqrt0
|
|
22
22
|
from pygeodesy.fsums import fsumf_, Fmt, unstr
|
|
23
|
-
# from pygeodesy.internals import
|
|
23
|
+
# from pygeodesy.internals import _DUNDER_nameof # from .named
|
|
24
24
|
from pygeodesy.interns import _delta_, _distant_, _inside_, _SPACE_, _too_
|
|
25
25
|
from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS
|
|
26
26
|
from pygeodesy.named import _name__, _name2__, _NamedTuple, _xnamed, \
|
|
27
|
-
|
|
27
|
+
_DUNDER_nameof
|
|
28
28
|
from pygeodesy.namedTuples import Bearing2Tuple, Distance4Tuple, LatLon2Tuple, \
|
|
29
29
|
Intersection3Tuple, PhiLam2Tuple, Vector3Tuple
|
|
30
30
|
# from pygeodesy.streprs import Fmt, unstr # from .fsums
|
|
@@ -43,7 +43,7 @@ from contextlib import contextmanager
|
|
|
43
43
|
from math import asin, atan, atan2, cos, degrees, fabs, radians, sin, sqrt # pow
|
|
44
44
|
|
|
45
45
|
__all__ = _ALL_LAZY.formy
|
|
46
|
-
__version__ = '24.
|
|
46
|
+
__version__ = '24.10.14'
|
|
47
47
|
|
|
48
48
|
_RADIANS2 = (PI / _180_0)**2 # degrees- to radians-squared
|
|
49
49
|
_ratio_ = 'ratio'
|
|
@@ -1136,7 +1136,7 @@ class _idllmn6(object): # see also .geodesicw._wargs, .latlonBase._toCartesian3
|
|
|
1136
1136
|
_, lat2, lon2 = _Wrap.latlon3(lon1, lat2, lon2, wrap)
|
|
1137
1137
|
kwds = _xkwds(kwds, wrap=wrap) # for _xError
|
|
1138
1138
|
m = small if small is _100km else Meter_(small=small)
|
|
1139
|
-
n =
|
|
1139
|
+
n = _DUNDER_nameof(intersections2 if s else intersection2)
|
|
1140
1140
|
if datum is None or euclidean(lat1, lon1, lat2, lon2) < m:
|
|
1141
1141
|
d, m = None, _MODS.vector3d
|
|
1142
1142
|
_i = m._intersects2 if s else m._intersect3d3
|
|
@@ -1156,7 +1156,7 @@ class _idllmn6(object): # see also .geodesicw._wargs, .latlonBase._toCartesian3
|
|
|
1156
1156
|
m = _MODS.ellipsoidalKarney
|
|
1157
1157
|
except ImportError:
|
|
1158
1158
|
m = _MODS.ellipsoidalExact
|
|
1159
|
-
_i = m._intersections2 if s else m._intersection3 #
|
|
1159
|
+
_i = m._intersections2 if s else m._intersection3 # ellipsoidalBaseDI
|
|
1160
1160
|
else:
|
|
1161
1161
|
raise _TypeError(datum=datum)
|
|
1162
1162
|
yield _i, d, lat2, lon2, m, n
|
|
@@ -1231,7 +1231,8 @@ def intersection2(lat1, lon1, bearing1,
|
|
|
1231
1231
|
|
|
1232
1232
|
else:
|
|
1233
1233
|
t = _i(m.LatLon(lat1, lon1, datum=d), b1,
|
|
1234
|
-
m.LatLon(lat2, lon2, datum=d), b2,
|
|
1234
|
+
m.LatLon(lat2, lon2, datum=d), b2,
|
|
1235
|
+
LatLon=None, height=0, wrap=False)
|
|
1235
1236
|
if isinstance(t, Intersection3Tuple): # ellipsoidal
|
|
1236
1237
|
t, _, _ = t
|
|
1237
1238
|
t = LatLon2Tuple(t.lat, t.lon, name=n)
|