pygeodesy 25.4.25__py2.py3-none-any.whl → 25.5.25__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 (85) hide show
  1. pygeodesy/__init__.py +191 -189
  2. pygeodesy/__main__.py +2 -2
  3. pygeodesy/albers.py +4 -4
  4. pygeodesy/auxilats/_CX_Rs.py +3 -3
  5. pygeodesy/auxilats/auxAngle.py +2 -2
  6. pygeodesy/auxilats/auxDLat.py +2 -2
  7. pygeodesy/auxilats/auxDST.py +2 -2
  8. pygeodesy/auxilats/auxLat.py +2 -2
  9. pygeodesy/auxilats/auxily.py +2 -2
  10. pygeodesy/azimuthal.py +2 -2
  11. pygeodesy/basics.py +1 -1
  12. pygeodesy/booleans.py +8 -8
  13. pygeodesy/cartesianBase.py +7 -6
  14. pygeodesy/clipy.py +2 -2
  15. pygeodesy/constants.py +2 -2
  16. pygeodesy/datums.py +2 -2
  17. pygeodesy/deprecated/__init__.py +8 -8
  18. pygeodesy/deprecated/bases.py +2 -2
  19. pygeodesy/deprecated/rhumbBase.py +2 -2
  20. pygeodesy/deprecated/rhumbaux.py +2 -2
  21. pygeodesy/deprecated/rhumbsolve.py +2 -2
  22. pygeodesy/deprecated/rhumbx.py +2 -2
  23. pygeodesy/ecef.py +15 -26
  24. pygeodesy/ecefLocals.py +186 -0
  25. pygeodesy/ellipsoidalBase.py +2 -2
  26. pygeodesy/ellipsoidalBaseDI.py +7 -6
  27. pygeodesy/ellipsoidalExact.py +3 -3
  28. pygeodesy/ellipsoidalNvector.py +4 -4
  29. pygeodesy/ellipsoidalVincenty.py +15 -14
  30. pygeodesy/ellipsoids.py +23 -30
  31. pygeodesy/elliptic.py +2 -2
  32. pygeodesy/errors.py +1 -1
  33. pygeodesy/etm.py +2 -2
  34. pygeodesy/fmath.py +28 -13
  35. pygeodesy/formy.py +2 -2
  36. pygeodesy/frechet.py +5 -5
  37. pygeodesy/fstats.py +2 -2
  38. pygeodesy/fsums.py +38 -29
  39. pygeodesy/gars.py +2 -3
  40. pygeodesy/geodesici.py +4 -4
  41. pygeodesy/geodesicx/__init__.py +3 -3
  42. pygeodesy/geodesicx/gx.py +2 -2
  43. pygeodesy/geodesicx/gxarea.py +2 -2
  44. pygeodesy/geodesicx/gxline.py +2 -2
  45. pygeodesy/geoids.py +5 -5
  46. pygeodesy/hausdorff.py +4 -4
  47. pygeodesy/heights.py +2 -2
  48. pygeodesy/iters.py +1 -1
  49. pygeodesy/karney.py +2 -2
  50. pygeodesy/ktm.py +2 -2
  51. pygeodesy/latlonBase.py +10 -8
  52. pygeodesy/lazily.py +46 -22
  53. pygeodesy/lcc.py +2 -2
  54. pygeodesy/ltp.py +54 -57
  55. pygeodesy/ltpTuples.py +34 -35
  56. pygeodesy/mgrs.py +3 -3
  57. pygeodesy/named.py +2 -147
  58. pygeodesy/namedTuples.py +3 -3
  59. pygeodesy/nvectorBase.py +2 -2
  60. pygeodesy/osgr.py +2 -2
  61. pygeodesy/points.py +2 -3
  62. pygeodesy/props.py +16 -16
  63. pygeodesy/resections.py +90 -82
  64. pygeodesy/rhumb/aux_.py +2 -2
  65. pygeodesy/rhumb/bases.py +3 -3
  66. pygeodesy/rhumb/ekx.py +3 -4
  67. pygeodesy/rhumb/solve.py +2 -2
  68. pygeodesy/simplify.py +2 -2
  69. pygeodesy/solveBase.py +2 -2
  70. pygeodesy/sphericalBase.py +6 -6
  71. pygeodesy/sphericalNvector.py +2 -2
  72. pygeodesy/sphericalTrigonometry.py +6 -5
  73. pygeodesy/trf.py +4 -4
  74. pygeodesy/triaxials.py +2 -2
  75. pygeodesy/units.py +7 -8
  76. pygeodesy/utily.py +2 -2
  77. pygeodesy/utmupsBase.py +55 -33
  78. pygeodesy/vector2d.py +16 -10
  79. pygeodesy/vector3d.py +3 -3
  80. pygeodesy/webmercator.py +2 -2
  81. {pygeodesy-25.4.25.dist-info → pygeodesy-25.5.25.dist-info}/METADATA +20 -19
  82. pygeodesy-25.5.25.dist-info/RECORD +119 -0
  83. pygeodesy-25.4.25.dist-info/RECORD +0 -118
  84. {pygeodesy-25.4.25.dist-info → pygeodesy-25.5.25.dist-info}/WHEEL +0 -0
  85. {pygeodesy-25.4.25.dist-info → pygeodesy-25.5.25.dist-info}/top_level.txt +0 -0
