pygeodesy 24.10.10__py2.py3-none-any.whl → 24.11.11__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 (76) hide show
  1. {PyGeodesy-24.10.10.dist-info → PyGeodesy-24.11.11.dist-info}/METADATA +12 -12
  2. PyGeodesy-24.11.11.dist-info/RECORD +118 -0
  3. {PyGeodesy-24.10.10.dist-info → PyGeodesy-24.11.11.dist-info}/WHEEL +1 -1
  4. pygeodesy/__init__.py +14 -14
  5. pygeodesy/__main__.py +5 -5
  6. pygeodesy/albers.py +12 -17
  7. pygeodesy/azimuthal.py +51 -61
  8. pygeodesy/basics.py +60 -62
  9. pygeodesy/booleans.py +87 -79
  10. pygeodesy/cartesianBase.py +6 -6
  11. pygeodesy/constants.py +23 -19
  12. pygeodesy/css.py +7 -8
  13. pygeodesy/datums.py +3 -3
  14. pygeodesy/deprecated/__init__.py +1 -1
  15. pygeodesy/deprecated/classes.py +9 -9
  16. pygeodesy/deprecated/functions.py +6 -6
  17. pygeodesy/dms.py +250 -270
  18. pygeodesy/ecef.py +11 -14
  19. pygeodesy/ellipsoidalBase.py +106 -121
  20. pygeodesy/ellipsoidalBaseDI.py +114 -118
  21. pygeodesy/ellipsoidalExact.py +35 -37
  22. pygeodesy/ellipsoidalNvector.py +4 -4
  23. pygeodesy/ellipsoidalVincenty.py +2 -2
  24. pygeodesy/ellipsoids.py +10 -51
  25. pygeodesy/elliptic.py +14 -14
  26. pygeodesy/errors.py +28 -28
  27. pygeodesy/etm.py +92 -68
  28. pygeodesy/fmath.py +42 -40
  29. pygeodesy/formy.py +7 -6
  30. pygeodesy/fsums.py +72 -51
  31. pygeodesy/geodesici.py +43 -40
  32. pygeodesy/geodesicw.py +17 -16
  33. pygeodesy/geodesicx/__init__.py +2 -2
  34. pygeodesy/geodesicx/gxarea.py +3 -2
  35. pygeodesy/geodsolve.py +79 -39
  36. pygeodesy/geohash.py +2 -2
  37. pygeodesy/geoids.py +32 -31
  38. pygeodesy/heights.py +2 -2
  39. pygeodesy/internals.py +201 -147
  40. pygeodesy/interns.py +23 -20
  41. pygeodesy/karney.py +62 -13
  42. pygeodesy/ktm.py +11 -13
  43. pygeodesy/latlonBase.py +18 -20
  44. pygeodesy/lazily.py +210 -218
  45. pygeodesy/lcc.py +4 -4
  46. pygeodesy/ltp.py +10 -10
  47. pygeodesy/ltpTuples.py +74 -75
  48. pygeodesy/mgrs.py +20 -21
  49. pygeodesy/named.py +15 -10
  50. pygeodesy/nvectorBase.py +1 -1
  51. pygeodesy/osgr.py +9 -12
  52. pygeodesy/points.py +2 -2
  53. pygeodesy/props.py +35 -14
  54. pygeodesy/resections.py +9 -10
  55. pygeodesy/rhumb/__init__.py +1 -1
  56. pygeodesy/rhumb/bases.py +5 -5
  57. pygeodesy/rhumb/solve.py +9 -10
  58. pygeodesy/simplify.py +5 -5
  59. pygeodesy/solveBase.py +7 -25
  60. pygeodesy/sphericalBase.py +20 -23
  61. pygeodesy/sphericalNvector.py +103 -145
  62. pygeodesy/sphericalTrigonometry.py +68 -73
  63. pygeodesy/streprs.py +5 -5
  64. pygeodesy/trf.py +6 -4
  65. pygeodesy/triaxials.py +46 -9
  66. pygeodesy/units.py +5 -4
  67. pygeodesy/ups.py +6 -6
  68. pygeodesy/utily.py +2 -2
  69. pygeodesy/utm.py +7 -7
  70. pygeodesy/vector2d.py +13 -13
  71. pygeodesy/vector3d.py +19 -21
  72. pygeodesy/vector3dBase.py +21 -19
  73. pygeodesy/webmercator.py +4 -4
  74. pygeodesy/wgrs.py +4 -4
  75. PyGeodesy-24.10.10.dist-info/RECORD +0 -118
  76. {PyGeodesy-24.10.10.dist-info → PyGeodesy-24.11.11.dist-info}/top_level.txt +0 -0
