pygeodesy 24.6.1__py2.py3-none-any.whl → 24.6.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.6.1.dist-info → PyGeodesy-24.6.24.dist-info}/METADATA +2 -2
- PyGeodesy-24.6.24.dist-info/RECORD +117 -0
- pygeodesy/__init__.py +33 -32
- pygeodesy/albers.py +2 -2
- pygeodesy/auxilats/__init__.py +1 -1
- pygeodesy/auxilats/auxAngle.py +40 -39
- pygeodesy/auxilats/auxDLat.py +3 -2
- pygeodesy/auxilats/auxLat.py +16 -18
- pygeodesy/auxilats/auxily.py +1 -1
- pygeodesy/azimuthal.py +10 -10
- pygeodesy/basics.py +9 -1
- pygeodesy/booleans.py +53 -66
- pygeodesy/cartesianBase.py +143 -155
- pygeodesy/css.py +14 -18
- pygeodesy/datums.py +6 -6
- pygeodesy/deprecated/__init__.py +1 -1
- pygeodesy/deprecated/classes.py +16 -2
- pygeodesy/deprecated/datum.py +3 -3
- pygeodesy/deprecated/functions.py +6 -8
- pygeodesy/dms.py +23 -27
- pygeodesy/ecef.py +49 -55
- pygeodesy/elevations.py +4 -4
- pygeodesy/ellipsoidalBase.py +28 -70
- pygeodesy/ellipsoidalBaseDI.py +19 -23
- pygeodesy/ellipsoidalExact.py +3 -3
- pygeodesy/ellipsoidalGeodSolve.py +15 -23
- pygeodesy/ellipsoidalKarney.py +37 -60
- pygeodesy/ellipsoidalNvector.py +44 -50
- pygeodesy/ellipsoidalVincenty.py +11 -14
- pygeodesy/ellipsoids.py +107 -101
- pygeodesy/errors.py +101 -49
- pygeodesy/etm.py +32 -44
- pygeodesy/formy.py +55 -58
- pygeodesy/frechet.py +20 -23
- pygeodesy/fsums.py +4 -4
- pygeodesy/gars.py +3 -4
- pygeodesy/geodesici.py +909 -0
- pygeodesy/geodesicw.py +11 -13
- pygeodesy/geodesicx/__init__.py +4 -4
- pygeodesy/geodesicx/gx.py +18 -28
- pygeodesy/geodesicx/gxbases.py +20 -8
- pygeodesy/geodesicx/gxline.py +16 -22
- pygeodesy/geodsolve.py +102 -34
- pygeodesy/geohash.py +39 -60
- pygeodesy/geoids.py +28 -37
- pygeodesy/hausdorff.py +21 -23
- pygeodesy/heights.py +15 -28
- pygeodesy/internals.py +19 -12
- pygeodesy/interns.py +4 -10
- pygeodesy/iters.py +2 -2
- pygeodesy/karney.py +20 -4
- pygeodesy/ktm.py +13 -16
- pygeodesy/latlonBase.py +202 -191
- pygeodesy/lazily.py +96 -59
- pygeodesy/lcc.py +29 -32
- pygeodesy/ltp.py +43 -24
- pygeodesy/ltpTuples.py +190 -183
- pygeodesy/mgrs.py +35 -9
- pygeodesy/named.py +106 -72
- pygeodesy/namedTuples.py +43 -14
- pygeodesy/nvectorBase.py +23 -27
- pygeodesy/osgr.py +9 -9
- pygeodesy/points.py +7 -7
- pygeodesy/rhumb/__init__.py +1 -1
- pygeodesy/rhumb/aux_.py +5 -5
- pygeodesy/rhumb/bases.py +30 -31
- pygeodesy/rhumb/ekx.py +3 -4
- pygeodesy/rhumb/solve.py +8 -61
- pygeodesy/solveBase.py +22 -19
- pygeodesy/sphericalBase.py +26 -21
- pygeodesy/sphericalNvector.py +13 -13
- pygeodesy/sphericalTrigonometry.py +86 -97
- pygeodesy/streprs.py +8 -36
- pygeodesy/trf.py +3 -3
- pygeodesy/triaxials.py +117 -91
- pygeodesy/units.py +229 -321
- pygeodesy/unitsBase.py +116 -108
- pygeodesy/ups.py +26 -31
- pygeodesy/utily.py +12 -11
- pygeodesy/utm.py +35 -40
- pygeodesy/utmups.py +43 -46
- pygeodesy/utmupsBase.py +9 -10
- pygeodesy/vector3d.py +59 -62
- pygeodesy/vector3dBase.py +17 -15
- pygeodesy/webmercator.py +19 -21
- pygeodesy/wgrs.py +18 -20
- PyGeodesy-24.6.1.dist-info/RECORD +0 -116
- {PyGeodesy-24.6.1.dist-info → PyGeodesy-24.6.24.dist-info}/WHEEL +0 -0
- {PyGeodesy-24.6.1.dist-info → PyGeodesy-24.6.24.dist-info}/top_level.txt +0 -0
pygeodesy/mgrs.py
CHANGED
|
@@ -55,7 +55,7 @@ from pygeodesy.utm import toUtm8, _to3zBlat, Utm, _UTM_ZONE_MAX, _UTM_ZONE_MIN
|
|
|
55
55
|
# from pygeodesy.utmupsBase import _UTM_ZONE_MAX, _UTM_ZONE_MIN # from .utm
|
|
56
56
|
|
|
57
57
|
__all__ = _ALL_LAZY.mgrs
|
|
58
|
-
__version__ = '24.
|
|
58
|
+
__version__ = '24.06.11'
|
|
59
59
|
|
|
60
60
|
_AN_ = 'AN' # default south pole grid tile and band B
|
|
61
61
|
_AtoPx_ = _AtoZnoIO_.tillP
|
|
@@ -596,18 +596,17 @@ def toMgrs(utmups, Mgrs=Mgrs, **name_Mgrs_kwds):
|
|
|
596
596
|
@arg utmups: A UTM or UPS coordinate (L{Utm}, L{Etm} or L{Ups}).
|
|
597
597
|
@kwarg Mgrs: Optional class to return the MGRS grid reference
|
|
598
598
|
(L{Mgrs}) or C{None}.
|
|
599
|
-
@kwarg name_Mgrs_kwds: Optional C{B{name}=NN} (C{str}) and
|
|
600
|
-
|
|
601
|
-
|
|
599
|
+
@kwarg name_Mgrs_kwds: Optional C{B{name}=NN} (C{str}) and optional,
|
|
600
|
+
additional B{C{Mgrs}} keyword arguments, ignored if
|
|
601
|
+
C{B{Mgrs} is None}.
|
|
602
602
|
|
|
603
|
-
@return: The MGRS grid reference as B{C{Mgrs}} or if C{B{Mgrs}
|
|
604
|
-
|
|
605
|
-
|
|
603
|
+
@return: The MGRS grid reference as B{C{Mgrs}} or if C{B{Mgrs} is
|
|
604
|
+
None} as an L{Mgrs6Tuple}C{(zone, EN, easting, northing,
|
|
605
|
+
band, datum)}.
|
|
606
606
|
|
|
607
607
|
@raise MGRSError: Invalid B{C{utmups}}.
|
|
608
608
|
|
|
609
|
-
@raise TypeError: If B{C{utmups}} is not L{Utm} nor L{
|
|
610
|
-
nor L{Ups}.
|
|
609
|
+
@raise TypeError: If B{C{utmups}} is not L{Utm}, L{Etm} nor L{Ups}.
|
|
611
610
|
'''
|
|
612
611
|
# _MODS.utmups.utmupsValidate(utmups, MGRS=True, Error-MGRSError)
|
|
613
612
|
_xinstanceof(Utm, Ups, utmups=utmups) # Utm, Etm, Ups
|
|
@@ -699,6 +698,33 @@ if __name__ == '__main__':
|
|
|
699
698
|
p = e * 100.0 / n
|
|
700
699
|
printf('%6s: %s errors (%.2f%%)', n, (e if e else 'no'), p)
|
|
701
700
|
|
|
701
|
+
# % python3 -m pygeodesy.mgrs
|
|
702
|
+
# using: /opt/local/bin/GeoConvert -m ...
|
|
703
|
+
# 0: lat -90 ... OK
|
|
704
|
+
# 361: lat -89 ... OK
|
|
705
|
+
# 722: lat -88 ... OK
|
|
706
|
+
# 1083: lat -87 ... OK
|
|
707
|
+
# 1444: lat -86 ... OK
|
|
708
|
+
# 1805: lat -85 ... OK
|
|
709
|
+
# 2166: lat -84 ... OK
|
|
710
|
+
# 2527: lat -83 ... OK
|
|
711
|
+
# 2888: lat -82 ... OK
|
|
712
|
+
# 3249: lat -81 ... OK
|
|
713
|
+
# 3610: lat -80 ... OK
|
|
714
|
+
# ...
|
|
715
|
+
# 61370: lat 80 ... OK
|
|
716
|
+
# 61731: lat 81 ... OK
|
|
717
|
+
# 62092: lat 82 ... OK
|
|
718
|
+
# 62453: lat 83 ... OK
|
|
719
|
+
# 62814: lat 84 ... OK
|
|
720
|
+
# 63175: lat 85 ... OK
|
|
721
|
+
# 63536: lat 86 ... OK
|
|
722
|
+
# 63897: lat 87 ... OK
|
|
723
|
+
# 64258: lat 88 ... OK
|
|
724
|
+
# 64619: lat 89 ... OK
|
|
725
|
+
# 64980: lat 90 ... OK
|
|
726
|
+
# 65341: no errors (0.00%)
|
|
727
|
+
|
|
702
728
|
# **) MIT License
|
|
703
729
|
#
|
|
704
730
|
# Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
|
pygeodesy/named.py
CHANGED
|
@@ -13,27 +13,28 @@ standard Python C{namedtuple}s.
|
|
|
13
13
|
@see: Module L{pygeodesy.namedTuples} for (most of) the C{Named-Tuples}.
|
|
14
14
|
'''
|
|
15
15
|
|
|
16
|
-
from pygeodesy.basics import
|
|
17
|
-
|
|
16
|
+
from pygeodesy.basics import isidentifier, iskeyword, isstr, itemsorted, len2, \
|
|
17
|
+
_xcopy, _xdup, _xinstanceof, _xsubclassof, _zip
|
|
18
18
|
from pygeodesy.errors import _AssertionError, _AttributeError, _incompatible, \
|
|
19
|
-
_IndexError,
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
_xkwds_item2, _xkwds_pop2
|
|
19
|
+
_IndexError, _KeyError, LenError, _NameError, \
|
|
20
|
+
_NotImplementedError, _TypeError, _TypesError, \
|
|
21
|
+
_UnexpectedError, UnitError, _ValueError, \
|
|
22
|
+
_xattr, _xkwds, _xkwds_item2, _xkwds_pop2
|
|
23
23
|
from pygeodesy.internals import _caller3, _dunder_nameof, _isPyPy, _sizeof, _under
|
|
24
24
|
from pygeodesy.interns import MISSING, NN, _AT_, _COLON_, _COLONSPACE_, _COMMA_, \
|
|
25
25
|
_COMMASPACE_, _doesn_t_exist_, _DOT_, _DUNDER_, \
|
|
26
26
|
_dunder_name_, _EQUAL_, _exists_, _immutable_, _name_, \
|
|
27
27
|
_NL_, _NN_, _no_, _other_, _s_, _SPACE_, _std_, \
|
|
28
|
-
_UNDER_,
|
|
28
|
+
_UNDER_, _vs_
|
|
29
29
|
from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS, _getenv
|
|
30
30
|
from pygeodesy.props import _allPropertiesOf_n, deprecated_method, _hasProperty, \
|
|
31
31
|
_update_all, property_doc_, Property_RO, property_RO, \
|
|
32
32
|
_update_attrs
|
|
33
33
|
from pygeodesy.streprs import attrs, Fmt, lrstrip, pairs, reprs, unstr
|
|
34
|
+
# from pygeodesy.units import _toUnit # _MODS
|
|
34
35
|
|
|
35
36
|
__all__ = _ALL_LAZY.named
|
|
36
|
-
__version__ = '24.
|
|
37
|
+
__version__ = '24.06.24'
|
|
37
38
|
|
|
38
39
|
_COMMANL_ = _COMMA_ + _NL_
|
|
39
40
|
_COMMASPACEDOT_ = _COMMASPACE_ + _DOT_
|
|
@@ -71,6 +72,15 @@ class ADict(dict):
|
|
|
71
72
|
'''
|
|
72
73
|
return self.toRepr()
|
|
73
74
|
|
|
75
|
+
def __setattr__(self, name, value):
|
|
76
|
+
'''Set the value of a I{known} item by B{C{name}}.
|
|
77
|
+
'''
|
|
78
|
+
try:
|
|
79
|
+
if self[name] != value:
|
|
80
|
+
self[name] = value
|
|
81
|
+
except KeyError:
|
|
82
|
+
dict.__setattr__(self, name, value)
|
|
83
|
+
|
|
74
84
|
def __str__(self):
|
|
75
85
|
'''Default C{str(self)}.
|
|
76
86
|
'''
|
|
@@ -240,13 +250,14 @@ class _Named(object):
|
|
|
240
250
|
# _update_all(d)
|
|
241
251
|
return d
|
|
242
252
|
|
|
243
|
-
def _instr(self,
|
|
244
|
-
'''(INTERNAL) Format, used by C{Conic}, C{Ellipsoid}, C{Transform}, C{Triaxial}.
|
|
253
|
+
def _instr(self, *attrs, **fmt_prec_props_sep_name__kwds):
|
|
254
|
+
'''(INTERNAL) Format, used by C{Conic}, C{Ellipsoid}, C{Geodesic...}, C{Transform}, C{Triaxial}.
|
|
245
255
|
'''
|
|
246
|
-
def
|
|
247
|
-
return fmt, props, kwds
|
|
256
|
+
def _fmt_prec_props_kwds(fmt=Fmt.F, prec=6, props=(), sep=_COMMASPACE_, **kwds):
|
|
257
|
+
return fmt, prec, props, sep, kwds
|
|
248
258
|
|
|
249
|
-
|
|
259
|
+
name, kwds = _name2__(**fmt_prec_props_sep_name__kwds)
|
|
260
|
+
fmt, prec, props, sep, kwds = _fmt_prec_props_kwds(**kwds)
|
|
250
261
|
|
|
251
262
|
t = () if name is None else (Fmt.EQUAL(name=repr(name or self.name)),)
|
|
252
263
|
if attrs:
|
|
@@ -257,7 +268,7 @@ class _Named(object):
|
|
|
257
268
|
prec=prec, ints=True)
|
|
258
269
|
if kwds:
|
|
259
270
|
t += pairs(kwds, prec=prec)
|
|
260
|
-
return
|
|
271
|
+
return sep.join(t) if sep else t
|
|
261
272
|
|
|
262
273
|
@property_RO
|
|
263
274
|
def iteration(self): # see .karney.GDict
|
|
@@ -309,6 +320,11 @@ class _Named(object):
|
|
|
309
320
|
'''
|
|
310
321
|
return _name__(name, _or_nameof=self) # nameof(self)
|
|
311
322
|
|
|
323
|
+
def _name1__(self, kwds):
|
|
324
|
+
'''(INTERNAL) Resolve and set the C{B{name}=NN}.
|
|
325
|
+
'''
|
|
326
|
+
return _name1__(kwds, _or_nameof=self.name) if self.name else kwds
|
|
327
|
+
|
|
312
328
|
@Property_RO
|
|
313
329
|
def named(self):
|
|
314
330
|
'''Get the name I{or} class name or C{""} (C{str}).
|
|
@@ -422,11 +438,8 @@ class _Named(object):
|
|
|
422
438
|
|
|
423
439
|
@raise TypeError: Not C{isinstance(B{inst}, _Named)}.
|
|
424
440
|
'''
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
_ = inst.rename(self.name)
|
|
429
|
-
return inst
|
|
441
|
+
_xinstanceof(_Named, inst=inst) # assert
|
|
442
|
+
return inst.renamed(self.name)
|
|
430
443
|
|
|
431
444
|
_Named_Property_ROs = _allPropertiesOf_n(5, _Named, Property_RO) # PYCHOK once
|
|
432
445
|
|
|
@@ -716,12 +729,14 @@ class _NamedEnum(_NamedDict):
|
|
|
716
729
|
if not (n and isstr(n) and isidentifier(n)):
|
|
717
730
|
raise ValueError()
|
|
718
731
|
except (AttributeError, ValueError, TypeError) as x:
|
|
719
|
-
|
|
732
|
+
n = _DOT_(_item_, _name_)
|
|
733
|
+
raise _NameError(n, item, cause=x)
|
|
720
734
|
if n in self:
|
|
721
735
|
t = _SPACE_(_item_, self._DOT_(n), _exists_)
|
|
722
736
|
raise _NameError(t, txt=repr(item))
|
|
723
|
-
if not isinstance(item, self._item_Classes):
|
|
724
|
-
|
|
737
|
+
if not isinstance(item, self._item_Classes): # _xinstanceof
|
|
738
|
+
n = self._DOT_(n)
|
|
739
|
+
raise _TypesError(n, item, *self._item_Classes)
|
|
725
740
|
self[n] = item
|
|
726
741
|
return n
|
|
727
742
|
|
|
@@ -843,7 +858,7 @@ class _NamedEnumItem(_NamedBase):
|
|
|
843
858
|
'''
|
|
844
859
|
name = _name__(name) or _NN_
|
|
845
860
|
if self._enum:
|
|
846
|
-
raise _NameError(name, self, txt=_registered_) #
|
|
861
|
+
raise _NameError(name, self, txt=_registered_) # _TypeError
|
|
847
862
|
if name:
|
|
848
863
|
self._name = name
|
|
849
864
|
|
|
@@ -870,8 +885,8 @@ class _NamedEnumItem(_NamedBase):
|
|
|
870
885
|
enum = self._enum
|
|
871
886
|
if enum and self.name and self.name in enum:
|
|
872
887
|
item = enum.unregister(self.name)
|
|
873
|
-
if item is not self:
|
|
874
|
-
t = _SPACE_(repr(item), _vs_, repr(self))
|
|
888
|
+
if item is not self: # PYCHOK no cover
|
|
889
|
+
t = _SPACE_(repr(item), _vs_, repr(self))
|
|
875
890
|
raise _AssertionError(t)
|
|
876
891
|
|
|
877
892
|
|
|
@@ -923,7 +938,11 @@ class _NamedTuple(tuple, _Named):
|
|
|
923
938
|
raise LenError(self.__class__, args=n, _Names_=N)
|
|
924
939
|
|
|
925
940
|
if iteration_name:
|
|
926
|
-
|
|
941
|
+
i, name = _xkwds_pop2(iteration_name, iteration=None)
|
|
942
|
+
if i is not None:
|
|
943
|
+
self._iteration = i
|
|
944
|
+
if name:
|
|
945
|
+
self.name = name
|
|
927
946
|
return self
|
|
928
947
|
|
|
929
948
|
def __delattr__(self, name):
|
|
@@ -932,7 +951,8 @@ class _NamedTuple(tuple, _Named):
|
|
|
932
951
|
@note: Items can not be deleted.
|
|
933
952
|
'''
|
|
934
953
|
if name in self._Names_:
|
|
935
|
-
|
|
954
|
+
t = _SPACE_(_del_, self._DOT_(name))
|
|
955
|
+
raise _TypeError(t, txt=_immutable_)
|
|
936
956
|
elif name in (_name_, _name):
|
|
937
957
|
_Named.__setattr__(self, name, NN) # XXX _Named.name.fset(self, NN)
|
|
938
958
|
else:
|
|
@@ -943,10 +963,10 @@ class _NamedTuple(tuple, _Named):
|
|
|
943
963
|
'''
|
|
944
964
|
try:
|
|
945
965
|
return tuple.__getitem__(self, self._Names_.index(name))
|
|
946
|
-
except IndexError:
|
|
947
|
-
raise _IndexError(
|
|
966
|
+
except IndexError as x:
|
|
967
|
+
raise _IndexError(self._DOT_(name), cause=x)
|
|
948
968
|
except ValueError: # e.g. _iteration
|
|
949
|
-
return tuple.
|
|
969
|
+
return tuple.__getattr__(self, name) # __getattribute__
|
|
950
970
|
|
|
951
971
|
# def __getitem__(self, index): # index, slice, etc.
|
|
952
972
|
# '''Get the item(s) at an B{C{index}} or slice.
|
|
@@ -965,7 +985,8 @@ class _NamedTuple(tuple, _Named):
|
|
|
965
985
|
'''Set attribute or item B{C{name}} to B{C{value}}.
|
|
966
986
|
'''
|
|
967
987
|
if name in self._Names_:
|
|
968
|
-
|
|
988
|
+
t = Fmt.EQUALSPACED(self._DOT_(name), repr(value))
|
|
989
|
+
raise _TypeError(t, txt=_immutable_)
|
|
969
990
|
elif name in (_name_, _name):
|
|
970
991
|
_Named.__setattr__(self, name, value) # XXX _Named.name.fset(self, value)
|
|
971
992
|
else: # e.g. _iteration
|
|
@@ -976,6 +997,11 @@ class _NamedTuple(tuple, _Named):
|
|
|
976
997
|
'''
|
|
977
998
|
return self.toStr()
|
|
978
999
|
|
|
1000
|
+
def _DOT_(self, *names):
|
|
1001
|
+
'''(INTERNAL) Period-join C{self.classname} and C{names}.
|
|
1002
|
+
'''
|
|
1003
|
+
return _DOT_(self.classname, *names)
|
|
1004
|
+
|
|
979
1005
|
def dup(self, name=NN, **items):
|
|
980
1006
|
'''Duplicate this tuple replacing one or more items.
|
|
981
1007
|
|
|
@@ -986,15 +1012,18 @@ class _NamedTuple(tuple, _Named):
|
|
|
986
1012
|
|
|
987
1013
|
@raise NameError: Some B{C{items}} invalid.
|
|
988
1014
|
'''
|
|
989
|
-
|
|
1015
|
+
t = list(self)
|
|
1016
|
+
U = self._Units_
|
|
990
1017
|
if items:
|
|
991
|
-
_ix =
|
|
1018
|
+
_ix = self._Names_.index
|
|
1019
|
+
_2U = _MODS.units._toUnit
|
|
992
1020
|
try:
|
|
993
1021
|
for n, v in items.items():
|
|
994
|
-
|
|
1022
|
+
i = _ix(n)
|
|
1023
|
+
t[i] = _2U(U[i], v, name=n)
|
|
995
1024
|
except ValueError: # bad item name
|
|
996
|
-
raise _NameError(_DOT_(
|
|
997
|
-
return self.classof(*
|
|
1025
|
+
raise _NameError(self._DOT_(n), v, this=self)
|
|
1026
|
+
return self.classof(*t).reUnit(*U, name=name)
|
|
998
1027
|
|
|
999
1028
|
def items(self):
|
|
1000
1029
|
'''Yield the items, each as a C{(name, value)} pair (C{2-tuple}).
|
|
@@ -1006,13 +1035,23 @@ class _NamedTuple(tuple, _Named):
|
|
|
1006
1035
|
|
|
1007
1036
|
iteritems = items
|
|
1008
1037
|
|
|
1009
|
-
def
|
|
1010
|
-
'''
|
|
1038
|
+
def reUnit(self, *Units, **name):
|
|
1039
|
+
'''Replace some of this C{Named-Tuple}'s C{Units}.
|
|
1040
|
+
|
|
1041
|
+
@arg Units: One or more C{Unit} classes, all positional.
|
|
1042
|
+
@kwarg name: Optional C{B{name}=NN} (C{str}).
|
|
1043
|
+
|
|
1044
|
+
@return: This instance with updated C{Units}.
|
|
1045
|
+
|
|
1046
|
+
@note: This C{Named-Tuple}'s values are I{not updated}.
|
|
1011
1047
|
'''
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
if
|
|
1015
|
-
|
|
1048
|
+
U = self._Units_
|
|
1049
|
+
n = min(len(U), len(Units))
|
|
1050
|
+
if n:
|
|
1051
|
+
R = Units + U[n:]
|
|
1052
|
+
if R != U:
|
|
1053
|
+
self._Units_ = R
|
|
1054
|
+
return self.renamed(name) if name else self
|
|
1016
1055
|
|
|
1017
1056
|
def toRepr(self, prec=6, sep=_COMMASPACE_, fmt=Fmt.F, **unused): # PYCHOK signature
|
|
1018
1057
|
'''Return this C{Named-Tuple} items as C{name=value} string(s).
|
|
@@ -1043,37 +1082,33 @@ class _NamedTuple(tuple, _Named):
|
|
|
1043
1082
|
'''
|
|
1044
1083
|
return Fmt.PAREN(sep.join(reprs(self, prec=prec, fmt=fmt)))
|
|
1045
1084
|
|
|
1046
|
-
def toUnits(self, Error=UnitError): # overloaded in .frechet, .hausdorff
|
|
1085
|
+
def toUnits(self, Error=UnitError, **name): # overloaded in .frechet, .hausdorff
|
|
1047
1086
|
'''Return a copy of this C{Named-Tuple} with each item value wrapped
|
|
1048
1087
|
as an instance of its L{units} class.
|
|
1049
1088
|
|
|
1050
1089
|
@kwarg Error: Error to raise for L{units} issues (C{UnitError}).
|
|
1090
|
+
@kwarg name: Optional C{B{name}=NN} (C{str}).
|
|
1051
1091
|
|
|
1052
1092
|
@return: A duplicate of this C{Named-Tuple} (C{C{Named-Tuple}}).
|
|
1053
1093
|
|
|
1054
1094
|
@raise Error: Invalid C{Named-Tuple} item or L{units} class.
|
|
1055
1095
|
'''
|
|
1056
|
-
t = (v for _, v in self.units(Error=Error))
|
|
1057
|
-
return self.classof(*
|
|
1096
|
+
t = tuple(v for _, v in self.units(Error=Error))
|
|
1097
|
+
return self.classof(*t).reUnit(*self._Units_, **name)
|
|
1058
1098
|
|
|
1059
|
-
def units(self, Error
|
|
1060
|
-
'''Yield the items, each as a C{(name, value})
|
|
1061
|
-
|
|
1099
|
+
def units(self, **Error):
|
|
1100
|
+
'''Yield the items, each as a C{2-tuple (name, value}) with the
|
|
1101
|
+
value wrapped as an instance of its L{units} class.
|
|
1062
1102
|
|
|
1063
|
-
@kwarg Error: Error to raise
|
|
1103
|
+
@kwarg Error: Optional C{B{Error}=UnitError} to raise.
|
|
1064
1104
|
|
|
1065
1105
|
@raise Error: Invalid C{Named-Tuple} item or L{units} class.
|
|
1066
1106
|
|
|
1067
1107
|
@see: Method C{.items}.
|
|
1068
1108
|
'''
|
|
1109
|
+
_2U = _MODS.units._toUnit
|
|
1069
1110
|
for n, v, U in _zip(self._Names_, self, self._Units_): # strict=True
|
|
1070
|
-
|
|
1071
|
-
or (isclass(U) and
|
|
1072
|
-
isinstance(v, U) and
|
|
1073
|
-
hasattr(v, _name_) and
|
|
1074
|
-
v.name == n)): # PYCHOK indent
|
|
1075
|
-
v = U(v, name=n, Error=Error)
|
|
1076
|
-
yield n, v
|
|
1111
|
+
yield n, _2U(U, v, name=n, **Error)
|
|
1077
1112
|
|
|
1078
1113
|
iterunits = units
|
|
1079
1114
|
|
|
@@ -1083,35 +1118,35 @@ class _NamedTuple(tuple, _Named):
|
|
|
1083
1118
|
'''
|
|
1084
1119
|
ns = self._Names_
|
|
1085
1120
|
if not (isinstance(ns, tuple) and len(ns) > 1): # XXX > 0
|
|
1086
|
-
raise _TypeError(_DOT_(
|
|
1121
|
+
raise _TypeError(self._DOT_(_Names_), ns)
|
|
1087
1122
|
for i, n in enumerate(ns):
|
|
1088
1123
|
if not _xvalid(n, underOK=underOK):
|
|
1089
1124
|
t = Fmt.SQUARE(_Names_=i) # PYCHOK no cover
|
|
1090
|
-
raise _ValueError(_DOT_(
|
|
1125
|
+
raise _ValueError(self._DOT_(t), n)
|
|
1091
1126
|
|
|
1092
1127
|
us = self._Units_
|
|
1093
1128
|
if not isinstance(us, tuple):
|
|
1094
|
-
raise _TypeError(_DOT_(
|
|
1129
|
+
raise _TypeError(self._DOT_(_Units_), us)
|
|
1095
1130
|
if len(us) != len(ns):
|
|
1096
1131
|
raise LenError(self.__class__, _Units_=len(us), _Names_=len(ns))
|
|
1097
1132
|
for i, u in enumerate(us):
|
|
1098
1133
|
if not (u is None or callable(u)):
|
|
1099
1134
|
t = Fmt.SQUARE(_Units_=i) # PYCHOK no cover
|
|
1100
|
-
raise _TypeError(_DOT_(
|
|
1135
|
+
raise _TypeError(self._DOT_(t), u)
|
|
1101
1136
|
|
|
1102
1137
|
self.__class__._validated = True
|
|
1103
1138
|
|
|
1104
1139
|
def _xtend(self, xTuple, *items, **name):
|
|
1105
1140
|
'''(INTERNAL) Extend this C{Named-Tuple} with C{items} to an other B{C{xTuple}}.
|
|
1106
1141
|
'''
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1142
|
+
_xsubclassof(_NamedTuple, xTuple=xTuple)
|
|
1143
|
+
if len(xTuple._Names_) != (len(self._Names_) + len(items)) or \
|
|
1144
|
+
xTuple._Names_[:len(self)] != self._Names_: # PYCHOK no cover
|
|
1145
|
+
c = NN(self.classname, repr(self._Names_))
|
|
1146
|
+
x = NN(xTuple.__name__, repr(xTuple._Names_))
|
|
1147
|
+
raise TypeError(_SPACE_(c, _vs_, x))
|
|
1148
|
+
t = self + items
|
|
1149
|
+
return xTuple(t, name=self._name__(name)) # .reUnit(*self._Units_)
|
|
1115
1150
|
|
|
1116
1151
|
|
|
1117
1152
|
def callername(up=1, dflt=NN, source=False, underOK=False):
|
|
@@ -1231,8 +1266,7 @@ def _name__(name=NN, **kwds):
|
|
|
1231
1266
|
if name or kwds:
|
|
1232
1267
|
name, kwds = _name2__(name, **kwds)
|
|
1233
1268
|
if kwds: # "unexpected keyword arguments ..."
|
|
1234
|
-
|
|
1235
|
-
raise m._UnexpectedError(**kwds)
|
|
1269
|
+
raise _UnexpectedError(**kwds)
|
|
1236
1270
|
return name if name or name is None else NN
|
|
1237
1271
|
|
|
1238
1272
|
|
|
@@ -1255,11 +1289,11 @@ def _name2__(name=NN, name__=None, _or_nameof=None, **kwds):
|
|
|
1255
1289
|
else:
|
|
1256
1290
|
n = str(name)
|
|
1257
1291
|
elif name__ is not None:
|
|
1258
|
-
n =
|
|
1292
|
+
n = _dunder_nameof(name__, NN)
|
|
1259
1293
|
else:
|
|
1260
1294
|
n = name if name is None else NN
|
|
1261
1295
|
if _or_nameof is not None and not n:
|
|
1262
|
-
n =
|
|
1296
|
+
n = _xattr(_or_nameof, name=NN) # nameof
|
|
1263
1297
|
return n, kwds # (str or None or {}), dict
|
|
1264
1298
|
|
|
1265
1299
|
|
pygeodesy/namedTuples.py
CHANGED
|
@@ -8,26 +8,27 @@ are all instances of some C{Named...Tuple} class, all sub-classes
|
|
|
8
8
|
of C{_NamedTuple} defined in C{pygeodesy.named}.
|
|
9
9
|
'''
|
|
10
10
|
|
|
11
|
-
from pygeodesy.basics import map1, _xinstanceof
|
|
11
|
+
from pygeodesy.basics import isinstanceof, map1, _xinstanceof
|
|
12
12
|
# from pygeodesy.constants import INT0 # from .units
|
|
13
|
-
from pygeodesy.
|
|
14
|
-
from pygeodesy.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
13
|
+
# from pygeodesy.dms import toDMS # _MODS
|
|
14
|
+
from pygeodesy.errors import _xattr, _xkwds, _xkwds_not, _ALL_LAZY, _MODS
|
|
15
|
+
from pygeodesy.interns import NN, _1_, _2_, _a_, _A_, _area_, _angle_, _b_, _B_, \
|
|
16
|
+
_band_, _c_, _C_, _D_, _datum_, _distance_, _E_, \
|
|
17
|
+
_easting_, _end_, _fi_, _gamma_, _h_, _height_, \
|
|
18
|
+
_hemipole_, _initial_, _j_, _lam_, _lat_, _lon_, \
|
|
19
|
+
_n_, _northing_, _number_, _outside_, _phi_, \
|
|
20
|
+
_point_, _precision_, _points_, _radius_, _scale_, \
|
|
21
|
+
_start_, _x_, _y_, _z_, _zone_
|
|
21
22
|
# from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS # from .errors
|
|
22
23
|
from pygeodesy.named import _NamedTuple, _Pass
|
|
23
24
|
from pygeodesy.props import deprecated_property_RO, property_RO
|
|
24
|
-
from pygeodesy.units import Band, Bearing, Degrees, Degrees2, Easting, \
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
from pygeodesy.units import Band, Bearing, Degrees, Degrees2, Easting, FIx, \
|
|
26
|
+
Height, Int, Lam, Lat, Lon, Meter, Meter2, \
|
|
27
|
+
Northing, Number_, Phi, Precision_, Radians, \
|
|
28
|
+
Radius, Scalar, Str, INT0
|
|
28
29
|
|
|
29
30
|
__all__ = _ALL_LAZY.namedTuples
|
|
30
|
-
__version__ = '24.
|
|
31
|
+
__version__ = '24.06.08'
|
|
31
32
|
|
|
32
33
|
# __DUNDER gets mangled in class
|
|
33
34
|
_closest_ = 'closest'
|
|
@@ -324,6 +325,34 @@ class LatLonPrec5Tuple(LatLonPrec3Tuple): # .wgrs.py
|
|
|
324
325
|
_Units_ = LatLonPrec3Tuple._Units_ + ( Height, Radius)
|
|
325
326
|
|
|
326
327
|
|
|
328
|
+
class _NamedTupleTo(_NamedTuple): # in .testNamedTuples
|
|
329
|
+
'''(INTERNAL) Base for C{-.toDegrees}, C{-.toRadians}.
|
|
330
|
+
'''
|
|
331
|
+
def _Degrees3(self, *xs, **toDMS_kwds):
|
|
332
|
+
'''(INTERNAL) Convert C{xs} from C{Radians} to C{Degrees} or C{toDMS}.
|
|
333
|
+
'''
|
|
334
|
+
if toDMS_kwds:
|
|
335
|
+
toDMS_kwds = _xkwds(toDMS_kwds, ddd=1, pos=NN)
|
|
336
|
+
toDMS, s = _MODS.dms.toDMS, None
|
|
337
|
+
else:
|
|
338
|
+
toDMS, s = None, self
|
|
339
|
+
for x in xs:
|
|
340
|
+
if not isinstanceof(x, Degrees):
|
|
341
|
+
x, s = x.toDegrees(), None
|
|
342
|
+
yield toDMS(x, **toDMS_kwds) if toDMS else x
|
|
343
|
+
yield s
|
|
344
|
+
|
|
345
|
+
def _Radians3(self, *xs, **unused):
|
|
346
|
+
'''(INTERNAL) Convert C{xs} from C{Degrees} to C{Radians}.
|
|
347
|
+
'''
|
|
348
|
+
s = self
|
|
349
|
+
for x in xs:
|
|
350
|
+
if not isinstanceof(x, Radians):
|
|
351
|
+
x, s = x.toRadians(), None
|
|
352
|
+
yield x
|
|
353
|
+
yield s
|
|
354
|
+
|
|
355
|
+
|
|
327
356
|
class NearestOn2Tuple(_NamedTuple): # .ellipsoidalBaseDI
|
|
328
357
|
'''2-Tuple C{(closest, fraction)} of the C{closest} point
|
|
329
358
|
on and C{fraction} along a line (segment) between two
|
pygeodesy/nvectorBase.py
CHANGED
|
@@ -14,7 +14,7 @@ and published under the same MIT Licence**, see U{Vector-based geodesy
|
|
|
14
14
|
from pygeodesy.constants import EPS, EPS1, EPS_2, R_M, _2_0, _N_2_0
|
|
15
15
|
# from pygeodesy.datums import _spherical_datum # from .formy
|
|
16
16
|
from pygeodesy.errors import IntersectionError, _ValueError, VectorError, \
|
|
17
|
-
_xkwds, _xkwds_pop2
|
|
17
|
+
_xattrs, _xkwds, _xkwds_pop2
|
|
18
18
|
from pygeodesy.fmath import fdot, fidw, hypot_ # PYCHOK fdot shared
|
|
19
19
|
from pygeodesy.fsums import Fsum, fsumf_
|
|
20
20
|
from pygeodesy.formy import _isequalTo, n_xyz2latlon, n_xyz2philam, \
|
|
@@ -22,8 +22,7 @@ from pygeodesy.formy import _isequalTo, n_xyz2latlon, n_xyz2philam, \
|
|
|
22
22
|
# from pygeodesy.internals import _under # from .named
|
|
23
23
|
from pygeodesy.interns import NN, _1_, _2_, _3_, _bearing_, _coincident_, \
|
|
24
24
|
_COMMASPACE_, _distance_, _h_, _insufficient_, \
|
|
25
|
-
_intersection_, _no_,
|
|
26
|
-
_pole_, _SPACE_, _SouthPole_
|
|
25
|
+
_intersection_, _no_, _point_, _pole_, _SPACE_
|
|
27
26
|
from pygeodesy.latlonBase import LatLonBase, _ALL_DOCS, _ALL_LAZY, _MODS
|
|
28
27
|
# from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS # from .latlonBase
|
|
29
28
|
from pygeodesy.named import _xother3, _under
|
|
@@ -31,15 +30,15 @@ from pygeodesy.namedTuples import Trilaterate5Tuple, Vector3Tuple, \
|
|
|
31
30
|
Vector4Tuple, map1
|
|
32
31
|
from pygeodesy.props import deprecated_method, Property_RO, property_doc_, \
|
|
33
32
|
property_RO, _update_all
|
|
34
|
-
from pygeodesy.streprs import Fmt, hstr, unstr
|
|
33
|
+
from pygeodesy.streprs import Fmt, hstr, unstr
|
|
35
34
|
from pygeodesy.units import Bearing, Height, Radius_, Scalar
|
|
36
35
|
from pygeodesy.utily import sincos2d, _unrollon, _unrollon3
|
|
37
|
-
from pygeodesy.vector3d import Vector3d,
|
|
36
|
+
from pygeodesy.vector3d import Vector3d, _xyzhdlln4
|
|
38
37
|
|
|
39
38
|
from math import fabs, sqrt
|
|
40
39
|
|
|
41
40
|
__all__ = _ALL_LAZY.nvectorBase
|
|
42
|
-
__version__ = '24.
|
|
41
|
+
__version__ = '24.06.12'
|
|
43
42
|
|
|
44
43
|
|
|
45
44
|
class NvectorBase(Vector3d): # XXX kept private
|
|
@@ -49,32 +48,29 @@ class NvectorBase(Vector3d): # XXX kept private
|
|
|
49
48
|
_h = Height(h=0) # height (C{meter})
|
|
50
49
|
_H = NN # height prefix (C{str}), '↑' in JS version
|
|
51
50
|
|
|
52
|
-
def __init__(self, x_xyz, y=None, z=None, h=0,
|
|
51
|
+
def __init__(self, x_xyz, y=None, z=None, h=0, datum=None, **ll_name):
|
|
53
52
|
'''New n-vector normal to the earth's surface.
|
|
54
53
|
|
|
55
54
|
@arg x_xyz: X component of vector (C{scalar}) or (3-D) vector
|
|
56
|
-
(C{Nvector}, L{Vector3d}, L{Vector3Tuple} or
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
@kwarg z: Z component of vector (C{scalar}), ignored if B{C{x_xyz}}
|
|
61
|
-
is not C{scalar}, otherwise same units as B{C{x_xyz}}.
|
|
55
|
+
(C{Nvector}, L{Vector3d}, L{Vector3Tuple} or L{Vector4Tuple}).
|
|
56
|
+
@kwarg y: Y component of vector (C{scalar}), required if B{C{x_xyz}} is
|
|
57
|
+
C{scalar} and same units as B{C{x_xyz}}, ignored otherwise.
|
|
58
|
+
@kwarg z: Z component of vector (C{scalar}), like B{C{y}}.
|
|
62
59
|
@kwarg h: Optional height above surface (C{meter}).
|
|
63
|
-
@kwarg ll: Optional, original latlon (C{LatLon}).
|
|
64
60
|
@kwarg datum: Optional, I{pass-thru} datum (L{Datum}).
|
|
65
|
-
@kwarg
|
|
61
|
+
@kwarg ll_name: Optional C{B{name}=NN} (C{str}) and optional, original
|
|
62
|
+
latlon C{B{ll}=None} (C{LatLon}).
|
|
66
63
|
|
|
67
|
-
@raise TypeError: Non-scalar B{C{x}}, B{C{y}} or B{C{z}}
|
|
68
|
-
|
|
69
|
-
L{
|
|
70
|
-
invalid B{C{datum}}.
|
|
64
|
+
@raise TypeError: Non-scalar B{C{x}}, B{C{y}} or B{C{z}} coordinate or
|
|
65
|
+
B{C{x_xyz}} not an C{Nvector}, L{Vector3Tuple} or
|
|
66
|
+
L{Vector4Tuple} or invalid B{C{datum}}.
|
|
71
67
|
'''
|
|
72
|
-
h, d, n =
|
|
68
|
+
h, d, ll, n = _xyzhdlln4(x_xyz, h, datum, **ll_name)
|
|
73
69
|
Vector3d.__init__(self, x_xyz, y=y, z=z, ll=ll, name=n)
|
|
74
70
|
if h:
|
|
75
71
|
self.h = h
|
|
76
72
|
if d is not None:
|
|
77
|
-
self._datum = _spherical_datum(d, name=
|
|
73
|
+
self._datum = _spherical_datum(d, name=n) # pass-thru
|
|
78
74
|
|
|
79
75
|
@Property_RO
|
|
80
76
|
def datum(self):
|
|
@@ -326,7 +322,7 @@ class NvectorBase(Vector3d): # XXX kept private
|
|
|
326
322
|
r = self.toCartesian(h=h, Cartesian=None, datum=d)
|
|
327
323
|
else:
|
|
328
324
|
kwds = _xkwds(LatLon_kwds, height=h, datum=d)
|
|
329
|
-
r =
|
|
325
|
+
r = LatLon(self.lat, self.lon, **self._name1__(kwds))
|
|
330
326
|
return r
|
|
331
327
|
|
|
332
328
|
def toStr(self, prec=5, fmt=Fmt.PAREN, sep=_COMMASPACE_): # PYCHOK expected
|
|
@@ -349,7 +345,7 @@ class NvectorBase(Vector3d): # XXX kept private
|
|
|
349
345
|
def toVector3d(self, norm=True):
|
|
350
346
|
'''Convert this n-vector to a 3-D vector, I{ignoring height}.
|
|
351
347
|
|
|
352
|
-
@kwarg norm:
|
|
348
|
+
@kwarg norm: If C{True}, normalize the 3-D vector (C{bool}).
|
|
353
349
|
|
|
354
350
|
@return: The (normalized) vector (L{Vector3d}).
|
|
355
351
|
'''
|
|
@@ -369,7 +365,7 @@ class NvectorBase(Vector3d): # XXX kept private
|
|
|
369
365
|
|
|
370
366
|
@return: Normalized vector (C{Nvector}).
|
|
371
367
|
'''
|
|
372
|
-
return _xattrs(Vector3d.unit(self, ll=ll), _under(_h_))
|
|
368
|
+
return _xattrs(Vector3d.unit(self, ll=ll), self, _under(_h_))
|
|
373
369
|
|
|
374
370
|
@Property_RO
|
|
375
371
|
def xyzh(self):
|
|
@@ -378,8 +374,8 @@ class NvectorBase(Vector3d): # XXX kept private
|
|
|
378
374
|
return self.xyz.to4Tuple(self.h)
|
|
379
375
|
|
|
380
376
|
|
|
381
|
-
NorthPole = NvectorBase(0, 0, +1, name=
|
|
382
|
-
SouthPole = NvectorBase(0, 0, -1, name=
|
|
377
|
+
NorthPole = NvectorBase(0, 0, +1, name='NorthPole') # North pole (C{Nvector})
|
|
378
|
+
SouthPole = NvectorBase(0, 0, -1, name='SouthPole') # South pole (C{Nvector})
|
|
383
379
|
|
|
384
380
|
|
|
385
381
|
class _N_vector_(NvectorBase):
|
|
@@ -575,7 +571,7 @@ def sumOf(nvectors, Vector=None, h=None, **Vector_kwds):
|
|
|
575
571
|
arguments, ignored if C{B{Vector} is None}.
|
|
576
572
|
|
|
577
573
|
@return: Vectorial sum (B{C{Vector}}) or a L{Vector4Tuple}C{(x, y,
|
|
578
|
-
z, h)} if B{
|
|
574
|
+
z, h)} if C{B{Vector} is None}.
|
|
579
575
|
|
|
580
576
|
@raise VectorError: No B{C{nvectors}}.
|
|
581
577
|
'''
|