@@ -13,7 +13,7 @@ under the MIT/X11 License. For more information, see the U{GeographicLib
13
13
  U{On auxiliary latitudes<https://ArXiv.org/abs/2212.05818>}.
14
14
  '''
15
15
  # make sure int/int division yields float quotient, see .basics
16
- from __future__ import division as _; del _ # PYCHOK semicolon
16
+ from __future__ import division as _; del _ # noqa: E702 ;
17
17
 
18
18
  from pygeodesy.auxilats.auxAngle import AuxAngle, AuxBeta, AuxChi, _AuxClass, \
19
19
  AuxMu, AuxPhi, AuxTheta, AuxXi
@@ -48,7 +48,7 @@ except ImportError: # Python 3.11-
48
48
  return pow(_2_0, x)
49
49
 
50
50
  __all__ = ()
51
- __version__ = '25.04.14'
51
+ __version__ = '25.05.12'
52
52
 
53
53
  _TRIPS = 1024 # XXX 2 or 3?
54
54
 
@@ -12,7 +12,7 @@ under the MIT/X11 License. For more information, see the U{GeographicLib
12
12
  <https://GeographicLib.SourceForge.io>} documentation.
13
13
  '''
14
14
  # make sure int/int division yields float quotient, see .basics
15
- from __future__ import division as _; del _ # PYCHOK semicolon
15
+ from __future__ import division as _; del _ # noqa: E702 ;
16
16
 
17
17
  # from pygeodesy import auxilats # _MODS
18
18
  from pygeodesy.auxilats._CX_Rs import _Rkey
@@ -29,7 +29,7 @@ from pygeodesy.utily import atan1
29
29
  from math import asinh, copysign
30
30
 
31
31
  __all__ = ()
32
- __version__ = '25.04.14'
32
+ __version__ = '25.05.12'
33
33
 
34
34
 
35
35
  class Aux(object):
pygeodesy/azimuthal.py CHANGED
@@ -40,7 +40,7 @@ altitude in Earth radii<https://WikiPedia.org/wiki/Azimuthal_equidistant_project
40
40
  #/media/File:Comparison_azimuthal_projections.svg>}.
41
41
  '''
42
42
  # make sure int/int division yields float quotient, see .basics
43
- from __future__ import division as _; del _ # PYCHOK semicolon
43
+ from __future__ import division as _; del _ # noqa: E702 ;
44
44
 
45
45
  # from pygeodesy.basics import _isin, _xinstanceof # from .ellipsoidalBase
46
46
  from pygeodesy.constants import EPS, EPS0, EPS1, NAN, isnon0, _umod_360, \
@@ -71,7 +71,7 @@ from pygeodesy.utily import asin1, atan1, atan2, atan2b, atan2d, \
71
71
  from math import acos, degrees, fabs, sin, sqrt
72
72
 
73
73
  __all__ = _ALL_LAZY.azimuthal
74
- __version__ = '25.04.14'
74
+ __version__ = '25.05.12'
75
75
 
76
76
  _EPS_K = _EPStol * _0_1 # Karney's eps_ or _EPSmin * _0_1?
77
77
  _over_horizon_ = 'over horizon'
pygeodesy/basics.py CHANGED
@@ -616,7 +616,7 @@ def map1(fun1, *xs): # XXX map_
616
616
 
617
617
  @return: Function results (C{tuple}).
618
618
  '''
619
- return tuple(map(fun1, xs))
619
+ return tuple(map(fun1, xs)) # if len(xs) != 1 else fun1(xs[0])
620
620
 
621
621
 
622
622
  def map2(fun, *xs, **strict):
pygeodesy/booleans.py CHANGED
@@ -15,14 +15,14 @@ C{reverse-difference}, C{sum} and C{union}.
15
15
  <http://www.Inf.USI.CH/hormann/papers/Greiner.1998.ECO.pdf>}.
16
16
  '''
17
17
  # make sure int/int division yields float quotient, see .basics
18
- from __future__ import division as _; del _ # PYCHOK semicolon
18
+ from __future__ import division as _; del _ # noqa: E702 ;
19
19
 
20
20
  from pygeodesy.basics import _isin, isodd, issubclassof, map2, \
21
21
  _xscalar, typename
22
22
  from pygeodesy.constants import EPS, EPS2, INT0, _0_0, _0_5, _1_0
23
23
  from pygeodesy.errors import ClipError, _IsnotError, _TypeError, \
24
24
  _ValueError, _xattr, _xkwds_get, _xkwds_pop2
25
- from pygeodesy.fmath import favg, fdot_, hypot, hypot2
25
+ from pygeodesy.fmath import favg, Fdot_, fdot_, hypot, hypot2
26
26
  # from pygeodesy.fsums import fsum1 # _MODS
27
27
  # from pygeodesy.internals import typename # from .basics
28
28
  from pygeodesy.interns import NN, _BANG_, _clipid_, _COMMASPACE_, \
@@ -45,7 +45,7 @@ from pygeodesy.utily import fabs, _unrollon, _Wrap
45
45
  # from math import fabs # from .utily
46
46
 
47
47
  __all__ = _ALL_LAZY.booleans
48
- __version__ = '25.04.14'
48
+ __version__ = '25.05.12'
49
49
 
50
50
  _0EPS = EPS # near-zero, positive
51
51
  _EPS0 = -EPS # near-zero, negative
@@ -1612,8 +1612,8 @@ class _EdgeGH(object):
1612
1612
 
1613
1613
  def _alpha2(self, x, y, dx, dy):
1614
1614
  # Return C{(alpha)}, see .points.nearestOn5
1615
- a = fdot_(y, dy, x, dx) / self._hypot2
1616
- d = fdot_(y, dx, -x, dy) / self._hypot0
1615
+ a = Fdot_(y, dy, x, dx).fover(self._hypot2)
1616
+ d = Fdot_(y, dx, -x, dy).fover(self._hypot0)
1617
1617
  return a, fabs(d)
1618
1618
 
1619
1619
  def _Error(self, n, *args, **kwds): # PYCHOK no cover
@@ -1655,10 +1655,10 @@ class _EdgeGH(object):
1655
1655
  if fabs(d) > _0EPS: # non-parallel edges
1656
1656
  dx = x - c1_x
1657
1657
  dy = y - c1_y
1658
- ca = fdot_(sx, dy, -sy, dx) / d
1658
+ ca = Fdot_(sx, dy, -sy, dx).fover(d)
1659
1659
  if _0EPS < ca < _EPS1 or (self._xtend and
1660
1660
  _EPS0 < ca < _1EPS):
1661
- sa = fdot_(cx, dy, -cy, dx) / d
1661
+ sa = Fdot_(cx, dy, -cy, dx).fover(d)
1662
1662
  if _0EPS < sa < _EPS1 or (self._xtend and
1663
1663
  _EPS0 < sa < _1EPS):
1664
1664
  yield (y + sa * sy), (x + sa * sx), sa, ca
@@ -1669,7 +1669,7 @@ class _EdgeGH(object):
1669
1669
 
1670
1670
  elif self._raiser and not (ca < _EPS0 or ca > _1EPS): # PYCHOK no cover
1671
1671
  # intersection at c1 or c2 or at c1 or c2 and s1 or s2
1672
- sa = fdot_(cx, dy, -cy, dx) / d
1672
+ sa = Fdot_(cx, dy, -cy, dx).fover(d)
1673
1673
  e = 2 if sa < _EPS0 or sa > _1EPS else 3
1674
1674
  raise self._Error(e, c1, c2, ca=ca)
1675
1675
 
@@ -16,6 +16,7 @@ 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
18
18
  # from pygeodesy.ecef import EcefKarney # _MODS
19
+ from pygeodesy.ecefLocals import _EcefLocal
19
20
  from pygeodesy.errors import _IsnotError, _TypeError, _ValueError, _xattr, \
20
21
  _xdatum, _xkwds, _xkwds_get, _xkwds_pop2
21
22
  from pygeodesy.fmath import cbrt, hypot, hypot_, hypot2, fabs, sqrt # hypot
@@ -25,9 +26,9 @@ from pygeodesy.fsums import fsumf_, Fmt
25
26
  from pygeodesy.interns import _COMMASPACE_, _datum_, _no_, _phi_
26
27
  from pygeodesy.interns import _ellipsoidal_, _spherical_ # PYCHOK used!
27
28
  from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS
28
- from pygeodesy.named import _name2__, _NamedLocal, _Pass
29
+ from pygeodesy.named import _name2__, _Pass
29
30
  from pygeodesy.namedTuples import LatLon4Tuple, _NamedTupleTo , Vector3Tuple, \
30
- Vector4Tuple, Bearing2Tuple # PYCHOK .sphericalBase
31
+ Vector4Tuple
31
32
  # from pygeodesy.nvectorBase import _N_vector # _MODS
32
33
  from pygeodesy.props import deprecated_method, Property, Property_RO, property_doc_, \
33
34
  property_RO, _update_all
@@ -43,14 +44,14 @@ from pygeodesy.vector3d import Vector3d, _xyzhdlln4
43
44
  # from math import degrees, fabs, radians, sqrt # from .fmath, .utily
44
45
 
45
46
  __all__ = _ALL_LAZY.cartesianBase
46
- __version__ = '25.04.21'
47
+ __version__ = '25.05.07'
47
48
 
48
49
  _r_ = 'r'
49
50
  _resections = _MODS.into(resections=__name__)
50
51
  _theta_ = 'theta'
51
52
 
52
53
 
53
- class CartesianBase(Vector3d, _NamedLocal):
54
+ class CartesianBase(Vector3d, _EcefLocal):
54
55
  '''(INTERNAL) Base class for ellipsoidal and spherical C{Cartesian}.
55
56
  '''
56
57
  _datum = None # L{Datum}, to be overriden
@@ -200,7 +201,7 @@ class CartesianBase(Vector3d, _NamedLocal):
200
201
  '''
201
202
  n, kwds = _name2__(name_Cartesian_kwds, _or_nameof=self)
202
203
  if Cartesian is None:
203
- r = self._Ltp._local2ecef(delta, nine=True)
204
+ r = self._ltp._local2ecef(delta, nine=True) # _EcefLocal._ltp
204
205
  else:
205
206
  d = self.datum
206
207
  if not d:
@@ -208,7 +209,7 @@ class CartesianBase(Vector3d, _NamedLocal):
208
209
  t = _xkwds_get(kwds, datum=d)
209
210
  if _xattr(t, ellipsoid=None) != d.ellipsoid:
210
211
  raise _TypeError(datum=t, txt=str(d))
211
- c = self._Ltp._local2ecef(delta, nine=False)
212
+ c = self._ltp._local2ecef(delta, nine=False) # _EcefLocal._ltp
212
213
  r = Cartesian(*c, **kwds)
213
214
  return r.renamed(n) if n else r
214
215
 
pygeodesy/clipy.py CHANGED
@@ -10,7 +10,7 @@ I{Greiner-Hormann} and L{clipSH} and L{clipSH3} I{Sutherland-Hodgeman}.
10
10
  .
11
11
  '''
12
12
  # make sure int/int division yields float quotient, see .basics
13
- from __future__ import division as _; del _ # PYCHOK semicolon
13
+ from __future__ import division as _; del _ # noqa: E702 ;
14
14
 
15
15
  from pygeodesy.basics import len2, typename
16
16
  from pygeodesy.constants import EPS, _0_0, _1_0
@@ -31,7 +31,7 @@ from pygeodesy.units import Bool, FIx, HeightX, Lat, Lon, Number_
31
31
  # from math import fabs # from .fmath
32
32
 
33
33
  __all__ = _ALL_LAZY.clipy
34
- __version__ = '25.04.14'
34
+ __version__ = '25.05.12'
35
35
 
36
36
  _fj_ = 'fj'
37
37
  _original_ = 'original'
pygeodesy/constants.py CHANGED
@@ -8,7 +8,7 @@ L{pygeodesy.isnear1}, L{pygeodesy.isnear90}, L{pygeodesy.isneg0}, L{pygeodesy.is
8
8
  L{pygeodesy.isnon0} and L{pygeodesy.remainder}.
9
9
  '''
10
10
  # make sure int/int division yields float quotient, see .basics
11
- from __future__ import division as _; del _ # PYCHOK semicolon
11
+ from __future__ import division as _; del _ # noqa: E702 ;
12
12
 
13
13
  from pygeodesy.basics import _copysign, isbool, iscomplex, isint
14
14
  from pygeodesy.errors import _xError, _xError2, _xkwds_get1, _xkwds_item2
@@ -26,7 +26,7 @@ except ImportError: # Python 2-
26
26
  _inf, _nan = float(_INF_), float(_NAN_)
27
27
 
28
28
  __all__ = _ALL_LAZY.constants
29
- __version__ = '25.04.14'
29
+ __version__ = '25.05.12'
30
30
 
31
31
 
32
32
  def _copysign_0_0(y):
pygeodesy/datums.py CHANGED
@@ -65,7 +65,7 @@ datum, q.v. U{"A Guide to Coordinate Systems in Great Britain", Section 6
65
65
  @var Transforms.WGS84: Transform(name='WGS84', tx=0.0, ty=0.0, tz=0.0, s1=1.0, rx=0.0, ry=0.0, rz=0.0, s=0.0, sx=0.0, sy=0.0, sz=0.0)
66
66
  '''
67
67
  # make sure int/int division yields float quotient, see .basics
68
- from __future__ import division as _; del _ # PYCHOK semicolon
68
+ from __future__ import division as _; del _ # noqa: E702 ;
69
69
 
70
70
  from pygeodesy.basics import _isin, islistuple, map2, neg, _xinstanceof, _zip
71
71
  from pygeodesy.constants import R_M, _float as _F, _0_0, _1_0, _2_0, _8_0, _3600_0
@@ -94,7 +94,7 @@ from pygeodesy.units import _isRadius, Radius_, radians
94
94
  # import operator as _operator # from .fmath
95
95
 
96
96
  __all__ = _ALL_LAZY.datums
97
- __version__ = '25.04.14'
97
+ __version__ = '25.05.12'
98
98
 
99
99
  _a_ellipsoid_ = _UNDER_(_a_, _ellipsoid_)
100
100
  _BD72_ = 'BD72'
@@ -10,13 +10,13 @@ bases} or C{from pygeodesy.deprecated import bases}. Likewise for C{datum} and
10
10
  C{nvector}.
11
11
  '''
12
12
 
13
- from pygeodesy.deprecated.bases import * # PYCHOK not pygeodesy.__init__
14
- from pygeodesy.deprecated.datum import * # PYCHOK not pygeodesy.__init__
15
- from pygeodesy.deprecated.nvector import * # PYCHOK not pygeodesy.__init__
13
+ from pygeodesy.deprecated.bases import * # noqa: F403 not pygeodesy.__init__
14
+ from pygeodesy.deprecated.datum import * # noqa: F403 not pygeodesy.__init__
15
+ from pygeodesy.deprecated.nvector import * # noqa: F403 not pygeodesy.__init__
16
16
 
17
- from pygeodesy.deprecated.classes import * # PYCHOK expected
18
- from pygeodesy.deprecated.consterns import * # PYCHOK expected
19
- from pygeodesy.deprecated.functions import * # PYCHOK expected
17
+ from pygeodesy.deprecated.classes import * # noqa: F403
18
+ from pygeodesy.deprecated.consterns import * # noqa: F403
19
+ from pygeodesy.deprecated.functions import * # noqa: F403
20
20
 
21
21
  from pygeodesy.lazily import _ALL_ATTRS, _ALL_DEPRECATED, _lazy_import_as, _unLazy0 # _lazy_import_star
22
22
 
@@ -27,11 +27,11 @@ __all__ = (_ALL_DEPRECATED.deprecated_bases +
27
27
  _ALL_DEPRECATED.deprecated_classes +
28
28
  _ALL_DEPRECATED.deprecated_consterns +
29
29
  _ALL_DEPRECATED.deprecated_functions)
30
- __version__ = '24.12.31'
30
+ __version__ = '25.05.12'
31
31
 
32
32
  if _unLazy0:
33
33
  from pygeodesy.deprecated import bases, datum, nvector, rhumbBase, \
34
- rhumbaux, rhumbsolve, rhumbx # PYCHOK expected
34
+ rhumbaux, rhumbsolve, rhumbx # noqa: F401 PYCHOK expected
35
35
  __all__ += _ALL_ATTRS(_ALL_DEPRECATED.deprecated) # DEPRECATED modules
36
36
 
37
37
  else: # lazily import modules and exported attrs
@@ -4,12 +4,12 @@
4
4
  u'''DEPRECATED on 2021.02.10, use (INTERNAL) module L{pygeodesy.latlonBase} instead.
5
5
  '''
6
6
 
7
- from pygeodesy.iters import points2 # PYCHOK exported
7
+ from pygeodesy.iters import points2 # noqa: F401
8
8
  from pygeodesy.latlonBase import LatLonBase as _LatLonBase
9
9
  from pygeodesy.lazily import _ALL_DEPRECATED
10
10
 
11
11
  __all__ = _ALL_DEPRECATED.deprecated_bases
12
- __version__ = '25.04.09'
12
+ __version__ = '25.05.12'
13
13
 
14
14
 
15
15
  class LatLonHeightBase(_LatLonBase): # PYCHOK no cover
@@ -4,10 +4,10 @@
4
4
  u'''DEPRECATED on 2023.11.26, use module L{pygeodesy.rhumb.bases} instead.
5
5
  '''
6
6
 
7
- from pygeodesy.rhumb.bases import * # PYCHOK expected
7
+ from pygeodesy.rhumb.bases import * # noqa: F403
8
8
 
9
9
  __all__ = () # _ALL_LAZY.rhumb._bases
10
- __version__ = '23.11.26'
10
+ __version__ = '25.05.12'
11
11
 
12
12
  # **) MIT License
13
13
  #
@@ -4,11 +4,11 @@
4
4
  u'''DEPRECATED on 2023.11.26, use module L{pygeodesy.rhumb.aux_} instead.
5
5
  '''
6
6
 
7
- from pygeodesy.rhumb.aux_ import * # PYCHOK expected
7
+ from pygeodesy.rhumb.aux_ import * # noqa: F403
8
8
  from pygeodesy.lazily import _ALL_LAZY
9
9
 
10
10
  __all__ = _ALL_LAZY.rhumb_aux_ # attrs NOT DEPRECATED
11
- __version__ = '23.12.02'
11
+ __version__ = '25.05.12'
12
12
 
13
13
  # **) MIT License
14
14
  #
@@ -4,11 +4,11 @@
4
4
  u'''DEPRECATED on 2023.11.26, use module L{pygeodesy.rhumb.solve} instead.
5
5
  '''
6
6
 
7
- from pygeodesy.rhumb.solve import * # PYCHOK expected
7
+ from pygeodesy.rhumb.solve import * # noqa: F403
8
8
  from pygeodesy.lazily import _ALL_LAZY
9
9
 
10
10
  __all__ = _ALL_LAZY.rhumb_solve # attrs NOT DEPRECATED
11
- __version__ = '23.11.26'
11
+ __version__ = '25.05.12'
12
12
 
13
13
  # **) MIT License
14
14
  #
@@ -4,11 +4,11 @@
4
4
  u'''DEPRECATED on 2023.11.26, use module L{pygeodesy.rhumb.ekx} instead.
5
5
  '''
6
6
 
7
- from pygeodesy.rhumb.ekx import * # PYCHOK expected
7
+ from pygeodesy.rhumb.ekx import * # noqa: F403
8
8
  from pygeodesy.lazily import _ALL_LAZY
9
9
 
10
10
  __all__ = _ALL_LAZY.rhumb_ekx # attrs NOT DEPRECATED
11
- __version__ = '23.11.30'
11
+ __version__ = '25.05.12'
12
12
 
13
13
  # **) MIT License
14
14
  #
pygeodesy/ecef.py CHANGED
@@ -60,22 +60,21 @@ plane} as opposed to I{geocentric} (ECEF) ones.
60
60
  from pygeodesy.basics import copysign0, _isin, isscalar, issubclassof, neg, map1, \
61
61
  _xinstanceof, _xsubclassof, typename # _args_kwds_names
62
62
  from pygeodesy.constants import EPS, EPS0, EPS02, EPS1, EPS2, EPS_2, INT0, PI, PI_2, \
63
- _0_0, _0_0001, _0_01, _0_5, _1_0, _1_0_1T, _N_1_0, \
64
- _2_0, _N_2_0, _3_0, _4_0, _6_0, _60_0, _90_0, _N_90_0, \
65
- _100_0, _copysign_1_0, isnon0 # PYCHOK used!
66
- from pygeodesy.datums import a_f2Tuple, _ellipsoidal_datum, _WGS84, _EWGS84
63
+ _0_0, _0_5, _1_0, _1_0_1T, _2_0, _N_2_0, _3_0, _4_0, \
64
+ _6_0, _90_0, _N_90_0, _copysign_1_0, isnon0 # PYCHOK used!
65
+ from pygeodesy.datums import _ellipsoidal_datum, _WGS84, a_f2Tuple, _EWGS84
66
+ from pygeodesy.ecefLocals import _EcefLocal
67
67
  # from pygeodesy.ellipsoids import a_f2Tuple, _EWGS84 # from .datums
68
68
  from pygeodesy.errors import _IndexError, LenError, _ValueError, _TypesError, \
69
69
  _xattr, _xdatum, _xkwds, _xkwds_get
70
- from pygeodesy.fmath import cbrt, fdot, Fpowers, hypot, hypot1, hypot2_, sqrt0
70
+ from pygeodesy.fmath import cbrt, fdot, hypot, hypot1, hypot2_, sqrt0
71
71
  from pygeodesy.fsums import Fsum, fsumf_, Fmt, unstr
72
72
  # from pygeodesy.internals import typename # from .basics
73
73
  from pygeodesy.interns import NN, _a_, _C_, _datum_, _ellipsoid_, _f_, _height_, \
74
74
  _lat_, _lon_, _M_, _name_, _singular_, _SPACE_, \
75
75
  _x_, _xyz_, _y_, _z_
76
76
  from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS
77
- from pygeodesy.named import _name__, _name1__, _NamedBase, _NamedLocal, \
78
- _NamedTuple, _Pass, _xnamed
77
+ from pygeodesy.named import _name__, _name1__, _NamedBase, _NamedTuple, _Pass, _xnamed
79
78
  from pygeodesy.namedTuples import LatLon2Tuple, LatLon3Tuple, \
80
79
  PhiLam2Tuple, Vector3Tuple, Vector4Tuple
81
80
  from pygeodesy.props import deprecated_method, Property_RO, property_RO, \
@@ -90,7 +89,7 @@ from pygeodesy.utily import atan1, atan1d, atan2, atan2d, degrees90, degrees180,
90
89
  from math import cos, degrees, fabs, radians, sqrt
91
90
 
92
91
  __all__ = _ALL_LAZY.ecef
93
- __version__ = '25.04.24'
92
+ __version__ = '25.05.07'
94
93
 
95
94
  _Ecef_ = 'Ecef'
96
95
  _prolate_ = 'prolate'
@@ -110,6 +109,7 @@ class _EcefBase(_NamedBase):
110
109
  '''
111
110
  _datum = _WGS84
112
111
  _E = _EWGS84
112
+ _isYou = False
113
113
  _lon00 = INT0 # arbitrary, "polar" lon for LocalCartesian, Ltp
114
114
 
115
115
  def __init__(self, a_ellipsoid=_EWGS84, f=None, lon00=INT0, **name):
@@ -272,12 +272,6 @@ class _EcefBase(_NamedBase):
272
272
  return (Ecef9Tuple, # overwrite property_ROver
273
273
  _MODS.vector3d.Vector3d) # _MODS.cartesianBase.CartesianBase
274
274
 
275
- @Property_RO
276
- def _isYou(self):
277
- '''(INTERNAL) Is this an C{EcefYou}?.
278
- '''
279
- return isinstance(self, EcefYou)
280
-
281
275
  @property
282
276
  def lon00(self):
283
277
  '''Get the I{"polar"} longitude (C{degrees}), see method C{reverse}.
@@ -790,6 +784,7 @@ class EcefYou(_EcefBase):
790
784
  11589/115114_9021_geod2ellip_final.pdf>} Studia Geophysica et Geodaetica, 2008, 52,
791
785
  pages 1-18 and U{PyMap3D <https://PyPI.org/project/pymap3d>}.
792
786
  '''
787
+ _isYou = True
793
788
 
794
789
  def __init__(self, a_ellipsoid=_EWGS84, f=None, **lon00_name): # PYCHOK signature
795
790
  _EcefBase.__init__(self, a_ellipsoid, f=f, **lon00_name) # inherited documentation
@@ -825,13 +820,14 @@ class EcefYou(_EcefBase):
825
820
  ellipsoid is I{prolate}.
826
821
  '''
827
822
  x, y, z, name = _xyzn4(xyz, y, z, self._Geocentrics, **lon00_name)
823
+ q = hypot(x, y) # R
828
824
 
829
825
  E = self.ellipsoid
830
826
  e, e2 = self._ee2
831
827
 
832
- q = hypot(x, y) # R
833
- u = Fpowers(2, x, y, z) - e2
834
- u = u.fadd_(hypot(u, e * z * _2_0)).fover(_2_0)
828
+ u = hypot2_(x, y, z) - e2
829
+ u += hypot(u, e * z * _2_0)
830
+ u *= _0_5
835
831
  if u > EPS02:
836
832
  u = sqrt(u)
837
833
  p = hypot(u, e)
@@ -1019,7 +1015,7 @@ class EcefMatrix(_NamedTuple):
1019
1015
  return xyz_
1020
1016
 
1021
1017
 
1022
- class Ecef9Tuple(_NamedTuple, _NamedLocal):
1018
+ class Ecef9Tuple(_NamedTuple, _EcefLocal):
1023
1019
  '''9-Tuple C{(x, y, z, lat, lon, height, C, M, datum)} with I{geocentric} C{x},
1024
1020
  C{y} and C{z} plus I{geodetic} C{lat}, C{lon} and C{height}, case C{C} (see
1025
1021
  the C{Ecef*.reverse} methods) and optionally, rotation matrix C{M} (L{EcefMatrix})
@@ -1041,7 +1037,7 @@ class Ecef9Tuple(_NamedTuple, _NamedLocal):
1041
1037
  return self.toDatum(datum2)
1042
1038
 
1043
1039
  @property_RO
1044
- def _ecef9(self):
1040
+ def _ecef9(self): # in ._EcefLocal._Ltp_ecef2local
1045
1041
  return self
1046
1042
 
1047
1043
  @Property_RO
@@ -1103,13 +1099,6 @@ class Ecef9Tuple(_NamedTuple, _NamedLocal):
1103
1099
  '''
1104
1100
  return Lon(Vermeille=degrees(self.lamVermeille))
1105
1101
 
1106
- def _ltp_toLocal(self, ltp, Xyz_kwds, **Xyz): # overloads C{_NamedLocal}'s
1107
- '''(INTERNAL) Invoke C{ltp._xLtp(ltp)._ecef2local}.
1108
- '''
1109
- Xyz_ = self._ltp_toLocal2(Xyz_kwds, **Xyz) # in ._NamedLocal
1110
- ltp = self._ltp._xLtp(ltp, self._Ltp) # both in ._NamedLocal
1111
- return ltp._ecef2local(self, *Xyz_)
1112
-
1113
1102
  @Property_RO
1114
1103
  def phi(self):
1115
1104
  '''Get the latitude in C{radians} (C{float}).
@@ -0,0 +1,186 @@
1
+
2
+ # -*- coding: utf-8 -*-
3
+
4
+ u'''(INTERNAL) ECEF to local coodinate conversions, separated from
5
+ module C{ecef} to defer importing the latter into C{CartesianBase}
6
+ and C{LatLonBase}.
7
+ '''
8
+
9
+ from pygeodesy.basics import _isin, _xsubclassof
10
+ # from pygeodesy.ecef import EcefKarney # _MODS
11
+ from pygeodesy.errors import _xkwds_item2, _xkwds_pop2
12
+ from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS
13
+ # from pygeodesy import ltp as _ltp # _MODS.into
14
+ # from pygeodesy import ltpTuples as _ltpTuples # _MODS.into
15
+ from pygeodesy.named import _Named, notOverloaded
16
+ from pygeodesy.props import Property_RO, property_RO, property_ROver
17
+
18
+ __all__ = _ALL_LAZY.ecefLocals
19
+ __version__ = '25.04.28'
20
+
21
+ _ltp = _MODS.into(ltp=__name__)
22
+ _ltpTuples = _MODS.into(ltpTuples=__name__)
23
+
24
+
25
+ class _EcefLocal(_Named):
26
+ '''(INTERNAL) Base class for C{CartesianBase}, C{Ecef9Tuple} and
27
+ C{LatLonBase}, providing ECEF to local coordinate conversions.
28
+ '''
29
+
30
+ @property_ROver
31
+ def Ecef(self):
32
+ '''Get the ECEF I{class} (L{EcefKarney}), I{once}.
33
+ '''
34
+ return _MODS.ecef.EcefKarney
35
+
36
+ @property_RO
37
+ def _ecef9(self):
38
+ '''I{Must be overloaded}.'''
39
+ notOverloaded(self)
40
+
41
+ @property_RO
42
+ def _ecef9datum(self):
43
+ try:
44
+ d = self.datum # PYCHOK C{CartesianBase}, ...
45
+ except AttributeError:
46
+ d = None
47
+ return d or self._ecef9.datum
48
+
49
+ @Property_RO
50
+ def _ltp(self):
51
+ '''(INTERNAL) Cache this instance' LTP (L{Ltp}).
52
+ '''
53
+ return _ltp.Ltp(self._ecef9, ecef=self.Ecef(self._ecef9datum), name=self.name)
54
+
55
+ def _ltp_ecef2local(self, ltp, Xyz_kwds, _None=None, **Xyz): # in C{Ecef9Tuple}
56
+ '''(INTERNAL) Invoke C{_ltp._xLtp(ltp, self._ltp)._ecef2local}.
57
+ '''
58
+ C, _ = Xyz_ = _xkwds_pop2(Xyz_kwds, **Xyz)
59
+ if C is not _None: # validate C, see .toLocal
60
+ n, X = _xkwds_item2(Xyz)
61
+ if X is not C:
62
+ _xsubclassof(X, **{n: C})
63
+ ltp = _ltp._xLtp(ltp, self._ltp)
64
+ return ltp._ecef2local(self._ecef9, *Xyz_)
65
+
66
+ def toAer(self, ltp=None, **Aer_and_kwds):
67
+ '''Convert this instance to I{local} I{Azimuth, Elevation, slant Range} (AER) components.
68
+
69
+ @kwarg ltp: The I{local tangent plane} (LTP) to use (L{Ltp}), overriding this
70
+ instance' L{LTP<pygeodesy.ecefLocals._EcefLocal.toLtp>}.
71
+ @kwarg Aer_and_kwds: Optional AER class C{B{Aer}=}L{Aer<pygeodesy.ltpTuples.Aer>}
72
+ to use and optionally, additional B{C{Aer}} keyword arguments.
73
+
74
+ @return: An B{C{Aer}} instance.
75
+
76
+ @raise TypeError: Invalid B{C{ltp}}.
77
+
78
+ @see: Method L{toLocal<pygeodesy.ecefLocals._EcefLocal.toLocal>}.
79
+ '''
80
+ return self._ltp_ecef2local(ltp, Aer_and_kwds, Aer=_ltpTuples.Aer)
81
+
82
+ def toEnu(self, ltp=None, **Enu_and_kwds):
83
+ '''Convert this instance to I{local} I{East, North, Up} (ENU) components.
84
+
85
+ @kwarg ltp: The I{local tangent plane} (LTP) to use (L{Ltp}), overriding this
86
+ instance' L{LTP<pygeodesy.ecefLocals._EcefLocal.toLtp>}.
87
+ @kwarg Enu_and_kwds: Optional ENU class C{B{Enu}=}L{Enu<pygeodesy.ltpTuples.Enu>}
88
+ to use and optionally, additional B{C{Enu}} keyword arguments.
89
+
90
+ @return: An B{C{Enu}} instance.
91
+
92
+ @raise TypeError: Invalid B{C{ltp}}.
93
+
94
+ @see: Method L{toLocal<pygeodesy.ecefLocals._EcefLocal.toLocal>}.
95
+ '''
96
+ return self._ltp_ecef2local(ltp, Enu_and_kwds, Enu=_ltpTuples.Enu)
97
+
98
+ def toLocal(self, Xyz=None, ltp=None, **Xyz_kwds):
99
+ '''Convert this instance to I{local} components in a I{local tangent plane} (LTP)
100
+
101
+ @kwarg Xyz: Optional I{local} components class (L{XyzLocal}, L{Aer}, L{Enu},
102
+ L{Ned}) or C{None}.
103
+ @kwarg ltp: The I{local tangent plane} (LTP) to use (L{Ltp}), overriding this
104
+ cartesian's L{LTP<pygeodesy.ecefLocals._EcefLocal.toLtp>}.
105
+ @kwarg Xyz_kwds: Optionally, additional B{C{Xyz}} keyword arguments, ignored
106
+ if C{B{Xyz} is None}.
107
+
108
+ @return: An B{C{Xyz}} instance or a L{Local9Tuple}C{(x, y, z, lat, lon,
109
+ height, ltp, ecef, M)} if C{B{Xyz} is None} (with C{M=None}).
110
+
111
+ @raise TypeError: Invalid B{C{ltp}}.
112
+ '''
113
+ return self._ltp_ecef2local(ltp, Xyz_kwds, Xyz=Xyz, _None=Xyz)
114
+
115
+ def toLtp(self, Ecef=None, **name):
116
+ '''Return the I{local tangent plane} (LTP) for this instance.
117
+
118
+ @kwarg Ecef: Optional ECEF I{class} (L{EcefKarney}, ... L{EcefYou}), overriding
119
+ this instance' L{Ecef<pygeodesy.ecefLocals._EcefLocal.Ecef>}.
120
+ @kwarg name: Optional C{B{name}=NN} (C{str}).
121
+
122
+ @return: An B{C{Ltp}} instance.
123
+ '''
124
+ if _isin(Ecef, None, self.Ecef) and not name:
125
+ ltp = self._ltp
126
+ else: # like self._ltp
127
+ ecef = (Ecef if Ecef else self.Ecef)(self._ecef9datum)
128
+ ltp = _ltp.Ltp(self._ecef9, ecef=ecef, name=self._name__(name))
129
+ return ltp
130
+
131
+ def toNed(self, ltp=None, **Ned_and_kwds):
132
+ '''Convert this instance to I{local} I{North, East, Down} (NED) components.
133
+
134
+ @kwarg ltp: The I{local tangent plane} (LTP) to use (L{Ltp}), overriding this
135
+ instance' L{LTP<pygeodesy.ecefLocals._EcefLocal.toLtp>}.
136
+ @kwarg Ned_and_kwds: Optional NED class C{B{Ned}=}L{Ned<pygeodesy.ltpTuples.Ned>}
137
+ to use and optionally, additional B{C{Ned}} keyword arguments.
138
+
139
+ @return: An B{C{Ned}} instance.
140
+
141
+ @raise TypeError: Invalid B{C{ltp}}.
142
+
143
+ @see: Method L{toLocal<pygeodesy.ecefLocals._EcefLocal.toLocal>}.
144
+ '''
145
+ return self._ltp_ecef2local(ltp, Ned_and_kwds, Ned=_ltpTuples.Ned)
146
+
147
+ def toXyz(self, ltp=None, **Xyz_and_kwds):
148
+ '''Convert this instance to I{local} I{X, Y, Z} (XYZ) components.
149
+
150
+ @kwarg ltp: The I{local tangent plane} (LTP) to use (L{Ltp}), overriding this
151
+ instance' L{LTP<pygeodesy.ecefLocals._EcefLocal.toLtp>}.
152
+ @kwarg Xyz_and_kwds: Optional XYZ class C{B{Xyz}=}L{Xyz<pygeodesy.ltpTuples.XyzLocal>}
153
+ to use and optionally, additional B{C{Xyz}} keyword arguments.
154
+
155
+ @return: An B{C{Xyz}} instance.
156
+
157
+ @raise TypeError: Invalid B{C{ltp}}.
158
+
159
+ @see: Method L{toLocal<pygeodesy.ecefLocals._EcefLocal.toLocal>}.
160
+ '''
161
+ return self._ltp_ecef2local(ltp, Xyz_and_kwds, Xyz=_ltpTuples.XyzLocal)
162
+
163
+
164
+ __all__ += _ALL_DOCS(_EcefLocal)
165
+
166
+ # **) MIT License
167
+ #
168
+ # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
169
+ #
170
+ # Permission is hereby granted, free of charge, to any person obtaining a
171
+ # copy of this software and associated documentation files (the "Software"),
172
+ # to deal in the Software without restriction, including without limitation
173
+ # the rights to use, copy, modify, merge, publish, distribute, sublicense,
174
+ # and/or sell copies of the Software, and to permit persons to whom the
175
+ # Software is furnished to do so, subject to the following conditions:
176
+ #
177
+ # The above copyright notice and this permission notice shall be included
178
+ # in all copies or substantial portions of the Software.
179
+ #
180
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
181
+ # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
182
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
183
+ # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
184
+ # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
185
+ # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
186
+ # OTHER DEALINGS IN THE SOFTWARE.
@@ -10,7 +10,7 @@ and published under the same MIT Licence**, see for example U{latlon-ellipsoidal
10
10
  <https://www.Movable-Type.co.UK/scripts/geodesy/docs/latlon-ellipsoidal.js.html>}.
11
11
  '''
12
12
  # make sure int/int division yields float quotient, see .basics
13
- from __future__ import division as _; del _ # PYCHOK semicolon
13
+ from __future__ import division as _; del _ # noqa: E702 ;
14
14
 
15
15
  # from pygeodesy.azimuthal import EquidistantExact, EquidistantKarney # _MODS
16
16
  from pygeodesy.basics import _isin, _xinstanceof
@@ -46,7 +46,7 @@ from pygeodesy.units import Epoch, _isDegrees, Radius_, _1mm as _TOL_M
46
46
  # from math import fabs # from .latlonBase
47
47
 
48
48
  __all__ = _ALL_LAZY.ellipsoidalBase
49
- __version__ = '25.04.14'
49
+ __version__ = '25.05.12'
50
50
 
51
51
 
52
52
  class CartesianEllipsoidalBase(CartesianBase):