pygeodesy/props.py CHANGED
@@ -12,22 +12,24 @@ choices, see callable L{DeprecationWarnings} below.
12
12
 
13
13
  from pygeodesy.basics import isclass as _isclass
14
14
  from pygeodesy.errors import _AssertionError, _AttributeError, \
15
- _xcallable, _xkwds, _xkwds_get
15
+ _xcallable, _xkwds_get
16
+ # from pygeodesy.internals import _tailof # from .lazily
16
17
  from pygeodesy.interns import MISSING, NN, _an_, _COMMASPACE_, \
17
18
  _DEPRECATED_, _DOT_, _EQUALSPACED_, \
18
- _immutable_, _invalid_, _module_, _N_A_, \
19
- _not_, _SPACE_, _UNDER_, _DNL_ # PYCHOK used!
19
+ _immutable_, _invalid_, _module_, \
20
+ _N_A_, _NL_, _not_, _SPACE_, _UNDER_
20
21
  # from pygeodesy.named import callname # _MODS, avoid circular
21
22
  from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS, \
22
- _FOR_DOCS, _WARNINGS_X_DEV
23
+ _FOR_DOCS, _WARNINGS_X_DEV, _tailof
23
24
  # from pygeodesy.streprs import Fmt # _MODS
24
25
 
25
26
  from functools import wraps as _wraps
26
27
 
27
28
  __all__ = _ALL_LAZY.props
28
- __version__ = '24.09.02'
29
+ __version__ = '24.11.06'
29
30
 
30
31
  _class_ = 'class'
32
+ _DNL_ = _NL_ * 2 # PYCHOK used!
31
33
  _dont_use_ = _DEPRECATED_ + ", don't use."
32
34
  _function_ = 'function'
33
35
  _has_been_ = 'has been' # PYCHOK used!
@@ -367,7 +369,7 @@ class _property_RO___(_PropertyBase):
367
369
  '''
368
370
  _PropertyBase.__init__(self, method, self._fget, self._fset_error, doc=doc)
369
371
 
370
- def _fdel(self, unused): # PYCHOK no cover
372
+ def _fdel(self, *unused): # PYCHOK no cover
371
373
  '''Silently ignored, always.
372
374
  '''
373
375
  pass
@@ -650,23 +652,42 @@ class DeprecationWarnings(object):
650
652
  '''
651
653
  return self.Warnings
652
654
 
655
+ @property_ROver
656
+ def _Fmt(self):
657
+ '''Get C{streprs.Fmt}, I{once}.
658
+ '''
659
+ return _MODS.streprs.Fmt
660
+
661
+ @property_ROver
662
+ def _stacklevel3(self):
663
+ '''Get C{dict(stacklevel=3)}, I{once}.
664
+ '''
665
+ return dict(stacklevel=3)
666
+
653
667
  def throw(self, kind, name, doc, **stacklevel): # stacklevel=3
654
668
  '''Report or raise a C{DeprecationWarning}.
669
+
670
+ @arg kind: Warning kind (C{str}), C{"method"}, C{"funtion"}, ...
671
+ @arg name: Qualified name (C{str}) of B{C{kind}}.
672
+ @arg doc: The __doc__ (C{str}) of B{C{kind}}, C{"DEPRECATED ...}.
655
673
  '''
656
- line = doc.split(_DNL_, 1)[0].strip()
657
- name = _MODS.streprs.Fmt.CURLY(L=name)
658
- text = _SPACE_(kind, name, _has_been_, *line.split())
659
- kwds = _xkwds(stacklevel, stacklevel=3)
674
+ link = _tailof(name) or name
675
+ if link is not name: # make "link<name>"
676
+ link = self._Fmt.ANGLE(link, name)
677
+ link = self._Fmt.CURLY(L=link) # "L{link}"
678
+ text = doc.split(_DNL_, 1)[0].strip()
679
+ text = _SPACE_(kind, link, _has_been_, *text.split())
680
+ kwds = stacklevel if stacklevel else self._stacklevel3
660
681
  # XXX invoke warn or raise DeprecationWarning(text)
661
682
  self._warn(text, category=DeprecationWarning, **kwds)
662
683
  self._Warnings += 1
663
684
 
664
- @Property_RO
685
+ @property_ROver
665
686
  def _warn(self):
