pygeodesy 24.6.1__py2.py3-none-any.whl → 24.6.24__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. {PyGeodesy-24.6.1.dist-info → PyGeodesy-24.6.24.dist-info}/METADATA +2 -2
  2. PyGeodesy-24.6.24.dist-info/RECORD +117 -0
  3. pygeodesy/__init__.py +33 -32
  4. pygeodesy/albers.py +2 -2
  5. pygeodesy/auxilats/__init__.py +1 -1
  6. pygeodesy/auxilats/auxAngle.py +40 -39
  7. pygeodesy/auxilats/auxDLat.py +3 -2
  8. pygeodesy/auxilats/auxLat.py +16 -18
  9. pygeodesy/auxilats/auxily.py +1 -1
  10. pygeodesy/azimuthal.py +10 -10
  11. pygeodesy/basics.py +9 -1
  12. pygeodesy/booleans.py +53 -66
  13. pygeodesy/cartesianBase.py +143 -155
  14. pygeodesy/css.py +14 -18
  15. pygeodesy/datums.py +6 -6
  16. pygeodesy/deprecated/__init__.py +1 -1
  17. pygeodesy/deprecated/classes.py +16 -2
  18. pygeodesy/deprecated/datum.py +3 -3
  19. pygeodesy/deprecated/functions.py +6 -8
  20. pygeodesy/dms.py +23 -27
  21. pygeodesy/ecef.py +49 -55
  22. pygeodesy/elevations.py +4 -4
  23. pygeodesy/ellipsoidalBase.py +28 -70
  24. pygeodesy/ellipsoidalBaseDI.py +19 -23
  25. pygeodesy/ellipsoidalExact.py +3 -3
  26. pygeodesy/ellipsoidalGeodSolve.py +15 -23
  27. pygeodesy/ellipsoidalKarney.py +37 -60
  28. pygeodesy/ellipsoidalNvector.py +44 -50
  29. pygeodesy/ellipsoidalVincenty.py +11 -14
  30. pygeodesy/ellipsoids.py +107 -101
  31. pygeodesy/errors.py +101 -49
  32. pygeodesy/etm.py +32 -44
  33. pygeodesy/formy.py +55 -58
  34. pygeodesy/frechet.py +20 -23
  35. pygeodesy/fsums.py +4 -4
  36. pygeodesy/gars.py +3 -4
  37. pygeodesy/geodesici.py +909 -0
  38. pygeodesy/geodesicw.py +11 -13
  39. pygeodesy/geodesicx/__init__.py +4 -4
  40. pygeodesy/geodesicx/gx.py +18 -28
  41. pygeodesy/geodesicx/gxbases.py +20 -8
  42. pygeodesy/geodesicx/gxline.py +16 -22
  43. pygeodesy/geodsolve.py +102 -34
  44. pygeodesy/geohash.py +39 -60
  45. pygeodesy/geoids.py +28 -37
  46. pygeodesy/hausdorff.py +21 -23
  47. pygeodesy/heights.py +15 -28
  48. pygeodesy/internals.py +19 -12
  49. pygeodesy/interns.py +4 -10
  50. pygeodesy/iters.py +2 -2
  51. pygeodesy/karney.py +20 -4
  52. pygeodesy/ktm.py +13 -16
  53. pygeodesy/latlonBase.py +202 -191
  54. pygeodesy/lazily.py +96 -59
  55. pygeodesy/lcc.py +29 -32
  56. pygeodesy/ltp.py +43 -24
  57. pygeodesy/ltpTuples.py +190 -183
  58. pygeodesy/mgrs.py +35 -9
  59. pygeodesy/named.py +106 -72
  60. pygeodesy/namedTuples.py +43 -14
  61. pygeodesy/nvectorBase.py +23 -27
  62. pygeodesy/osgr.py +9 -9
  63. pygeodesy/points.py +7 -7
  64. pygeodesy/rhumb/__init__.py +1 -1
  65. pygeodesy/rhumb/aux_.py +5 -5
  66. pygeodesy/rhumb/bases.py +30 -31
  67. pygeodesy/rhumb/ekx.py +3 -4
  68. pygeodesy/rhumb/solve.py +8 -61
  69. pygeodesy/solveBase.py +22 -19
  70. pygeodesy/sphericalBase.py +26 -21
  71. pygeodesy/sphericalNvector.py +13 -13
  72. pygeodesy/sphericalTrigonometry.py +86 -97
  73. pygeodesy/streprs.py +8 -36
  74. pygeodesy/trf.py +3 -3
  75. pygeodesy/triaxials.py +117 -91
  76. pygeodesy/units.py +229 -321
  77. pygeodesy/unitsBase.py +116 -108
  78. pygeodesy/ups.py +26 -31
  79. pygeodesy/utily.py +12 -11
  80. pygeodesy/utm.py +35 -40
  81. pygeodesy/utmups.py +43 -46
  82. pygeodesy/utmupsBase.py +9 -10
  83. pygeodesy/vector3d.py +59 -62
  84. pygeodesy/vector3dBase.py +17 -15
  85. pygeodesy/webmercator.py +19 -21
  86. pygeodesy/wgrs.py +18 -20
  87. PyGeodesy-24.6.1.dist-info/RECORD +0 -116
  88. {PyGeodesy-24.6.1.dist-info → PyGeodesy-24.6.24.dist-info}/WHEEL +0 -0
  89. {PyGeodesy-24.6.1.dist-info → PyGeodesy-24.6.24.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.11'
47
47
 
48
48
  _r_ = 'r'
49
49
  _theta_ = 'theta'
@@ -55,26 +55,25 @@ 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},
62
62
  L{Ecef9Tuple}, L{Vector3Tuple} or L{Vector4Tuple}.
