pygeodesy 24.5.8__py2.py3-none-any.whl → 24.5.24__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.5.8.dist-info → PyGeodesy-24.5.24.dist-info}/METADATA +2 -2
- PyGeodesy-24.5.24.dist-info/RECORD +116 -0
- pygeodesy/__init__.py +16 -12
- pygeodesy/__main__.py +9 -10
- pygeodesy/albers.py +42 -42
- pygeodesy/auxilats/__init__.py +1 -1
- pygeodesy/auxilats/__main__.py +7 -10
- pygeodesy/auxilats/auxAngle.py +32 -31
- pygeodesy/auxilats/auxLat.py +81 -51
- pygeodesy/azimuthal.py +123 -124
- pygeodesy/basics.py +165 -176
- pygeodesy/booleans.py +14 -15
- pygeodesy/cartesianBase.py +25 -23
- pygeodesy/clipy.py +3 -3
- pygeodesy/constants.py +8 -6
- pygeodesy/css.py +50 -42
- pygeodesy/datums.py +50 -48
- pygeodesy/dms.py +6 -6
- pygeodesy/ecef.py +27 -27
- pygeodesy/elevations.py +2 -2
- pygeodesy/ellipsoidalBase.py +28 -27
- pygeodesy/ellipsoidalBaseDI.py +8 -7
- pygeodesy/ellipsoidalNvector.py +11 -12
- pygeodesy/ellipsoids.py +41 -35
- pygeodesy/elliptic.py +12 -10
- pygeodesy/epsg.py +4 -3
- pygeodesy/errors.py +35 -13
- pygeodesy/etm.py +62 -53
- pygeodesy/fmath.py +48 -41
- pygeodesy/formy.py +93 -65
- pygeodesy/frechet.py +117 -102
- pygeodesy/fstats.py +52 -46
- pygeodesy/fsums.py +169 -145
- pygeodesy/gars.py +10 -9
- pygeodesy/geodesicw.py +32 -30
- pygeodesy/geodesicx/__init__.py +1 -1
- pygeodesy/geodesicx/__main__.py +4 -4
- pygeodesy/geodesicx/gx.py +40 -32
- pygeodesy/geodesicx/gxarea.py +15 -12
- pygeodesy/geodesicx/gxbases.py +3 -4
- pygeodesy/geodesicx/gxline.py +6 -8
- pygeodesy/geodsolve.py +28 -26
- pygeodesy/geohash.py +47 -44
- pygeodesy/geoids.py +37 -35
- pygeodesy/hausdorff.py +112 -99
- pygeodesy/heights.py +136 -129
- pygeodesy/internals.py +576 -0
- pygeodesy/interns.py +6 -207
- pygeodesy/iters.py +22 -19
- pygeodesy/karney.py +18 -15
- pygeodesy/ktm.py +31 -24
- pygeodesy/latlonBase.py +12 -11
- pygeodesy/lazily.py +140 -218
- pygeodesy/lcc.py +24 -25
- pygeodesy/ltp.py +83 -71
- pygeodesy/ltpTuples.py +7 -5
- pygeodesy/mgrs.py +5 -4
- pygeodesy/named.py +136 -49
- pygeodesy/namedTuples.py +33 -25
- pygeodesy/nvectorBase.py +10 -9
- pygeodesy/osgr.py +14 -12
- pygeodesy/points.py +13 -13
- pygeodesy/props.py +7 -7
- pygeodesy/rhumb/__init__.py +1 -1
- pygeodesy/rhumb/bases.py +3 -2
- pygeodesy/rhumb/solve.py +2 -2
- pygeodesy/solveBase.py +8 -7
- pygeodesy/sphericalTrigonometry.py +5 -5
- pygeodesy/streprs.py +8 -7
- pygeodesy/trf.py +8 -8
- pygeodesy/triaxials.py +67 -63
- pygeodesy/units.py +48 -50
- pygeodesy/unitsBase.py +24 -11
- pygeodesy/ups.py +7 -6
- pygeodesy/utily.py +4 -4
- pygeodesy/utm.py +53 -52
- pygeodesy/utmupsBase.py +11 -8
- pygeodesy/vector2d.py +6 -7
- pygeodesy/vector3d.py +16 -17
- pygeodesy/vector3dBase.py +5 -5
- PyGeodesy-24.5.8.dist-info/RECORD +0 -115
- {PyGeodesy-24.5.8.dist-info → PyGeodesy-24.5.24.dist-info}/WHEEL +0 -0
- {PyGeodesy-24.5.8.dist-info → PyGeodesy-24.5.24.dist-info}/top_level.txt +0 -0
pygeodesy/errors.py
CHANGED
|
@@ -14,10 +14,11 @@ C{PYGEODESY_EXCEPTION_CHAINING=std} or to any non-empty string.
|
|
|
14
14
|
# from pygeodesy.basics import isint, isodd, issubclassof, itemsorted, _xinstanceof, _zip # _MODS
|
|
15
15
|
# from pygeodesy.ellipsoidalBase import CartesianEllipsoidalBase, LatLonEllipsoidalBase # _MODS
|
|
16
16
|
# from pygeodesy import errors # _MODS, _MODS.getattr
|
|
17
|
-
from pygeodesy.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
from pygeodesy.internals import _plural, _tailof
|
|
18
|
+
from pygeodesy.interns import MISSING, NN, _a_, _an_, _and_, _clip_, _COLON_, _COLONSPACE_, \
|
|
19
|
+
_COMMASPACE_, _datum_, _ellipsoidal_, _incompatible_, _invalid_, \
|
|
20
|
+
_keyword_, _len_, _not_, _or_, _SPACE_, _specified_, _UNDER_, \
|
|
21
|
+
_vs_, _with_
|
|
21
22
|
from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS, _getenv, _PYTHON_X_DEV
|
|
22
23
|
# from pygeodesy.streprs import Fmt, unstr # _MODS
|
|
23
24
|
# from pygeodesy.vector3dBase import Vector3dBase # _MODS
|
|
@@ -25,9 +26,11 @@ from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS, _getenv, _PYTHON_X_D
|
|
|
25
26
|
from copy import copy as _copy
|
|
26
27
|
|
|
27
28
|
__all__ = _ALL_LAZY.errors # _ALL_DOCS('_InvalidError', '_IsnotError') _under
|
|
28
|
-
__version__ = '24.05.
|
|
29
|
+
__version__ = '24.05.19'
|
|
29
30
|
|
|
31
|
+
_argument_ = 'argument'
|
|
30
32
|
_box_ = 'box'
|
|
33
|
+
_expected_ = 'expected'
|
|
31
34
|
_limiterrors = True # in .formy
|
|
32
35
|
_name_value_ = repr('name=value')
|
|
33
36
|
_rangerrors = True # in .dms
|
|
@@ -142,6 +145,21 @@ def _TypesError(name, value, *Types, **kwds):
|
|
|
142
145
|
return _TypeError(name, value, txt=t, **kwds)
|
|
143
146
|
|
|
144
147
|
|
|
148
|
+
class _UnexpectedError(TypeError): # note, a TypeError!
|
|
149
|
+
'''(INTERNAL) Format a C{TypeError} I{without exception chaining}.
|
|
150
|
+
'''
|
|
151
|
+
def __init__(self, *args, **kwds):
|
|
152
|
+
n = len(kwds)
|
|
153
|
+
if args:
|
|
154
|
+
a = _plural(_argument_, len(args))
|
|
155
|
+
n = _and(a, _plural(_keyword_, n)) if n else a
|
|
156
|
+
else:
|
|
157
|
+
n = _plural(_SPACE_(_keyword_, _argument_), n)
|
|
158
|
+
u = _MODS.streprs.unstr(_SPACE_(n, NN), *args, **kwds)
|
|
159
|
+
# _error_init(TypeError, self, (u,), txt_not_=_expected_)
|
|
160
|
+
TypeError.__init__(self, _SPACE_(u, _not_, _expected_))
|
|
161
|
+
|
|
162
|
+
|
|
145
163
|
class _ValueError(ValueError):
|
|
146
164
|
'''(INTERNAL) Format a C{ValueError} with/-out exception chaining.
|
|
147
165
|
'''
|
|
@@ -375,8 +393,8 @@ def crosserrors(raiser=None):
|
|
|
375
393
|
return t
|
|
376
394
|
|
|
377
395
|
|
|
378
|
-
def _error_init(Error, inst, args, fmt_name_value='%s (%r)',
|
|
379
|
-
cause=None, **kwds):
|
|
396
|
+
def _error_init(Error, inst, args, fmt_name_value='%s (%r)', txt_not_=NN,
|
|
397
|
+
txt__=None, txt=NN, cause=None, **kwds):
|
|
380
398
|
'''(INTERNAL) Format an error text and initialize an C{Error} instance.
|
|
381
399
|
|
|
382
400
|
@arg Error: The error super-class (C{Exception}).
|
|
@@ -388,6 +406,8 @@ def _error_init(Error, inst, args, fmt_name_value='%s (%r)', txt=NN,
|
|
|
388
406
|
given as C{name=value} keyword arguments.
|
|
389
407
|
@kwarg fmt_name_value: Format for (name, value) (C{str}).
|
|
390
408
|
@kwarg txt: Optional explanation of the error (C{str}).
|
|
409
|
+
@kwarg txt__: Alternate C{B{txt}=B{txt__}.__name__}.
|
|
410
|
+
@kwarg txt_not_: Negative explanation C{B{txt}=_not_(B{txt_not_})}.
|
|
391
411
|
@kwarg cause: Optional, caught error (L{Exception}), for
|
|
392
412
|
exception chaining (supported in Python 3+).
|
|
393
413
|
@kwarg kwds: Additional C{B{name}=value} pairs, if any.
|
|
@@ -409,8 +429,10 @@ def _error_init(Error, inst, args, fmt_name_value='%s (%r)', txt=NN,
|
|
|
409
429
|
t += _fmtuple(_MODS.basics.itemsorted(kwds))
|
|
410
430
|
t = _or(*t) if t else _SPACE_(_name_value_, MISSING)
|
|
411
431
|
|
|
412
|
-
if txt is
|
|
413
|
-
|
|
432
|
+
x = _not_(txt_not_) if txt_not_ else (txt if txt__ is None
|
|
433
|
+
else txt__.__name__)
|
|
434
|
+
if x is not None:
|
|
435
|
+
x = str(x) or (str(cause) if cause else _invalid_)
|
|
414
436
|
C = _COMMASPACE_ if _COLON_ in t else _COLONSPACE_
|
|
415
437
|
t = C(t, x)
|
|
416
438
|
# else: # LenError, _xzip, .dms, .heights, .vector2d
|
|
@@ -599,7 +621,7 @@ def _xcallable(**names_callables):
|
|
|
599
621
|
'''
|
|
600
622
|
for n, c in names_callables.items():
|
|
601
623
|
if not callable(c):
|
|
602
|
-
raise _TypeError(n, c,
|
|
624
|
+
raise _TypeError(n, c, txt_not_=callable.__name__) # txt__
|
|
603
625
|
|
|
604
626
|
|
|
605
627
|
def _xdatum(datum1, datum2, Error=None):
|
|
@@ -625,7 +647,7 @@ def _xellipsoidal(**name_value): # see _xellipsoidall elel
|
|
|
625
647
|
return v
|
|
626
648
|
except AttributeError:
|
|
627
649
|
pass
|
|
628
|
-
raise _TypeError(n, v,
|
|
650
|
+
raise _TypeError(n, v, txt_not_=_ellipsoidal_)
|
|
629
651
|
raise _xAssertionError(_xellipsoidal, name_value)
|
|
630
652
|
|
|
631
653
|
|
|
@@ -716,7 +738,7 @@ except AttributeError:
|
|
|
716
738
|
# b = getattr(inst, n, None)
|
|
717
739
|
# if b is None: # invalid bool attr
|
|
718
740
|
# t = _SPACE_(_EQUAL_(n, repr(v)), 'for', inst.__class__.__name__) # XXX .classname
|
|
719
|
-
# raise _AttributeError(t,
|
|
741
|
+
# raise _AttributeError(t, txt_not_='applicable')
|
|
720
742
|
# if v in (False, True) and v != b:
|
|
721
743
|
# setattr(inst, NN(_UNDER_, n), v)
|
|
722
744
|
|
|
@@ -777,7 +799,7 @@ def _Xorder(_Coeffs, Error, **Xorder): # in .auxLat, .ktm, .rhumb.bases, .rhumb
|
|
|
777
799
|
if m in _Coeffs and _MODS.basics.isint(m):
|
|
778
800
|
return m
|
|
779
801
|
t = sorted(map(str, _Coeffs.keys()))
|
|
780
|
-
raise Error(X, m,
|
|
802
|
+
raise Error(X, m, txt_not_=_or(*t))
|
|
781
803
|
|
|
782
804
|
# **) MIT License
|
|
783
805
|
#
|
pygeodesy/etm.py
CHANGED
|
@@ -71,10 +71,10 @@ from pygeodesy.datums import _ellipsoidal_datum, _WGS84, _EWGS84
|
|
|
71
71
|
# from pygeodesy.ellipsoids import _EWGS84 # from .datums
|
|
72
72
|
from pygeodesy.elliptic import _ALL_LAZY, Elliptic
|
|
73
73
|
# from pygeodesy.errors import _incompatible # from .named
|
|
74
|
-
from pygeodesy.
|
|
75
|
-
from pygeodesy.
|
|
76
|
-
from pygeodesy.interns import
|
|
77
|
-
|
|
74
|
+
# from pygeodesy.fsums import Fsum # from .fmath
|
|
75
|
+
from pygeodesy.fmath import cbrt, hypot, hypot1, hypot2, Fsum
|
|
76
|
+
from pygeodesy.interns import _COMMASPACE_, _DASH_, _near_, _SPACE_, \
|
|
77
|
+
_spherical_
|
|
78
78
|
from pygeodesy.karney import _copyBit, _diff182, _fix90, _norm2, _norm180, \
|
|
79
79
|
_tand, _unsigned2
|
|
80
80
|
# from pygeodesy.lazily import _ALL_LAZY # from .elliptic
|
|
@@ -92,7 +92,7 @@ from pygeodesy.utm import _cmlon, _LLEB, _parseUTM5, _toBand, _toXtm8, \
|
|
|
92
92
|
from math import asinh, atan2, degrees, radians, sinh, sqrt
|
|
93
93
|
|
|
94
94
|
__all__ = _ALL_LAZY.etm
|
|
95
|
-
__version__ = '24.
|
|
95
|
+
__version__ = '24.05.24'
|
|
96
96
|
|
|
97
97
|
_OVERFLOW = _1_EPS**2 # about 2e+31
|
|
98
98
|
_TAYTOL = pow(EPS, 0.6)
|
|
@@ -157,13 +157,13 @@ class Etm(Utm):
|
|
|
157
157
|
self._exactTM = exactTM
|
|
158
158
|
self._scale0 = exactTM.k0
|
|
159
159
|
|
|
160
|
-
def parse(self, strETM, name
|
|
160
|
+
def parse(self, strETM, **name):
|
|
161
161
|
'''Parse a string to a similar L{Etm} instance.
|
|
162
162
|
|
|
163
|
-
@arg strETM: The ETM coordinate (C{str}),
|
|
164
|
-
|
|
165
|
-
@kwarg name: Optional
|
|
166
|
-
|
|
163
|
+
@arg strETM: The ETM coordinate (C{str}), see function
|
|
164
|
+
L{parseETM5}.
|
|
165
|
+
@kwarg name: Optional C{B{name}=NN} (C{str}), overriding
|
|
166
|
+
this name.
|
|
167
167
|
|
|
168
168
|
@return: The instance (L{Etm}).
|
|
169
169
|
|
|
@@ -173,7 +173,7 @@ class Etm(Utm):
|
|
|
173
173
|
and L{pygeodesy.parseUTMUPS5}.
|
|
174
174
|
'''
|
|
175
175
|
return parseETM5(strETM, datum=self.datum, Etm=self.classof,
|
|
176
|
-
name=
|
|
176
|
+
name=self._name__(name))
|
|
177
177
|
|
|
178
178
|
@deprecated_method
|
|
179
179
|
def parseETM(self, strETM): # PYCHOK no cover
|
|
@@ -247,7 +247,7 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
247
247
|
_sigmaC = None # most recent _sigmaInv04 case C{int}
|
|
248
248
|
_zetaC = None # most recent _zetaInv04 case C{int}
|
|
249
249
|
|
|
250
|
-
def __init__(self, datum=_WGS84, lon0=0, k0=_K0_UTM, extendp=False,
|
|
250
|
+
def __init__(self, datum=_WGS84, lon0=0, k0=_K0_UTM, extendp=False, raiser=False, **name):
|
|
251
251
|
'''New L{ExactTransverseMercator} projection.
|
|
252
252
|
|
|
253
253
|
@kwarg datum: The I{non-spherical} datum or ellipsoid (L{Datum},
|
|
@@ -255,8 +255,8 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
255
255
|
@kwarg lon0: Central meridian, default (C{degrees180}).
|
|
256
256
|
@kwarg k0: Central scale factor (C{float}).
|
|
257
257
|
@kwarg extendp: Use the I{extended} domain (C{bool}), I{standard} otherwise.
|
|
258
|
-
@kwarg name: Optional name for the projection (C{str}).
|
|
259
258
|
@kwarg raiser: If C{True}, throw an L{ETMError} for convergence failures (C{bool}).
|
|
259
|
+
@kwarg name: Optional C{B{name}=NN} for the projection (C{str}).
|
|
260
260
|
|
|
261
261
|
@raise ETMError: Near-spherical B{C{datum}} or C{ellipsoid} or invalid B{C{lon0}}
|
|
262
262
|
or B{C{k0}}.
|
|
@@ -444,14 +444,14 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
444
444
|
|
|
445
445
|
f = flattening
|
|
446
446
|
|
|
447
|
-
def forward(self, lat, lon, lon0=None, name
|
|
447
|
+
def forward(self, lat, lon, lon0=None, **name): # MCCABE 13
|
|
448
448
|
'''Forward projection, from geographic to transverse Mercator.
|
|
449
449
|
|
|
450
450
|
@arg lat: Latitude of point (C{degrees}).
|
|
451
451
|
@arg lon: Longitude of point (C{degrees}).
|
|
452
452
|
@kwarg lon0: Central meridian (C{degrees180}), overriding
|
|
453
453
|
the default if not C{None}.
|
|
454
|
-
@kwarg name: Optional name (C{str}).
|
|
454
|
+
@kwarg name: Optional C{B{name}=NN} (C{str}).
|
|
455
455
|
|
|
456
456
|
@return: L{Forward4Tuple}C{(easting, northing, gamma, scale)}.
|
|
457
457
|
|
|
@@ -500,7 +500,7 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
500
500
|
if _lon:
|
|
501
501
|
x, g = neg_(x, g)
|
|
502
502
|
return Forward4Tuple(x, y, g, k, iteration=self._iteration,
|
|
503
|
-
name=
|
|
503
|
+
name=self._name__(name))
|
|
504
504
|
|
|
505
505
|
def _Inv03(self, psi, dlam, _3_mv_e): # (xi, deta, _3_mv)
|
|
506
506
|
'''(INTERNAL) Partial C{_zetaInv04} or C{_sigmaInv04}, Case 2
|
|
@@ -609,6 +609,7 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
609
609
|
_U_2 = Fsum(u).fsum2f_
|
|
610
610
|
_V_2 = Fsum(v).fsum2f_
|
|
611
611
|
# min iterations 2, max 6 or 7, mean 3.9 or 4.0
|
|
612
|
+
_hy2 = hypot2
|
|
612
613
|
for i in range(1, _TRIPS): # GEOGRAPHICLIB_PANIC
|
|
613
614
|
sncndn6 = self._sncndn6(u, v)
|
|
614
615
|
du, dv = _zetaDwd2(*sncndn6)
|
|
@@ -620,7 +621,7 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
620
621
|
if d2 < tol2:
|
|
621
622
|
r = False
|
|
622
623
|
break
|
|
623
|
-
d2 =
|
|
624
|
+
d2 = _hy2(dU, dV)
|
|
624
625
|
|
|
625
626
|
self._iteration = i
|
|
626
627
|
if r: # PYCHOK no cover
|
|
@@ -680,14 +681,14 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
680
681
|
self._mu = mu
|
|
681
682
|
self._mv = mv
|
|
682
683
|
|
|
683
|
-
def reverse(self, x, y, lon0=None, name
|
|
684
|
+
def reverse(self, x, y, lon0=None, **name):
|
|
684
685
|
'''Reverse projection, from Transverse Mercator to geographic.
|
|
685
686
|
|
|
686
687
|
@arg x: Easting of point (C{meters}).
|
|
687
688
|
@arg y: Northing of point (C{meters}).
|
|
688
|
-
@kwarg lon0:
|
|
689
|
-
the default
|
|
690
|
-
@kwarg name: Optional name (C{str}).
|
|
689
|
+
@kwarg lon0: Optional central meridian (C{degrees180}),
|
|
690
|
+
overriding the default (C{iff not None}).
|
|
691
|
+
@kwarg name: Optional C{B{name}=NN} (C{str}).
|
|
691
692
|
|
|
692
693
|
@return: L{Reverse4Tuple}C{(lat, lon, gamma, scale)}.
|
|
693
694
|
|
|
@@ -730,9 +731,9 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
730
731
|
lon, g = neg_(lon, g)
|
|
731
732
|
lat += self._lat0
|
|
732
733
|
lon += self._lon0 if lon0 is None else _norm180(lon0)
|
|
733
|
-
return Reverse4Tuple(lat, _norm180(lon), g, k, #
|
|
734
|
+
return Reverse4Tuple(lat, _norm180(lon), g, k, # _fix90(lat)
|
|
734
735
|
iteration=self._iteration,
|
|
735
|
-
name=
|
|
736
|
+
name=self._name__(name))
|
|
736
737
|
|
|
737
738
|
def _scaled2(self, tau, d2, snu, cnu, dnu, snv, cnv, dnv):
|
|
738
739
|
'''(INTERNAL) C{scaled}.
|
|
@@ -768,7 +769,7 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
768
769
|
# = sqrt(mv + mv * tau**2 + mu) * sqrt(q2)
|
|
769
770
|
k, q2 = _0_0, (mv * snv**2 + cnudnv**2)
|
|
770
771
|
if q2 > 0:
|
|
771
|
-
k2 =
|
|
772
|
+
k2 = (tau**2 + _1_0) * mv + mu
|
|
772
773
|
if k2 > 0:
|
|
773
774
|
k = sqrt(k2) * sqrt(q2 / d2) * self.k0
|
|
774
775
|
else:
|
|
@@ -811,13 +812,14 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
811
812
|
real /*v*/, real snv, real cnv, real dnv,
|
|
812
813
|
real &du, real &dv)}.
|
|
813
814
|
'''
|
|
815
|
+
mu = self._mu
|
|
814
816
|
snuv = snu * snv
|
|
815
817
|
# Reciprocal of 55.9: dw / ds = dn(w)^2/_mv,
|
|
816
818
|
# expanding complex dn(w) using A+S 16.21.4
|
|
817
|
-
d =
|
|
818
|
-
r =
|
|
819
|
-
i =
|
|
820
|
-
du = (r**2 - i**2) / d
|
|
819
|
+
d = (cnv**2 + snuv**2 * mu)**2 * self._mv
|
|
820
|
+
r = cnv * dnu * dnv
|
|
821
|
+
i = cnu * snuv * mu
|
|
822
|
+
du = (r**2 - i**2) / d # (r + i) * (r - i) / d
|
|
821
823
|
dv = neg(r * i * _2_0 / d)
|
|
822
824
|
return du, dv
|
|
823
825
|
|
|
@@ -1030,7 +1032,7 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
1030
1032
|
return g_k # or (g, k, lat, lon)
|
|
1031
1033
|
|
|
1032
1034
|
|
|
1033
|
-
def parseETM5(strUTM, datum=_WGS84, Etm=Etm, falsed=True, name
|
|
1035
|
+
def parseETM5(strUTM, datum=_WGS84, Etm=Etm, falsed=True, **name):
|
|
1034
1036
|
'''Parse a string representing a UTM coordinate, consisting
|
|
1035
1037
|
of C{"zone[band] hemisphere easting northing"}.
|
|
1036
1038
|
|
|
@@ -1040,7 +1042,7 @@ def parseETM5(strUTM, datum=_WGS84, Etm=Etm, falsed=True, name=NN):
|
|
|
1040
1042
|
@kwarg Etm: Optional class to return the UTM coordinate
|
|
1041
1043
|
(L{Etm}) or C{None}.
|
|
1042
1044
|
@kwarg falsed: Both easting and northing are C{falsed} (C{bool}).
|
|
1043
|
-
@kwarg name: Optional B{C{Etm}} name (C{str}).
|
|
1045
|
+
@kwarg name: Optional B{C{Etm}} C{B{name}=NN} (C{str}).
|
|
1044
1046
|
|
|
1045
1047
|
@return: The UTM coordinate (B{C{Etm}}) or if B{C{Etm}} is
|
|
1046
1048
|
C{None}, a L{UtmUps5Tuple}C{(zone, hemipole, easting,
|
|
@@ -1051,29 +1053,31 @@ def parseETM5(strUTM, datum=_WGS84, Etm=Etm, falsed=True, name=NN):
|
|
|
1051
1053
|
|
|
1052
1054
|
@raise TypeError: Invalid or near-spherical B{C{datum}}.
|
|
1053
1055
|
'''
|
|
1054
|
-
r = _parseUTM5(strUTM, datum, Etm, falsed, Error=ETMError, name
|
|
1056
|
+
r = _parseUTM5(strUTM, datum, Etm, falsed, Error=ETMError, **name)
|
|
1055
1057
|
return r
|
|
1056
1058
|
|
|
1057
1059
|
|
|
1058
1060
|
def toEtm8(latlon, lon=None, datum=None, Etm=Etm, falsed=True,
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
+
strict=True, zone=None,
|
|
1062
|
+
**name_cmoff):
|
|
1061
1063
|
'''Convert a geodetic lat-/longitude to an ETM coordinate.
|
|
1062
1064
|
|
|
1063
1065
|
@arg latlon: Latitude (C{degrees}) or an (ellipsoidal)
|
|
1064
1066
|
geodetic C{LatLon} instance.
|
|
1065
|
-
@kwarg lon: Optional longitude (C{degrees})
|
|
1067
|
+
@kwarg lon: Optional longitude (C{degrees}), required
|
|
1068
|
+
if B{C{latlon}} is in C{degrees}.
|
|
1066
1069
|
@kwarg datum: Optional datum for the ETM coordinate,
|
|
1067
1070
|
overriding B{C{latlon}}'s datum (L{Datum},
|
|
1068
1071
|
L{Ellipsoid}, L{Ellipsoid2} or L{a_f2Tuple}).
|
|
1069
1072
|
@kwarg Etm: Optional class to return the ETM coordinate
|
|
1070
1073
|
(L{Etm}) or C{None}.
|
|
1071
1074
|
@kwarg falsed: False both easting and northing (C{bool}).
|
|
1072
|
-
@kwarg name: Optional B{C{Utm}} name (C{str}).
|
|
1073
1075
|
@kwarg strict: Restrict B{C{lat}} to UTM ranges (C{bool}).
|
|
1074
1076
|
@kwarg zone: Optional UTM zone to enforce (C{int} or C{str}).
|
|
1075
|
-
@kwarg
|
|
1076
|
-
|
|
1077
|
+
@kwarg name_cmoff: Optional B{C{Etm}} C{B{name}=NN} (C{str})
|
|
1078
|
+
and DEPRECATED C{B{cmoff}=True} to offset longitude
|
|
1079
|
+
from the zone's central meridian (C{bool}), instead
|
|
1080
|
+
use C{B{falsed}=True}.
|
|
1077
1081
|
|
|
1078
1082
|
@return: The ETM coordinate as an B{C{Etm}} instance or a
|
|
1079
1083
|
L{UtmUps8Tuple}C{(zone, hemipole, easting, northing,
|
|
@@ -1097,23 +1101,25 @@ def toEtm8(latlon, lon=None, datum=None, Etm=Etm, falsed=True,
|
|
|
1097
1101
|
@raise ValueError: The B{C{lon}} value is missing or B{C{latlon}}
|
|
1098
1102
|
is invalid.
|
|
1099
1103
|
'''
|
|
1100
|
-
z, B, lat, lon, d, f,
|
|
1101
|
-
|
|
1102
|
-
|
|
1104
|
+
z, B, lat, lon, d, f, n = _to7zBlldfn(latlon, lon, datum,
|
|
1105
|
+
falsed, zone, strict,
|
|
1106
|
+
ETMError, **name_cmoff)
|
|
1103
1107
|
lon0 = _cmlon(z) if f else None
|
|
1104
1108
|
x, y, g, k = d.exactTM.forward(lat, lon, lon0=lon0)
|
|
1105
1109
|
|
|
1106
1110
|
return _toXtm8(Etm, z, lat, x, y, B, d, g, k, f,
|
|
1107
|
-
|
|
1111
|
+
n, latlon, d.exactTM, Error=ETMError)
|
|
1108
1112
|
|
|
1109
1113
|
|
|
1110
1114
|
if __name__ == '__main__': # MCCABE 13
|
|
1111
1115
|
|
|
1112
1116
|
from pygeodesy import fstr, KTransverseMercator, printf
|
|
1117
|
+
from pygeodesy.internals import _usage
|
|
1113
1118
|
from sys import argv, exit as _exit
|
|
1114
1119
|
|
|
1115
1120
|
# mimick some of I{Karney}'s utility C{TransverseMercatorProj}
|
|
1116
1121
|
_f = _r = _s = _t = False
|
|
1122
|
+
_p = -6
|
|
1117
1123
|
_as = argv[1:]
|
|
1118
1124
|
while _as and _as[0].startswith(_DASH_):
|
|
1119
1125
|
_a = _as.pop(0)
|
|
@@ -1123,16 +1129,19 @@ if __name__ == '__main__': # MCCABE 13
|
|
|
1123
1129
|
_f, _r = True, False
|
|
1124
1130
|
elif '-reverse'.startswith(_a):
|
|
1125
1131
|
_f, _r = False, True
|
|
1132
|
+
elif '-precision'.startswith(_a):
|
|
1133
|
+
_p = int(_as.pop(0))
|
|
1126
1134
|
elif '-series'.startswith(_a):
|
|
1127
1135
|
_s, _t = True, False
|
|
1128
1136
|
elif _a == '-t':
|
|
1129
1137
|
_s, _t = False, True
|
|
1130
1138
|
elif '-help'.startswith(_a):
|
|
1131
|
-
_exit(_usage(argv[0], '[-s | -t]',
|
|
1139
|
+
_exit(_usage(argv[0], '[-s | -t ]',
|
|
1140
|
+
'[-p[recision] <ndigits>',
|
|
1132
1141
|
'[-f[orward] <lat> <lon>',
|
|
1133
|
-
'
|
|
1134
|
-
'
|
|
1135
|
-
'
|
|
1142
|
+
'|-r[everse] <easting> <northing>',
|
|
1143
|
+
'|<lat> <lon>]',
|
|
1144
|
+
'|-h[elp]'))
|
|
1136
1145
|
else:
|
|
1137
1146
|
_exit('%s: option %r not supported' % (_usage(*argv), _a))
|
|
1138
1147
|
if len(_as) > 1:
|
|
@@ -1151,18 +1160,18 @@ if __name__ == '__main__': # MCCABE 13
|
|
|
1151
1160
|
t = tm.reverse(*f2)
|
|
1152
1161
|
else:
|
|
1153
1162
|
t = tm.forward(*f2)
|
|
1154
|
-
printf('%s: %s', tm.classname, fstr(t, sep=_SPACE_))
|
|
1163
|
+
printf('%s: %s', tm.classname, fstr(t, prec=_p, sep=_SPACE_))
|
|
1155
1164
|
t = tm.reverse(t.easting, t.northing)
|
|
1156
|
-
printf('%s: %s', tm.classname, fstr(t, sep=_SPACE_))
|
|
1165
|
+
printf('%s: %s', tm.classname, fstr(t, prec=_p, sep=_SPACE_))
|
|
1157
1166
|
|
|
1158
1167
|
|
|
1159
|
-
# % python3 -m pygeodesy.etm 33.33 44.44
|
|
1160
|
-
# ExactTransverseMercator: 4276926.
|
|
1161
|
-
# ExactTransverseMercator: 33.33 44.44 28.
|
|
1168
|
+
# % python3 -m pygeodesy.etm -p 12 33.33 44.44
|
|
1169
|
+
# ExactTransverseMercator: 4276926.11480390653 4727193.767015309073 28.375536563148 1.233325101778
|
|
1170
|
+
# ExactTransverseMercator: 33.33 44.44 28.375536563148 1.233325101778
|
|
1162
1171
|
|
|
1163
|
-
# % python3 -m pygeodesy.etm -s 33.33 44.44
|
|
1164
|
-
# KTransverseMercator: 4276926.
|
|
1165
|
-
# KTransverseMercator: 33.33 44.44 28.
|
|
1172
|
+
# % python3 -m pygeodesy.etm -s -p 12 33.33 44.44
|
|
1173
|
+
# KTransverseMercator: 4276926.114803904667 4727193.767015310004 28.375536563148 1.233325101778
|
|
1174
|
+
# KTransverseMercator: 33.33 44.44 28.375536563148 1.233325101778
|
|
1166
1175
|
|
|
1167
1176
|
# % echo 33.33 44.44 | .../bin/TransverseMercatorProj
|
|
1168
1177
|
# 4276926.114804 4727193.767015 28.375536563148 1.233325101778
|
pygeodesy/fmath.py
CHANGED
|
@@ -7,7 +7,7 @@ u'''Utilities using precision floating point summation.
|
|
|
7
7
|
from __future__ import division as _; del _ # PYCHOK semicolon
|
|
8
8
|
|
|
9
9
|
from pygeodesy.basics import _copysign, copysign0, isbool, isint, isscalar, \
|
|
10
|
-
len2, map1
|
|
10
|
+
len2, map1, _xiterable
|
|
11
11
|
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
|
_N_1_0, _1_5, _copysign_0_0, _isfinite, remainder
|
|
@@ -24,7 +24,7 @@ from math import fabs, sqrt # pow
|
|
|
24
24
|
import operator as _operator # in .datums, .trf, .utm
|
|
25
25
|
|
|
26
26
|
__all__ = _ALL_LAZY.fmath
|
|
27
|
-
__version__ = '24.05.
|
|
27
|
+
__version__ = '24.05.24'
|
|
28
28
|
|
|
29
29
|
# sqrt(2) <https://WikiPedia.org/wiki/Square_root_of_2>
|
|
30
30
|
_0_4142 = 0.41421356237309504880 # ... sqrt(2) - 1
|
|
@@ -39,12 +39,13 @@ class Fdot(Fsum):
|
|
|
39
39
|
'''New L{Fdot} precision dot product M{sum(a[i] * b[i] for
|
|
40
40
|
i=0..len(a)-1)}.
|
|
41
41
|
|
|
42
|
-
@arg a: Iterable of values (each C{scalar} or an L{Fsum} or
|
|
43
|
-
|
|
44
|
-
@arg b: Other values (each C{scalar} or an L{Fsum} or L{Fsum2Tuple}
|
|
45
|
-
|
|
46
|
-
@kwarg name_RESIDUAL: Optional C{B{name}=NN} and C{B{RESIDUAL}=0.0}
|
|
47
|
-
threshold
|
|
42
|
+
@arg a: Iterable of values (each C{scalar} or an L{Fsum} or L{Fsum2Tuple}
|
|
43
|
+
instance).
|
|
44
|
+
@arg b: Other values (each C{scalar} or an L{Fsum} or L{Fsum2Tuple} instance),
|
|
45
|
+
all positional.
|
|
46
|
+
@kwarg name_RESIDUAL: Optional C{B{name}=NN} (C{str}) and the C{B{RESIDUAL}=0.0}
|
|
47
|
+
threshold (C{scalar}) for raising L{ResidualError}s, see class
|
|
48
|
+
L{Fsum<Fsum.__init__>}.
|
|
48
49
|
|
|
49
50
|
@raise LenError: Unequal C{len(B{a})} and C{len(B{b})}.
|
|
50
51
|
|
|
@@ -68,10 +69,11 @@ class Fhorner(Fsum):
|
|
|
68
69
|
i=0..len(cs)-1)}.
|
|
69
70
|
|
|
70
71
|
@arg x: Polynomial argument (C{scalar} or an L{Fsum} or L{Fsum2Tuple}).
|
|
71
|
-
@arg cs: Polynomial coeffients (each C{scalar} or an L{Fsum} or
|
|
72
|
-
|
|
73
|
-
@kwarg name_RESIDUAL: Optional C{B{name}=NN} and C{B{RESIDUAL}=0.0}
|
|
74
|
-
threshold
|
|
72
|
+
@arg cs: Polynomial coeffients (each C{scalar} or an L{Fsum} or L{Fsum2Tuple}
|
|
73
|
+
instance), all positional.
|
|
74
|
+
@kwarg name_RESIDUAL: Optional C{B{name}=NN} (C{str}) and the C{B{RESIDUAL}=0.0}
|
|
75
|
+
threshold (C{scalar}) for raising L{ResidualError}s, see class
|
|
76
|
+
L{Fsum<Fsum.__init__>}.
|
|
75
77
|
|
|
76
78
|
@raise OverflowError: Partial C{2sum} overflow.
|
|
77
79
|
|
|
@@ -107,11 +109,12 @@ class Fhypot(Fsum):
|
|
|
107
109
|
'''New L{Fhypot} hypotenuse of (the I{root} of) several components
|
|
108
110
|
(raised to the power I{root}).
|
|
109
111
|
|
|
110
|
-
@arg xs: Components (each C{scalar} or an L{Fsum} or L{Fsum2Tuple}
|
|
111
|
-
|
|
112
|
-
@kwarg root_name_RESIDUAL_raiser: Optional, exponent and C{B{root}=2}
|
|
113
|
-
|
|
114
|
-
C{B{raiser}=True}
|
|
112
|
+
@arg xs: Components (each C{scalar} or an L{Fsum} or L{Fsum2Tuple} instance),
|
|
113
|
+
all positional.
|
|
114
|
+
@kwarg root_name_RESIDUAL_raiser: Optional, exponent and C{B{root}=2} order
|
|
115
|
+
(C{scalar}), C{B{name}=NN} (C{str}), the C{B{RESIDUAL}=0.0}
|
|
116
|
+
threshold (C{scalar}) and C{B{raiser}=True} (C{bool}) for
|
|
117
|
+
raising L{ResidualError}s, see class L{Fsum<Fsum.__init__>} and
|
|
115
118
|
method L{root<Fsum.root>}.
|
|
116
119
|
'''
|
|
117
120
|
r = None # _xkwds_pop2 error
|
|
@@ -134,10 +137,11 @@ class Fpolynomial(Fsum):
|
|
|
134
137
|
M{sum(cs[i] * x**i for i=0..len(cs)-1)}.
|
|
135
138
|
|
|
136
139
|
@arg x: Polynomial argument (C{scalar} or an L{Fsum} or L{Fsum2Tuple}).
|
|
137
|
-
@arg cs: Polynomial coeffients (each C{scalar} or an L{Fsum} or
|
|
138
|
-
|
|
139
|
-
@kwarg name_RESIDUAL: Optional C{B{name}=NN} and C{B{RESIDUAL}=0.0}
|
|
140
|
-
threshold
|
|
140
|
+
@arg cs: Polynomial coeffients (each C{scalar} or an L{Fsum} or L{Fsum2Tuple}
|
|
141
|
+
instance), all positional.
|
|
142
|
+
@kwarg name_RESIDUAL: Optional C{B{name}=NN} (C{str}) and the C{B{RESIDUAL}=0.0}
|
|
143
|
+
threshold (C{scalar}) for raising L{ResidualError}s, see class
|
|
144
|
+
L{Fsum<Fsum.__init__>}.
|
|
141
145
|
|
|
142
146
|
@raise OverflowError: Partial C{2sum} overflow.
|
|
143
147
|
|
|
@@ -162,11 +166,12 @@ class Fpowers(Fsum):
|
|
|
162
166
|
'''New L{Fpowers} sum of (the I{power} of) several bases.
|
|
163
167
|
|
|
164
168
|
@arg power: The exponent (C{scalar} or an L{Fsum} or L{Fsum2Tuple}).
|
|
165
|
-
@arg xs: One or more bases (each C{scalar} or an L{Fsum} or L{Fsum2Tuple}
|
|
166
|
-
|
|
167
|
-
@kwarg name_RESIDUAL_raiser: Optional C{B{name}=NN}, C{B{RESIDUAL}=0.0}
|
|
168
|
-
threshold and C{B{raiser}=True}
|
|
169
|
-
|
|
169
|
+
@arg xs: One or more bases (each C{scalar} or an L{Fsum} or L{Fsum2Tuple} instance),
|
|
170
|
+
all positional.
|
|
171
|
+
@kwarg name_RESIDUAL_raiser: Optional C{B{name}=NN} (C{str}), the C{B{RESIDUAL}=0.0}
|
|
172
|
+
threshold (C{scalar}) and C{B{raiser}=True} (C{bool}) for raising
|
|
173
|
+
L{ResidualError}s, see class L{Fsum<Fsum.__init__>} and method
|
|
174
|
+
L{fpow<Fsum.fpow>}.
|
|
170
175
|
'''
|
|
171
176
|
try:
|
|
172
177
|
raiser = _Fsum__init__(self, **name_RESIDUAL_raiser)
|
|
@@ -183,11 +188,12 @@ class Froot(Fsum):
|
|
|
183
188
|
'''New L{Froot} root of a precision sum.
|
|
184
189
|
|
|
185
190
|
@arg root: The order (C{scalar} or an L{Fsum} or L{Fsum2Tuple}), non-zero.
|
|
186
|
-
@arg xs: Items to summate (each a C{scalar} or an L{Fsum} or L{Fsum2Tuple}
|
|
187
|
-
|
|
188
|
-
@kwarg name_RESIDUAL_raiser: Optional C{B{name}=NN}, C{B{RESIDUAL}=0.0}
|
|
189
|
-
threshold and C{B{raiser}=True}
|
|
190
|
-
|
|
191
|
+
@arg xs: Items to summate (each a C{scalar} or an L{Fsum} or L{Fsum2Tuple} instance),
|
|
192
|
+
all positional.
|
|
193
|
+
@kwarg name_RESIDUAL_raiser: Optional C{B{name}=NN} (C{str}), the C{B{RESIDUAL}=0.0}
|
|
194
|
+
threshold (C{scalar}) and C{B{raiser}=True} (C{bool}) for raising
|
|
195
|
+
L{ResidualError}s, see class L{Fsum<Fsum.__init__>} and method
|
|
196
|
+
L{fpow<Fsum.fpow>}.
|
|
191
197
|
'''
|
|
192
198
|
try:
|
|
193
199
|
raiser = _Fsum__init__(self, **name_RESIDUAL_raiser)
|
|
@@ -521,17 +527,18 @@ def fidw(xs, ds, beta=2):
|
|
|
521
527
|
_F = Fsum
|
|
522
528
|
W = _F()
|
|
523
529
|
X = _F()
|
|
524
|
-
for i, d in enumerate(ds):
|
|
530
|
+
for i, d in enumerate(_xiterable(ds)):
|
|
525
531
|
x = xs[i]
|
|
526
|
-
|
|
527
|
-
|
|
532
|
+
D = _F(d)
|
|
533
|
+
if D < EPS0:
|
|
534
|
+
if D < 0:
|
|
528
535
|
raise ValueError(_negative_)
|
|
529
536
|
x = float(x)
|
|
530
537
|
i = n
|
|
531
538
|
break
|
|
532
|
-
D
|
|
533
|
-
|
|
534
|
-
|
|
539
|
+
if D.fpow(b):
|
|
540
|
+
W += D
|
|
541
|
+
X += D.fmul(x)
|
|
535
542
|
else:
|
|
536
543
|
x = X.fover(W, raiser=False)
|
|
537
544
|
i += 1 # len(xs) >= len(ds)
|
|
@@ -630,12 +637,12 @@ except ImportError:
|
|
|
630
637
|
def fprod(xs, start=1):
|
|
631
638
|
'''Iterable product, like C{math.prod} or C{numpy.prod}.
|
|
632
639
|
|
|
633
|
-
@arg xs:
|
|
634
|
-
|
|
635
|
-
@kwarg start: Initial
|
|
640
|
+
@arg xs: Iterable of values to be multiplied (each
|
|
641
|
+
C{scalar} or an L{Fsum}).
|
|
642
|
+
@kwarg start: Initial value, also the value returned
|
|
636
643
|
for an empty B{C{xs}} (C{scalar}).
|
|
637
644
|
|
|
638
|
-
@return: The product (C{float}).
|
|
645
|
+
@return: The product (C{float} or an L{Fsum}).
|
|
639
646
|
|
|
640
647
|
@see: U{NumPy.prod<https://docs.SciPy.org/doc/
|
|
641
648
|
numpy/reference/generated/numpy.prod.html>}.
|