666
- '''Get Python's C{warnings.warn}.
687
+ '''Get Python's C{warnings.warn} function, I{once}.
667
688
  '''
668
- from warnings import warn
669
- return warn
689
+ from warnings import warn as w
690
+ return w
670
691
 
671
692
  @property_RO
672
693
  def Warnings(self):
pygeodesy/resections.py CHANGED
@@ -34,7 +34,7 @@ from pygeodesy.vector3d import _otherV3d, Vector3d
34
34
  from math import cos, atan2, degrees, fabs, radians, sin, sqrt
35
35
 
36
36
  __all__ = _ALL_LAZY.resections
37
- __version__ = '24.09.23'
37
+ __version__ = '24.11.04'
38
38
 
39
39
  _concyclic_ = 'concyclic'
40
40
  _PA_ = 'PA'
@@ -200,11 +200,11 @@ def cassini(pointA, pointB, pointC, alpha, beta, useZ=False, **Clas_and_kwds):
200
200
  alpha=alpha, beta=beta, cause=x)
201
201
 
202
202
 
203
- def _Clas(where, point, Clas_and_kwds, *args):
203
+ def _Clas(which, point, Clas_and_kwds, *args):
204
204
  '''(INTERNAL) Return a C{B{Clas}=point.classof} survey point.
205
205
  '''
206
206
  Clas, kwds = _xkwds_pop2(Clas_and_kwds, Clas=point.classof)
207
- return Clas(*args, **_xkwds(kwds, name=where.__name__))
207
+ return Clas(*args, **_xkwds(kwds, name=which.__name__))
208
208
 
209
209
 
210
210
  def collins5(pointA, pointB, pointC, alpha, beta, useZ=False, **Clas_and_kwds):
@@ -252,8 +252,8 @@ def collins5(pointA, pointB, pointC, alpha, beta, useZ=False, **Clas_and_kwds):
252
252
 
253
253
  def _xyz(d, r, A, B, C, useZ):
254
254
  s, c = sincos2(r)
255
- x = A.x + d * s
256
- y = A.y + d * c
255
+ x = d * s + A.x # fma(d, s, A.x)
256
+ y = d * c + A.y # fma(d, c, A.y)
257
257
  z = _zidw(x, y, useZ, A, B, C)
258
258
  return x, y, z
259
259
 
@@ -282,11 +282,10 @@ def collins5(pointA, pointB, pointC, alpha, beta, useZ=False, **Clas_and_kwds):
282
282
  d = b * sin(zb - zh) / sra # A.minus(P).length
283
283
  r = zh - ra # zb - PI + (PI - ra - (zb - zh))
284
284
  P = _xyz(d, r, A, B, C, useZ)
285
- P = _Clas(collins5, pointA, Clas_and_kwds, *P)
286
285
 
286
+ P = _Clas(collins5, pointA, Clas_and_kwds, *P)
287
287
  H = _Clas(collins5, pointA, Clas_and_kwds, *H)
288
288
  a = B.minus(C).length
289
-
290
289
  return Collins5Tuple(P, H, a, b, c, name=collins5.__name__)
291
290
 
292
291
  except (TypeError, ValueError) as x:
@@ -312,7 +311,7 @@ def pierlot(point1, point2, point3, alpha12, alpha23, useZ=False, eps=EPS,
312
311
  B{C{alpha3 - alpha2}}(C{degrees}).
313
312
  @kwarg useZ: If C{True}, interpolate the survey point's Z component,
314
313
  otherwise use C{z=INT0} (C{bool}).
315
- @kwarg eps: Tolerance for C{cot} (pseudo-)singularities (C{float}).
314
+ @kwarg eps: Tolerance for C{cot}angent (pseudo-)singularities (C{float}).
316
315
  @kwarg Clas_and_kwds: Optional class C{B{Clas}=B{point1}.classof} to
317
316
  return the survey point with optionally other B{C{Clas}}
318
317
  keyword arguments to instantiate the survey point.
@@ -427,8 +426,8 @@ def pierlotx(point1, point2, point3, alpha1, alpha2, alpha3, useZ=False,
427
426
  return the survey point with optionally other B{C{Clas}}
428
427
  keyword arguments to instantiate the survey point.
429
428
 
430
- @return: The survey (or robot) point, an instance of B{C{Clas}} or B{C{point1}}'s
431
- (sub-)class.
429
+ @return: The survey (or robot) point, an instance of B{C{Clas}} or
430
+ B{C{point1}}'s (sub-)class.
432
431
 
433
432
  @raise ResectionError: Near-coincident, -colinear or -concyclic points or
434
433
  invalid B{C{alpha1}}, B{C{alpha2}} or B{C{alpha3}}.
@@ -9,7 +9,7 @@ u'''Package of lazily imported C{rhumb} modules L{rhumb.aux_}, L{rhumb.ekx} and
9
9
  from pygeodesy.lazily import _ALL_LAZY, _ALL_OTHER, _lazy_import_as, _unLazy0