63
63
  @kwarg y: Cartesian Y coordinate (C{scalar}), ignored if B{C{x_xyz}}
64
64
  is not C{scalar}, otherwise same units as B{C{x_xyz}}.
65
- @kwarg z: Cartesian Z coordinate (C{scalar}), ignored if B{C{x_xyz}}
66
- is not C{scalar}, otherwise same units as B{C{x_xyz}}.
65
+ @kwarg z: Cartesian Z coordinate (C{scalar}), like B{C{y}}.
67
66
  @kwarg datum: Optional datum (L{Datum}, L{Ellipsoid}, L{Ellipsoid2}
68
67
  or L{a_f2Tuple}).
69
- @kwarg ll: Optional, original latlon (C{LatLon}).
70
- @kwarg name: Optional C{B{name}=NN} (C{str}).
68
+ @kwarg ll_name: Optional C{B{name}=NN} (C{str}) and optional, original
69
+ latlon C{B{ll}=None} (C{LatLon}).
71
70
 
72
71
  @raise TypeError: Non-scalar B{C{x_xyz}}, B{C{y}} or B{C{z}} coordinate
73
72
  or B{C{x_xyz}} not a C{Cartesian}, L{Ecef9Tuple},
74
73
  L{Vector3Tuple} or L{Vector4Tuple} or B{C{datum}} is
75
74
  not a L{Datum}.
76
75
  '''
77
- h, d, n = _xyzhdn3(x_xyz, None, datum, ll, **name)
76
+ h, d, ll, n = _xyzhdlln4(x_xyz, None, datum, **ll_name)
78
77
  Vector3d.__init__(self, x_xyz, y=y, z=z, ll=ll, name=n)
79
78
  if h is not None:
80
79
  self._height = Height(h)
@@ -113,7 +112,7 @@ class CartesianBase(Vector3d):
113
112
 
114
113
  @see: Function L{pygeodesy.cassini} for references and more details.
115
114
  '''
116
- return self._resections.cassini(self, pointB, pointC, alpha, beta,
115
+ return _MODS.resections.cassini(self, pointB, pointC, alpha, beta,
117
116
  useZ=useZ, datum=self.datum)
118
117
 
119
118
  @deprecated_method
@@ -149,7 +148,7 @@ class CartesianBase(Vector3d):
149
148
 
150
149
  @see: Function L{pygeodesy.collins5} for references and more details.
151
150
  '''
152
- return self._resections.collins5(self, pointB, pointC, alpha, beta,
151
+ return _MODS.resections.collins5(self, pointB, pointC, alpha, beta,
153
152
  useZ=useZ, datum=self.datum)
154
153
 
155
154
  @deprecated_method
@@ -180,29 +179,37 @@ class CartesianBase(Vector3d):
180
179
  _update_all(self)
181
180
  self._datum = d
182
181
 
183
- def destinationXyz(self, delta, Cartesian=None, **Cartesian_kwds):
182
+ def destinationXyz(self, delta, Cartesian=None, **name_Cartesian_kwds):
184
183
  '''Calculate the destination using a I{local} delta from this cartesian.
185
184
 
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}.
185
+ @arg delta: Local delta to the destination (L{XyzLocal}, L{Enu}, L{Ned}
186
+ or L{Local9Tuple}).
187
+ @kwarg Cartesian: Optional (geocentric) class to return the destination
188
+ or C{None}.
189
+ @kwarg name_Cartesian_kwds: Optional C{B{name}=NN} (C{str}) and optional,
190
+ additional B{C{Cartesian}} keyword arguments, ignored if
191
+ C{B{Cartesian} is None}.
192
192
 
193
193
  @return: Destination as a C{B{Cartesian}(x, y, z, **B{Cartesian_kwds})}
