pygeodesy 24.5.24__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.
Files changed (71) hide show
  1. {PyGeodesy-24.5.24.dist-info → PyGeodesy-24.6.9.dist-info}/METADATA +6 -5
  2. PyGeodesy-24.6.9.dist-info/RECORD +116 -0
  3. pygeodesy/__init__.py +4 -4
  4. pygeodesy/auxilats/__init__.py +1 -1
  5. pygeodesy/auxilats/__main__.py +2 -2
  6. pygeodesy/auxilats/auxAngle.py +4 -4
  7. pygeodesy/basics.py +39 -5
  8. pygeodesy/booleans.py +54 -67
  9. pygeodesy/cartesianBase.py +138 -147
  10. pygeodesy/constants.py +3 -3
  11. pygeodesy/deprecated/functions.py +9 -3
  12. pygeodesy/ecef.py +67 -72
  13. pygeodesy/ellipsoidalBase.py +18 -56
  14. pygeodesy/ellipsoidalGeodSolve.py +2 -2
  15. pygeodesy/ellipsoidalKarney.py +3 -3
  16. pygeodesy/ellipsoidalNvector.py +7 -7
  17. pygeodesy/ellipsoids.py +6 -5
  18. pygeodesy/errors.py +20 -10
  19. pygeodesy/etm.py +16 -21
  20. pygeodesy/fmath.py +9 -20
  21. pygeodesy/formy.py +60 -74
  22. pygeodesy/frechet.py +13 -14
  23. pygeodesy/fsums.py +60 -26
  24. pygeodesy/geodesicx/__init__.py +1 -1
  25. pygeodesy/geodesicx/__main__.py +2 -2
  26. pygeodesy/geodesicx/gx.py +3 -5
  27. pygeodesy/geodsolve.py +24 -26
  28. pygeodesy/geohash.py +27 -40
  29. pygeodesy/geoids.py +1 -1
  30. pygeodesy/hausdorff.py +17 -18
  31. pygeodesy/heights.py +17 -30
  32. pygeodesy/internals.py +15 -14
  33. pygeodesy/interns.py +3 -9
  34. pygeodesy/iters.py +2 -2
  35. pygeodesy/karney.py +8 -7
  36. pygeodesy/latlonBase.py +189 -176
  37. pygeodesy/lazily.py +92 -56
  38. pygeodesy/lcc.py +2 -2
  39. pygeodesy/ltp.py +93 -55
  40. pygeodesy/ltpTuples.py +304 -240
  41. pygeodesy/mgrs.py +51 -24
  42. pygeodesy/named.py +159 -136
  43. pygeodesy/namedTuples.py +43 -14
  44. pygeodesy/nvectorBase.py +20 -23
  45. pygeodesy/osgr.py +40 -48
  46. pygeodesy/points.py +11 -11
  47. pygeodesy/props.py +29 -16
  48. pygeodesy/rhumb/aux_.py +13 -15
  49. pygeodesy/rhumb/bases.py +12 -5
  50. pygeodesy/rhumb/ekx.py +24 -18
  51. pygeodesy/rhumb/solve.py +20 -70
  52. pygeodesy/simplify.py +16 -16
  53. pygeodesy/solveBase.py +35 -32
  54. pygeodesy/sphericalBase.py +33 -31
  55. pygeodesy/sphericalTrigonometry.py +17 -17
  56. pygeodesy/streprs.py +6 -4
  57. pygeodesy/trf.py +11 -9
  58. pygeodesy/triaxials.py +71 -50
  59. pygeodesy/units.py +40 -65
  60. pygeodesy/unitsBase.py +2 -2
  61. pygeodesy/ups.py +66 -70
  62. pygeodesy/utily.py +7 -6
  63. pygeodesy/utm.py +152 -156
  64. pygeodesy/utmups.py +38 -38
  65. pygeodesy/utmupsBase.py +102 -106
  66. pygeodesy/vector3d.py +34 -36
  67. pygeodesy/vector3dBase.py +12 -9
  68. pygeodesy/webmercator.py +43 -51
  69. PyGeodesy-24.5.24.dist-info/RECORD +0 -116
  70. {PyGeodesy-24.5.24.dist-info → PyGeodesy-24.6.9.dist-info}/WHEEL +0 -0
  71. {PyGeodesy-24.5.24.dist-info → PyGeodesy-24.6.9.dist-info}/top_level.txt +0 -0
@@ -16,34 +16,34 @@ from pygeodesy.constants import EPS, EPS0, INT0, PI2, _isfinite, isnear0, \
16
16
  from pygeodesy.datums import Datum, _earth_ellipsoid, _spherical_datum, \
17
17
  Transform, _WGS84, _xinstanceof
18
18
  # from pygeodesy.ecef import EcefKarney # _MODS
19
- from pygeodesy.errors import _IsnotError, _TypeError, _ValueError, \
20
- _xdatum, _xkwds
19
+ from pygeodesy.errors import _IsnotError, _TypeError, _ValueError, _xattr, \
20
+ _xdatum, _xkwds, _xkwds_get, _xkwds_pop2
21
21
  from pygeodesy.fmath import cbrt, hypot, hypot_, hypot2, fabs, sqrt # hypot
22
22
  # from pygeodesy.formy import _hartzell # _MODS
23
23
  from pygeodesy.fsums import fsumf_, Fmt
