pygeodesy 24.6.1__py2.py3-none-any.whl → 24.6.9__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.9.dist-info}/METADATA +2 -2
- {PyGeodesy-24.6.1.dist-info → PyGeodesy-24.6.9.dist-info}/RECORD +43 -43
- pygeodesy/__init__.py +1 -1
- pygeodesy/booleans.py +52 -65
- pygeodesy/cartesianBase.py +138 -147
- pygeodesy/ecef.py +46 -52
- pygeodesy/ellipsoidalBase.py +6 -43
- pygeodesy/ellipsoidalNvector.py +7 -7
- pygeodesy/errors.py +2 -2
- pygeodesy/frechet.py +3 -4
- pygeodesy/fsums.py +2 -2
- pygeodesy/geodsolve.py +23 -25
- pygeodesy/geohash.py +14 -27
- pygeodesy/geoids.py +1 -1
- pygeodesy/hausdorff.py +6 -7
- pygeodesy/heights.py +14 -27
- pygeodesy/internals.py +13 -12
- pygeodesy/interns.py +3 -9
- pygeodesy/iters.py +2 -2
- pygeodesy/latlonBase.py +189 -176
- pygeodesy/lazily.py +90 -54
- pygeodesy/lcc.py +2 -2
- pygeodesy/ltp.py +37 -17
- pygeodesy/ltpTuples.py +124 -115
- pygeodesy/mgrs.py +28 -1
- pygeodesy/named.py +92 -67
- pygeodesy/namedTuples.py +43 -14
- pygeodesy/nvectorBase.py +19 -22
- pygeodesy/points.py +2 -2
- pygeodesy/rhumb/solve.py +8 -61
- pygeodesy/solveBase.py +22 -19
- pygeodesy/sphericalBase.py +17 -11
- pygeodesy/streprs.py +6 -4
- pygeodesy/trf.py +3 -3
- pygeodesy/triaxials.py +70 -49
- pygeodesy/units.py +40 -65
- pygeodesy/unitsBase.py +2 -2
- pygeodesy/utily.py +5 -4
- pygeodesy/utmupsBase.py +2 -2
- pygeodesy/vector3d.py +34 -36
- pygeodesy/vector3dBase.py +12 -9
- {PyGeodesy-24.6.1.dist-info → PyGeodesy-24.6.9.dist-info}/WHEEL +0 -0
- {PyGeodesy-24.6.1.dist-info → PyGeodesy-24.6.9.dist-info}/top_level.txt +0 -0
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.10'
|
|
37
38
|
|
|
38
39
|
_COMMANL_ = _COMMA_ + _NL_
|
|
39
40
|
_COMMASPACEDOT_ = _COMMASPACE_ + _DOT_
|
|
@@ -248,7 +249,7 @@ class _Named(object):
|
|
|
248
249
|
|
|
249
250
|
fmt, props, kwds = _fmt_props_kwds(**fmt_props_kwds)
|
|
250
251
|
|
|
251
|
-
t = () if name is None else (Fmt.EQUAL(name=repr(
|
|
252
|
+
t = () if name is None else (Fmt.EQUAL(name=repr(self._name__(name))),)
|
|
252
253
|
if attrs:
|
|
253
254
|
t += pairs(((a, getattr(self, a)) for a in attrs),
|
|
254
255
|
prec=prec, ints=True, fmt=fmt)
|
|
@@ -309,6 +310,11 @@ class _Named(object):
|
|
|
309
310
|
'''
|
|
310
311
|
return _name__(name, _or_nameof=self) # nameof(self)
|
|
311
312
|
|
|
313
|
+
def _name1__(self, kwds):
|
|
314
|
+
'''(INTERNAL) Resolve and set the C{B{name}=NN}.
|
|
315
|
+
'''
|
|
316
|
+
return _name1__(kwds, _or_nameof=self.name) if self.name else kwds
|
|
317
|
+
|
|
312
318
|
@Property_RO
|
|
313
319
|
def named(self):
|
|
314
320
|
'''Get the name I{or} class name or C{""} (C{str}).
|
|
@@ -422,11 +428,8 @@ class _Named(object):
|
|
|
422
428
|
|
|
423
429
|
@raise TypeError: Not C{isinstance(B{inst}, _Named)}.
|
|
424
430
|
'''
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
_ = inst.rename(self.name)
|
|
429
|
-
return inst
|
|
431
|
+
_xinstanceof(_Named, inst=inst) # assert
|
|
432
|
+
return inst.renamed(self.name)
|
|
430
433
|
|
|
431
434
|
_Named_Property_ROs = _allPropertiesOf_n(5, _Named, Property_RO) # PYCHOK once
|
|
432
435
|
|
|
@@ -716,12 +719,14 @@ class _NamedEnum(_NamedDict):
|
|
|
716
719
|
if not (n and isstr(n) and isidentifier(n)):
|
|
717
720
|
raise ValueError()
|
|
718
721
|
except (AttributeError, ValueError, TypeError) as x:
|
|
719
|
-
|
|
722
|
+
n = _DOT_(_item_, _name_)
|
|
723
|
+
raise _NameError(n, item, cause=x)
|
|
720
724
|
if n in self:
|
|
721
725
|
t = _SPACE_(_item_, self._DOT_(n), _exists_)
|
|
722
726
|
raise _NameError(t, txt=repr(item))
|
|
723
|
-
if not isinstance(item, self._item_Classes):
|
|
724
|
-
|
|
727
|
+
if not isinstance(item, self._item_Classes): # _xinstanceof
|
|
728
|
+
n = self._DOT_(n)
|
|
729
|
+
raise _TypesError(n, item, *self._item_Classes)
|
|
725
730
|
self[n] = item
|
|
726
731
|
return n
|
|
727
732
|
|
|
@@ -843,7 +848,7 @@ class _NamedEnumItem(_NamedBase):
|
|
|
843
848
|
'''
|
|
844
849
|
name = _name__(name) or _NN_
|
|
845
850
|
if self._enum:
|
|
846
|
-
raise _NameError(name, self, txt=_registered_) #
|
|
851
|
+
raise _NameError(name, self, txt=_registered_) # _TypeError
|
|
847
852
|
if name:
|
|
848
853
|
self._name = name
|
|
849
854
|
|
|
@@ -870,8 +875,8 @@ class _NamedEnumItem(_NamedBase):
|
|
|
870
875
|
enum = self._enum
|
|
871
876
|
if enum and self.name and self.name in enum:
|
|
872
877
|
item = enum.unregister(self.name)
|
|
873
|
-
if item is not self:
|
|
874
|
-
t = _SPACE_(repr(item), _vs_, repr(self))
|
|
878
|
+
if item is not self: # PYCHOK no cover
|
|
879
|
+
t = _SPACE_(repr(item), _vs_, repr(self))
|
|
875
880
|
raise _AssertionError(t)
|
|
876
881
|
|
|
877
882
|
|
|
@@ -923,7 +928,11 @@ class _NamedTuple(tuple, _Named):
|
|
|
923
928
|
raise LenError(self.__class__, args=n, _Names_=N)
|
|
924
929
|
|
|
925
930
|
if iteration_name:
|
|
926
|
-
|
|
931
|
+
i, name = _xkwds_pop2(iteration_name, iteration=None)
|
|
932
|
+
if i is not None:
|
|
933
|
+
self._iteration = i
|
|
934
|
+
if name:
|
|
935
|
+
self.name = name
|
|
927
936
|
return self
|
|
928
937
|
|
|
929
938
|
def __delattr__(self, name):
|
|
@@ -932,7 +941,8 @@ class _NamedTuple(tuple, _Named):
|
|
|
932
941
|
@note: Items can not be deleted.
|
|
933
942
|
'''
|
|
934
943
|
if name in self._Names_:
|
|
935
|
-
|
|
944
|
+
t = _SPACE_(_del_, self._DOT_(name))
|
|
945
|
+
raise _TypeError(t, txt=_immutable_)
|
|
936
946
|
elif name in (_name_, _name):
|
|
937
947
|
_Named.__setattr__(self, name, NN) # XXX _Named.name.fset(self, NN)
|
|
938
948
|
else:
|
|
@@ -943,10 +953,10 @@ class _NamedTuple(tuple, _Named):
|
|
|
943
953
|
'''
|
|
944
954
|
try:
|
|
945
955
|
return tuple.__getitem__(self, self._Names_.index(name))
|
|
946
|
-
except IndexError:
|
|
947
|
-
raise _IndexError(
|
|
956
|
+
except IndexError as x:
|
|
957
|
+
raise _IndexError(self._DOT_(name), cause=x)
|
|
948
958
|
except ValueError: # e.g. _iteration
|
|
949
|
-
return tuple.
|
|
959
|
+
return tuple.__getattr__(self, name) # __getattribute__
|
|
950
960
|
|
|
951
961
|
# def __getitem__(self, index): # index, slice, etc.
|
|
952
962
|
# '''Get the item(s) at an B{C{index}} or slice.
|
|
@@ -965,7 +975,8 @@ class _NamedTuple(tuple, _Named):
|
|
|
965
975
|
'''Set attribute or item B{C{name}} to B{C{value}}.
|
|
966
976
|
'''
|
|
967
977
|
if name in self._Names_:
|
|
968
|
-
|
|
978
|
+
t = Fmt.EQUALSPACED(self._DOT_(name), repr(value))
|
|
979
|
+
raise _TypeError(t, txt=_immutable_)
|
|
969
980
|
elif name in (_name_, _name):
|
|
970
981
|
_Named.__setattr__(self, name, value) # XXX _Named.name.fset(self, value)
|
|
971
982
|
else: # e.g. _iteration
|
|
@@ -976,6 +987,11 @@ class _NamedTuple(tuple, _Named):
|
|
|
976
987
|
'''
|
|
977
988
|
return self.toStr()
|
|
978
989
|
|
|
990
|
+
def _DOT_(self, *names):
|
|
991
|
+
'''(INTERNAL) Period-join C{self.classname} and C{names}.
|
|
992
|
+
'''
|
|
993
|
+
return _DOT_(self.classname, *names)
|
|
994
|
+
|
|
979
995
|
def dup(self, name=NN, **items):
|
|
980
996
|
'''Duplicate this tuple replacing one or more items.
|
|
981
997
|
|
|
@@ -986,15 +1002,18 @@ class _NamedTuple(tuple, _Named):
|
|
|
986
1002
|
|
|
987
1003
|
@raise NameError: Some B{C{items}} invalid.
|
|
988
1004
|
'''
|
|
989
|
-
|
|
1005
|
+
t = list(self)
|
|
1006
|
+
U = self._Units_
|
|
990
1007
|
if items:
|
|
991
|
-
_ix =
|
|
1008
|
+
_ix = self._Names_.index
|
|
1009
|
+
_2U = _MODS.units._toUnit
|
|
992
1010
|
try:
|
|
993
1011
|
for n, v in items.items():
|
|
994
|
-
|
|
1012
|
+
i = _ix(n)
|
|
1013
|
+
t[i] = _2U(U[i], v, name=n)
|
|
995
1014
|
except ValueError: # bad item name
|
|
996
|
-
raise _NameError(_DOT_(
|
|
997
|
-
return self.classof(*
|
|
1015
|
+
raise _NameError(self._DOT_(n), v, this=self)
|
|
1016
|
+
return self.classof(*t).reUnit(*U, name=name)
|
|
998
1017
|
|
|
999
1018
|
def items(self):
|
|
1000
1019
|
'''Yield the items, each as a C{(name, value)} pair (C{2-tuple}).
|
|
@@ -1006,13 +1025,23 @@ class _NamedTuple(tuple, _Named):
|
|
|
1006
1025
|
|
|
1007
1026
|
iteritems = items
|
|
1008
1027
|
|
|
1009
|
-
def
|
|
1010
|
-
'''
|
|
1028
|
+
def reUnit(self, *Units, **name):
|
|
1029
|
+
'''Replace some of this C{Named-Tuple}'s C{Units}.
|
|
1030
|
+
|
|
1031
|
+
@arg Units: One or more C{Unit} classes, all positional.
|
|
1032
|
+
@kwarg name: Optional C{B{name}=NN} (C{str}).
|
|
1033
|
+
|
|
1034
|
+
@return: This instance with updated C{Units}.
|
|
1035
|
+
|
|
1036
|
+
@note: This C{Named-Tuple}'s values are I{not updated}.
|
|
1011
1037
|
'''
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
if
|
|
1015
|
-
|
|
1038
|
+
U = self._Units_
|
|
1039
|
+
n = min(len(U), len(Units))
|
|
1040
|
+
if n:
|
|
1041
|
+
R = Units + U[n:]
|
|
1042
|
+
if R != U:
|
|
1043
|
+
self._Units_ = R
|
|
1044
|
+
return self.renamed(name) if name else self
|
|
1016
1045
|
|
|
1017
1046
|
def toRepr(self, prec=6, sep=_COMMASPACE_, fmt=Fmt.F, **unused): # PYCHOK signature
|
|
1018
1047
|
'''Return this C{Named-Tuple} items as C{name=value} string(s).
|
|
@@ -1043,37 +1072,34 @@ class _NamedTuple(tuple, _Named):
|
|
|
1043
1072
|
'''
|
|
1044
1073
|
return Fmt.PAREN(sep.join(reprs(self, prec=prec, fmt=fmt)))
|
|
1045
1074
|
|
|
1046
|
-
def toUnits(self, Error=UnitError): # overloaded in .frechet, .hausdorff
|
|
1075
|
+
def toUnits(self, Error=UnitError, **name): # overloaded in .frechet, .hausdorff
|
|
1047
1076
|
'''Return a copy of this C{Named-Tuple} with each item value wrapped
|
|
1048
1077
|
as an instance of its L{units} class.
|
|
1049
1078
|
|
|
1050
1079
|
@kwarg Error: Error to raise for L{units} issues (C{UnitError}).
|
|
1080
|
+
@kwarg name: Optional C{B{name}=NN} (C{str}).
|
|
1051
1081
|
|
|
1052
1082
|
@return: A duplicate of this C{Named-Tuple} (C{C{Named-Tuple}}).
|
|
1053
1083
|
|
|
1054
1084
|
@raise Error: Invalid C{Named-Tuple} item or L{units} class.
|
|
1055
1085
|
'''
|
|
1056
|
-
t = (v for _, v in self.units(Error=Error))
|
|
1057
|
-
return self.classof(*
|
|
1086
|
+
t = tuple(v for _, v in self.units(Error=Error))
|
|
1087
|
+
return self.classof(*t).reUnit(*self._Units_, **name)
|
|
1058
1088
|
|
|
1059
|
-
def units(self, Error
|
|
1060
|
-
'''Yield the items, each as a C{(name, value})
|
|
1061
|
-
|
|
1089
|
+
def units(self, **Error):
|
|
1090
|
+
'''Yield the items, each as a C{2-tuple (name, value}) with the
|
|
1091
|
+
value wrapped as an instance of its L{units} class.
|
|
1062
1092
|
|
|
1063
|
-
@kwarg Error: Error to raise for
|
|
1093
|
+
@kwarg Error: Optional C{B{Error}=UnitError} to raise for
|
|
1094
|
+
L{units} issues.
|
|
1064
1095
|
|
|
1065
1096
|
@raise Error: Invalid C{Named-Tuple} item or L{units} class.
|
|
1066
1097
|
|
|
1067
1098
|
@see: Method C{.items}.
|
|
1068
1099
|
'''
|
|
1100
|
+
_2U = _MODS.units._toUnit
|
|
1069
1101
|
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
|
|
1102
|
+
yield n, _2U(U, v, name=n, **Error)
|
|
1077
1103
|
|
|
1078
1104
|
iterunits = units
|
|
1079
1105
|
|
|
@@ -1083,35 +1109,35 @@ class _NamedTuple(tuple, _Named):
|
|
|
1083
1109
|
'''
|
|
1084
1110
|
ns = self._Names_
|
|
1085
1111
|
if not (isinstance(ns, tuple) and len(ns) > 1): # XXX > 0
|
|
1086
|
-
raise _TypeError(_DOT_(
|
|
1112
|
+
raise _TypeError(self._DOT_(_Names_), ns)
|
|
1087
1113
|
for i, n in enumerate(ns):
|
|
1088
1114
|
if not _xvalid(n, underOK=underOK):
|
|
1089
1115
|
t = Fmt.SQUARE(_Names_=i) # PYCHOK no cover
|
|
1090
|
-
raise _ValueError(_DOT_(
|
|
1116
|
+
raise _ValueError(self._DOT_(t), n)
|
|
1091
1117
|
|
|
1092
1118
|
us = self._Units_
|
|
1093
1119
|
if not isinstance(us, tuple):
|
|
1094
|
-
raise _TypeError(_DOT_(
|
|
1120
|
+
raise _TypeError(self._DOT_(_Units_), us)
|
|
1095
1121
|
if len(us) != len(ns):
|
|
1096
1122
|
raise LenError(self.__class__, _Units_=len(us), _Names_=len(ns))
|
|
1097
1123
|
for i, u in enumerate(us):
|
|
1098
1124
|
if not (u is None or callable(u)):
|
|
1099
1125
|
t = Fmt.SQUARE(_Units_=i) # PYCHOK no cover
|
|
1100
|
-
raise _TypeError(_DOT_(
|
|
1126
|
+
raise _TypeError(self._DOT_(t), u)
|
|
1101
1127
|
|
|
1102
1128
|
self.__class__._validated = True
|
|
1103
1129
|
|
|
1104
1130
|
def _xtend(self, xTuple, *items, **name):
|
|
1105
1131
|
'''(INTERNAL) Extend this C{Named-Tuple} with C{items} to an other B{C{xTuple}}.
|
|
1106
1132
|
'''
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1133
|
+
_xsubclassof(_NamedTuple, xTuple=xTuple)
|
|
1134
|
+
if len(xTuple._Names_) != (len(self._Names_) + len(items)) or \
|
|
1135
|
+
xTuple._Names_[:len(self)] != self._Names_: # PYCHOK no cover
|
|
1136
|
+
c = NN(self.classname, repr(self._Names_))
|
|
1137
|
+
x = NN(xTuple.__name__, repr(xTuple._Names_))
|
|
1138
|
+
raise TypeError(_SPACE_(c, _vs_, x))
|
|
1139
|
+
t = self + items
|
|
1140
|
+
return xTuple(t, name=self._name__(name)) # .reUnit(*self._Units_)
|
|
1115
1141
|
|
|
1116
1142
|
|
|
1117
1143
|
def callername(up=1, dflt=NN, source=False, underOK=False):
|
|
@@ -1231,8 +1257,7 @@ def _name__(name=NN, **kwds):
|
|
|
1231
1257
|
if name or kwds:
|
|
1232
1258
|
name, kwds = _name2__(name, **kwds)
|
|
1233
1259
|
if kwds: # "unexpected keyword arguments ..."
|
|
1234
|
-
|
|
1235
|
-
raise m._UnexpectedError(**kwds)
|
|
1260
|
+
raise _UnexpectedError(**kwds)
|
|
1236
1261
|
return name if name or name is None else NN
|
|
1237
1262
|
|
|
1238
1263
|
|
|
@@ -1255,11 +1280,11 @@ def _name2__(name=NN, name__=None, _or_nameof=None, **kwds):
|
|
|
1255
1280
|
else:
|
|
1256
1281
|
n = str(name)
|
|
1257
1282
|
elif name__ is not None:
|
|
1258
|
-
n =
|
|
1283
|
+
n = _dunder_nameof(name__, NN)
|
|
1259
1284
|
else:
|
|
1260
1285
|
n = name if name is None else NN
|
|
1261
1286
|
if _or_nameof is not None and not n:
|
|
1262
|
-
n =
|
|
1287
|
+
n = _xattr(_or_nameof, name=NN) # nameof
|
|
1263
1288
|
return n, kwds # (str or None or {}), dict
|
|
1264
1289
|
|
|
1265
1290
|
|
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
|
@@ -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
|
|
@@ -34,12 +33,12 @@ from pygeodesy.props import deprecated_method, Property_RO, property_doc_, \
|
|
|
34
33
|
from pygeodesy.streprs import Fmt, hstr, unstr, _xattrs
|
|
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.06'
|
|
43
42
|
|
|
44
43
|
|
|
45
44
|
class NvectorBase(Vector3d): # XXX kept private
|
|
@@ -49,32 +48,30 @@ 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
|
-
|
|
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}), ignored if B{C{x_xyz}} is not
|
|
57
|
+
C{scalar}, otherwise same units as B{C{x_xyz}}.
|
|
58
|
+
@kwarg z: Z component of vector (C{scalar}), ignored if B{C{x_xyz}} is not
|
|
59
|
+
C{scalar}, otherwise same units as B{C{x_xyz}}.
|
|
62
60
|
@kwarg h: Optional height above surface (C{meter}).
|
|
63
|
-
@kwarg ll: Optional, original latlon (C{LatLon}).
|
|
64
61
|
@kwarg datum: Optional, I{pass-thru} datum (L{Datum}).
|
|
65
|
-
@kwarg
|
|
62
|
+
@kwarg ll_name: Optional C{B{name}=NN} (C{str}) and optional, original
|
|
63
|
+
latlon C{B{ll}=None} (C{LatLon}).
|
|
66
64
|
|
|
67
|
-
@raise TypeError: Non-scalar B{C{x}}, B{C{y}} or B{C{z}}
|
|
68
|
-
|
|
69
|
-
L{
|
|
70
|
-
invalid B{C{datum}}.
|
|
65
|
+
@raise TypeError: Non-scalar B{C{x}}, B{C{y}} or B{C{z}} coordinate or
|
|
66
|
+
B{C{x_xyz}} not an C{Nvector}, L{Vector3Tuple} or
|
|
67
|
+
L{Vector4Tuple} or invalid B{C{datum}}.
|
|
71
68
|
'''
|
|
72
|
-
h, d, n =
|
|
69
|
+
h, d, ll, n = _xyzhdlln4(x_xyz, h, datum, **ll_name)
|
|
73
70
|
Vector3d.__init__(self, x_xyz, y=y, z=z, ll=ll, name=n)
|
|
74
71
|
if h:
|
|
75
72
|
self.h = h
|
|
76
73
|
if d is not None:
|
|
77
|
-
self._datum = _spherical_datum(d, name=
|
|
74
|
+
self._datum = _spherical_datum(d, name=n) # pass-thru
|
|
78
75
|
|
|
79
76
|
@Property_RO
|
|
80
77
|
def datum(self):
|
|
@@ -326,7 +323,7 @@ class NvectorBase(Vector3d): # XXX kept private
|
|
|
326
323
|
r = self.toCartesian(h=h, Cartesian=None, datum=d)
|
|
327
324
|
else:
|
|
328
325
|
kwds = _xkwds(LatLon_kwds, height=h, datum=d)
|
|
329
|
-
r =
|
|
326
|
+
r = LatLon(self.lat, self.lon, **self._name1__(kwds))
|
|
330
327
|
return r
|
|
331
328
|
|
|
332
329
|
def toStr(self, prec=5, fmt=Fmt.PAREN, sep=_COMMASPACE_): # PYCHOK expected
|
|
@@ -378,8 +375,8 @@ class NvectorBase(Vector3d): # XXX kept private
|
|
|
378
375
|
return self.xyz.to4Tuple(self.h)
|
|
379
376
|
|
|
380
377
|
|
|
381
|
-
NorthPole = NvectorBase(0, 0, +1, name=
|
|
382
|
-
SouthPole = NvectorBase(0, 0, -1, name=
|
|
378
|
+
NorthPole = NvectorBase(0, 0, +1, name='NorthPole') # North pole (C{Nvector})
|
|
379
|
+
SouthPole = NvectorBase(0, 0, -1, name='SouthPole') # South pole (C{Nvector})
|
|
383
380
|
|
|
384
381
|
|
|
385
382
|
class _N_vector_(NvectorBase):
|
pygeodesy/points.py
CHANGED
|
@@ -62,7 +62,7 @@ from pygeodesy.utily import atan2b, degrees90, degrees180, degrees2m, \
|
|
|
62
62
|
from math import cos, fabs, fmod as _fmod, radians, sin
|
|
63
63
|
|
|
64
64
|
__all__ = _ALL_LAZY.points
|
|
65
|
-
__version__ = '24.
|
|
65
|
+
__version__ = '24.06.06'
|
|
66
66
|
|
|
67
67
|
_ilat_ = 'ilat'
|
|
68
68
|
_ilon_ = 'ilon'
|
|
@@ -1479,7 +1479,7 @@ def nearestOn5(point, points, closed=False, wrap=False, adjust=True,
|
|
|
1479
1479
|
spherical earth radius L{R_KM}).
|
|
1480
1480
|
@kwarg LatLon_and_kwds: Optional, C{B{LatLon}=None} class to use for
|
|
1481
1481
|
the closest point and additional B{C{LatLon}} keyword
|
|
1482
|
-
arguments, ignored if C{B{LatLon}
|
|
1482
|
+
arguments, ignored if C{B{LatLon} is None} or not given.
|
|
1483
1483
|
|
|
1484
1484
|
@return: A L{NearestOn3Tuple}C{(closest, distance, angle)} with the
|
|
1485
1485
|
{closest} point (B{C{LatLon}}) or if C{B{LatLon} is None},
|
pygeodesy/rhumb/solve.py
CHANGED
|
@@ -21,7 +21,7 @@ from pygeodesy.solveBase import _SolveBase, _SolveLineBase
|
|
|
21
21
|
from pygeodesy.utily import _unrollon, _Wrap, wrap360
|
|
22
22
|
|
|
23
23
|
__all__ = _ALL_LAZY.rhumb_solve
|
|
24
|
-
__version__ = '24.
|
|
24
|
+
__version__ = '24.06.04'
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
class _RhumbSolveBase(_SolveBase):
|
|
@@ -37,9 +37,9 @@ class _RhumbSolveBase(_SolveBase):
|
|
|
37
37
|
def _cmdBasic(self):
|
|
38
38
|
'''(INTERNAL) Get the basic C{RhumbSolve} cmd (C{tuple}).
|
|
39
39
|
'''
|
|
40
|
-
return (self.RhumbSolve,) + self._e_option
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
return (self.RhumbSolve,) + (self._e_option +
|
|
41
|
+
self._p_option +
|
|
42
|
+
self._s_option)
|
|
43
43
|
|
|
44
44
|
@Property
|
|
45
45
|
def RhumbSolve(self):
|
|
@@ -423,59 +423,6 @@ if __name__ == '__main__':
|
|
|
423
423
|
# p = rlS.ArcPosition(49.475527)
|
|
424
424
|
# printf('ArcPosition: %s %r', p == r, p)
|
|
425
425
|
|
|
426
|
-
# % python3 -m pygeodesy.rhumb.solve
|
|
427
|
-
|
|
428
|
-
# version: /opt/local/bin/RhumbSolve: GeographicLib version 1.51
|
|
429
|
-
#
|
|
430
|
-
# Direct: GDict(S12=44095641862956.148438, azi12=51, lat1=40.6, lat2=71.6889, lon1=-73.8, lon2=0.25552, s12=5500000.0)
|
|
431
|
-
# Direct3: Destination3Tuple(lat=71.6889, lon=0.25552, final=51.0)
|
|
432
|
-
#
|
|
433
|
-
# Inverse: GDict(S12=37395209100030.367188, a12=51.929543, azi12=77.76839, lat1=40.6, lat2=51.6, lon1=-73.8, lon2=-0.5, s12=5771083.383328)
|
|
434
|
-
# Inverse1: 51.92954250756195
|
|
435
|
-
# Inverse3: Distance3Tuple(distance=5771083.383328, initial=77.76839, final=77.76839)
|
|
436
|
-
#
|
|
437
|
-
# Inverse: GDict(S12=-63760642939072.492188, a12=115.02062, azi12=-92.388888, lat1=40.6, lat2=35.8, lon1=-73.8, lon2=140.3, s12=12782581.067684)
|
|
438
|
-
# Inverse1: 115.02061966879258
|
|
439
|
-
# Inverse3: Distance3Tuple(distance=12782581.067684, initial=267.611112, final=267.611112)
|
|
440
|
-
#
|
|
441
|
-
# Position: True GDict(S12=44095641862956.148438, azi12=51, lat1=40.6, lat2=71.6889, lon1=-73.8, lon2=0.25552, s12=5500000.0)
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
# % python3 -m pygeodesy.rhumb.solve --verbose
|
|
445
|
-
|
|
446
|
-
# RhumbSolve 'Test' 1: /opt/local/bin/RhumbSolve --version (invoke)
|
|
447
|
-
# RhumbSolve 'Test' 1: /opt/local/bin/RhumbSolve: GeographicLib version 1.51 (0)
|
|
448
|
-
# version: /opt/local/bin/RhumbSolve: GeographicLib version 1.51
|
|
449
|
-
# RhumbSolve 'Test' 2: /opt/local/bin/RhumbSolve -p 10 \ 40.600000000000001 -73.799999999999997 51.0 5500000.0 (Direct)
|
|
450
|
-
# RhumbSolve 'Test' 2: lat2=71.688899882813047, lon2=0.255519824423445, S12=44095641862956.148 (0)
|
|
451
|
-
|
|
452
|
-
# Direct: GDict(S12=44095641862956.148438, azi12=51, lat1=40.6, lat2=71.6889, lon1=-73.8, lon2=0.25552, s12=5500000.0)
|
|
453
|
-
# RhumbSolve 'Test' 3: /opt/local/bin/RhumbSolve -p 10 \ 40.600000000000001 -73.799999999999997 51.0 5500000.0 (Direct3)
|
|
454
|
-
# RhumbSolve 'Test' 3: lat2=71.688899882813047, lon2=0.255519824423445, S12=44095641862956.148 (0)
|
|
455
|
-
# Direct3: Destination3Tuple(lat=71.6889, lon=0.25552, final=51.0)
|
|
456
|
-
# RhumbSolve 'Test' 4: /opt/local/bin/RhumbSolve -p 10 -i \ 40.600000000000001 -73.799999999999997 51.600000000000001 -0.5 (Inverse)
|
|
457
|
-
# RhumbSolve 'Test' 4: azi12=77.768389710255661, s12=5771083.3833280317, S12=37395209100030.367 (0)
|
|
458
|
-
|
|
459
|
-
# Inverse: GDict(S12=37395209100030.367188, a12=51.929543, azi12=77.76839, lat1=40.6, lat2=51.6, lon1=-73.8, lon2=-0.5, s12=5771083.383328)
|
|
460
|
-
# RhumbSolve 'Test' 5: /opt/local/bin/RhumbSolve -p 10 -i \ 40.600000000000001 -73.799999999999997 51.600000000000001 -0.5 (Inverse1)
|
|
461
|
-
# RhumbSolve 'Test' 5: azi12=77.768389710255661, s12=5771083.3833280317, S12=37395209100030.367 (0)
|
|
462
|
-
# Inverse1: 51.92954250756195
|
|
463
|
-
# RhumbSolve 'Test' 6: /opt/local/bin/RhumbSolve -p 10 -i \ 40.600000000000001 -73.799999999999997 51.600000000000001 -0.5 (Inverse3)
|
|
464
|
-
# RhumbSolve 'Test' 6: azi12=77.768389710255661, s12=5771083.3833280317, S12=37395209100030.367 (0)
|
|
465
|
-
# Inverse3: Distance3Tuple(distance=5771083.383328, initial=77.76839, final=77.76839)
|
|
466
|
-
# RhumbSolve 'Test' 7: /opt/local/bin/RhumbSolve -p 10 -i \ 40.600000000000001 -73.799999999999997 35.799999999999997 140.300000000000011 (Inverse)
|
|
467
|
-
# RhumbSolve 'Test' 7: azi12=-92.388887981699639, s12=12782581.0676841792, S12=-63760642939072.492 (0)
|
|
468
|
-
|
|
469
|
-
# Inverse: GDict(S12=-63760642939072.492188, a12=115.02062, azi12=-92.388888, lat1=40.6, lat2=35.8, lon1=-73.8, lon2=140.3, s12=12782581.067684)
|
|
470
|
-
# RhumbSolve 'Test' 8: /opt/local/bin/RhumbSolve -p 10 -i \ 40.600000000000001 -73.799999999999997 35.799999999999997 140.300000000000011 (Inverse1)
|
|
471
|
-
# RhumbSolve 'Test' 8: azi12=-92.388887981699639, s12=12782581.0676841792, S12=-63760642939072.492 (0)
|
|
472
|
-
# Inverse1: 115.02061966879258
|
|
473
|
-
# RhumbSolve 'Test' 9: /opt/local/bin/RhumbSolve -p 10 -i \ 40.600000000000001 -73.799999999999997 35.799999999999997 140.300000000000011 (Inverse3)
|
|
474
|
-
# RhumbSolve 'Test' 9: azi12=-92.388887981699639, s12=12782581.0676841792, S12=-63760642939072.492 (0)
|
|
475
|
-
# Inverse3: Distance3Tuple(distance=12782581.067684, initial=267.611112, final=267.611112)
|
|
476
|
-
|
|
477
|
-
# Position: True GDict(S12=44095641862956.148438, azi12=51, lat1=40.6, lat2=71.6889, lon1=-73.8, lon2=0.25552, s12=5500000.0)
|
|
478
|
-
|
|
479
426
|
|
|
480
427
|
# % python3 -m pygeodesy.rhumb.solve
|
|
481
428
|
|
|
@@ -485,11 +432,11 @@ if __name__ == '__main__':
|
|
|
485
432
|
# Direct3: Destination3Tuple(lat=71.6889, lon=0.25552, final=51.0)
|
|
486
433
|
|
|
487
434
|
# Inverse: GDict(a12=51.929543, azi12=77.76839, lat1=40.6, lat2=51.6, lon1=-73.8, lon2=-0.5, s12=5771083.383328, S12=37395209100030.390625)
|
|
488
|
-
# Inverse1: 51.
|
|
435
|
+
# Inverse1: 51.929542507561905
|
|
489
436
|
# Inverse3: Distance3Tuple(distance=5771083.383328, initial=77.76839, final=77.76839)
|
|
490
437
|
|
|
491
438
|
# Inverse: GDict(a12=115.02062, azi12=-92.388888, lat1=40.6, lat2=35.8, lon1=-73.8, lon2=140.3, s12=12782581.067684, S12=-63760642939072.5)
|
|
492
|
-
# Inverse1: 115.
|
|
439
|
+
# Inverse1: 115.02061966879248
|
|
493
440
|
# Inverse3: Distance3Tuple(distance=12782581.067684, initial=267.611112, final=267.611112)
|
|
494
441
|
|
|
495
442
|
# Position: True GDict(azi12=51, lat1=40.6, lat2=71.6889, lon1=-73.8, lon2=0.25552, s12=5500000.0, S12=44095641862956.109375)
|
|
@@ -513,7 +460,7 @@ if __name__ == '__main__':
|
|
|
513
460
|
# Inverse: GDict(a12=51.929543, azi12=77.76839, lat1=40.6, lat2=51.6, lon1=-73.8, lon2=-0.5, s12=5771083.383328, S12=37395209100030.390625)
|
|
514
461
|
# RhumbSolve 'Test' 5: /opt/local/bin/RhumbSolve -p 10 -i \ 40.600000000000001 -73.799999999999997 51.600000000000001 -0.5 (Inverse1)
|
|
515
462
|
# RhumbSolve 'Test' 5: azi12=77.768389710255661, s12=5771083.383328028, S12=37395209100030.391 (0)
|
|
516
|
-
# Inverse1: 51.
|
|
463
|
+
# Inverse1: 51.929542507561905
|
|
517
464
|
# RhumbSolve 'Test' 6: /opt/local/bin/RhumbSolve -p 10 -i \ 40.600000000000001 -73.799999999999997 51.600000000000001 -0.5 (Inverse3)
|
|
518
465
|
# RhumbSolve 'Test' 6: azi12=77.768389710255661, s12=5771083.383328028, S12=37395209100030.391 (0)
|
|
519
466
|
# Inverse3: Distance3Tuple(distance=5771083.383328, initial=77.76839, final=77.76839)
|
|
@@ -523,7 +470,7 @@ if __name__ == '__main__':
|
|
|
523
470
|
# Inverse: GDict(a12=115.02062, azi12=-92.388888, lat1=40.6, lat2=35.8, lon1=-73.8, lon2=140.3, s12=12782581.067684, S12=-63760642939072.5)
|
|
524
471
|
# RhumbSolve 'Test' 8: /opt/local/bin/RhumbSolve -p 10 -i \ 40.600000000000001 -73.799999999999997 35.799999999999997 140.300000000000011 (Inverse1)
|
|
525
472
|
# RhumbSolve 'Test' 8: azi12=-92.388887981699654, s12=12782581.0676841699, S12=-63760642939072.5 (0)
|
|
526
|
-
# Inverse1: 115.
|
|
473
|
+
# Inverse1: 115.02061966879248
|
|
527
474
|
# RhumbSolve 'Test' 9: /opt/local/bin/RhumbSolve -p 10 -i \ 40.600000000000001 -73.799999999999997 35.799999999999997 140.300000000000011 (Inverse3)
|
|
528
475
|
# RhumbSolve 'Test' 9: azi12=-92.388887981699654, s12=12782581.0676841699, S12=-63760642939072.5 (0)
|
|
529
476
|
# Inverse3: Distance3Tuple(distance=12782581.067684, initial=267.611112, final=267.611112)
|