pygeodesy 24.9.29__py2.py3-none-any.whl → 24.10.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 (56) hide show
  1. {PyGeodesy-24.9.29.dist-info → PyGeodesy-24.10.24.dist-info}/METADATA +15 -15
  2. {PyGeodesy-24.9.29.dist-info → PyGeodesy-24.10.24.dist-info}/RECORD +56 -56
  3. pygeodesy/__init__.py +20 -19
  4. pygeodesy/__main__.py +5 -5
  5. pygeodesy/albers.py +12 -17
  6. pygeodesy/basics.py +38 -41
  7. pygeodesy/booleans.py +54 -46
  8. pygeodesy/cartesianBase.py +2 -2
  9. pygeodesy/constants.py +20 -16
  10. pygeodesy/datums.py +3 -3
  11. pygeodesy/dms.py +250 -270
  12. pygeodesy/ellipsoidalBase.py +2 -2
  13. pygeodesy/ellipsoidalBaseDI.py +10 -10
  14. pygeodesy/ellipsoidalNvector.py +4 -4
  15. pygeodesy/ellipsoidalVincenty.py +2 -2
  16. pygeodesy/ellipsoids.py +7 -48
  17. pygeodesy/elliptic.py +14 -14
  18. pygeodesy/errors.py +15 -10
  19. pygeodesy/etm.py +18 -2
  20. pygeodesy/fmath.py +188 -176
  21. pygeodesy/formy.py +4 -4
  22. pygeodesy/fstats.py +54 -56
  23. pygeodesy/fsums.py +304 -266
  24. pygeodesy/geodesici.py +43 -40
  25. pygeodesy/geodesicw.py +3 -3
  26. pygeodesy/geodesicx/gxarea.py +3 -2
  27. pygeodesy/geodsolve.py +73 -24
  28. pygeodesy/geohash.py +2 -2
  29. pygeodesy/geoids.py +28 -27
  30. pygeodesy/internals.py +156 -85
  31. pygeodesy/interns.py +23 -20
  32. pygeodesy/karney.py +61 -12
  33. pygeodesy/latlonBase.py +13 -15
  34. pygeodesy/lazily.py +206 -214
  35. pygeodesy/mgrs.py +13 -13
  36. pygeodesy/named.py +11 -10
  37. pygeodesy/nvectorBase.py +1 -1
  38. pygeodesy/points.py +2 -2
  39. pygeodesy/props.py +34 -13
  40. pygeodesy/rhumb/bases.py +5 -5
  41. pygeodesy/rhumb/solve.py +7 -8
  42. pygeodesy/solveBase.py +7 -25
  43. pygeodesy/sphericalBase.py +20 -23
  44. pygeodesy/sphericalNvector.py +24 -23
  45. pygeodesy/sphericalTrigonometry.py +9 -8
  46. pygeodesy/streprs.py +11 -8
  47. pygeodesy/trf.py +6 -4
  48. pygeodesy/triaxials.py +46 -9
  49. pygeodesy/units.py +4 -3
  50. pygeodesy/ups.py +6 -6
  51. pygeodesy/utily.py +2 -2
  52. pygeodesy/utm.py +2 -2
  53. pygeodesy/vector3d.py +5 -5
  54. pygeodesy/vector3dBase.py +4 -5
  55. {PyGeodesy-24.9.29.dist-info → PyGeodesy-24.10.24.dist-info}/WHEEL +0 -0
  56. {PyGeodesy-24.9.29.dist-info → PyGeodesy-24.10.24.dist-info}/top_level.txt +0 -0
pygeodesy/mgrs.py CHANGED
@@ -55,7 +55,7 @@ from pygeodesy.utm import toUtm8, _to3zBlat, Utm, _UTM_ZONE_MAX, _UTM_ZONE_MIN
55
55
  # from pygeodesy.utmupsBase import _UTM_ZONE_MAX, _UTM_ZONE_MIN # from .utm
56
56
 
57
57
  __all__ = _ALL_LAZY.mgrs
58
- __version__ = '24.09.04'
58
+ __version__ = '24.10.13'
59
59
 
60
60
  _AN_ = 'AN' # default south pole grid tile and band B
61
61
  _AtoPx_ = _AtoZnoIO_.tillP
@@ -654,32 +654,32 @@ if __name__ == '__main__':
654
654
 
655
655
  def _main():
656
656
 
657
- from pygeodesy.ellipsoidalVincenty import fabs, LatLon
657
+ from pygeodesy.ellipsoidalVincenty import LatLon, fabs
658
658
  from pygeodesy.internals import _fper, printf