194
194
  instance or if C{B{Cartesian} is None}, an L{Ecef9Tuple}C{(x, y,
195
195
  z, lat, lon, height, C, M, datum)} with C{M=None} always.
196
196
 
197
- @raise TypeError: Invalid B{C{delta}}, B{C{Cartesian}} or
198
- B{C{Cartesian_kwds}}.
197
+ @raise TypeError: Invalid B{C{delta}}, B{C{Cartesian}} or B{C{Cartesian_kwds}}
198
+ item or C{datum} missing or incompatible.
199
199
  '''
200
+ n, kwds = _name2__(name_Cartesian_kwds, _or_nameof=self)
200
201
  if Cartesian is None:
201
202
  r = self._Ltp._local2ecef(delta, nine=True)
202
203
  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
204
+ d = self.datum
205
+ if not d:
206
+ raise _TypeError(delta=delta, txt=_no_(_datum_))
207
+ t = _xkwds_get(kwds, datum=d)
208
+ if _xattr(t, ellipsoid=None) != d.ellipsoid:
209
+ raise _TypeError(datum=t, txt=str(d))
210
+ c = self._Ltp._local2ecef(delta, nine=False)
211
+ r = Cartesian(*c, **kwds)
212
+ return r.renamed(n) if n else r
206
213
 
207
214
  @property_RO
208
215
  def Ecef(self):
@@ -379,13 +386,13 @@ class CartesianBase(Vector3d):
379
386
  def isEllipsoidal(self):
380
387
  '''Check whether this cartesian is ellipsoidal (C{bool} or C{None} if unknown).
381
388
  '''
382
- return self.datum.isEllipsoidal if self._datum else None
389
+ return _xattr(self.datum, isEllipsoidal=None)
383
390
 
384
391
  @Property_RO
385
392
  def isSpherical(self):
386
393
  '''Check whether this cartesian is spherical (C{bool} or C{None} if unknown).
387
394
  '''
388
- return self.datum.isSpherical if self._datum else None
395
+ return _xattr(self.datum, isSpherical=None)
389
396
 
390
397
  @Property_RO
391
398
  def latlon(self):
@@ -405,26 +412,19 @@ class CartesianBase(Vector3d):
405
412
  '''
406
413
  return self.toEcef().latlonheightdatum
407
414
 
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
415
  @Property_RO
416
416
  def _Ltp(self):
417
417
  '''(INTERNAL) Cache for L{toLtp}.
418
418
  '''
419
- return self._ltp.Ltp(self._ecef9, ecef=self.Ecef(self.datum), name=self.name)
419
+ return _MODS.ltp.Ltp(self._ecef9, ecef=self.Ecef(self.datum), name=self.name)
420
420
 
421
421
  @Property_RO
422
422
  def _N_vector(self):
423
423
  '''(INTERNAL) Get the (C{nvectorBase._N_vector_}).
424
424
  '''
425
- m = _MODS.nvectorBase
425
+ _N = _MODS.nvectorBase._N_vector_
426
426
  x, y, z, h = self._n_xyzh4(self.datum)
427
- return m._N_vector_(x, y, z, h=h, name=self.name)
427
+ return _N(x, y, z, h=h, name=self.name)
428
428
 
429
429
  def _n_xyzh4(self, datum):
430
430
  '''(INTERNAL) Get the n-vector components as L{Vector4Tuple}.
@@ -516,7 +516,7 @@ class CartesianBase(Vector3d):
516
516
 
517
517
  @see: Function L{pygeodesy.pierlot} for references and more details.
518
518
  '''