10
10
 
11
11
  __all__ = _ALL_LAZY.rhumb
12
- __version__ = '24.09.02'
12
+ __version__ = '24.11.07'
13
13
 
14
14
  if _unLazy0: # or _isfrozen
15
15
  from pygeodesy.rhumb.aux_ import RhumbAux, RhumbLineAux
pygeodesy/rhumb/bases.py CHANGED
@@ -33,7 +33,7 @@ from pygeodesy.errors import IntersectionError, RhumbError, _xdatum, \
33
33
  from pygeodesy.fmath import euclid, favg, sqrt_a, Fsum
34
34
  # from pygeodesy.formy import opposing # _MODS
35
35
  # from pygeodesy.fsums import Fsum # from .fmath
36
- from pygeodesy.internals import _dunder_nameof, _under
36
+ from pygeodesy.internals import _DUNDER_nameof, _under
37
37
  from pygeodesy.interns import NN, _coincident_, _COMMASPACE_, _Dash, \
38
38
  _parallel_, _too_
39
39
  from pygeodesy.karney import _atan2d, Caps, _CapsBase, _diff182, _fix90, \
@@ -52,7 +52,7 @@ from pygeodesy.vector3d import _intersect3d3, Vector3d # in .Intersection below
52
52
  from math import cos, fabs
53
53
 
54
54
  __all__ = ()
55
- __version__ = '24.06.18'
55
+ __version__ = '24.10.14'
56
56
 
57
57
  _anti_ = _Dash('anti')
58
58
  _rls = [] # instances of C{RbumbLine...} to be updated
@@ -634,7 +634,7 @@ class RhumbLineBase(_CapsBase):
634
634
  t = dict(lat3=q.lat2, lon3=q.lon2, azi03=q.azi02, a03=q.a02, s03=a)
635
635
  if a < r:
636
636
  t.update(iteration=q.iteration, lat0=q.lat1, lon0=q.lon1, # or lat0, lon0
637
- name=_dunder_nameof(self.Intersecant2, self.name))
637
+ name=_DUNDER_nameof(self.Intersecant2, self.name))
638
638
  if fabs(a) < EPS0: # coincident centers
639
639
  d, h = _0_0, r
640
640
  else:
@@ -723,7 +723,7 @@ class RhumbLineBase(_CapsBase):
723
723
 
724
724
  P = GDict(lat1=self.lat1, lat2=p.lat, lat0=other.lat1,
725
725
  lon1=self.lon1, lon2=p.lon, lon0=other.lon1,
726
- name=_dunder_nameof(self.Intersection, self.name))
726
+ name=_DUNDER_nameof(self.Intersection, self.name))
727
727
  r = self.Inverse(p.lat, p.lon, outmask=Caps.DISTANCE)
728
728
  t = other.Inverse(p.lat, p.lon, outmask=Caps.DISTANCE)
729
729
  P.set_(azi12= self.azi12, a12=r.a12, s12=r.s12,
@@ -897,7 +897,7 @@ class RhumbLineBase(_CapsBase):
897
897
  break
898
898
  P.set_(azi0=r.azi1, a02=r.a12, s02=r.s12, # azi2=r.azi2,
899
899
  lat0=lat0, lon0=lon0, iteration=i, at=r.azi2 - self.azi12,
900
- name=_dunder_nameof(self.PlumbTo, self.name))
900
+ name=_DUNDER_nameof(self.PlumbTo, self.name))
901
901
  except Exception as x: # Fsum(NAN) Value-, ZeroDivisionError
902
902
  raise IntersectionError(lat0=lat0, lon0=lon0, tol=tol, exact=exact,
903
903
  eps=eps, est=est, iteration=i, cause=x)
pygeodesy/rhumb/solve.py CHANGED
@@ -12,16 +12,15 @@ from pygeodesy.basics import _xinstanceof
12
12
  from pygeodesy.constants import _0_0, _180_0, _N_180_0, _over, _90_0 # PYCHOK used!
13
13
  from pygeodesy.errors import RhumbError # PYCHOK used!
