pygeodesy 24.5.15__py2.py3-none-any.whl → 24.6.1__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.15.dist-info → PyGeodesy-24.6.1.dist-info}/METADATA +6 -5
- PyGeodesy-24.6.1.dist-info/RECORD +116 -0
- pygeodesy/__init__.py +4 -4
- pygeodesy/albers.py +41 -41
- pygeodesy/auxilats/__init__.py +1 -1
- pygeodesy/auxilats/__main__.py +2 -2
- pygeodesy/auxilats/auxAngle.py +32 -31
- pygeodesy/auxilats/auxLat.py +80 -51
- pygeodesy/azimuthal.py +123 -124
- pygeodesy/basics.py +46 -10
- pygeodesy/booleans.py +13 -14
- pygeodesy/cartesianBase.py +25 -23
- pygeodesy/clipy.py +3 -3
- pygeodesy/constants.py +3 -3
- pygeodesy/css.py +50 -42
- pygeodesy/datums.py +42 -41
- pygeodesy/deprecated/functions.py +9 -3
- pygeodesy/dms.py +6 -6
- pygeodesy/ecef.py +41 -41
- pygeodesy/ellipsoidalBase.py +41 -41
- pygeodesy/ellipsoidalBaseDI.py +3 -4
- pygeodesy/ellipsoidalGeodSolve.py +2 -2
- pygeodesy/ellipsoidalKarney.py +3 -3
- pygeodesy/ellipsoidalNvector.py +11 -12
- pygeodesy/ellipsoids.py +45 -38
- pygeodesy/elliptic.py +3 -4
- pygeodesy/epsg.py +4 -3
- pygeodesy/errors.py +52 -20
- pygeodesy/etm.py +68 -65
- pygeodesy/fmath.py +44 -49
- pygeodesy/formy.py +129 -115
- pygeodesy/frechet.py +118 -103
- pygeodesy/fstats.py +21 -14
- pygeodesy/fsums.py +124 -80
- pygeodesy/gars.py +10 -9
- pygeodesy/geodesicw.py +19 -17
- pygeodesy/geodesicx/__init__.py +1 -1
- pygeodesy/geodesicx/__main__.py +2 -2
- pygeodesy/geodesicx/gx.py +39 -33
- pygeodesy/geodesicx/gxarea.py +12 -9
- pygeodesy/geodesicx/gxbases.py +3 -4
- pygeodesy/geodesicx/gxline.py +6 -8
- pygeodesy/geodsolve.py +29 -28
- pygeodesy/geohash.py +60 -57
- pygeodesy/geoids.py +34 -32
- pygeodesy/hausdorff.py +114 -101
- pygeodesy/heights.py +137 -130
- pygeodesy/internals.py +16 -11
- pygeodesy/interns.py +3 -6
- pygeodesy/iters.py +19 -17
- pygeodesy/karney.py +21 -17
- pygeodesy/ktm.py +25 -18
- pygeodesy/latlonBase.py +12 -11
- pygeodesy/lazily.py +6 -6
- pygeodesy/lcc.py +24 -25
- pygeodesy/ltp.py +143 -113
- pygeodesy/ltpTuples.py +207 -150
- pygeodesy/mgrs.py +26 -26
- pygeodesy/named.py +172 -90
- pygeodesy/namedTuples.py +33 -25
- pygeodesy/nvectorBase.py +8 -8
- pygeodesy/osgr.py +40 -48
- pygeodesy/points.py +18 -18
- pygeodesy/props.py +29 -16
- pygeodesy/rhumb/__init__.py +1 -1
- pygeodesy/rhumb/aux_.py +13 -15
- pygeodesy/rhumb/bases.py +12 -5
- pygeodesy/rhumb/ekx.py +24 -18
- pygeodesy/rhumb/solve.py +13 -10
- pygeodesy/simplify.py +16 -16
- pygeodesy/solveBase.py +18 -18
- pygeodesy/sphericalBase.py +17 -21
- pygeodesy/sphericalTrigonometry.py +21 -21
- pygeodesy/streprs.py +5 -5
- pygeodesy/trf.py +13 -11
- pygeodesy/triaxials.py +68 -64
- pygeodesy/units.py +35 -35
- pygeodesy/unitsBase.py +24 -11
- pygeodesy/ups.py +66 -70
- pygeodesy/utily.py +3 -3
- pygeodesy/utm.py +183 -187
- pygeodesy/utmups.py +38 -38
- pygeodesy/utmupsBase.py +104 -106
- pygeodesy/vector2d.py +6 -7
- pygeodesy/vector3d.py +16 -17
- pygeodesy/vector3dBase.py +4 -5
- pygeodesy/webmercator.py +43 -51
- PyGeodesy-24.5.15.dist-info/RECORD +0 -116
- {PyGeodesy-24.5.15.dist-info → PyGeodesy-24.6.1.dist-info}/WHEEL +0 -0
- {PyGeodesy-24.5.15.dist-info → PyGeodesy-24.6.1.dist-info}/top_level.txt +0 -0
pygeodesy/epsg.py
CHANGED
|
@@ -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__ = '
|
|
31
|
+
__version__ = '24.05.18'
|
|
32
32
|
|
|
33
33
|
# _EPSG_INVALID = _UTMUPS_ZONE_INVALID
|
|
34
34
|
_EPSG_N_01 = 32601 # EPSG code for UTM zone 01 N
|
|
@@ -49,11 +49,12 @@ class Epsg(Int):
|
|
|
49
49
|
_utmups = None
|
|
50
50
|
_zone = _UTMUPS_ZONE_INVALID
|
|
51
51
|
|
|
52
|
-
def __new__(cls, eisu, name
|
|
52
|
+
def __new__(cls, eisu, **name):
|
|
53
53
|
'''New L{Epsg} (I{European Petroleum Survey Group}) code from a
|
|
54
54
|
UTM/USP coordinate or other EPSG code.
|
|
55
55
|
|
|
56
56
|
@arg eisu: Other code (L{Epsg}, C{int}, C{str}, L{Utm} or L{Ups}).
|
|
57
|
+
@kwarg name: Optional C{B{name}=NN} (C{str}).
|
|
57
58
|
|
|
58
59
|
@return: New L{Epsg}.
|
|
59
60
|
|
|
@@ -88,7 +89,7 @@ class Epsg(Int):
|
|
|
88
89
|
self.name = u.name
|
|
89
90
|
|
|
90
91
|
if name:
|
|
91
|
-
self.name
|
|
92
|
+
self.rename(name)
|
|
92
93
|
return self
|
|
93
94
|
|
|
94
95
|
def __repr__(self):
|
pygeodesy/errors.py
CHANGED
|
@@ -14,20 +14,23 @@ 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
|
-
|
|
17
|
+
from pygeodesy.internals import _plural, _tailof
|
|
18
18
|
from pygeodesy.interns import MISSING, NN, _a_, _an_, _and_, _clip_, _COLON_, _COLONSPACE_, \
|
|
19
19
|
_COMMASPACE_, _datum_, _ellipsoidal_, _incompatible_, _invalid_, \
|
|
20
|
-
_len_, _not_, _or_, _SPACE_, _specified_, _UNDER_,
|
|
21
|
-
|
|
20
|
+
_keyword_, _len_, _not_, _or_, _SPACE_, _specified_, _UNDER_, \
|
|
21
|
+
_vs_, _with_
|
|
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
|
|
24
25
|
|
|
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.29'
|
|
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
|
'''
|
|
@@ -234,7 +252,7 @@ class LenError(_ValueError): # in .ecef, .fmath, .heights, .iters, .named
|
|
|
234
252
|
class LimitError(_ValueError):
|
|
235
253
|
'''Error raised for lat- or longitudinal values or deltas exceeding
|
|
236
254
|
the given B{C{limit}} in functions L{pygeodesy.equirectangular},
|
|
237
|
-
L{pygeodesy.
|
|
255
|
+
L{pygeodesy.equirectangular4}, C{nearestOn*} and C{simplify*}
|
|
238
256
|
or methods with C{limit} or C{options} keyword arguments.
|
|
239
257
|
|
|
240
258
|
@see: Subclass L{UnitError}.
|
|
@@ -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
|
|
|
@@ -726,8 +748,8 @@ def _xkwds_get(kwds, **name_default):
|
|
|
726
748
|
C{default} if not present.
|
|
727
749
|
'''
|
|
728
750
|
if isinstance(kwds, dict) and len(name_default) == 1:
|
|
729
|
-
for n,
|
|
730
|
-
return kwds.get(n,
|
|
751
|
+
for n, v in name_default.items():
|
|
752
|
+
return kwds.get(n, v)
|
|
731
753
|
raise _xAssertionError(_xkwds_get, kwds, **name_default)
|
|
732
754
|
|
|
733
755
|
|
|
@@ -737,8 +759,18 @@ def _xkwds_get_(kwds, **names_defaults):
|
|
|
737
759
|
'''
|
|
738
760
|
if not isinstance(kwds, dict):
|
|
739
761
|
raise _xAssertionError(_xkwds_get_, kwds)
|
|
740
|
-
for n,
|
|
741
|
-
yield kwds.get(n,
|
|
762
|
+
for n, v in _MODS.basics.itemsorted(names_defaults):
|
|
763
|
+
yield kwds.get(n, v)
|
|
764
|
+
|
|
765
|
+
|
|
766
|
+
def _xkwds_get1(kwds, **name_default):
|
|
767
|
+
'''(INTERNAL) Get one C{kwds} value by C{name} or the
|
|
768
|
+
C{default} if not present.
|
|
769
|
+
'''
|
|
770
|
+
v, kwds = _xkwds_pop2(kwds, **name_default)
|
|
771
|
+
if kwds:
|
|
772
|
+
raise _UnexpectedError(**kwds)
|
|
773
|
+
return v
|
|
742
774
|
|
|
743
775
|
|
|
744
776
|
def _xkwds_item2(kwds):
|
|
@@ -762,11 +794,11 @@ def _xkwds_pop2(kwds, **name_default):
|
|
|
762
794
|
reduced C{kwds} copy, otherwise the C{default} and original C{kwds}.
|
|
763
795
|
'''
|
|
764
796
|
if isinstance(kwds, dict) and len(name_default) == 1:
|
|
765
|
-
for n,
|
|
797
|
+
for n, v in name_default.items():
|
|
766
798
|
if n in kwds:
|
|
767
799
|
kwds = _copy(kwds)
|
|
768
|
-
|
|
769
|
-
return
|
|
800
|
+
v = kwds.pop(n, v)
|
|
801
|
+
return v, kwds
|
|
770
802
|
raise _xAssertionError(_xkwds_pop2, kwds, **name_default)
|
|
771
803
|
|
|
772
804
|
|
|
@@ -777,7 +809,7 @@ def _Xorder(_Coeffs, Error, **Xorder): # in .auxLat, .ktm, .rhumb.bases, .rhumb
|
|
|
777
809
|
if m in _Coeffs and _MODS.basics.isint(m):
|
|
778
810
|
return m
|
|
779
811
|
t = sorted(map(str, _Coeffs.keys()))
|
|
780
|
-
raise Error(X, m,
|
|
812
|
+
raise Error(X, m, txt_not_=_or(*t))
|
|
781
813
|
|
|
782
814
|
# **) MIT License
|
|
783
815
|
#
|
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.05.
|
|
95
|
+
__version__ = '24.05.31'
|
|
96
96
|
|
|
97
97
|
_OVERFLOW = _1_EPS**2 # about 2e+31
|
|
98
98
|
_TAYTOL = pow(EPS, 0.6)
|
|
@@ -101,12 +101,6 @@ _TOL_10 = EPS * _0_1
|
|
|
101
101
|
_TRIPS = 21 # C++ 10
|
|
102
102
|
|
|
103
103
|
|
|
104
|
-
def _overflow(x):
|
|
105
|
-
'''(INTERNAL) Like C{copysign0(OVERFLOW, B{x})}.
|
|
106
|
-
'''
|
|
107
|
-
return _copyBit(_OVERFLOW, x)
|
|
108
|
-
|
|
109
|
-
|
|
110
104
|
class ETMError(UTMError):
|
|
111
105
|
'''Exact Transverse Mercator (ETM) parse, projection or other
|
|
112
106
|
L{Etm} issue or L{ExactTransverseMercator} conversion failure.
|
|
@@ -157,23 +151,21 @@ class Etm(Utm):
|
|
|
157
151
|
self._exactTM = exactTM
|
|
158
152
|
self._scale0 = exactTM.k0
|
|
159
153
|
|
|
160
|
-
def parse(self, strETM, name
|
|
154
|
+
def parse(self, strETM, **name):
|
|
161
155
|
'''Parse a string to a similar L{Etm} instance.
|
|
162
156
|
|
|
163
|
-
@arg strETM: The ETM coordinate (C{str}),
|
|
164
|
-
|
|
165
|
-
@kwarg name: Optional instance name (C{str}),
|
|
166
|
-
overriding this name.
|
|
157
|
+
@arg strETM: The ETM coordinate (C{str}), see function L{parseETM5}.
|
|
158
|
+
@kwarg name: Optional C{B{name}=NN} (C{str}), overriding this name.
|
|
167
159
|
|
|
168
160
|
@return: The instance (L{Etm}).
|
|
169
161
|
|
|
170
162
|
@raise ETMError: Invalid B{C{strETM}}.
|
|
171
163
|
|
|
172
|
-
@see: Function L{pygeodesy.parseUPS5}, L{pygeodesy.parseUTM5}
|
|
173
|
-
|
|
164
|
+
@see: Function L{pygeodesy.parseUPS5}, L{pygeodesy.parseUTM5} and
|
|
165
|
+
L{pygeodesy.parseUTMUPS5}.
|
|
174
166
|
'''
|
|
175
167
|
return parseETM5(strETM, datum=self.datum, Etm=self.classof,
|
|
176
|
-
name=
|
|
168
|
+
name=self._name__(name))
|
|
177
169
|
|
|
178
170
|
@deprecated_method
|
|
179
171
|
def parseETM(self, strETM): # PYCHOK no cover
|
|
@@ -217,9 +209,7 @@ class Etm(Utm):
|
|
|
217
209
|
lat, lon, g, k = xTM.reverse(e, n, lon0=lon0)
|
|
218
210
|
|
|
219
211
|
ll = _LLEB(lat, lon, datum=d, name=self.name) # utm._LLEB
|
|
220
|
-
ll
|
|
221
|
-
ll._scale = k
|
|
222
|
-
self._latlon5args(ll, _toBand, unfalse, xTM)
|
|
212
|
+
self._latlon5args(ll, g, k, _toBand, unfalse, xTM)
|
|
223
213
|
|
|
224
214
|
def toUtm(self): # PYCHOK signature
|
|
225
215
|
'''Copy this ETM to a UTM coordinate.
|
|
@@ -247,7 +237,7 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
247
237
|
_sigmaC = None # most recent _sigmaInv04 case C{int}
|
|
248
238
|
_zetaC = None # most recent _zetaInv04 case C{int}
|
|
249
239
|
|
|
250
|
-
def __init__(self, datum=_WGS84, lon0=0, k0=_K0_UTM, extendp=False,
|
|
240
|
+
def __init__(self, datum=_WGS84, lon0=0, k0=_K0_UTM, extendp=False, raiser=False, **name):
|
|
251
241
|
'''New L{ExactTransverseMercator} projection.
|
|
252
242
|
|
|
253
243
|
@kwarg datum: The I{non-spherical} datum or ellipsoid (L{Datum},
|
|
@@ -255,8 +245,8 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
255
245
|
@kwarg lon0: Central meridian, default (C{degrees180}).
|
|
256
246
|
@kwarg k0: Central scale factor (C{float}).
|
|
257
247
|
@kwarg extendp: Use the I{extended} domain (C{bool}), I{standard} otherwise.
|
|
258
|
-
@kwarg name: Optional name for the projection (C{str}).
|
|
259
248
|
@kwarg raiser: If C{True}, throw an L{ETMError} for convergence failures (C{bool}).
|
|
249
|
+
@kwarg name: Optional C{B{name}=NN} for the projection (C{str}).
|
|
260
250
|
|
|
261
251
|
@raise ETMError: Near-spherical B{C{datum}} or C{ellipsoid} or invalid B{C{lon0}}
|
|
262
252
|
or B{C{k0}}.
|
|
@@ -444,14 +434,14 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
444
434
|
|
|
445
435
|
f = flattening
|
|
446
436
|
|
|
447
|
-
def forward(self, lat, lon, lon0=None, name
|
|
437
|
+
def forward(self, lat, lon, lon0=None, **name): # MCCABE 13
|
|
448
438
|
'''Forward projection, from geographic to transverse Mercator.
|
|
449
439
|
|
|
450
440
|
@arg lat: Latitude of point (C{degrees}).
|
|
451
441
|
@arg lon: Longitude of point (C{degrees}).
|
|
452
442
|
@kwarg lon0: Central meridian (C{degrees180}), overriding
|
|
453
443
|
the default if not C{None}.
|
|
454
|
-
@kwarg name: Optional name (C{str}).
|
|
444
|
+
@kwarg name: Optional C{B{name}=NN} (C{str}).
|
|
455
445
|
|
|
456
446
|
@return: L{Forward4Tuple}C{(easting, northing, gamma, scale)}.
|
|
457
447
|
|
|
@@ -500,7 +490,7 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
500
490
|
if _lon:
|
|
501
491
|
x, g = neg_(x, g)
|
|
502
492
|
return Forward4Tuple(x, y, g, k, iteration=self._iteration,
|
|
503
|
-
name=
|
|
493
|
+
name=self._name__(name))
|
|
504
494
|
|
|
505
495
|
def _Inv03(self, psi, dlam, _3_mv_e): # (xi, deta, _3_mv)
|
|
506
496
|
'''(INTERNAL) Partial C{_zetaInv04} or C{_sigmaInv04}, Case 2
|
|
@@ -609,6 +599,7 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
609
599
|
_U_2 = Fsum(u).fsum2f_
|
|
610
600
|
_V_2 = Fsum(v).fsum2f_
|
|
611
601
|
# min iterations 2, max 6 or 7, mean 3.9 or 4.0
|
|
602
|
+
_hy2 = hypot2
|
|
612
603
|
for i in range(1, _TRIPS): # GEOGRAPHICLIB_PANIC
|
|
613
604
|
sncndn6 = self._sncndn6(u, v)
|
|
614
605
|
du, dv = _zetaDwd2(*sncndn6)
|
|
@@ -620,7 +611,7 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
620
611
|
if d2 < tol2:
|
|
621
612
|
r = False
|
|
622
613
|
break
|
|
623
|
-
d2 =
|
|
614
|
+
d2 = _hy2(dU, dV)
|
|
624
615
|
|
|
625
616
|
self._iteration = i
|
|
626
617
|
if r: # PYCHOK no cover
|
|
@@ -680,14 +671,14 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
680
671
|
self._mu = mu
|
|
681
672
|
self._mv = mv
|
|
682
673
|
|
|
683
|
-
def reverse(self, x, y, lon0=None, name
|
|
674
|
+
def reverse(self, x, y, lon0=None, **name):
|
|
684
675
|
'''Reverse projection, from Transverse Mercator to geographic.
|
|
685
676
|
|
|
686
677
|
@arg x: Easting of point (C{meters}).
|
|
687
678
|
@arg y: Northing of point (C{meters}).
|
|
688
|
-
@kwarg lon0:
|
|
689
|
-
the default
|
|
690
|
-
@kwarg name: Optional name (C{str}).
|
|
679
|
+
@kwarg lon0: Optional central meridian (C{degrees180}),
|
|
680
|
+
overriding the default (C{iff not None}).
|
|
681
|
+
@kwarg name: Optional C{B{name}=NN} (C{str}).
|
|
691
682
|
|
|
692
683
|
@return: L{Reverse4Tuple}C{(lat, lon, gamma, scale)}.
|
|
693
684
|
|
|
@@ -730,9 +721,9 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
730
721
|
lon, g = neg_(lon, g)
|
|
731
722
|
lat += self._lat0
|
|
732
723
|
lon += self._lon0 if lon0 is None else _norm180(lon0)
|
|
733
|
-
return Reverse4Tuple(lat, _norm180(lon), g, k, #
|
|
724
|
+
return Reverse4Tuple(lat, _norm180(lon), g, k, # _fix90(lat)
|
|
734
725
|
iteration=self._iteration,
|
|
735
|
-
name=
|
|
726
|
+
name=self._name__(name))
|
|
736
727
|
|
|
737
728
|
def _scaled2(self, tau, d2, snu, cnu, dnu, snv, cnv, dnv):
|
|
738
729
|
'''(INTERNAL) C{scaled}.
|
|
@@ -768,7 +759,7 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
768
759
|
# = sqrt(mv + mv * tau**2 + mu) * sqrt(q2)
|
|
769
760
|
k, q2 = _0_0, (mv * snv**2 + cnudnv**2)
|
|
770
761
|
if q2 > 0:
|
|
771
|
-
k2 =
|
|
762
|
+
k2 = (tau**2 + _1_0) * mv + mu
|
|
772
763
|
if k2 > 0:
|
|
773
764
|
k = sqrt(k2) * sqrt(q2 / d2) * self.k0
|
|
774
765
|
else:
|
|
@@ -811,13 +802,14 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
811
802
|
real /*v*/, real snv, real cnv, real dnv,
|
|
812
803
|
real &du, real &dv)}.
|
|
813
804
|
'''
|
|
805
|
+
mu = self._mu
|
|
814
806
|
snuv = snu * snv
|
|
815
807
|
# Reciprocal of 55.9: dw / ds = dn(w)^2/_mv,
|
|
816
808
|
# expanding complex dn(w) using A+S 16.21.4
|
|
817
|
-
d =
|
|
818
|
-
r =
|
|
819
|
-
i =
|
|
820
|
-
du = (r**2 - i**2) / d
|
|
809
|
+
d = (cnv**2 + snuv**2 * mu)**2 * self._mv
|
|
810
|
+
r = cnv * dnu * dnv
|
|
811
|
+
i = cnu * snuv * mu
|
|
812
|
+
du = (r**2 - i**2) / d # (r + i) * (r - i) / d
|
|
821
813
|
dv = neg(r * i * _2_0 / d)
|
|
822
814
|
return du, dv
|
|
823
815
|
|
|
@@ -1030,7 +1022,13 @@ class ExactTransverseMercator(_NamedBase):
|
|
|
1030
1022
|
return g_k # or (g, k, lat, lon)
|
|
1031
1023
|
|
|
1032
1024
|
|
|
1033
|
-
def
|
|
1025
|
+
def _overflow(x):
|
|
1026
|
+
'''(INTERNAL) Like C{copysign0(OVERFLOW, B{x})}.
|
|
1027
|
+
'''
|
|
1028
|
+
return _copyBit(_OVERFLOW, x)
|
|
1029
|
+
|
|
1030
|
+
|
|
1031
|
+
def parseETM5(strUTM, datum=_WGS84, Etm=Etm, falsed=True, **name):
|
|
1034
1032
|
'''Parse a string representing a UTM coordinate, consisting
|
|
1035
1033
|
of C{"zone[band] hemisphere easting northing"}.
|
|
1036
1034
|
|
|
@@ -1040,7 +1038,7 @@ def parseETM5(strUTM, datum=_WGS84, Etm=Etm, falsed=True, name=NN):
|
|
|
1040
1038
|
@kwarg Etm: Optional class to return the UTM coordinate
|
|
1041
1039
|
(L{Etm}) or C{None}.
|
|
1042
1040
|
@kwarg falsed: Both easting and northing are C{falsed} (C{bool}).
|
|
1043
|
-
@kwarg name: Optional B{C{Etm}} name (C{str}).
|
|
1041
|
+
@kwarg name: Optional B{C{Etm}} C{B{name}=NN} (C{str}).
|
|
1044
1042
|
|
|
1045
1043
|
@return: The UTM coordinate (B{C{Etm}}) or if B{C{Etm}} is
|
|
1046
1044
|
C{None}, a L{UtmUps5Tuple}C{(zone, hemipole, easting,
|
|
@@ -1051,29 +1049,30 @@ def parseETM5(strUTM, datum=_WGS84, Etm=Etm, falsed=True, name=NN):
|
|
|
1051
1049
|
|
|
1052
1050
|
@raise TypeError: Invalid or near-spherical B{C{datum}}.
|
|
1053
1051
|
'''
|
|
1054
|
-
r = _parseUTM5(strUTM, datum, Etm, falsed, Error=ETMError, name
|
|
1052
|
+
r = _parseUTM5(strUTM, datum, Etm, falsed, Error=ETMError, **name)
|
|
1055
1053
|
return r
|
|
1056
1054
|
|
|
1057
1055
|
|
|
1058
1056
|
def toEtm8(latlon, lon=None, datum=None, Etm=Etm, falsed=True,
|
|
1059
|
-
|
|
1060
|
-
zone=None, **cmoff):
|
|
1057
|
+
strict=True, zone=None, **name_cmoff):
|
|
1061
1058
|
'''Convert a geodetic lat-/longitude to an ETM coordinate.
|
|
1062
1059
|
|
|
1063
1060
|
@arg latlon: Latitude (C{degrees}) or an (ellipsoidal)
|
|
1064
1061
|
geodetic C{LatLon} instance.
|
|
1065
|
-
@kwarg lon: Optional longitude (C{degrees})
|
|
1062
|
+
@kwarg lon: Optional longitude (C{degrees}), required
|
|
1063
|
+
if B{C{latlon}} is in C{degrees}.
|
|
1066
1064
|
@kwarg datum: Optional datum for the ETM coordinate,
|
|
1067
1065
|
overriding B{C{latlon}}'s datum (L{Datum},
|
|
1068
1066
|
L{Ellipsoid}, L{Ellipsoid2} or L{a_f2Tuple}).
|
|
1069
1067
|
@kwarg Etm: Optional class to return the ETM coordinate
|
|
1070
1068
|
(L{Etm}) or C{None}.
|
|
1071
1069
|
@kwarg falsed: False both easting and northing (C{bool}).
|
|
1072
|
-
@kwarg name: Optional B{C{Utm}} name (C{str}).
|
|
1073
1070
|
@kwarg strict: Restrict B{C{lat}} to UTM ranges (C{bool}).
|
|
1074
1071
|
@kwarg zone: Optional UTM zone to enforce (C{int} or C{str}).
|
|
1075
|
-
@kwarg
|
|
1076
|
-
|
|
1072
|
+
@kwarg name_cmoff: Optional B{C{Etm}} C{B{name}=NN} (C{str})
|
|
1073
|
+
and DEPRECATED keyword argument C{B{cmoff}=True}
|
|
1074
|
+
to offset the longitude from the zone's central
|
|
1075
|
+
meridian (C{bool}), use B{C{falsed}} instead.
|
|
1077
1076
|
|
|
1078
1077
|
@return: The ETM coordinate as an B{C{Etm}} instance or a
|
|
1079
1078
|
L{UtmUps8Tuple}C{(zone, hemipole, easting, northing,
|
|
@@ -1097,24 +1096,25 @@ def toEtm8(latlon, lon=None, datum=None, Etm=Etm, falsed=True,
|
|
|
1097
1096
|
@raise ValueError: The B{C{lon}} value is missing or B{C{latlon}}
|
|
1098
1097
|
is invalid.
|
|
1099
1098
|
'''
|
|
1100
|
-
z, B, lat, lon, d, f,
|
|
1101
|
-
|
|
1102
|
-
|
|
1099
|
+
z, B, lat, lon, d, f, n = _to7zBlldfn(latlon, lon, datum,
|
|
1100
|
+
falsed, zone, strict,
|
|
1101
|
+
ETMError, **name_cmoff)
|
|
1103
1102
|
lon0 = _cmlon(z) if f else None
|
|
1104
1103
|
x, y, g, k = d.exactTM.forward(lat, lon, lon0=lon0)
|
|
1105
1104
|
|
|
1106
1105
|
return _toXtm8(Etm, z, lat, x, y, B, d, g, k, f,
|
|
1107
|
-
|
|
1106
|
+
n, latlon, d.exactTM, Error=ETMError)
|
|
1108
1107
|
|
|
1109
1108
|
|
|
1110
1109
|
if __name__ == '__main__': # MCCABE 13
|
|
1111
1110
|
|
|
1112
|
-
from pygeodesy.internals import _usage
|
|
1113
1111
|
from pygeodesy import fstr, KTransverseMercator, printf
|
|
1112
|
+
from pygeodesy.internals import _usage
|
|
1114
1113
|
from sys import argv, exit as _exit
|
|
1115
1114
|
|
|
1116
1115
|
# mimick some of I{Karney}'s utility C{TransverseMercatorProj}
|
|
1117
1116
|
_f = _r = _s = _t = False
|
|
1117
|
+
_p = -6
|
|
1118
1118
|
_as = argv[1:]
|
|
1119
1119
|
while _as and _as[0].startswith(_DASH_):
|
|
1120
1120
|
_a = _as.pop(0)
|
|
@@ -1124,16 +1124,19 @@ if __name__ == '__main__': # MCCABE 13
|
|
|
1124
1124
|
_f, _r = True, False
|
|
1125
1125
|
elif '-reverse'.startswith(_a):
|
|
1126
1126
|
_f, _r = False, True
|
|
1127
|
+
elif '-precision'.startswith(_a):
|
|
1128
|
+
_p = int(_as.pop(0))
|
|
1127
1129
|
elif '-series'.startswith(_a):
|
|
1128
1130
|
_s, _t = True, False
|
|
1129
1131
|
elif _a == '-t':
|
|
1130
1132
|
_s, _t = False, True
|
|
1131
1133
|
elif '-help'.startswith(_a):
|
|
1132
|
-
_exit(_usage(argv[0], '[-s | -t]',
|
|
1134
|
+
_exit(_usage(argv[0], '[-s | -t ]',
|
|
1135
|
+
'[-p[recision] <ndigits>',
|
|
1133
1136
|
'[-f[orward] <lat> <lon>',
|
|
1134
|
-
'
|
|
1135
|
-
'
|
|
1136
|
-
'
|
|
1137
|
+
'|-r[everse] <easting> <northing>',
|
|
1138
|
+
'|<lat> <lon>]',
|
|
1139
|
+
'|-h[elp]'))
|
|
1137
1140
|
else:
|
|
1138
1141
|
_exit('%s: option %r not supported' % (_usage(*argv), _a))
|
|
1139
1142
|
if len(_as) > 1:
|
|
@@ -1152,18 +1155,18 @@ if __name__ == '__main__': # MCCABE 13
|
|
|
1152
1155
|
t = tm.reverse(*f2)
|
|
1153
1156
|
else:
|
|
1154
1157
|
t = tm.forward(*f2)
|
|
1155
|
-
printf('%s: %s', tm.classname, fstr(t, sep=_SPACE_))
|
|
1158
|
+
printf('%s: %s', tm.classname, fstr(t, prec=_p, sep=_SPACE_))
|
|
1156
1159
|
t = tm.reverse(t.easting, t.northing)
|
|
1157
|
-
printf('%s: %s', tm.classname, fstr(t, sep=_SPACE_))
|
|
1160
|
+
printf('%s: %s', tm.classname, fstr(t, prec=_p, sep=_SPACE_))
|
|
1158
1161
|
|
|
1159
1162
|
|
|
1160
|
-
# % python3 -m pygeodesy.etm 33.33 44.44
|
|
1161
|
-
# ExactTransverseMercator: 4276926.
|
|
1162
|
-
# ExactTransverseMercator: 33.33 44.44 28.
|
|
1163
|
+
# % python3 -m pygeodesy.etm -p 12 33.33 44.44
|
|
1164
|
+
# ExactTransverseMercator: 4276926.11480390653 4727193.767015309073 28.375536563148 1.233325101778
|
|
1165
|
+
# ExactTransverseMercator: 33.33 44.44 28.375536563148 1.233325101778
|
|
1163
1166
|
|
|
1164
|
-
# % python3 -m pygeodesy.etm -s 33.33 44.44
|
|
1165
|
-
# KTransverseMercator: 4276926.
|
|
1166
|
-
# KTransverseMercator: 33.33 44.44 28.
|
|
1167
|
+
# % python3 -m pygeodesy.etm -s -p 12 33.33 44.44
|
|
1168
|
+
# KTransverseMercator: 4276926.114803904667 4727193.767015310004 28.375536563148 1.233325101778
|
|
1169
|
+
# KTransverseMercator: 33.33 44.44 28.375536563148 1.233325101778
|
|
1167
1170
|
|
|
1168
1171
|
# % echo 33.33 44.44 | .../bin/TransverseMercatorProj
|
|
1169
1172
|
# 4276926.114804 4727193.767015 28.375536563148 1.233325101778
|