pygeodesy 24.10.24__py2.py3-none-any.whl → 24.12.12__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.24.dist-info → PyGeodesy-24.12.12.dist-info}/METADATA +6 -6
- PyGeodesy-24.12.12.dist-info/RECORD +118 -0
- {PyGeodesy-24.10.24.dist-info → PyGeodesy-24.12.12.dist-info}/WHEEL +1 -1
- pygeodesy/__init__.py +5 -5
- pygeodesy/__main__.py +1 -1
- pygeodesy/albers.py +5 -5
- pygeodesy/auxilats/_CX_4.py +1 -1
- pygeodesy/auxilats/_CX_6.py +1 -1
- pygeodesy/auxilats/_CX_8.py +1 -1
- pygeodesy/auxilats/_CX_Rs.py +1 -1
- pygeodesy/auxilats/__init__.py +1 -1
- pygeodesy/auxilats/__main__.py +1 -1
- pygeodesy/auxilats/auxAngle.py +5 -5
- pygeodesy/auxilats/auxDLat.py +6 -6
- pygeodesy/auxilats/auxDST.py +2 -2
- pygeodesy/auxilats/auxLat.py +5 -5
- pygeodesy/auxilats/auxily.py +2 -2
- pygeodesy/azimuthal.py +55 -65
- pygeodesy/basics.py +35 -34
- pygeodesy/booleans.py +37 -37
- pygeodesy/cartesianBase.py +26 -65
- pygeodesy/clipy.py +1 -1
- pygeodesy/constants.py +7 -7
- pygeodesy/css.py +8 -9
- pygeodesy/datums.py +1 -1
- pygeodesy/deprecated/__init__.py +2 -2
- pygeodesy/deprecated/bases.py +1 -1
- pygeodesy/deprecated/classes.py +10 -10
- pygeodesy/deprecated/consterns.py +1 -1
- pygeodesy/deprecated/datum.py +1 -1
- pygeodesy/deprecated/functions.py +23 -13
- pygeodesy/deprecated/nvector.py +1 -1
- pygeodesy/deprecated/rhumbBase.py +1 -1
- pygeodesy/deprecated/rhumbaux.py +1 -1
- pygeodesy/deprecated/rhumbsolve.py +1 -1
- pygeodesy/deprecated/rhumbx.py +1 -1
- pygeodesy/dms.py +1 -1
- pygeodesy/ecef.py +63 -69
- pygeodesy/elevations.py +1 -1
- pygeodesy/ellipsoidalBase.py +106 -121
- pygeodesy/ellipsoidalBaseDI.py +115 -119
- pygeodesy/ellipsoidalExact.py +36 -38
- pygeodesy/ellipsoidalGeodSolve.py +1 -1
- pygeodesy/ellipsoidalKarney.py +1 -1
- pygeodesy/ellipsoidalNvector.py +1 -1
- pygeodesy/ellipsoidalVincenty.py +6 -5
- pygeodesy/ellipsoids.py +7 -8
- pygeodesy/elliptic.py +6 -6
- pygeodesy/epsg.py +1 -1
- pygeodesy/errors.py +25 -25
- pygeodesy/etm.py +84 -76
- pygeodesy/fmath.py +54 -51
- pygeodesy/formy.py +74 -106
- pygeodesy/frechet.py +1 -1
- pygeodesy/fstats.py +1 -1
- pygeodesy/fsums.py +82 -72
- pygeodesy/gars.py +1 -1
- pygeodesy/geodesici.py +4 -4
- pygeodesy/geodesicw.py +16 -15
- pygeodesy/geodesicx/_C4_24.py +2 -2
- pygeodesy/geodesicx/_C4_27.py +2 -2
- pygeodesy/geodesicx/_C4_30.py +2 -2
- pygeodesy/geodesicx/__init__.py +3 -3
- pygeodesy/geodesicx/__main__.py +1 -1
- pygeodesy/geodesicx/gx.py +6 -5
- pygeodesy/geodesicx/gxarea.py +2 -2
- pygeodesy/geodesicx/gxbases.py +2 -2
- pygeodesy/geodesicx/gxline.py +16 -12
- pygeodesy/geodsolve.py +8 -17
- pygeodesy/geohash.py +1 -1
- pygeodesy/geoids.py +6 -6
- pygeodesy/hausdorff.py +1 -1
- pygeodesy/heights.py +3 -3
- pygeodesy/internals.py +64 -80
- pygeodesy/interns.py +2 -3
- pygeodesy/iters.py +1 -1
- pygeodesy/karney.py +4 -4
- pygeodesy/ktm.py +20 -21
- pygeodesy/latlonBase.py +296 -346
- pygeodesy/lazily.py +15 -15
- pygeodesy/lcc.py +5 -5
- pygeodesy/ltp.py +55 -59
- pygeodesy/ltpTuples.py +208 -192
- pygeodesy/mgrs.py +9 -10
- pygeodesy/named.py +153 -3
- pygeodesy/namedTuples.py +58 -7
- pygeodesy/nvectorBase.py +122 -105
- pygeodesy/osgr.py +10 -13
- pygeodesy/points.py +1 -1
- pygeodesy/props.py +3 -3
- pygeodesy/resections.py +26 -26
- pygeodesy/rhumb/__init__.py +2 -2
- pygeodesy/rhumb/aux_.py +2 -2
- pygeodesy/rhumb/bases.py +2 -2
- pygeodesy/rhumb/ekx.py +4 -4
- pygeodesy/rhumb/solve.py +4 -4
- pygeodesy/simplify.py +291 -403
- pygeodesy/solveBase.py +1 -1
- pygeodesy/sphericalBase.py +1 -1
- pygeodesy/sphericalNvector.py +84 -127
- pygeodesy/sphericalTrigonometry.py +66 -71
- pygeodesy/streprs.py +10 -5
- pygeodesy/trf.py +1 -1
- pygeodesy/triaxials.py +23 -16
- pygeodesy/units.py +17 -17
- pygeodesy/unitsBase.py +1 -1
- pygeodesy/ups.py +4 -4
- pygeodesy/utily.py +202 -145
- pygeodesy/utm.py +10 -10
- pygeodesy/utmups.py +1 -1
- pygeodesy/utmupsBase.py +1 -1
- pygeodesy/vector2d.py +17 -17
- pygeodesy/vector3d.py +32 -23
- pygeodesy/vector3dBase.py +22 -19
- pygeodesy/webmercator.py +5 -5
- pygeodesy/wgrs.py +5 -5
- PyGeodesy-24.10.24.dist-info/RECORD +0 -118
- {PyGeodesy-24.10.24.dist-info → PyGeodesy-24.12.12.dist-info}/top_level.txt +0 -0
pygeodesy/etm.py
CHANGED
|
@@ -11,13 +11,13 @@ 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>}
|
|
18
18
|
file C{Header}.
|
|
19
19
|
|
|
20
|
-
Copyright (C) U{Charles Karney<mailto:Karney@Alum.MIT.edu>} (2008-
|
|
20
|
+
Copyright (C) U{Charles Karney<mailto:Karney@Alum.MIT.edu>} (2008-2024) and licensed
|
|
21
21
|
under the MIT/X11 License. For more information, see the U{GeographicLib<https://
|
|
22
22
|
GeographicLib.SourceForge.io>} documentation.
|
|
23
23
|
|
|
@@ -65,38 +65,40 @@ 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
|
-
from pygeodesy.utily import atan1d, atan2d, _loneg, sincos2
|
|
89
|
+
from pygeodesy.utily import atan1d, atan2, atan2d, _loneg, sincos2
|
|
88
90
|
from pygeodesy.utm import _cmlon, _LLEB, _parseUTM5, _toBand, _toXtm8, \
|
|
89
91
|
_to7zBlldfn, Utm, UTMError
|
|
90
92
|
|
|
91
|
-
from math import asinh,
|
|
93
|
+
from math import asinh, degrees, radians, sinh, sqrt
|
|
92
94
|
|
|
93
95
|
__all__ = _ALL_LAZY.etm
|
|
94
|
-
__version__ = '24.
|
|
96
|
+
__version__ = '24.11.24'
|
|
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,52 +1149,46 @@ 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.13 -m pygeodesy.etm -p 12
|
|
1171
|
+
# % python3.13 -m pygeodesy.etm -p 12 33.33 44.44
|
|
1164
1172
|
# ExactTransverseMercator: 4276926.114803905599 4727193.767015309073 28.375536563148 1.233325101778
|
|
1165
1173
|
# ExactTransverseMercator: 33.33 44.44 28.375536563148 1.233325101778
|
|
1166
1174
|
|
|
1167
|
-
# % python3.13 -m pygeodesy.etm -s
|
|
1175
|
+
# % python3.13 -m pygeodesy.etm -s -p 12 33.33 44.44
|
|
1168
1176
|
# KTransverseMercator: 4276926.114803904667 4727193.767015310004 28.375536563148 1.233325101778
|
|
1169
1177
|
# KTransverseMercator: 33.33 44.44 28.375536563148 1.233325101778
|
|
1170
1178
|
|
|
1171
|
-
# % python3.12 -m pygeodesy.etm -p 12
|
|
1179
|
+
# % python3.12 -m pygeodesy.etm -p 12 33.33 44.44
|
|
1172
1180
|
# ExactTransverseMercator: 4276926.11480390653 4727193.767015309073 28.375536563148 1.233325101778
|
|
1173
1181
|
# ExactTransverseMercator: 33.33 44.44 28.375536563148 1.233325101778
|
|
1174
1182
|
|
|
1175
|
-
# % python3.12 -m pygeodesy.etm -s
|
|
1183
|
+
# % python3.12 -m pygeodesy.etm -s -p 12 33.33 44.44
|
|
1176
1184
|
# KTransverseMercator: 4276926.114803904667 4727193.767015310004 28.375536563148 1.233325101778
|
|
1177
1185
|
# KTransverseMercator: 33.33 44.44 28.375536563148 1.233325101778
|
|
1178
1186
|
|
|
1179
|
-
# % python2 -m pygeodesy.etm -p 12
|
|
1187
|
+
# % python2 -m pygeodesy.etm -p 12 33.33 44.44
|
|
1180
1188
|
# ExactTransverseMercator: 4276926.11480390653 4727193.767015309073 28.375536563148 1.233325101778
|
|
1181
1189
|
# ExactTransverseMercator: 33.33 44.44 28.375536563148 1.233325101778
|
|
1182
1190
|
|
|
1183
|
-
# % python2 -m pygeodesy.etm -s
|
|
1191
|
+
# % python2 -m pygeodesy.etm -s -p 12 33.33 44.44
|
|
1184
1192
|
# KTransverseMercator: 4276926.114803904667 4727193.767015310004 28.375536563148 1.233325101778
|
|
1185
1193
|
# KTransverseMercator: 33.33 44.44 28.375536563148 1.233325101778
|
|
1186
1194
|
|
|
@@ -1189,7 +1197,7 @@ if __name__ == '__main__': # MCCABE 16
|
|
|
1189
1197
|
|
|
1190
1198
|
# **) MIT License
|
|
1191
1199
|
#
|
|
1192
|
-
# Copyright (C) 2016-
|
|
1200
|
+
# Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
|
|
1193
1201
|
#
|
|
1194
1202
|
# Permission is hereby granted, free of charge, to any person obtaining a
|
|
1195
1203
|
# copy of this software and associated documentation files (the "Software"),
|
pygeodesy/fmath.py
CHANGED
|
@@ -12,9 +12,8 @@ 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
18
|
from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS
|
|
20
19
|
# from pygeodesy.streprs import Fmt, unstr # from .fsums
|
|
@@ -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.12.02'
|
|
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):
|
|
@@ -115,21 +107,23 @@ class Fhypot(Fsum):
|
|
|
115
107
|
other settings, see class L{Fsum<Fsum.__init__>} and method
|
|
116
108
|
L{root<Fsum.root>}.
|
|
117
109
|
'''
|
|
110
|
+
def _r_X_kwds(power=None, raiser=True, root=2, **kwds):
|
|
111
|
+
# DEPRECATED keyword argument C{power=2}, use C{root=2}
|
|
112
|
+
return (root if power is None else power), raiser, kwds
|
|
113
|
+
|
|
118
114
|
r = None # _xkwds_pop2 error
|
|
119
115
|
try:
|
|
120
|
-
r, kwds =
|
|
121
|
-
r, kwds = _xkwds_pop2(kwds, power=r) # for backward compatibility
|
|
122
|
-
t, kwds = _xkwds_pop2(kwds, raiser=True)
|
|
116
|
+
r, X, kwds = _r_X_kwds(**root_name_f2product_nonfinites_RESIDUAL_raiser)
|
|
123
117
|
Fsum.__init__(self, **kwds)
|
|
124
118
|
self(_0_0)
|
|
125
119
|
if xs:
|
|
126
|
-
self._facc_power(r, xs, Fhypot, raiser=
|
|
127
|
-
self._fset(self.root(r, raiser=
|
|
120
|
+
self._facc_power(r, xs, Fhypot, raiser=X)
|
|
121
|
+
self._fset(self.root(r, raiser=X))
|
|
128
122
|
except Exception as X:
|
|
129
123
|
raise self._ErrorXs(X, xs, root=r)
|
|
130
124
|
|
|
131
125
|
|
|
132
|
-
class Fpolynomial(
|
|
126
|
+
class Fpolynomial(Fsum):
|
|
133
127
|
'''Precision polynomial evaluation.
|
|
134
128
|
'''
|
|
135
129
|
def __init__(self, x, *cs, **name_f2product_nonfinites_RESIDUAL):
|
|
@@ -150,12 +144,10 @@ class Fpolynomial(Fdot):
|
|
|
150
144
|
|
|
151
145
|
@see: Class L{Fhorner}, function L{fpolynomial} and method L{Fsum.fadd}.
|
|
152
146
|
'''
|
|
153
|
-
Fsum.__init__(self,
|
|
147
|
+
Fsum.__init__(self, **name_f2product_nonfinites_RESIDUAL)
|
|
154
148
|
n = len(cs) - 1
|
|
155
|
-
if n
|
|
156
|
-
|
|
157
|
-
elif n < 0:
|
|
158
|
-
self(_0_0)
|
|
149
|
+
self(_0_0 if n < 0 else cs[0])
|
|
150
|
+
self._facc_dot(n, cs[1:], _powers(x, n), **name_f2product_nonfinites_RESIDUAL)
|
|
159
151
|
|
|
160
152
|
|
|
161
153
|
class Fpowers(Fsum):
|
|
@@ -173,11 +165,11 @@ class Fpowers(Fsum):
|
|
|
173
165
|
L{fpow<Fsum.fpow>}.
|
|
174
166
|
'''
|
|
175
167
|
try:
|
|
176
|
-
|
|
168
|
+
X, kwds = _xkwds_pop2(name_f2product_nonfinites_RESIDUAL_raiser, raiser=True)
|
|
177
169
|
Fsum.__init__(self, **kwds)
|
|
178
170
|
self(_0_0)
|
|
179
171
|
if xs:
|
|
180
|
-
self._facc_power(power, xs, Fpowers, raiser=
|
|
172
|
+
self._facc_power(power, xs, Fpowers, raiser=X) # x**0 == 1
|
|
181
173
|
except Exception as X:
|
|
182
174
|
raise self._ErrorXs(X, xs, power=power)
|
|
183
175
|
|
|
@@ -197,12 +189,12 @@ class Froot(Fsum):
|
|
|
197
189
|
L{fpow<Fsum.fpow>}.
|
|
198
190
|
'''
|
|
199
191
|
try:
|
|
200
|
-
|
|
192
|
+
X, kwds = _xkwds_pop2(name_f2product_nonfinites_RESIDUAL_raiser, raiser=True)
|
|
201
193
|
Fsum.__init__(self, **kwds)
|
|
202
194
|
self(_0_0)
|
|
203
195
|
if xs:
|
|
204
196
|
self.fadd(xs)
|
|
205
|
-
self(self.root(root, raiser=
|
|
197
|
+
self(self.root(root, raiser=X))
|
|
206
198
|
except Exception as X:
|
|
207
199
|
raise self._ErrorXs(X, xs, root=root)
|
|
208
200
|
|
|
@@ -431,35 +423,47 @@ def favg(a, b, f=_0_5, nonfinites=True):
|
|
|
431
423
|
return float(F)
|
|
432
424
|
|
|
433
425
|
|
|
434
|
-
def fdot(
|
|
435
|
-
'''Return the precision dot product M{sum(
|
|
426
|
+
def fdot(xs, *ys, **start_f2product_nonfinites):
|
|
427
|
+
'''Return the precision dot product M{sum(xs[i] * ys[i] for i in range(len(xs)))}.
|
|
436
428
|
|
|
437
|
-
@arg
|
|
438
|
-
@arg
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
429
|
+
@arg xs: Iterable of values (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
|
|
430
|
+
@arg ys: Other values (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}), all positional.
|
|
431
|
+
@kwarg start_f2product_nonfinites: Optional bias C{B{start}=0} (C{scalar}, an
|
|
432
|
+
L{Fsum} or L{Fsum2Tuple}) and settings C{B{f2product}=None} (C{bool})
|
|
433
|
+
and C{B{nonfinites=True}} (C{bool}), see class L{Fsum<Fsum.__init__>}.
|
|
442
434
|
|
|
443
435
|
@return: Dot product (C{float}).
|
|
444
436
|
|
|
445
|
-
@raise LenError: Unequal C{len(B{
|
|
437
|
+
@raise LenError: Unequal C{len(B{xs})} and C{len(B{ys})}.
|
|
446
438
|
|
|
447
439
|
@see: Class L{Fdot}, U{Algorithm 5.10 B{DotK}
|
|
448
440
|
<https://www.TUHH.De/ti3/paper/rump/OgRuOi05.pdf>} and function
|
|
449
441
|
C{math.sumprod} in Python 3.12 and later.
|
|
450
442
|
'''
|
|
451
|
-
D = Fdot(
|
|
443
|
+
D = Fdot(xs, *ys, **_xkwds(start_f2product_nonfinites, nonfinites=True))
|
|
452
444
|
return float(D)
|
|
453
445
|
|
|
454
446
|
|
|
455
|
-
def
|
|
456
|
-
'''Return the precision dot product M{
|
|
457
|
-
|
|
447
|
+
def fdot_(*xys, **start_f2product_nonfinites):
|
|
448
|
+
'''Return the (precision) dot product M{sum(xys[i] * xys[i+1] for i in range(0, len(xys), B{2}))}.
|
|
449
|
+
|
|
450
|
+
@arg xys: Pairwise values (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}), all positional.
|
|
451
|
+
|
|
452
|
+
@see: Function L{fdot} for further details.
|
|
453
|
+
|
|
454
|
+
@return: Dot product (C{float}).
|
|
455
|
+
'''
|
|
456
|
+
return fdot(xys[0::2], *xys[1::2], **start_f2product_nonfinites)
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
def fdot3(xs, ys, zs, **start_f2product_nonfinites):
|
|
460
|
+
'''Return the (precision) dot product M{start + sum(xs[i] * ys[i] * zs[i] for i in range(len(xs)))}.
|
|
461
|
+
|
|
462
|
+
@arg xs: X values iterable (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
|
|
463
|
+
@arg ys: Y values iterable (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
|
|
464
|
+
@arg zs: Z values iterable (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
|
|
458
465
|
|
|
459
|
-
@
|
|
460
|
-
@arg ys: Iterable (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
|
|
461
|
-
@arg zs: Iterable (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
|
|
462
|
-
@kwarg start: Optional bias (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
|
|
466
|
+
@see: Function L{fdot} for further details.
|
|
463
467
|
|
|
464
468
|
@return: Dot product (C{float}).
|
|
465
469
|
|
|
@@ -469,17 +473,16 @@ def fdot3(xs, ys, zs, start=0):
|
|
|
469
473
|
if not n == len(ys) == len(zs):
|
|
470
474
|
raise LenError(fdot3, xs=n, ys=len(ys), zs=len(zs))
|
|
471
475
|
|
|
472
|
-
D = Fdot((), nonfinites=True
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
D = D.
|
|
476
|
+
D = Fdot((), **_xkwds(start_f2product_nonfinites, nonfinites=True))
|
|
477
|
+
kwds = dict(f2product=D.f2product(), nonfinites=D.nonfinites())
|
|
478
|
+
_f = Fsum(**kwds)
|
|
479
|
+
D = D._facc(_f(x).f2mul_(y, z, **kwds) for x, y, z in zip(xs, ys, zs))
|
|
476
480
|
return float(D)
|
|
477
481
|
|
|
478
482
|
|
|
479
483
|
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}.
|
|
484
|
+
'''Horner form evaluation of polynomial M{sum(cs[i] * x**i for i=0..n)} as
|
|
485
|
+
in- or decreasing exponent M{sum(... i=n..0)}, where C{n = len(cs) - 1}.
|
|
483
486
|
|
|
484
487
|
@return: Horner sum (C{float}).
|
|
485
488
|
|
|
@@ -1092,7 +1095,7 @@ def zqrt(x):
|
|
|
1092
1095
|
|
|
1093
1096
|
# **) MIT License
|
|
1094
1097
|
#
|
|
1095
|
-
# Copyright (C) 2016-
|
|
1098
|
+
# Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
|
|
1096
1099
|
#
|
|
1097
1100
|
# Permission is hereby granted, free of charge, to any person obtaining a
|
|
1098
1101
|
# copy of this software and associated documentation files (the "Software"),
|