14
14
  from pygeodesy.interns import NN, _a12_, _azi12_, _lat2_, _lon2_, _s12_, _S12_, _UNDER_
15
- from pygeodesy.karney import Caps, GDict, _norm180, Rhumb8Tuple, _sincos2d
16
- from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS, _getenv, \
17
- _PYGEODESY_RHUMBSOLVE_
15
+ from pygeodesy.karney import Caps, GDict, _norm180, Rhumb8Tuple, _sincos2d, _Xables
16
+ from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS
18
17
  from pygeodesy.namedTuples import Destination3Tuple, Distance3Tuple
19
18
  from pygeodesy.props import deprecated_method, Property, Property_RO
20
19
  from pygeodesy.solveBase import _SolveGDictBase, _SolveGDictLineBase
21
20
  from pygeodesy.utily import _unrollon, _Wrap, wrap360
22
21
 
23
22
  __all__ = _ALL_LAZY.rhumb_solve
24
- __version__ = '24.08.13'
23
+ __version__ = '24.11.07'
25
24
 
26
25
 
27
26
  class _RhumbSolveBase(_SolveGDictBase):
@@ -30,8 +29,8 @@ class _RhumbSolveBase(_SolveGDictBase):
30
29
  _Error = RhumbError
31
30
  _Names_Direct = _lat2_, _lon2_, _S12_
32
31
  _Names_Inverse = _azi12_, _s12_, _S12_
33
- _Xable_name = 'RhumbSolve'
34
- _Xable_path = _getenv(_PYGEODESY_RHUMBSOLVE_, _PYGEODESY_RHUMBSOLVE_)
32
+ _Xable_name = _Xables.RhumbSolve.__name__
33
+ _Xable_path = _Xables.RhumbSolve()
35
34
 
36
35
  @Property_RO
37
36
  def _cmdBasic(self):
@@ -184,7 +183,7 @@ class RhumbSolve(_RhumbSolveBase):
184
183
  def _Inverse(self, ll1, ll2, wrap, **unused):
185
184
  '''(INTERNAL) Short-cut version, see .latlonBase.
186
185
  '''
187
- if wrap:
186
+ if wrap: # PYCHOK no cover
188
187
  ll2 = _unrollon(ll1, _Wrap.point(ll2))
189
188
  return self._GDictInverse(ll1.lat, ll1.lon, ll2.lat, ll2.lon)
190
189
 
@@ -202,7 +201,7 @@ class RhumbSolve(_RhumbSolveBase):
202
201
  def _InverseLine(self, ll1, ll2, wrap, **name_caps):
203
202
  '''(INTERNAL) Short-cut version, see .latlonBase.
204
203
  '''
205
- if wrap:
204
+ if wrap: # PYCHOK no cover
206
205
  ll2 = _unrollon(ll1, _Wrap.point(ll2))
207
206
  return self.InverseLine(ll1.lat, ll1.lon, ll2.lat, ll2.lon, **name_caps)
208
207
 
@@ -394,8 +393,8 @@ if __name__ == '__main__':
394
393
  rS = RhumbSolve(name='Test')
395
394
  rS.verbose = '--verbose' in argv # or '-v' in argv
396
395
 
397
- if rS.RhumbSolve in (_PYGEODESY_RHUMBSOLVE_, None): # not set
398
- rS.RhumbSolve = '/opt/local/bin/RhumbSolve' # '/opt/local/Cellar/geographiclib/2.3/bin/RhumbSolve' # HomeBrew
396
+ if not _Xables.X_OK(rS.RhumbSolve): # not set
397
+ rS.RhumbSolve = _Xables.RhumbSolve(_Xables.bin_)
399
398
  printf('version: %s', rS.version)
400
399
 
401
400
  if len(argv) > 6: # 60 0 30 0 45 1e6
pygeodesy/simplify.py CHANGED
@@ -76,7 +76,7 @@ from __future__ import division as _; del _ # PYCHOK semicolon
76
76
  # from pygeodesy.basics import len2 # from .fmath
77
77
  from pygeodesy.constants import EPS, R_M, _1_0
78
78
  from pygeodesy.errors import _AttributeError, _ValueError
79
- from pygeodesy.fmath import len2, sqrt0
79
+ from pygeodesy.fmath import fdot_, len2, sqrt0
80
80
  from pygeodesy.formy import equirectangular4
81
81
  from pygeodesy.interns import _small_, _too_
82
82
  from pygeodesy.iters import isNumpy2, isTuple2
