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/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 isclass, isidentifier, iskeyword, isstr, issubclassof, \
17
- itemsorted, len2, _xcopy, _xdup, _zip
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, _IsnotError, _KeyError, LenError, \
20
- _NameError, _NotImplementedError, _TypeError, \
21
- _TypesError, UnitError, _ValueError, _xattr, _xkwds, \
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_, _valid_, _vs_
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.05.31'
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(name or self.name)),)
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
- if not isinstance(inst, _Named):
426
- raise _IsnotError(_valid_, inst=inst)
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
- raise _NameError(_DOT_(_item_, _name_), item, cause=x)
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
- raise _TypesError(self._DOT_(n), item, *self._item_Classes)
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_) # XXX _TypeError
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)) # PYCHOK no cover
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
- self._kwdself(**iteration_name)
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
- raise _TypeError(_del_, _DOT_(self.classname, name), txt=_immutable_)
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(_DOT_(self.classname, Fmt.ANGLE(_name_)), name)
956
+ except IndexError as x:
957
+ raise _IndexError(self._DOT_(name), cause=x)
948
958
  except ValueError: # e.g. _iteration
949
- return tuple.__getattribute__(self, name)
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
- raise _TypeError(_DOT_(self.classname, name), value, txt=_immutable_)
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
- tl = list(self)
1005
+ t = list(self)
1006
+ U = self._Units_
990
1007
  if items:
991
- _ix = self._Names_.index
1008
+ _ix = self._Names_.index
1009
+ _2U = _MODS.units._toUnit
992
1010
  try:
993
1011
  for n, v in items.items():
994
- tl[_ix(n)] = v
1012
+ i = _ix(n)
1013
+ t[i] = _2U(U[i], v, name=n)
995
1014
  except ValueError: # bad item name
996
- raise _NameError(_DOT_(self.classname, n), v, this=self)
997
- return self.classof(*tl, name=name or self.name)
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 _kwdself(self, iteration=None, **name):
1010
- '''(INTERNAL) Set C{__new__} keyword arguments.
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
- if iteration is not None:
1013
- self._iteration = iteration
1014
- if name:
1015
- self.name = name
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(*tuple(t))
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=UnitError):
1060
- '''Yield the items, each as a C{(name, value}) pair (C{2-tuple}) with
1061
- the value wrapped as an instance of its L{units} class.
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 L{units} issues (C{UnitError}).
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
- if not (v is None or U is None
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_(self.classname, _Names_), ns)
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_(self.classname, t), n)
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_(self.classname, _Units_), us)
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_(self.classname, t), u)
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
- if (issubclassof(xTuple, _NamedTuple) and
1108
- (len(self._Names_) + len(items)) == len(xTuple._Names_) and
1109
- self._Names_ == xTuple._Names_[:len(self)]):
1110
- n = _name__(**name) or self.name
1111
- return xTuple(self + items, name=n) # *(self + items)
1112
- c = NN(self.classname, repr(self._Names_)) # PYCHOK no cover
1113
- x = NN(xTuple.__name__, repr(xTuple._Names_)) # PYCHOK no cover
1114
- raise TypeError(_SPACE_(c, _vs_, x))
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
- m = _MODS.errors
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 = getattr(name__, _dunder_name_, NN) # _xattr(name__, __name__=NN)
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 = getattr(_or_nameof, _name_, NN) # _xattr(_or_nameof, name=NN)
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.errors import _ALL_LAZY, _MODS, _xattr, _xkwds_not # _xkwds
14
- from pygeodesy.interns import _1_, _2_, _a_, _A_, _area_, _angle_, _b_, _B_, \
15
- _band_, _c_, _C_, _datum_, _D_, _distance_, \
16
- _E_, _easting_, _end_, _fi_, _gamma_, _height_, \
17
- _h_, _j_, _hemipole_, _initial_, _lam_, _lat_, \
18
- _lon_, _n_, _northing_, _number_, _outside_, \
19
- _phi_, _point_, _precision_, _points_, _radius_, \
20
- _scale_, _start_, _x_, _y_, _z_, _zone_
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
- FIx, Height, Int, INT0, Lam, Lat, Lon, Meter, \
26
- Meter2, Northing, Number_, Phi, Precision_, \
27
- Radians, Radius, Scalar, Str
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.05.18'
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_, _NorthPole_, _point_, \
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, _xyzhdn3
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.05.31'
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, ll=None, datum=None, **name):
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
- L{Vector4Tuple}).
58
- @kwarg y: Y component of vector (C{scalar}), ignored if B{C{x_xyz}}
59
- is not C{scalar}, otherwise same units as B{C{x_xyz}}.
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}), 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 name: Optional C{B{name}=NN} (C{str}).
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
- coordinate or B{C{x}} not an C{Nvector},
69
- L{Vector3Tuple} or L{Vector4Tuple} or
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 = _xyzhdn3(x_xyz, h, datum, ll, **name)
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=self.name) # pass-thru
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 = self._xnamed(LatLon(self.lat, self.lon, **kwds))
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=_NorthPole_) # North pole (C{Nvector})
382
- SouthPole = NvectorBase(0, 0, -1, name=_SouthPole_) # South pole (C{Nvector})
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.05.25'
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}=None} or not given.
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.05.31'
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
- + self._p_option \
42
- + self._s_option
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.92954250756191
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.02061966879249
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.92954250756191
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.02061966879249
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)