659
- from pygeodesy.lazily import _getenv, _PYGEODESY_GEOCONVERT_
659
+ from pygeodesy.karney import _Xables
660
660
 
661
661
  # from math import fabs # from .ellipsoidalVincenty
662
- from os import access as _access, linesep as _NL, X_OK as _X_OK
663
662
 
664
663
  # <https://GeographicLib.sourceforge.io/C++/doc/GeoConvert.1.html>
665
- _GeoConvert = _getenv(_PYGEODESY_GEOCONVERT_, '/opt/local/bin/GeoConvert')
666
- if _access(_GeoConvert, _X_OK):
667
- GC_m = _GeoConvert, '-m' # -m converts latlon to MGRS
668
- printf(' using: %s ...', _SPACE_.join(GC_m))
669
- from pygeodesy.solveBase import _popen2
664
+ G = _Xables.GeoConvert(_Xables.bin_)
665
+ if _Xables.X_OK(G):
666
+ from pygeodesy.internals import _popen2
667
+ printf(' using: %s', _Xables.name_version(G, base=False))
668
+ cmd = G, '-m' # -m converts latlon to MGRS
670
669
  else:
671
- GC_m = _popen2 = None
670
+ printf(' sorry: %s', _Xables.X_not(G))
671
+ cmd = _popen2 = None
672
672
 
673
673
  e = n = 0
674
674
  try:
675
675
  for lat in range(-90, 91, 1):
676
676
  printf('%6s: lat %s ...', n, lat, end=NN, flush=True)
677
- nl = _NL
677
+ nl = _MODS.os.linesep
678
678
  for lon in range(-180, 181, 1):
679
679
  m = LatLon(lat, lon).toMgrs()
680
- if _popen2:
680
+ if _popen2: # and cmd
681
681
  t = '%s %s' % (lat, lon)
682
- g = _popen2(GC_m, stdin=t)[1]
682
+ g = _popen2(cmd, stdin=t)[0]
683
683
  t = m.toStr() # sep=NN
684
684
  if t != g:
685
685
  e += 1
pygeodesy/named.py CHANGED
@@ -20,13 +20,14 @@ from pygeodesy.errors import _AssertionError, _AttributeError, _incompatible, \
20
20
  _NotImplementedError, _TypeError, _TypesError, \
21
21
  _UnexpectedError, UnitError, _ValueError, \
22
22
  _xattr, _xkwds, _xkwds_item2, _xkwds_pop2
23
- from pygeodesy.internals import _caller3, _dunder_nameof, _isPyPy, _sizeof, _under
23
+ from pygeodesy.internals import _caller3, _DUNDER_nameof, _getPYGEODESY, _isPyPy, \
24
+ _sizeof, _under
24
25
  from pygeodesy.interns import MISSING, NN, _AT_, _COLON_, _COLONSPACE_, _COMMA_, \
25
26
  _COMMASPACE_, _doesn_t_exist_, _DOT_, _DUNDER_, \
26
- _dunder_name_, _EQUAL_, _exists_, _immutable_, _name_, \
27
+ _DUNDER_name_, _EQUAL_, _exists_, _immutable_, _name_, \
27
28
  _NL_, _NN_, _no_, _other_, _s_, _SPACE_, _std_, \
28
29
  _UNDER_, _vs_
29
- from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS, _getenv
30
+ from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS
30
31
  from pygeodesy.props import _allPropertiesOf_n, deprecated_method, _hasProperty, \
31
32
  _update_all, property_doc_, Property_RO, property_RO, \
32
33
  _update_attrs
@@ -34,7 +35,7 @@ from pygeodesy.streprs import attrs, Fmt, lrstrip, pairs, reprs, unstr
34
35
  # from pygeodesy.units import _toUnit # _MODS
35
36
 
36
37
  __all__ = _ALL_LAZY.named
37
- __version__ = '24.09.02'
38
+ __version__ = '24.10.14'
38
39
 
39
40
  _COMMANL_ = _COMMA_ + _NL_
40
41
  _COMMASPACEDOT_ = _COMMASPACE_ + _DOT_
@@ -45,7 +46,7 @@ _MRO_ = 'MRO'
45
46
  _name = _under(_name_)
46
47
  _Names_ = '_Names_'
47
48
  _registered_ = 'registered' # PYCHOK used!