@@ -86,7 +86,7 @@ from pygeodesy.units import _ALL_LAZY, _1mm, Radius_
86
86
  from math import degrees, fabs, radians
87
87
 
88
88
  __all__ = _ALL_LAZY.simplify
89
- __version__ = '24.08.13'
89
+ __version__ = '24.11.07'
90
90
 
91
91
 
92
92
  # try:
@@ -222,11 +222,11 @@ class _Sy(object):
222
222
  # distance points[i] to -[s]
223
223
  d2, y01, x01, _ = _d2yxu4(s, i)
224
224
  if d2 > eps:
225
- w = y01 * y21 + x01 * x21
225
+ w = fdot_(y01, y21, x01, x21)
226
226
  if w > 0:
227
227
  if w < d21:
228
228
  # perpendicular distance squared
229
- d2 = (y01 * x21 - x01 * y21)**2 / d21
229
+ d2 = fdot_(y01, x21, -x01, y21)**2 / d21
230
230
  else: # distance points[i] to -[e]
231
231
  d2, _, _, _ = _d2yxu4(e, i)
232
232
  if d2 > t2:
@@ -252,7 +252,7 @@ class _Sy(object):
252
252
  if d21 > self.eps:
253
253
  d01, y01, x01, _ = self.d2yxu4(i1, i0)
254
254
  if d01 > self.eps:
255
- h2 = fabs(y01 * x21 - x01 * y21)
255
+ h2 = fabs(fdot_(y01, x21, -x01, y21))
256
256
  # triangle height h = h2 / sqrt(d21) and
257
257
  # the area = h * sqrt(d21) / 2 == h2 / 2
258
258
  return h2 # double triangle area
pygeodesy/solveBase.py CHANGED
@@ -4,36 +4,28 @@
4
4
  u'''(INTERNAL) Private base classes for L{pygeodesy.geodsolve} and L{pygeodesy.rhumb.solve}.
5
5
  '''
6
6
 
7
- from pygeodesy.basics import clips, map2, ub2str, _zip
7
+ from pygeodesy.basics import clips, map2, _zip
8
8
  from pygeodesy.constants import DIG
9
9
  from pygeodesy.datums import _earth_datum, _WGS84, _EWGS84
10
10
  # from pygeodesy.ellipsoids import _EWGS84 # from .datums
11
11
  from pygeodesy.errors import _AssertionError, _xkwds_get, _xkwds_get1, \
12
12
  _xkwds_item2
13
- from pygeodesy.internals import _enquote, printf
13
+ from pygeodesy.internals import _enquote, _popen2, printf
14
14
  from pygeodesy.interns import NN, _0_, _AT_,_BACKSLASH_, _COLONSPACE_, \
15
15
  _COMMASPACE_, _EQUAL_, _Error_, _SPACE_, \
16
16
  _UNUSED_
17
17
  from pygeodesy.karney import Caps, _CapsBase, GDict
18
- from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _sys_version_info2
18
+ from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY
19
19
  from pygeodesy.named import callername, _name2__, notOverloaded
20
20
  from pygeodesy.props import Property, Property_RO, property_RO, _update_all
21
21
  from pygeodesy.streprs import Fmt, fstr, fstrzs, pairs, strs
22
22
  from pygeodesy.units import Precision_
23
23
  from pygeodesy.utily import unroll180, wrap360 # PYCHOK shared
24
24
 
25
- from subprocess import PIPE as _PIPE, Popen as _Popen, STDOUT as _STDOUT
26
-
27
25
  __all__ = _ALL_LAZY.solveBase
28
- __version__ = '24.07.11'
26
+ __version__ = '24.10.13'
29
27
 
30
- _ERROR_ = 'ERROR'
31
- _Popen_kwds = dict(creationflags=0,
32
- # executable=sys.executable, shell=True,
33
- stdin=_PIPE, stdout=_PIPE, stderr=_STDOUT)
34
- if _sys_version_info2 > (3, 6):
35
- _Popen_kwds.update(text=True)
36
- del _PIPE, _STDOUT, _sys_version_info2 # _ALL_LAZY
28
+ _ERROR_ = 'ERROR'
37
29
 
38
30
 
39
31
  def _cmd_stdin_(cmd, stdin): # PYCHOK no cover
@@ -53,15 +45,6 @@ def _cmd_stdin_(cmd, stdin): # PYCHOK no cover
53
45
  # return i if float(i) == f else f # PYCHOK inconsistent
54
46
 
55
47
 