519
- return self._resections.pierlot(self, point2, point3, alpha12, alpha23,
519
+ return _MODS.resections.pierlot(self, point2, point3, alpha12, alpha23,
520
520
  useZ=useZ, eps=eps, datum=self.datum)
521
521
 
522
522
  def pierlotx(self, point2, point3, alpha1, alpha2, alpha3, useZ=False):
@@ -543,16 +543,9 @@ class CartesianBase(Vector3d):
543
543
 
544
544
  @see: Function L{pygeodesy.pierlotx} for references and more details.
545
545
  '''
546
- return self._resections.pierlotx(self, point2, point3, alpha1, alpha2, alpha3,
546
+ return _MODS.resections.pierlotx(self, point2, point3, alpha1, alpha2, alpha3,
547
547
  useZ=useZ, datum=self.datum)
548
548
 
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
549
  def Roc2(self, earth=None):
557
550
  '''Compute this cartesian's I{normal} and I{pseudo, z-based} radius of curvature.
558
551
 
@@ -624,7 +617,7 @@ class CartesianBase(Vector3d):
624
617
 
625
618
  @see: Function L{pygeodesy.tienstra7} for references and more details.
626
619
  '''
627
- return self._resections.tienstra7(self, pointB, pointC, alpha, beta, gamma,
620
+ return _MODS.resections.tienstra7(self, pointB, pointC, alpha, beta, gamma,
628
621
  useZ=useZ, datum=self.datum)
629
622
 
630
623
  @deprecated_method
@@ -685,8 +678,8 @@ class CartesianBase(Vector3d):
685
678
  if d == datum2:
686
679
  return c.copy() if c is self else c
687
680
 
688
- elif datum2.transform.isunity and \
689
- d.transform.isunity:
681
+ elif d is None or (d.transform.isunity and
682
+ datum2.transform.isunity):
690
683
  return c.dup(datum=datum2)
691
684
 
692
685
  elif d == _WGS84:
@@ -717,15 +710,15 @@ class CartesianBase(Vector3d):
717
710
  @kwarg datum: Optional datum (L{Datum}, L{Ellipsoid}, L{Ellipsoid2}
718
711
  or L{a_f2Tuple}).
719
712
  @kwarg height: Optional height, overriding the converted height
720
- (C{meter}), iff B{C{LatLon}} is not C{None}.
713
+ (C{meter}), only if C{B{LatLon} is not None}.
721
714
  @kwarg LatLon: Optional class to return the geodetic point
722
715
  (C{LatLon}) or C{None}.
723
716
  @kwarg LatLon_kwds: Optional, additional B{C{LatLon}} keyword
724
717
  arguments, ignored if C{B{LatLon} is None}.
725
718
 
726
- @return: The geodetic point (B{C{LatLon}}) or if B{C{LatLon}}
727
- is C{None}, an L{Ecef9Tuple}C{(x, y, z, lat, lon,
728
- height, C, M, datum)} with C{C} and C{M} if available.
719
+ @return: The geodetic point (B{C{LatLon}}) or if C{B{LatLon}
720
+ is None}, an L{Ecef9Tuple}C{(x, y, z, lat, lon, height,
721
+ C, M, datum)} with C{C} and C{M} if available.
729
722
 
730
723
  @raise TypeError: Invalid B{C{datum}} or B{C{LatLon_kwds}}.
731
724
  '''
@@ -746,46 +739,45 @@ class CartesianBase(Vector3d):
746
739
  def toLocal(self, Xyz=None, ltp=None, **Xyz_kwds):
747
740
  '''Convert this I{geocentric} cartesian to I{local} C{X}, C{Y} and C{Z}.
748
741
 
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}.
742
+ @kwarg Xyz: Optional class to return C{X}, C{Y} and C{Z} (L{XyzLocal},
743
+ L{Enu}, L{Ned}) or C{None}.
744
+ @kwarg ltp: The I{local tangent plane} (LTP) to use, overriding this
745
+ cartesian's LTP (L{Ltp}).
746
+ @kwarg Xyz_kwds: Optional, additional B{C{Xyz}} keyword arguments,
747
+ ignored if C{B{Xyz} is None}.
755
748
 
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.
749
+ @return: An B{C{Xyz}} instance or a L{Local9Tuple}C{(x, y, z, lat, lon,
750
+ height, ltp, ecef, M)} if C{B{Xyz} is None} (with C{M=None}).
759
751
 
760
752
  @raise TypeError: Invalid B{C{ltp}}.
761
753
  '''
762
- p = self._ltp._xLtp(ltp, self._Ltp)
763
- return p._ecef2local(self._ecef9, Xyz, Xyz_kwds)
754
+ return _MODS.ltp._toLocal(self, ltp, Xyz, Xyz_kwds) # self._ecef9
764
755
 
765
- def toLtp(self, Ecef=None):
756
+ def toLtp(self, Ecef=None, **name):
766
757
  '''Return the I{local tangent plane} (LTP) for this cartesian.
767
758
 
768
759
  @kwarg Ecef: Optional ECEF I{class} (L{EcefKarney}, ...
769
760
  L{EcefYou}), overriding this cartesian's C{Ecef}.
761
+ @kwarg name: Optional C{B{name}=NN} (C{str}).
770
762
  '''
771
- return self._Ltp if Ecef in (None, self.Ecef) else self._ltp.Ltp(
772
- self._ecef9, ecef=Ecef(self.datum), name=self.name)
763
+ return _MODS.ltp._toLtp(self, Ecef, self._ecef9, name) # self._Ltp
773
764
 
774
- def toNvector(self, Nvector=None, datum=None, **Nvector_kwds):
765
+ def toNvector(self, Nvector=None, datum=None, **name_Nvector_kwds):
775
766
  '''Convert this cartesian to C{n-vector} components, I{including height}.
776
767
 
777
768
  @kwarg Nvector: Optional class to return the C{n-vector} components
778
769
  (C{Nvector}) or C{None}.
779
770
  @kwarg datum: Optional datum (L{Datum}, L{Ellipsoid}, L{Ellipsoid2}
780
771
  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}.
772
+ @kwarg name_Nvector_kwds: Optional C{B{name}=NN} (C{str}) and optional,
773
+ additional B{C{Nvector}} keyword arguments, ignored if
774
+ C{B{Nvector} is None}.
783
775
 
784
776
  @return: An B{C{Nvector}} or a L{Vector4Tuple}C{(x, y, z, h)} if
785
- B{C{Nvector}} is C{None}.
777
+ C{B{Nvector} is None}.
786
778
 
787
- @raise TypeError: Invalid B{C{Nvector}}, B{C{Nvector_kwds}} or
788
- B{C{datum}}.
779
+ @raise TypeError: Invalid B{C{Nvector}}, B{C{datum}} or
780
+ B{C{name_Nvector_kwds}} item.
789
781
 
790
782
  @raise ValueError: B{C{Cartesian}} at origin.
791
783
  '''
@@ -795,9 +787,13 @@ class CartesianBase(Vector3d):
795
787
  if d != self.datum:
796
788
  r = self._n_xyzh4(d)
797
789
 
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))
790
+ if Nvector is None:
791
+ n, _ = _name2__(name_Nvector_kwds, _or_nameof=self)
792
+ if n:
793
+ r = r.dup(name=n)
794
+ else:
795
+ kwds = _xkwds(name_Nvector_kwds, h=r.h, datum=d)
796
+ r = Nvector(r.x, r.y, r.z, **self._name1__(kwds))
801
797
  return r