48
- _std_NotImplemented = _getenv('PYGEODESY_NOTIMPLEMENTED', NN).lower() == _std_
49
+ _std_NotImplemented = _getPYGEODESY('NOTIMPLEMENTED', NN).lower() == _std_
49
50
  _such_ = 'such'
50
51
  _Units_ = '_Units_'
51
52
  _UP = 2
@@ -614,7 +615,7 @@ class _NamedEnum(_NamedDict):
614
615
  @arg Classes: Additional, acceptable classes or C{type}s.
615
616
  '''
616
617
  self._item_Classes = (Class,) + Classes
617
- n = _name__(**name) or NN(Class.__name__, _s_) # _dunder_nameof
618
+ n = _name__(**name) or NN(Class.__name__, _s_) # _DUNDER_nameof
618
619
  if n and _xvalid(n, underOK=True):
619
620
  _Named.name.fset(self, n) # see _Named.name
620
621
 
@@ -1237,7 +1238,7 @@ def modulename(clas, prefixed=None): # in .basics._xversion
1237
1238
  try:
1238
1239
  n = clas.__name__
1239
1240
  except AttributeError:
1240
- n = clas if isstr(clas) else _dunder_name_
1241
+ n = clas if isstr(clas) else _DUNDER_name_
1241
1242
  if prefixed or (classnaming() if prefixed is None else False):
1242
1243
  try:
1243
1244
  m = clas.__module__.rsplit(_DOT_, 1)
@@ -1256,7 +1257,7 @@ def modulename(clas, prefixed=None): # in .basics._xversion
1256
1257
  # if name: # is given
1257
1258
  # n = _name__(**name) if isinstance(name, dict) else str(name)
1258
1259
  # elif name__ is not None:
1259
- # n = getattr(name__, _dunder_name_, NN) # _xattr(name__, __name__=NN)
1260
+ # n = getattr(name__, _DUNDER_name_, NN) # _xattr(name__, __name__=NN)
1260
1261
  # else:
1261
1262
  # n = name # NN or None or {} or any False type
1262
1263
  # if _or_nameof is not None and not n:
@@ -1293,7 +1294,7 @@ def _name2__(name=NN, name__=None, _or_nameof=None, **kwds):
1293
1294
  else:
1294
1295
  n = str(name)
1295
1296
  elif name__ is not None:
1296
- n = _dunder_nameof(name__, NN)
1297
+ n = _DUNDER_nameof(name__, NN)
1297
1298
  else:
1298
1299
  n = name if name is None else NN
1299
1300
  if _or_nameof is not None and not n:
@@ -1328,7 +1329,7 @@ def _notDecap(where):
1328
1329
  def _notError(inst, name, args, kwds): # PYCHOK no cover
1329
1330
  '''(INTERNAL) Format an error message.
1330
1331
  '''
1331
- n = _DOT_(classname(inst, prefixed=True), _dunder_nameof(name, name))
1332
+ n = _DOT_(classname(inst, prefixed=True), _DUNDER_nameof(name, name))
1332
1333
  m = _COMMASPACE_.join(modulename(c, prefixed=True) for c in inst.__class__.__mro__[1:-1])
1333
1334
  return _COMMASPACE_(unstr(n, *args, **kwds), Fmt.PAREN(_MRO_, m))
1334
1335
 
pygeodesy/nvectorBase.py CHANGED
@@ -38,7 +38,7 @@ from pygeodesy.vector3d import Vector3d, _xyzhdlln4
38
38
  from math import fabs, sqrt
39
39
 
40
40
  __all__ = _ALL_LAZY.nvectorBase
41
- __version__ = '24.07.12'
41
+ __version__ = '24.10.12'
42
42
 
43
43
 
44
44
  class NvectorBase(Vector3d): # XXX kept private
pygeodesy/points.py CHANGED
@@ -62,7 +62,7 @@ from pygeodesy.utily import atan2b, degrees90, degrees180, degrees2m, \
62
62
  from math import cos, fabs, fmod as _fmod, radians, sin
63
63
 
64
64
  __all__ = _ALL_LAZY.points
65
- __version__ = '24.09.23'
65
+ __version__ = '24.10.24'
66
66
 
67
67
  _ilat_ = 'ilat'
68
68
  _ilon_ = 'ilon'
@@ -147,7 +147,7 @@ class LatLon_(LatLonBase): # XXX in heights._HeightBase.height
147
147
  @kwarg wrap: If C{True}, wrap or I{normalize} and unroll
148
148
  the B{C{other}} point (C{bool}).
149
149
 
150
- @return: Intermediate point (this C{LatLon}).
150
+ @return: Intermediate point (same C{LatLon} class).
151
151
 
152
152
  @raise TypeError: Incompatible B{C{other}} C{type}.
153
153
  '''
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.10.19'
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!
@@ -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/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.10.12'
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):
@@ -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/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}).
@@ -9,7 +9,7 @@ L{meanOf}, L{nearestOn3}, L{perimeterOf}, L{sumOf}, L{triangulate} and
9
9
  L{trilaterate}, I{all spherical}.