56
- def _popen2(cmd, stdin=None): # in .mgrs, test.bases, .testMgrs
57
- '''(INTERNAL) Invoke C{B{cmd} tuple} and return C{exitcode}
58
- and all output from C{stdout/-err}, I{stripped}.
59
- '''
60
- p = _Popen(cmd, **_Popen_kwds) # PYCHOK kwArgs
61
- r = p.communicate(stdin)[0] # stdout + NL + stderr
62
- return p.returncode, ub2str(r).strip()
63
-
64
-
65
48
  class _SolveCapsBase(_CapsBase):
66
49
  '''(NTERNAL) Base class for C{_SolveBase} and C{_LineSolveBase}.
67
50
  '''
@@ -85,8 +68,7 @@ class _SolveCapsBase(_CapsBase):
85
68
  return self.ellipsoid.a
86
69
 
87
70
  @property_RO
88
- def _cmdBasic(self): # PYCHOK no cover
89
- '''(INTERNAL) I{Must be overloaded}.'''
71
+ def _cmdBasic(self): # PYCHOK no covers '''(INTERNAL) I{Must be overloaded}.'''
90
72
  notOverloaded(self, underOK=True)
91
73
 
92
74
  @property_RO
@@ -228,7 +210,7 @@ class _SolveCapsBase(_CapsBase):
228
210
  t = _cmd_stdin_(cmd, stdin)
229
211
  self._print(t)
230
212
  try: # invoke and write to stdin
231
- s, r = _popen2(cmd, stdin)
213
+ r, s = _popen2(cmd, stdin)
232
214
  if len(r) < 6 or r[:5] in (_Error_, _ERROR_):
233
215
  raise ValueError(r)
234
216
  except (IOError, OSError, TypeError, ValueError) as x:
@@ -5,7 +5,7 @@ u'''(INTERNAL) Private spherical base classes C{CartesianSphericalBase} and
5
5
  C{LatLonSphericalBase} for L{sphericalNvector} and L{sphericalTrigonometry}.
6
6
 
7
7
  A pure Python implementation of geodetic (lat-/longitude) functions,
8
- transcoded in part from JavaScript originals by I{(C) Chris Veness 2011-2016}
8
+ transcoded in part from JavaScript originals by I{(C) Chris Veness 2011-2024}
9
9
  and published under the same MIT Licence**, see
10
10
  U{Latitude/Longitude<https://www.Movable-Type.co.UK/scripts/latlong.html>}.
11
11
  '''
@@ -40,7 +40,7 @@ from pygeodesy.utily import acos1, asin1, atan2b, atan2d, degrees90, \
40
40
  from math import cos, fabs, log, sin, sqrt
41
41
 
42
42
  __all__ = _ALL_LAZY.sphericalBase
43
- __version__ = '24.08,13'
43
+ __version__ = '24.10.19'
44
44
 
45
45
 
46
46
  class CartesianSphericalBase(CartesianBase):
@@ -126,24 +126,23 @@ class LatLonSphericalBase(LatLonBase):
126
126
  @kwarg lon: Longitude (C{degrees} or DMS C{str} with E or W suffix) or
127
127
  C(None), indicating B{C{latlonh}} is a C{LatLon}.
128
128
  @kwarg height: Optional height above (or below) the earth surface (C{meter},
129
- same units as the datum's ellipsoid axes or radius).
129
+ same units as the datum's radius or axes).
130
130
  @kwarg datum: Optional, spherical datum to use (L{Datum}, L{Ellipsoid},
131
- L{Ellipsoid2}, L{a_f2Tuple}) or earth radius in C{meter},
132
- conventionally).
131
+ L{Ellipsoid2}, L{a_f2Tuple}) or the mean earth radius
132
+ (C{meter}, conventionally).
133
133
  @kwarg wrap: If C{True}, wrap or I{normalize} B{C{lat}} and B{C{lon}}
134
134
  (C{bool}).
135
135
  @kwarg name: Optional C{B{name}=NN} (C{str}).
136
136
 