24
- from pygeodesy.interns import _COMMASPACE_, _phi_
24
+ from pygeodesy.interns import _COMMASPACE_, _datum_, _no_, _phi_
25
25
  from pygeodesy.interns import _ellipsoidal_, _spherical_ # PYCHOK used!
26
26
  from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS
27
- from pygeodesy.named import _name__, _name2__, _NamedTuple, _Pass
28
- from pygeodesy.namedTuples import LatLon4Tuple, Vector3Tuple, Vector4Tuple, \
29
- Bearing2Tuple # PYCHOK .sphericalBase
27
+ from pygeodesy.named import _name2__, _Pass
28
+ from pygeodesy.namedTuples import LatLon4Tuple, _NamedTupleTo , Vector3Tuple, \
29
+ Vector4Tuple, Bearing2Tuple # PYCHOK .sphericalBase
30
30
  # from pygeodesy.nvectorBase import _N_vector # _MODS
31
31
  from pygeodesy.props import deprecated_method, Property, Property_RO, \
32
32
  property_doc_, property_RO, _update_all
33
- # from pygeodesy.resections import cassini, collins5, pierlot, tienstra7
33
+ # from pygeodesy,resections import cassini, collins5, pierlot, pierlotx, \
34
+ # tienstra7 # _MODS
34
35
  # from pygeodesy.streprs import Fmt # from .fsums
35
36
  # from pygeodesy.triaxials import Triaxial_ # _MODS
36
- from pygeodesy.units import Degrees, Height, _heigHt, _isMeter, Meter, \
37
- Radians, _toDegrees, _toRadians
37
+ from pygeodesy.units import Degrees, Height, _heigHt, _isMeter, Meter, Radians
38
38
  from pygeodesy.utily import acos1, sincos2d, sincos2_, atan2, degrees, radians
39
- from pygeodesy.vector3d import Vector3d, _xyzhdn3
39
+ from pygeodesy.vector3d import Vector3d, _xyzhdlln4
40
40
  # from pygeodesy.vector3dBase import _xyz3 # _MODS
41
- # from pygeodesy import ltp, resections # _MODS
41
+ # from pygeodesy import ltp # _MODS
42
42
 
43
43
  # from math import atan2, degrees, fabs, radians, sqrt # from .fmath, .utily
44
44
 
45
45
  __all__ = _ALL_LAZY.cartesianBase
46
- __version__ = '24.05.24'
46
+ __version__ = '24.06.10'
47
47
 
48
48
  _r_ = 'r'
49
49
  _theta_ = 'theta'
@@ -55,7 +55,7 @@ class CartesianBase(Vector3d):
55
55
  _datum = None # L{Datum}, to be overriden
56
56
  _height = None # height (L{Height}), set or approximated
57
57
 
58
- def __init__(self, x_xyz, y=None, z=None, datum=None, ll=None, **name):
58
+ def __init__(self, x_xyz, y=None, z=None, datum=None, **ll_name):
59
59
  '''New C{Cartesian...}.
60
60
 
61
61
  @arg x_xyz: Cartesian X coordinate (C{scalar}) or a C{Cartesian},
@@ -66,15 +66,15 @@ class CartesianBase(Vector3d):
66
66
  is not C{scalar}, otherwise same units as B{C{x_xyz}}.
67
67
  @kwarg datum: Optional datum (L{Datum}, L{Ellipsoid}, L{Ellipsoid2}
68
68
  or L{a_f2Tuple}).
69
- @kwarg ll: Optional, original latlon (C{LatLon}).
70
- @kwarg name: Optional C{B{name}=NN} (C{str}).
69
+ @kwarg ll_name: Optional C{B{name}=NN} (C{str}) and optional, original
70
+ latlon C{B{ll}=None} (C{LatLon}).
71
71
 
72
72
  @raise TypeError: Non-scalar B{C{x_xyz}}, B{C{y}} or B{C{z}} coordinate
73
73
  or B{C{x_xyz}} not a C{Cartesian}, L{Ecef9Tuple},
74
74
  L{Vector3Tuple} or L{Vector4Tuple} or B{C{datum}} is
75
75
  not a L{Datum}.
76
76
  '''
77
- h, d, n = _xyzhdn3(x_xyz, None, datum, ll, **name)
77
+ h, d, ll, n = _xyzhdlln4(x_xyz, None, datum, **ll_name)
78
78
  Vector3d.__init__(self, x_xyz, y=y, z=z, ll=ll, name=n)
79
79
  if h is not None:
80
80
  self._height = Height(h)
@@ -113,7 +113,7 @@ class CartesianBase(Vector3d):
113
113
 
114
114
  @see: Function L{pygeodesy.cassini} for references and more details.
115
115
  '''
116
- return self._resections.cassini(self, pointB, pointC, alpha, beta,
116
+ return _MODS.resections.cassini(self, pointB, pointC, alpha, beta,
117
117
  useZ=useZ, datum=self.datum)
118
118
 
119
119
  @deprecated_method
@@ -149,7 +149,7 @@ class CartesianBase(Vector3d):
149
149
 
150
150
  @see: Function L{pygeodesy.collins5} for references and more details.
151
151
  '''