802
798
 
803
799
  def toRtp(self):
@@ -854,15 +850,15 @@ class CartesianBase(Vector3d):
854
850
  arguments, ignored if C{B{Vector} is None}.
855
851
 
856
852
  @return: A B{C{Vector}} or a L{Vector3Tuple}C{(x, y, z)} if
857
- B{C{Vector}} is C{None}.
853
+ C{B{Vector} is None}.
858
854
 
859
855
  @raise TypeError: Invalid B{C{Vector}} or B{C{Vector_kwds}}.
860
856
  '''
861
- return self.xyz if Vector is None else self._xnamed(
862
- Vector(self.x, self.y, self.z, **Vector_kwds))
857
+ return self.xyz if Vector is None else Vector(
858
+ self.x, self.y, self.z, **self._name1__(Vector_kwds))
863
859
 
864
860
 
865
- class RadiusThetaPhi3Tuple(_NamedTuple):
861
+ class RadiusThetaPhi3Tuple(_NamedTupleTo):
866
862
  '''3-Tuple C{(r, theta, phi)} with radial distance C{r} in C{meter}, inclination
867
863
  C{theta} (with respect to the positive z-axis) and azimuthal angle C{phi} in
868
864
  L{Degrees} I{or} L{Radians} representing a U{spherical, polar position
@@ -885,89 +881,87 @@ class RadiusThetaPhi3Tuple(_NamedTuple):
885
881
  @see: Function L{rtp2xyz_}.
886
882
  '''
887
883
  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)
884
+ t, p, _ = _NamedTupleTo._Radians3(self, t, p)
885
+ return rtp2xyz_(r, t, p, **name_Cartesian_and_kwds)
891
886
 
892
887
  def toDegrees(self, **name):
893
888
  '''Convert this L{RadiusThetaPhi3Tuple}'s angles to L{Degrees}.
894
889
 
895
- @kwarg name: Optional name (C{str}), overriding this name.
890
+ @kwarg name: Optional C{B{name}=NN} (C{str}), overriding this name.
896
891
 
897
892
  @return: L{RadiusThetaPhi3Tuple}C{(r, theta, phi)} with C{theta}
898
893
  and C{phi} both in L{Degrees}.
899
894
  '''
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))
895
+ return self._toX3U(_NamedTupleTo._Degrees3, Degrees, name)
904
896
 
905
897
  def toRadians(self, **name):
906
898
  '''Convert this L{RadiusThetaPhi3Tuple}'s angles to L{Radians}.
907
899
 
908
- @kwarg name: Optional, overriding C{B{name}=NN} (C{str}).
900
+ @kwarg name: Optional C{B{name}=NN} (C{str}), overriding this name.
909
901
 
910
- @return: L{RadiusThetaPhi3Tuple}C{(r, theta, phi)} with
911
- C{theta} and C{phi} both in L{Radians}.
902
+ @return: L{RadiusThetaPhi3Tuple}C{(r, theta, phi)} with C{theta}
903
+ and C{phi} both in L{Radians}.
912
904
  '''
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))
905
+ return self._toX3U(_NamedTupleTo._Radians3, Radians, name)
917
906
 
907
+ def _toU(self, U):
908
+ M = RadiusThetaPhi3Tuple._Units_[0] # Meter
909
+ return self.reUnit(M, U, U).toUnits()
918
910
 
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.
911
+ def _toX3U(self, _X3, U, name):
912
+ r, t, p = self
913
+ t, p, s = _X3(self, t, p)
914
+ if s is None or name:
915
+ n = self._name__(name)
916
+ s = self.classof(r, t, p, name=n)._toU(U)
917
+ return s
921
918
 
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
919
 
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.
920
+ def rtp2xyz(r_rtp, theta=0, phi=0, **name_Cartesian_and_kwds):
921
+ '''Convert I{spherical, polar} C{(r, theta, phi)} to cartesian C{(x, y, z)} coordinates.
934
922
 
935
- @raise TypeError: Invalid B{C{r_rtp}}.
923
+ @arg theta: Inclination B{C{theta}} (C{degrees} with respect to the positive z-axis),
924
+ required if C{B{r_rtp}} is C{scalar}, ignored otherwise.
925
+ @arg phi: Azimuthal angle B{C{phi}} (C{degrees}), like B{C{theta}}.
936
926
 
937
- @see: Functions L{rtp2xyz_} and L{xyz2rtp}.
927
+ @see: Function L{rtp2xyz_} for further details.
938
928
  '''
939
929
  if isinstance(r_rtp, RadiusThetaPhi3Tuple):
940
930
  c = r_rtp.toCartesian(**name_Cartesian_and_kwds)
941
931
  else:
942
- c = rtp2xyz_(r_rtp, *map(radians, theta_phi), **name_Cartesian_and_kwds)
932
+ c = rtp2xyz_(r_rtp, radians(theta), radians(phi), **name_Cartesian_and_kwds)
943
933
  return c
944
934
 
945
935
 
946
- def rtp2xyz_(r_rtp, *theta_phi, **name_Cartesian_and_kwds):
936
+ def rtp2xyz_(r_rtp, theta=0, phi=0, **name_Cartesian_and_kwds):
947
937
  '''Convert I{spherical, polar} C{(r, theta, phi)} to cartesian C{(x, y, z)} coordinates.
948
938
 
949
939
  @arg r_rtp: Radial distance (C{scalar}, conventially C{meter}) or a previous
950
940
  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}.