137
- @raise TypeError: If B{C{latlonh}} is not a C{LatLon} or B{C{datum}} not
138
- spherical.
137
+ @raise TypeError: Invalid B{C{latlonh}} or B{C{datum}} not spherical.
139
138
  '''
140
139
  LatLonBase.__init__(self, latlonh, lon=lon, height=height, wrap=wrap, **name)
141
140
  if datum not in (None, self.datum):
142
141
  self.datum = datum
143
142
 
144
143
  def bearingTo2(self, other, wrap=False, raiser=False):
145
- '''Return the initial and final bearing (forward and reverse
146
- azimuth) from this to an other point.
144
+ '''Return the initial and final bearing (forward and reverse azimuth)
145
+ from this to an other point.
147
146
 
148
147
  @arg other: The other point (C{LatLon}).
149
148
  @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the
@@ -204,10 +203,10 @@ class LatLonSphericalBase(LatLonBase):
204
203
 
205
204
  @arg circle: Radius of the circle centered at this location (C{meter},
206
205
  same units as B{C{radius}}) or a point on the circle
207
- (this C{LatLon}).
208
- @arg point: A point on the (great circle) line (this C{LatLon}).
209
- @arg other: An other point I{on} (this {LatLon}) or the bearing at
210
- B{C{point}} I{of} the (great circle) line (compass
206
+ (same C{LatLon} class).
207
+ @arg point: A point on the (great circle) line (same C{LatLon} class).
208
+ @arg other: An other point I{on} (same C{LatLon} class) or the bearing
209
+ at B{C{point}} I{of} the (great circle) line (compass
211
210
  C{degrees}).
212
211
  @kwarg radius: Mean earth radius (C{meter}, conventionally).
213
212
  @kwarg exact: If C{True}, use the I{exact} rhumb methods for azimuth,
@@ -216,8 +215,8 @@ class LatLonSphericalBase(LatLonBase):
216
215
  circle} methods.
217
216
  @kwarg height: Optional height for the intersection points (C{meter},
218
217
  conventionally) or C{None} for interpolated heights.
219
- @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the points
220
- B{C{circle}}, B{C{point}} and/or B{C{other}} (C{bool}).
218
+ @kwarg wrap: If C{True}, wrap or I{normalize} and unroll B{C{circle}},
219
+ B{C{point}} and B{C{other}} iff points (C{bool}).
221
220
 
222
221
  @return: 2-Tuple of the intersection points (representing a chord), each
223
222
  an instance of the B{C{point}} class. Both points are the same
@@ -225,8 +224,7 @@ class LatLonSphericalBase(LatLonBase):
225
224
 
226
225
  @raise IntersectionError: The circle and line do not intersect.
227
226
 
228
- @raise TypeError: If B{C{point}} is not this C{LatLon} or B{C{circle}}
229
- or B{C{other}} invalid.
227
+ @raise TypeError: Invalid B{C{point}}, B{C{circle}} or B{C{other}}.
230
228
 
231
229
  @raise UnitError: Invalid B{C{circle}}, B{C{other}}, B{C{radius}},
232
230
  B{C{exact}}, B{C{height}} or B{C{napieradius}}.
@@ -469,8 +467,8 @@ class LatLonSphericalBase(LatLonBase):
469
467
 
470
468
  @arg circle: Radius of the circle centered at this location (C{meter},
471
469
  same units as B{C{radius}}) or a point on the circle
472
- (this C{LatLon}).
473
- @arg point: The rhumb line's start point (this C{LatLon}).
470
+ (same C{LatLon} class).
471
+ @arg point: The rhumb line's start point (same C{LatLon} class).
474
472
  @arg other: An other point (this I{on} C{LatLon}) or the azimuth I{of}
475
473
  (compass C{degrees}) the rhumb line.
476
474
  @kwarg radius: Mean earth radius (C{meter}, conventionally).
@@ -489,8 +487,7 @@ class LatLonSphericalBase(LatLonBase):
489
487
 
490
488
  @raise IntersectionError: The circle and line do not intersect.
491
489
 
492
- @raise TypeError: If B{C{point}} is not this C{LatLon} or B{C{circle}}
493
- or B{C{other}} invalid.
490
+ @raise TypeError: Invalid B{C{point}}, B{C{circle}} or B{C{other}}.
494
491
 
495
492
  @raise UnitError: Invalid B{C{circle}}, B{C{other}}, B{C{radius}},
496
493
  B{C{exact}} or B{C{height}}.
@@ -502,8 +499,8 @@ class LatLonSphericalBase(LatLonBase):
502
499
 
503
500
  def rhumbMidpointTo(self, other, height=None, radius=R_M, exact=False,
504
501
  fraction=_0_5, **wrap_name):
505
- '''Return the (loxodromic) midpoint on the rhumb line between
506
- this and an other point.
502
+ '''Return the (loxodromic) midpoint on the rhumb line between this
503
+ and an other point.
507
504
 
508
505
  @arg other: The other point (spherical LatLon).
509
506
  @kwarg height: Optional height, overriding the mean height (C{meter}).