152
- return self._resections.collins5(self, pointB, pointC, alpha, beta,
152
+ return _MODS.resections.collins5(self, pointB, pointC, alpha, beta,
153
153
  useZ=useZ, datum=self.datum)
154
154
 
155
155
  @deprecated_method
@@ -180,29 +180,37 @@ class CartesianBase(Vector3d):
180
180
  _update_all(self)
181
181
  self._datum = d
182
182
 
183
- def destinationXyz(self, delta, Cartesian=None, **Cartesian_kwds):
183
+ def destinationXyz(self, delta, Cartesian=None, **name_Cartesian_kwds):
184
184
  '''Calculate the destination using a I{local} delta from this cartesian.
185
185
 
186
- @arg delta: Local delta to the destination (L{XyzLocal}, L{Enu},
187
- L{Ned} or L{Local9Tuple}).
188
- @kwarg Cartesian: Optional (geocentric) class to return the
189
- destination or C{None}.
190
- @kwarg Cartesian_kwds: Optional, additional B{C{Cartesian}} keyword
191
- arguments, ignored if C{B{Cartesian} is None}.
186
+ @arg delta: Local delta to the destination (L{XyzLocal}, L{Enu}, L{Ned}
187
+ or L{Local9Tuple}).
188
+ @kwarg Cartesian: Optional (geocentric) class to return the destination
189
+ or C{None}.
190
+ @kwarg name_Cartesian_kwds: Optional C{B{name}=NN} (C{str}) and optional,
191
+ additional B{C{Cartesian}} keyword arguments, ignored if
192
+ C{B{Cartesian} is None}.
192
193
 
193
194
  @return: Destination as a C{B{Cartesian}(x, y, z, **B{Cartesian_kwds})}
194
195
  instance or if C{B{Cartesian} is None}, an L{Ecef9Tuple}C{(x, y,
195
196
  z, lat, lon, height, C, M, datum)} with C{M=None} always.
196
197
 
197
- @raise TypeError: Invalid B{C{delta}}, B{C{Cartesian}} or
198
- B{C{Cartesian_kwds}}.
198
+ @raise TypeError: Invalid B{C{delta}}, B{C{Cartesian}} or B{C{Cartesian_kwds}}
199
+ item or C{datum} missing or incompatible.
199
200
  '''
201
+ n, kwds = _name2__(name_Cartesian_kwds, _or_nameof=self)
200
202
  if Cartesian is None:
201
203
  r = self._Ltp._local2ecef(delta, nine=True)
202
204
  else:
203
- r = self._Ltp._local2ecef(delta, nine=False)
204
- r = Cartesian(*r, **_xkwds(Cartesian_kwds, datum=self.datum))
205
- return r._xnamed(r) if self.name else r
205
+ d = self.datum
206
+ if not d:
207
+ raise _TypeError(delta=delta, txt=_no_(_datum_))
208
+ t = _xkwds_get(kwds, datum=d)
209
+ if _xattr(t, ellipsoid=None) != d.ellipsoid:
210
+ raise _TypeError(datum=t, txt=str(d))
211
+ c = self._Ltp._local2ecef(delta, nine=False)
212
+ r = Cartesian(*c, **kwds)
213
+ return r.renamed(n) if n else r
206
214
 
207
215
  @property_RO
208
216
  def Ecef(self):
@@ -379,13 +387,13 @@ class CartesianBase(Vector3d):
379
387
  def isEllipsoidal(self):
380
388
  '''Check whether this cartesian is ellipsoidal (C{bool} or C{None} if unknown).
381
389
  '''
382
- return self.datum.isEllipsoidal if self._datum else None
390
+ return _xattr(self.datum, isEllipsoidal=None)
383
391
 
384
392
  @Property_RO
385
393
  def isSpherical(self):
386
394
  '''Check whether this cartesian is spherical (C{bool} or C{None} if unknown).
387
395
  '''
388
- return self.datum.isSpherical if self._datum else None
396
+ return _xattr(self.datum, isSpherical=None)
389
397
 
390
398
  @Property_RO
391
399
  def latlon(self):
@@ -405,26 +413,19 @@ class CartesianBase(Vector3d):
405
413
  '''
406
414
  return self.toEcef().latlonheightdatum
407
415
 
408
- @property_RO
409
- def _ltp(self):
410
- '''(INTERNAL) Get module C{.ltp}, I{once}.
411
- '''
412
- CartesianBase._ltp = m = _MODS.ltp # overwrite property_RO
413
- return m
414
-
415
416
  @Property_RO
416
417
  def _Ltp(self):
417
418
  '''(INTERNAL) Cache for L{toLtp}.
418
419
  '''
419
- return self._ltp.Ltp(self._ecef9, ecef=self.Ecef(self.datum), name=self.name)
420
+ return _MODS.ltp.Ltp(self._ecef9, ecef=self.Ecef(self.datum), name=self.name)
420
421
 
421
422
  @Property_RO
422
423
  def _N_vector(self):
423
424
  '''(INTERNAL) Get the (C{nvectorBase._N_vector_}).
424
425
  '''
425
- m = _MODS.nvectorBase
426
+ _N = _MODS.nvectorBase._N_vector_
426
427
  x, y, z, h = self._n_xyzh4(self.datum)
427
- return m._N_vector_(x, y, z, h=h, name=self.name)
428
+ return _N(x, y, z, h=h, name=self.name)
428
429
 
429
430
  def _n_xyzh4(self, datum):
430
431
  '''(INTERNAL) Get the n-vector components as L{Vector4Tuple}.
@@ -516,7 +517,7 @@ class CartesianBase(Vector3d):
516
517
 
517
518
  @see: Function L{pygeodesy.pierlot} for references and more details.
518
519
  '''
519
- return self._resections.pierlot(self, point2, point3, alpha12, alpha23,
520
+ return _MODS.resections.pierlot(self, point2, point3, alpha12, alpha23,
520
521
  useZ=useZ, eps=eps, datum=self.datum)
521
522
 
522
523
  def pierlotx(self, point2, point3, alpha1, alpha2, alpha3, useZ=False):
@@ -543,16 +544,9 @@ class CartesianBase(Vector3d):
543
544
 
544
545
  @see: Function L{pygeodesy.pierlotx} for references and more details.
545
546
  '''
546
- return self._resections.pierlotx(self, point2, point3, alpha1, alpha2, alpha3,
547
+ return _MODS.resections.pierlotx(self, point2, point3, alpha1, alpha2, alpha3,
547
548
  useZ=useZ, datum=self.datum)
548
549
 
549
- @property_RO
550
- def _resections(self):
551
- '''(INTERNAL) Import the C{.resections} module, I{once}.
552
- '''
553
- CartesianBase._resections = m = _MODS.resections # overwrite property_RO
554
- return m
555
-
556
550
  def Roc2(self, earth=None):
557
551
  '''Compute this cartesian's I{normal} and I{pseudo, z-based} radius of curvature.
558
552
 
@@ -624,7 +618,7 @@ class CartesianBase(Vector3d):
624
618
 
625
619
  @see: Function L{pygeodesy.tienstra7} for references and more details.
626
620
  '''
627
- return self._resections.tienstra7(self, pointB, pointC, alpha, beta, gamma,
621
+ return _MODS.resections.tienstra7(self, pointB, pointC, alpha, beta, gamma,
628
622
  useZ=useZ, datum=self.datum)
629
623
 
630
624
  @deprecated_method
@@ -685,8 +679,8 @@ class CartesianBase(Vector3d):
685
679
  if d == datum2:
686
680
  return c.copy() if c is self else c
687
681
 
688
- elif datum2.transform.isunity and \
689
- d.transform.isunity:
682
+ elif d is None or (d.transform.isunity and
683
+ datum2.transform.isunity):
690
684
  return c.dup(datum=datum2)
691
685
 
692
686
  elif d == _WGS84:
@@ -746,46 +740,45 @@ class CartesianBase(Vector3d):
746
740
  def toLocal(self, Xyz=None, ltp=None, **Xyz_kwds):
747
741
  '''Convert this I{geocentric} cartesian to I{local} C{X}, C{Y} and C{Z}.
748
742
 
749
- @kwarg Xyz: Optional class to return C{X}, C{Y} and C{Z}
750
- (L{XyzLocal}, L{Enu}, L{Ned}) or C{None}.
751
- @kwarg ltp: The I{local tangent plane} (LTP) to use,
752
- overriding this cartesian's LTP (L{Ltp}).
753
- @kwarg Xyz_kwds: Optional, additional B{C{Xyz}} keyword
754
- arguments, ignored if C{B{Xyz} is None}.
743
+ @kwarg Xyz: Optional class to return C{X}, C{Y} and C{Z} (L{XyzLocal},
744
+ L{Enu}, L{Ned}) or C{None}.
745
+ @kwarg ltp: The I{local tangent plane} (LTP) to use, overriding this
746
+ cartesian's LTP (L{Ltp}).
747
+ @kwarg Xyz_kwds: Optional, additional B{C{Xyz}} keyword arguments,
748
+ ignored if C{B{Xyz} is None}.
755
749
 
756
- @return: An B{C{Xyz}} instance or if C{B{Xyz} is None},
757
- a L{Local9Tuple}C{(x, y, z, lat, lon, height,
758
- ltp, ecef, M)} with C{M=None} always.
750
+ @return: An B{C{Xyz}} instance or a L{Local9Tuple}C{(x, y, z, lat, lon,
751
+ height, ltp, ecef, M)} if C{B{Xyz} is None} (with C{M=None}).
759
752
 
760
753
  @raise TypeError: Invalid B{C{ltp}}.
761
754
  '''
762
- p = self._ltp._xLtp(ltp, self._Ltp)
763
- return p._ecef2local(self._ecef9, Xyz, Xyz_kwds)
755
+ return _MODS.ltp._toLocal(self, ltp, Xyz, Xyz_kwds) # self._ecef9
764
756
 
765
- def toLtp(self, Ecef=None):
757
+ def toLtp(self, Ecef=None, **name):
766
758
  '''Return the I{local tangent plane} (LTP) for this cartesian.
767
759
 
768
760
  @kwarg Ecef: Optional ECEF I{class} (L{EcefKarney}, ...
769
761
  L{EcefYou}), overriding this cartesian's C{Ecef}.
762
+ @kwarg name: Optional C{B{name}=NN} (C{str}).
770
763
  '''
771
- return self._Ltp if Ecef in (None, self.Ecef) else self._ltp.Ltp(
772
- self._ecef9, ecef=Ecef(self.datum), name=self.name)
764
+ return _MODS.ltp._toLtp(self, Ecef, self._ecef9, name) # self._Ltp
773
765
 
774
- def toNvector(self, Nvector=None, datum=None, **Nvector_kwds):
766
+ def toNvector(self, Nvector=None, datum=None, **name_Nvector_kwds):
775
767
  '''Convert this cartesian to C{n-vector} components, I{including height}.
776
768
 
777
769
  @kwarg Nvector: Optional class to return the C{n-vector} components
778
770
  (C{Nvector}) or C{None}.
779
771
  @kwarg datum: Optional datum (L{Datum}, L{Ellipsoid}, L{Ellipsoid2}
780
772
  or L{a_f2Tuple}) overriding this cartesian's datum.
781
- @kwarg Nvector_kwds: Optional, additional B{C{Nvector}} keyword
782
- arguments, ignored if C{B{Nvector} is None}.
773
+ @kwarg name_Nvector_kwds: Optional C{B{name}=NN} (C{str}) and optional,
774
+ additional B{C{Nvector}} keyword arguments, ignored if
775
+ C{B{Nvector} is None}.
783
776
 
784
777
  @return: An B{C{Nvector}} or a L{Vector4Tuple}C{(x, y, z, h)} if
785
778
  B{C{Nvector}} is C{None}.
786
779
 
787
- @raise TypeError: Invalid B{C{Nvector}}, B{C{Nvector_kwds}} or
788
- B{C{datum}}.
780
+ @raise TypeError: Invalid B{C{Nvector}}, B{C{datum}} or
781
+ B{C{name_Nvector_kwds}} item.
789
782
 
790
783
  @raise ValueError: B{C{Cartesian}} at origin.
791
784
  '''
@@ -795,9 +788,13 @@ class CartesianBase(Vector3d):
795
788
  if d != self.datum:
796
789
  r = self._n_xyzh4(d)
797
790
 
798
- if Nvector is not None:
799
- kwds = _xkwds(Nvector_kwds, h=r.h, datum=d)
800
- r = self._xnamed(Nvector(r.x, r.y, r.z, **kwds))
791
+ if Nvector is None:
792
+ n, _ = _name2__(name_Nvector_kwds, _or_nameof=self)
793
+ if n:
794
+ r = r.dup(name=n)
795
+ else:
796
+ kwds = _xkwds(name_Nvector_kwds, h=r.h, datum=d)
797
+ r = Nvector(r.x, r.y, r.z, **self._name1__(kwds))
801
798
  return r
802
799
 
803
800
  def toRtp(self):
@@ -858,11 +855,11 @@ class CartesianBase(Vector3d):
858
855
 
859
856
  @raise TypeError: Invalid B{C{Vector}} or B{C{Vector_kwds}}.
860
857
  '''
861
- return self.xyz if Vector is None else self._xnamed(
862
- Vector(self.x, self.y, self.z, **Vector_kwds))
858
+ return self.xyz if Vector is None else Vector(
859
+ self.x, self.y, self.z, **self._name1__(Vector_kwds))
863
860
 
864
861
 
865
- class RadiusThetaPhi3Tuple(_NamedTuple):
862
+ class RadiusThetaPhi3Tuple(_NamedTupleTo):
866
863
  '''3-Tuple C{(r, theta, phi)} with radial distance C{r} in C{meter}, inclination
867
864
  C{theta} (with respect to the positive z-axis) and azimuthal angle C{phi} in
868
865
  L{Degrees} I{or} L{Radians} representing a U{spherical, polar position
@@ -885,89 +882,89 @@ class RadiusThetaPhi3Tuple(_NamedTuple):
885
882
  @see: Function L{rtp2xyz_}.
886
883
  '''
887
884
  r, t, p = self
888
- t, p, _ = _toRadians(self, t, p)
889
- n, kwds = _name2__(name_Cartesian_and_kwds, _or_nameof=self)
890
- return rtp2xyz_(r, t, p, name=n, **kwds)
885
+ t, p, _ = _NamedTupleTo._Radians3(self, t, p)
886
+ return rtp2xyz_(r, t, p, **name_Cartesian_and_kwds)
891
887
 
892
888
  def toDegrees(self, **name):
893
889
  '''Convert this L{RadiusThetaPhi3Tuple}'s angles to L{Degrees}.
894
890
 
895
- @kwarg name: Optional name (C{str}), overriding this name.
891
+ @kwarg name: Optional C{B{name}=NN} (C{str}), overriding this name.
896
892
 
897
893
  @return: L{RadiusThetaPhi3Tuple}C{(r, theta, phi)} with C{theta}
898
894
  and C{phi} both in L{Degrees}.
899
895
  '''
900
- r, t, p = self
901
- t, p, _ = _toDegrees(self, t, p)
902
- return _ or self.classof(r, Degrees(theta=t), Degrees(phi=p),
903
- name=_name__(name, _or_nameof=self))
896
+ return self._toX3U(_NamedTupleTo._Degrees3, Degrees, name)
904
897
 
905
898
  def toRadians(self, **name):
906
899
  '''Convert this L{RadiusThetaPhi3Tuple}'s angles to L{Radians}.
907
900
 
908
- @kwarg name: Optional, overriding C{B{name}=NN} (C{str}).
901
+ @kwarg name: Optional C{B{name}=NN} (C{str}), overriding this name.
909
902
 
910
- @return: L{RadiusThetaPhi3Tuple}C{(r, theta, phi)} with
911
- C{theta} and C{phi} both in L{Radians}.
903
+ @return: L{RadiusThetaPhi3Tuple}C{(r, theta, phi)} with C{theta}
904
+ and C{phi} both in L{Radians}.
912
905
  '''
913
- r, t, p = self
914
- t, p, _ = _toRadians(self, t, p)
915
- return _ or self.classof(r, Radians(theta=t), Radians(phi=p),
916
- name=_name__(name, _or_nameof=self))
906
+ return self._toX3U(_NamedTupleTo._Radians3, Radians, name)
917
907
 
908
+ def _toU(self, U):
909
+ M = RadiusThetaPhi3Tuple._Units_[0] # Meter
910
+ return self.reUnit(M, U, U).toUnits()
918
911
 
919
- def rtp2xyz(r_rtp, *theta_phi, **name_Cartesian_and_kwds):
920
- '''Convert I{spherical, polar} C{(r, theta, phi)} to cartesian C{(x, y, z)} coordinates.
912
+ def _toX3U(self, _X3, U, name):
913
+ r, t, p = self
914
+ t, p, s = _X3(self, t, p)
915
+ if s is None or name:
916
+ n = self._name__(name)
917
+ s = self.classof(r, t, p, name=n)._toU(U)
918
+ return s
921
919
 
922
- @arg r_rtp: Radial distance (C{scalar}, conventially C{meter}) or a previous
923
- L{RadiusThetaPhi3Tuple} instance.
924
- @arg theta_phi: Inclination B{C{theta}} (C{degrees} with respect to the positive z-axis)
925
- and azimuthal angle B{C{phi}} (C{degrees}), ignored if C{B{r_rtp}} is a
926
- L{RadiusThetaPhi3Tuple}.
927
- @kwarg name_Cartesian_and_kwds: Optional C{B{name}=NN} (C{str}), a C{B{Cartesian}=None}
928
- class to return the coordinates and additional C{B{Cartesian}}
929
- keyword arguments.
930
920
 
931
- @return: A C{B{Cartesian}(x, y, z)} instance or if no C{B{Cartesian}} keyword argument
932
- is given a L{Vector3Tuple}C{(x, y, z)}, with C{x}, C{y} and C{z} in the same
933
- units as radius C{r}, C{meter} conventionally.
921
+ def rtp2xyz(r_rtp, theta=0, phi=0, **name_Cartesian_and_kwds):
922
+ '''Convert I{spherical, polar} C{(r, theta, phi)} to cartesian C{(x, y, z)} coordinates.
934
923
 
935
- @raise TypeError: Invalid B{C{r_rtp}}.
924
+ @arg theta: Inclination B{C{theta}} (C{degrees} with respect to the positive z-axis),
925
+ required if C{B{r_rtp}} is C{scalar}, ignored otherwise.
926
+ @arg phi: Azimuthal angle B{C{phi}} (C{degrees}), required if C{B{r_rtp}} is C{scalar},
927
+ ignored otherwise.
936
928
 
937
- @see: Functions L{rtp2xyz_} and L{xyz2rtp}.
929
+ @see: Function L{rtp2xyz_} for further details.
938
930
  '''
939
931
  if isinstance(r_rtp, RadiusThetaPhi3Tuple):
940
932
  c = r_rtp.toCartesian(**name_Cartesian_and_kwds)
941
933
  else:
942
- c = rtp2xyz_(r_rtp, *map(radians, theta_phi), **name_Cartesian_and_kwds)
934
+ c = rtp2xyz_(r_rtp, radians(theta), radians(phi), **name_Cartesian_and_kwds)
943
935
  return c
944
936
 
945
937
 
946
- def rtp2xyz_(r_rtp, *theta_phi, **name_Cartesian_and_kwds):
938
+ def rtp2xyz_(r_rtp, theta=0, phi=0, **name_Cartesian_and_kwds):
947
939
  '''Convert I{spherical, polar} C{(r, theta, phi)} to cartesian C{(x, y, z)} coordinates.
948
940
 
949
941
  @arg r_rtp: Radial distance (C{scalar}, conventially C{meter}) or a previous
950
942
  L{RadiusThetaPhi3Tuple} instance.
951
- @arg theta_phi: Inclination B{C{theta}} (C{radians} with respect to the positive z-axis)
952
- and azimuthal angle B{C{phi}} (C{degrees}), ignored is C{B{r_rtp}} is a
953
- L{RadiusThetaPhi3Tuple}.
943
+ @arg theta: Inclination B{C{theta}} (C{radians} with respect to the positive z-axis),
944
+ required if C{B{r_rtp}} is C{scalar}, ignored otherwise.
945
+ @arg phi: Azimuthal angle B{C{phi}} (C{radians}), required if C{B{r_rtp}} is C{scalar},
946
+ ignored otherwise.
954
947
  @kwarg name_Cartesian_and_kwds: Optional C{B{name}=NN} (C{str}), a C{B{Cartesian}=None}
955
- class to return the coordinates and additional C{B{Cartesian}}
956
- keyword arguments.
948
+ class to return the coordinates and optional, additional C{B{Cartesian}}
949
+ keyword arguments.
957
950
 
958
951
  @return: A C{B{Cartesian}(x, y, z)} instance or if no C{B{Cartesian}} keyword argument
959
952
  is given a L{Vector3Tuple}C{(x, y, z)}, with C{x}, C{y} and C{z} in the same
960
953
  units as radius C{r}, C{meter} conventionally.
961
954
 
962
- @raise TypeError: Invalid B{C{r_rtp}} or B{C{theta_phi}}.
955
+ @raise TypeError: Invalid B{C{r_rtp}}, B{C{theta}}, B{C{phi}} or
956
+ B{C{name_Cartesian_and_kwds}} item.
963
957
 
964
958
  @see: U{Physics convention<https://WikiPedia.org/wiki/Spherical_coordinate_system>}
965
- (ISO 80000-2:2019).
959
+ (ISO 80000-2:2019), class L{RadiusThetaPhi3Tuple} and functions L{rtp2xyz}
960
+ and L{xyz2rtp}.
966
961
  '''
967
- if _isMeter(r_rtp) and len(theta_phi) == 2:
962
+ if isinstance(r_rtp, RadiusThetaPhi3Tuple):
963
+ c = r_rtp.toCartesian(**name_Cartesian_and_kwds)
964
+ elif _isMeter(r_rtp):
968
965
  r = r_rtp
969
966
  if r and _isfinite(r):
970
- s, z, y, x = sincos2_(*theta_phi)
967
+ s, z, y, x = sincos2_(theta, phi)
971
968
  s *= r
972
969
  z *= r
973
970
  y *= s
@@ -975,22 +972,16 @@ def rtp2xyz_(r_rtp, *theta_phi, **name_Cartesian_and_kwds):
975
972
  else:
976
973
  x = y = z = r
977
974
 
978
- def _n_C_kwds3(Cartesian=None, **name_kwds):
979
- n, kwds = _name2__(**name_kwds)
980
- return n, Cartesian, kwds
981
-
982
- n, C, kwds = _n_C_kwds3(**name_Cartesian_and_kwds)
975
+ n, kwds = _name2__(**name_Cartesian_and_kwds)
976
+ C, kwds = _xkwds_pop2(kwds, Cartesian=None)
983
977
  c = Vector3Tuple(x, y, z, name=n) if C is None else \
984
978
  C(x, y, z, name=n, **kwds)
985
-
986
- elif isinstance(r_rtp, RadiusThetaPhi3Tuple):
987
- c = r_rtp.toCartesian(**name_Cartesian_and_kwds)
988
979
  else:
989
- raise _TypeError(r_rtp=r_rtp, theta_phi=theta_phi)
980
+ raise _TypeError(r_rtp=r_rtp, theta=theta, phi=phi)
990
981
  return c
991
982
 
992
983
 
993
- def _rtp3(where, Unit, *x_y_z, **name):
984
+ def _rtp3(where, U, *x_y_z, **name):
994
985
  '''(INTERNAL) Helper for C{.toRtp}, C{xyz2rtp} and C{xyz2rtp_}.
995
986
  '''
996
987
  x, y, z = _MODS.vector3dBase._xyz3(where, *x_y_z)
@@ -1000,43 +991,43 @@ def _rtp3(where, Unit, *x_y_z, **name):
1000
991
  p = atan2(y, x)
1001
992
  while p < 0:
1002
993
  p += PI2
1003
- if Unit is Degrees:
994
+ if U is Degrees:
1004
995
  t = degrees(t)
1005
996
  p = degrees(p)
1006
997
  else:
1007
998
  t = p = _0_0
1008
- return RadiusThetaPhi3Tuple(r, Unit(theta=t), Unit(phi=p), **name)
999
+ return RadiusThetaPhi3Tuple(r, t, p, **name)._toU(U)
1009
1000
 
1010
1001
 
1011
- def xyz2rtp(x_xyz, *y_z, **name):
1002
+ def xyz2rtp(x_xyz, y=0, z=0, **name):
1012
1003
  '''Convert cartesian C{(x, y, z)} to I{spherical, polar} C{(r, theta, phi)} coordinates.
1013
1004
 
1014
- @return: L{RadiusThetaPhi3Tuple}C{(r, theta, phi)} with C{theta} and C{phi},
1015
- both in L{Degrees}.
1005
+ @return: L{RadiusThetaPhi3Tuple}C{(r, theta, phi)} with C{theta} and C{phi}, both
1006
+ in L{Degrees}.
1016
1007
 
1017
- @see: Function L{xyz2rtp_} and class L{RadiusThetaPhi3Tuple}.
1008
+ @see: Function L{xyz2rtp_} for further details.
1018
1009
  '''
1019
- return _rtp3(xyz2rtp, Degrees, x_xyz, *y_z, **name)
1010
+ return _rtp3(xyz2rtp, Degrees, x_xyz, y, z, **name)
1020
1011
 
1021
1012
 
1022
- def xyz2rtp_(x_xyz, *y_z, **name):
1013
+ def xyz2rtp_(x_xyz, y=0, z=0, **name):
1023
1014
  '''Convert cartesian C{(x, y, z)} to I{spherical, polar} C{(r, theta, phi)} coordinates.
1024
1015
 
1025
1016
  @arg x_xyz: X component (C{scalar}) or a cartesian (C{Cartesian}, L{Ecef9Tuple},
1026
- C{Nvector}, L{Vector3d}, L{Vector3Tuple}, L{Vector4Tuple} or a
1027
- C{tuple} or C{list} of 3+ C{scalar} items) if no C{y_z} specified.
1028
- @arg y_z: Y and Z component (C{scalar}s), ignored if C{x_xyz} is not a C{scalar}.
1017
+ C{Nvector}, L{Vector3d}, L{Vector3Tuple}, L{Vector4Tuple} or a C{tuple} or
1018
+ C{list} of 3+ C{scalar} items) if no C{y_z} specified.
1019
+ @arg y: Y component (C{scalar}), required if C{B{x_xyz}} is C{scalar}, ignored otherwise.
1020
+ @arg z: Z component (C{scalar}), required if C{B{x_xyz}} is C{scalar}, ignored otherwise.
1029
1021
  @kwarg name: Optional C{B{name}=NN} (C{str}).
1030
1022
 
1031
- @return: L{RadiusThetaPhi3Tuple}C{(r, theta, phi)} with radial distance C{r}
1032
- (C{meter}, same units as C{x}, C{y} and C{z}), inclination C{theta}
1033
- (with respect to the positive z-axis) and azimuthal angle C{phi},
1034
- both in L{Radians}.
1023
+ @return: L{RadiusThetaPhi3Tuple}C{(r, theta, phi)} with radial distance C{r} (C{meter},
1024
+ same units as C{x}, C{y} and C{z}), inclination C{theta} (with respect to the
1025
+ positive z-axis) and azimuthal angle C{phi}, both in L{Radians}.
1035
1026
 
1036
1027
  @see: U{Physics convention<https://WikiPedia.org/wiki/Spherical_coordinate_system>}
1037
- (ISO 80000-2:2019).
1028
+ (ISO 80000-2:2019), class L{RadiusThetaPhi3Tuple} and function L{xyz2rtp}.
1038
1029
  '''
1039
- return _rtp3(xyz2rtp_, Radians, x_xyz, *y_z, **name)
1030
+ return _rtp3(xyz2rtp_, Radians, x_xyz, y, z, **name)
1040
1031
 
1041
1032
 
1042
1033
  __all__ += _ALL_DOCS(CartesianBase)
pygeodesy/constants.py CHANGED
@@ -10,7 +10,7 @@ L{pygeodesy.isnon0} and L{pygeodesy.remainder}.
10
10
  from __future__ import division as _; del _ # PYCHOK semicolon
11
11
 
12
12
  from pygeodesy.basics import _copysign, isbool, iscomplex, isint, _0_0
13
- from pygeodesy.errors import _xError, _xError2, _xkwds_get, _xkwds_item2
13
+ from pygeodesy.errors import _xError, _xError2, _xkwds_get1, _xkwds_item2
14
14
  # from pygeodesy.internals import _0_0 # from .basics
15
15
  from pygeodesy.interns import _INF_, _NAN_, _UNDER_
16
16
  # from pygeodesy.lazily import _ALL_LAZY # from .unitsBase
@@ -24,7 +24,7 @@ except ImportError: # Python 2-
24
24
  _inf, _nan = float(_INF_), float(_NAN_)
25
25
 
26
26
  __all__ = _ALL_LAZY.constants
27
- __version__ = '24.05.14'
27
+ __version__ = '24.05.29'
28
28
 
29
29
 
30
30
  def _copysign_0_0(y):
@@ -73,7 +73,7 @@ def float_(*fs, **sets): # sets=False
73
73
  '''
74
74
  fl = []
75
75
  _a = fl.append
76
- _f = _floats.setdefault if _xkwds_get(sets, sets=False) else \
76
+ _f = _floats.setdefault if _xkwds_get1(sets, sets=False) else \
77
77
  _floats.get
78
78
  try:
79
79
  for i, f in enumerate(fs):
@@ -14,7 +14,7 @@ from pygeodesy.props import deprecated_function
14
14
  from pygeodesy.units import Number_, Scalar_
15
15
 
16
16
  __all__ = _ALL_DEPRECATED.deprecated_functions
17
- __version__ = '24.02.08'
17
+ __version__ = '24.05.25'
18
18
 
19
19
  _WGS84 = _UTM = object()
20
20
 
@@ -109,13 +109,19 @@ def enStr2(easting, northing, prec, *extras): # PYCHOK no cover
109
109
  return _MODS.streprs.enstr2(easting, northing, (int(prec) // 2 - 5), *extras)
110
110
 
111
111
 
112
+ @deprecated_function
113
+ def equirectangular_(lat1, lon1, lat2, lon2, **options): # PYCHOK no cover
114
+ '''DEPRECATED on 2024.05.25, use function L{pygeodesy.equirectangular4}.'''
115
+ return _MODS.formy.equirectangular4(lat1, lon1, lat2, lon2, **options)
116
+
117
+
112
118
  @deprecated_function
113
119
  def equirectangular3(lat1, lon1, lat2, lon2, **options): # PYCHOK no cover
114
- '''DEPRECATED, use function L{pygeodesy.equirectangular_}.
120
+ '''DEPRECATED, use function L{pygeodesy.equirectangular4}.
115
121
 
116
122
  @return: 3-Tuple C{(distance2, delta_lat, delta_lon)}.
117
123
  '''
118
- return tuple(_MODS.formy.equirectangular_(lat1, lon1, lat2, lon2, **options)[:3])
124
+ return tuple(_MODS.formy.equirectangular4(lat1, lon1, lat2, lon2, **options)[:3])
119
125
 
120
126
 
121
127
  @deprecated_function