941
+ @arg theta: Inclination B{C{theta}} (C{radians} with respect to the positive z-axis),
942
+ required if C{B{r_rtp}} is C{scalar}, ignored otherwise.
943
+ @arg phi: Azimuthal angle B{C{phi}} (C{radians}), like B{C{theta}}.
954
944
  @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.
945
+ class to return the coordinates and optional, additional C{B{Cartesian}}
946
+ keyword arguments.
957
947
 
958
948
  @return: A C{B{Cartesian}(x, y, z)} instance or if no C{B{Cartesian}} keyword argument
959
949
  is given a L{Vector3Tuple}C{(x, y, z)}, with C{x}, C{y} and C{z} in the same
960
950
  units as radius C{r}, C{meter} conventionally.
961
951
 
962
- @raise TypeError: Invalid B{C{r_rtp}} or B{C{theta_phi}}.
952
+ @raise TypeError: Invalid B{C{r_rtp}}, B{C{theta}}, B{C{phi}} or
953
+ B{C{name_Cartesian_and_kwds}} item.
963
954
 
964
955
  @see: U{Physics convention<https://WikiPedia.org/wiki/Spherical_coordinate_system>}
965
- (ISO 80000-2:2019).
956
+ (ISO 80000-2:2019), class L{RadiusThetaPhi3Tuple} and functions L{rtp2xyz}
957
+ and L{xyz2rtp}.
966
958
  '''
967
- if _isMeter(r_rtp) and len(theta_phi) == 2:
959
+ if isinstance(r_rtp, RadiusThetaPhi3Tuple):
960
+ c = r_rtp.toCartesian(**name_Cartesian_and_kwds)
961
+ elif _isMeter(r_rtp):
968
962
  r = r_rtp
969
963
  if r and _isfinite(r):
970
- s, z, y, x = sincos2_(*theta_phi)
964
+ s, z, y, x = sincos2_(theta, phi)
971
965
  s *= r
972
966
  z *= r
973
967
  y *= s
@@ -975,22 +969,16 @@ def rtp2xyz_(r_rtp, *theta_phi, **name_Cartesian_and_kwds):
975
969
  else:
976
970
  x = y = z = r
977
971
 
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)
972
+ n, kwds = _name2__(**name_Cartesian_and_kwds)
973
+ C, kwds = _xkwds_pop2(kwds, Cartesian=None)
983
974
  c = Vector3Tuple(x, y, z, name=n) if C is None else \
984
975
  C(x, y, z, name=n, **kwds)
985
-
986
- elif isinstance(r_rtp, RadiusThetaPhi3Tuple):
987
- c = r_rtp.toCartesian(**name_Cartesian_and_kwds)
988
976
  else:
989
- raise _TypeError(r_rtp=r_rtp, theta_phi=theta_phi)
977
+ raise _TypeError(r_rtp=r_rtp, theta=theta, phi=phi)
990
978
  return c
991
979
 
992
980
 
993
- def _rtp3(where, Unit, *x_y_z, **name):
981
+ def _rtp3(where, U, *x_y_z, **name):
994
982
  '''(INTERNAL) Helper for C{.toRtp}, C{xyz2rtp} and C{xyz2rtp_}.
995
983
  '''
996
984
  x, y, z = _MODS.vector3dBase._xyz3(where, *x_y_z)
@@ -1000,43 +988,43 @@ def _rtp3(where, Unit, *x_y_z, **name):
1000
988
  p = atan2(y, x)
1001
989
  while p < 0:
1002
990
  p += PI2
1003
- if Unit is Degrees:
991
+ if U is Degrees:
1004
992
  t = degrees(t)
1005
993
  p = degrees(p)
1006
994
  else:
1007
995
  t = p = _0_0
1008
- return RadiusThetaPhi3Tuple(r, Unit(theta=t), Unit(phi=p), **name)
996
+ return RadiusThetaPhi3Tuple(r, t, p, **name)._toU(U)
1009
997
 
1010
998
 
1011
- def xyz2rtp(x_xyz, *y_z, **name):
999
+ def xyz2rtp(x_xyz, y=0, z=0, **name):
1012
1000
  '''Convert cartesian C{(x, y, z)} to I{spherical, polar} C{(r, theta, phi)} coordinates.
1013
1001
 
1014
- @return: L{RadiusThetaPhi3Tuple}C{(r, theta, phi)} with C{theta} and C{phi},
1015
- both in L{Degrees}.
1002
+ @return: L{RadiusThetaPhi3Tuple}C{(r, theta, phi)} with C{theta} and C{phi}, both
1003
+ in L{Degrees}.
1016
1004
 
1017
- @see: Function L{xyz2rtp_} and class L{RadiusThetaPhi3Tuple}.
1005
+ @see: Function L{xyz2rtp_} for further details.
1018
1006
  '''
1019
- return _rtp3(xyz2rtp, Degrees, x_xyz, *y_z, **name)
1007
+ return _rtp3(xyz2rtp, Degrees, x_xyz, y, z, **name)
1020
1008
 
1021
1009
 
1022
- def xyz2rtp_(x_xyz, *y_z, **name):
1010
+ def xyz2rtp_(x_xyz, y=0, z=0, **name):
1023
1011
  '''Convert cartesian C{(x, y, z)} to I{spherical, polar} C{(r, theta, phi)} coordinates.
1024
1012
 
1025
1013
  @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}.