10
10
 
11
11
  Pure Python implementation of n-vector-based spherical geodetic (lat-/longitude)
12
- methods, transcoded from JavaScript originals by I{(C) Chris Veness 2011-2016},
12
+ methods, transcoded from JavaScript originals by I{(C) Chris Veness 2011-2024},
13
13
  published under the same MIT Licence**. See U{Vector-based geodesy
14
14
  <https://www.Movable-Type.co.UK/scripts/latlong-vectors.html>} and
15
15
  U{Module latlon-nvector-spherical
@@ -61,7 +61,7 @@ from pygeodesy.utily import atan2, degrees360, fabs, sincos2, sincos2_, \
61
61
  # from math import atan2, fabs # from utily
62
62
 
63
63
  __all__ = _ALL_LAZY.sphericalNvector
64
- __version__ = '24.09.23'
64
+ __version__ = '24.10.19'
65
65
 
66
66
  _lines_ = 'lines'
67
67
 
@@ -797,7 +797,7 @@ class Nvector(NvectorBase):
797
797
  return n.minus(e)
798
798
 
799
799
 
800
- _Nvll = LatLon(_0_0, _0_0, name=_Nv00_) # reference instance (L{LatLon})
800
+ _Nv00 = LatLon(_0_0, _0_0, name=_Nv00_) # reference instance (L{LatLon})
801
801
 
802
802
 
803
803
  def areaOf(points, radius=R_M, wrap=False):
@@ -821,7 +821,7 @@ def areaOf(points, radius=R_M, wrap=False):
821
821
  and L{ellipsoidalKarney.areaOf}.
822
822
  '''
823
823
  def _interangles(ps, w): # like .karney._polygon
824
- Ps = _Nvll.PointsIter(ps, loop=2, wrap=w)
824
+ Ps = _Nv00.PointsIter(ps, loop=2, wrap=w)
825
825
  # use vector to 1st point as plane normal for sign of α
826
826
  n0 = Ps[0].toNvector()
827
827
 
@@ -858,13 +858,14 @@ def intersecant2(center, circle, point, other, **radius_exact_height_wrap):
858
858
  two points or as a point and bearing.
859
859
 
860
860
  @arg center: Center of the circle (L{LatLon}).
861
- @arg circle: Radius of the circle (C{meter}, same units as B{C{radius}})
862
- or a point on the circle (L{LatLon}).
861
+ @arg circle: Radius of the circle (C{meter}, same units as the earth
862
+ B{C{radius}}) or a point on the circle (L{LatLon}).
863
863
  @arg point: A point on the (great circle) line (L{LatLon}).
864
864
  @arg other: An other point on the (great circle) line (L{LatLon}) or
865
865
  the bearing at the B{C{point}} (compass C{degrees360}).
866
- @kwarg radius_exact_height_wrap: Optional keyword arguments, see
867
- method L{LatLon.intersecant2} for further details.
866
+ @kwarg radius_exact_height_wrap: Optional keyword arguments, see method
867
+ L{intersecant2<pygeodesy.sphericalBase.LatLonSphericalBase.
868
+ intersecant2>} for further details.
868
869
 
869
870
  @return: 2-Tuple of the intersection points (representing a chord), each
870
871
  an instance of the B{C{point}} class. Both points are the same
@@ -872,14 +873,14 @@ def intersecant2(center, circle, point, other, **radius_exact_height_wrap):
872
873
 
873
874
  @raise IntersectionError: The circle and line do not intersect.
874
875
 
875
- @raise TypeError: If B{C{center}} or B{C{point}} not L{LatLon} or
876
- B{C{circle}} or B{C{other}} invalid.
876
+ @raise TypeError: If B{C{center}}, B{C{point}}, B{C{circle}} or B{C{other}}
877
+ not L{LatLon}.
877
878
 
878
879
  @raise UnitError: Invalid B{C{circle}}, B{C{other}}, B{C{radius}},
879
880
  B{C{exact}}, B{C{height}} or B{C{napieradius}}.
880
881
  '''
881
- c = _Nvll.others(center=center)
882
- p = _Nvll.others(point=point)
882
+ c = _Nv00.others(center=center)
883
+ p = _Nv00.others(point=point)
883
884
  try:
884
885
  return _intersecant2(c, circle, p, other, **radius_exact_height_wrap)
885
886
  except (TypeError, ValueError) as x:
@@ -966,8 +967,8 @@ def _intersect3(start1, end1, start2, end2, height, wrap):
966
967
  '''(INTERNAL) Return the intersection and antipodal points for
967
968
  functions C{intersection} and C{intersection2}.
968
969
  '''
969
- p1 = _Nvll.others(start1=start1)
970
- p2 = _Nvll.others(start2=start2)
970
+ p1 = _Nv00.others(start1=start1)
971
+ p2 = _Nv00.others(start2=start2)
971
972
  if wrap:
972
973
  p2 = _unrollon(p1, p2, wrap=wrap)
973
974
  # If gc1 and gc2 are great circles through start and end points
@@ -976,8 +977,8 @@ def _intersect3(start1, end1, start2, end2, height, wrap):
976
977
  # work is deciding the correct intersection point to select! If
977
978
  # bearing is given, that determines the intersection, but if both
978
979
  # lines are defined by start/end points, take closer intersection.
979
- gc1, s1, e1 = _Nvll._gc3(p1, end1, 'end1', wrap=wrap)
980
- gc2, s2, e2 = _Nvll._gc3(p2, end2, 'end2', wrap=wrap)
980
+ gc1, s1, e1 = _Nv00._gc3(p1, end1, 'end1', wrap=wrap)
981
+ gc2, s2, e2 = _Nv00._gc3(p2, end2, 'end2', wrap=wrap)
981
982
 
982
983
  hs = start1.height, start2.height
983
984
  # there are two (antipodal) candidate intersection
@@ -1038,7 +1039,7 @@ def meanOf(points, height=None, wrap=False, LatLon=LatLon, **LatLon_kwds):
1038
1039
  some B{C{points}} are not C{LatLon}.
1039
1040
  '''
1040
1041
  def _N_vs(ps, w):
1041
- Ps = _Nvll.PointsIter(ps, wrap=w)
1042
+ Ps = _Nv00.PointsIter(ps, wrap=w)
1042
1043
  for p in Ps.iterate(closed=False):
1043
1044
  yield p._N_vector
1044
1045
 
@@ -1122,7 +1123,7 @@ def perimeterOf(points, closed=False, radius=R_M, wrap=False):
1122
1123
  and L{sphericalTrigonometry.perimeterOf}.
1123
1124
  '''
1124
1125
  def _rads(ps, c, w): # angular edge lengths in radians
1125
- Ps = _Nvll.PointsIter(ps, loop=1, wrap=w)
1126
+ Ps = _Nv00.PointsIter(ps, loop=1, wrap=w)
1126
1127
  p1 = Ps[0]
1127
1128
  v1 = p1._N_vector
1128
1129
  for p2 in Ps.iterate(closed=c):
@@ -1184,8 +1185,8 @@ def triangulate(point1, bearing1, point2, bearing2,
1184
1185
 
1185
1186
  @raise Valuerror: Points coincide.
1186
1187
  '''
1187
- return _triangulate(_Nvll.others(point1=point1), bearing1,
1188
- _Nvll.others(point2=point2), bearing2,
1188
+ return _triangulate(_Nv00.others(point1=point1), bearing1,
1189
+ _Nv00.others(point2=point2), bearing2,
1189
1190
  height=height, wrap=wrap,
1190
1191
  LatLon=LatLon, **LatLon_kwds)
1191
1192
 
@@ -1225,9 +1226,9 @@ def trilaterate(point1, distance1, point2, distance2, point3, distance3, # PYCH
1225
1226
 
1226
1227
  @see: U{Trilateration<https://WikiPedia.org/wiki/Trilateration>}.
1227
1228
  '''
1228
- return _trilaterate(_Nvll.others(point1=point1), distance1,
1229
- _Nvll.others(point2=point2), distance2,
1230
- _Nvll.others(point3=point3), distance3,
1229
+ return _trilaterate(_Nv00.others(point1=point1), distance1,
1230
+ _Nv00.others(point2=point2), distance2,
1231
+ _Nv00.others(point3=point3), distance3,
1231
1232
  radius=radius, height=height, useZ=useZ,
1232
1233
  wrap=wrap, LatLon=LatLon, **LatLon_kwds)
1233
1234