1014
+ C{Nvector}, L{Vector3d}, L{Vector3Tuple}, L{Vector4Tuple} or a C{tuple} or
1015
+ C{list} of 3+ C{scalar} items) if no C{y_z} specified.
1016
+ @arg y: Y component (C{scalar}), required if C{B{x_xyz}} is C{scalar}, ignored otherwise.
1017
+ @arg z: Z component (C{scalar}), like B{C{y}}.
1029
1018
  @kwarg name: Optional C{B{name}=NN} (C{str}).
1030
1019
 
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}.
1020
+ @return: L{RadiusThetaPhi3Tuple}C{(r, theta, phi)} with radial distance C{r} (C{meter},
1021
+ same units as C{x}, C{y} and C{z}), inclination C{theta} (with respect to the
1022
+ positive z-axis) and azimuthal angle C{phi}, both in L{Radians}.
1035
1023
 
1036
1024
  @see: U{Physics convention<https://WikiPedia.org/wiki/Spherical_coordinate_system>}
1037
- (ISO 80000-2:2019).
1025
+ (ISO 80000-2:2019), class L{RadiusThetaPhi3Tuple} and function L{xyz2rtp}.
1038
1026
  '''
1039
- return _rtp3(xyz2rtp_, Radians, x_xyz, *y_z, **name)
1027
+ return _rtp3(xyz2rtp_, Radians, x_xyz, y, z, **name)
1040
1028
 
1041
1029
 
1042
1030
  __all__ += _ALL_DOCS(CartesianBase)
pygeodesy/css.py CHANGED
@@ -33,7 +33,7 @@ from pygeodesy.units import Bearing, Degrees, Easting, Height, _heigHt, \
33
33
  # from math import fabs # from .karney
34
34
 
35
35
  __all__ = _ALL_LAZY.css
36
- __version__ = '24.05.24'
36
+ __version__ = '24.06.11'
37
37
 
38
38
 
39
39
  def _CS0(cs0):
@@ -312,7 +312,7 @@ class CassiniSoldner(_NamedBase):
312
312
  s, c = _sincos2d(m.lat1) # == self.lat0 == self.LatitudeOrigin()
313
313
  self._sb0, self._cb0 = _norm2(s * g.f1, c)
314
314
 
315
- def reverse(self, easting, northing, LatLon=None, **LatLon_kwds_name):
315
+ def reverse(self, easting, northing, LatLon=None, **name_LatLon_kwds):
316
316
  '''Convert a Cassini-Soldner location to (ellipsoidal) geodetic
317
317
  lat- and longitude.
318
318
 
@@ -320,12 +320,11 @@ class CassiniSoldner(_NamedBase):
320
320
  @arg northing: Northing of the location (C{meter}).
321
321
  @kwarg LatLon: Optional, ellipsoidal class to return the geodetic
322
322
  location as (C{LatLon}) or C{None}.
323
- @kwarg LatLon_kwds_name: Optional (C{LatLon}) keyword arguments,
324
- ignored if C{B{LatLon} is None} and optional
325
- C{B{name}=NN} inlieu of this this projection's
326
- name (C{str}).
323
+ @kwarg name_LatLon_kwds: Optional name C{B{name}=NN} (C{str}) and
324
+ optional, additional B{C{LatLon}} keyword arguments,
325
+ ignored if C{B{LatLon} is None}.
327
326
 
328
- @return: Geodetic location B{C{LatLon}} or if B{C{LatLon}} is C{None},
327
+ @return: Geodetic location B{C{LatLon}} or if C{B{LatLon} is None},
329
328
  a L{LatLon2Tuple}C{(lat, lon)}.
330
329
 
331
330
  @raise CSSError: Ellipsoidal mismatch of B{C{LatLon}} and this projection.
@@ -335,7 +334,7 @@ class CassiniSoldner(_NamedBase):
335
334
  @see: Method L{CassiniSoldner.reverse4}, L{CassiniSoldner.forward}.
336
335
  L{CassiniSoldner.forward4} and L{CassiniSoldner.forward6}.
337
336
  '''
338
- n, kwds = _name2__(LatLon_kwds_name, _or_nameof=self)
337
+ n, kwds = _name2__(name_LatLon_kwds, _or_nameof=self)
339
338
  r = self.reverse4(easting, northing, name=n)
340
339
  if LatLon is None:
341
340
  r = LatLon2Tuple(r.lat, r.lon, name=r.name) # PYCHOK expected
@@ -520,9 +519,8 @@ class Css(_NamedBase):
520
519
  @kwarg LatLon_kwds: Optional, additional B{C{LatLon}} keyword
521
520
  arguments, ignored if C{B{LatLon} is None}.
522
521
 
523
- @return: The geodetic point (B{C{LatLon}}) or if B{C{LatLon}}
524
- is C{None}, a L{LatLon4Tuple}C{(lat, lon, height,
525
- datum)}.
522
+ @return: The geodetic point (B{C{LatLon}}) or if C{B{LatLon} is
523
+ None}, a L{LatLon4Tuple}C{(lat, lon, height, datum)}.
526
524
 
527
525
  @raise TypeError: If B{C{LatLon}} or B{C{datum}} is not
528
526
  ellipsoidal or invalid B{C{height}} or
@@ -610,15 +608,13 @@ def toCss(latlon, cs0=None, height=None, Css=Css, **name):
610
608
  @arg latlon: Ellipsoidal point (C{LatLon} or L{LatLon4Tuple}).
611
609
  @kwarg cs0: Optional, the Cassini-Soldner projection to use
612
610
  (L{CassiniSoldner}).
613
- @kwarg height: Optional height for the point, overriding the
614
- default height (C{meter}).
615
- @kwarg Css: Optional class to return the location (L{Css}) or
616
- C{None}.
611
+ @kwarg height: Optional height for the point, overriding the default
612
+ height (C{meter}).
613
+ @kwarg Css: Optional class to return the location (L{Css}) or C{None}.
617
614
  @kwarg name: Optional B{C{Css}} C{B{name}=NN} (C{str}).
618
615
 
619
- @return: The Cassini-Soldner location (B{C{Css}}) or an
620
- L{EasNor3Tuple}C{(easting, northing, height)}
621
- if B{C{Css}} is C{None}.
616
+ @return: The Cassini-Soldner location (B{C{Css}}) or if C{B{Css} is
617
+ None}, an L{EasNor3Tuple}C{(easting, northing, height)}.
622
618
 
623
619
  @raise CSSError: Ellipsoidal mismatch of B{C{latlon}} and B{C{cs0}}.
624
620