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.
- {PyGeodesy-24.9.29.dist-info → PyGeodesy-24.10.24.dist-info}/METADATA +15 -15
- {PyGeodesy-24.9.29.dist-info → PyGeodesy-24.10.24.dist-info}/RECORD +56 -56
- pygeodesy/__init__.py +20 -19
- pygeodesy/__main__.py +5 -5
- pygeodesy/albers.py +12 -17
- pygeodesy/basics.py +38 -41
- pygeodesy/booleans.py +54 -46
- pygeodesy/cartesianBase.py +2 -2
- pygeodesy/constants.py +20 -16
- pygeodesy/datums.py +3 -3
- pygeodesy/dms.py +250 -270
- pygeodesy/ellipsoidalBase.py +2 -2
- pygeodesy/ellipsoidalBaseDI.py +10 -10
- pygeodesy/ellipsoidalNvector.py +4 -4
- pygeodesy/ellipsoidalVincenty.py +2 -2
- pygeodesy/ellipsoids.py +7 -48
- pygeodesy/elliptic.py +14 -14
- pygeodesy/errors.py +15 -10
- pygeodesy/etm.py +18 -2
- pygeodesy/fmath.py +188 -176
- pygeodesy/formy.py +4 -4
- pygeodesy/fstats.py +54 -56
- pygeodesy/fsums.py +304 -266
- pygeodesy/geodesici.py +43 -40
- pygeodesy/geodesicw.py +3 -3
- pygeodesy/geodesicx/gxarea.py +3 -2
- pygeodesy/geodsolve.py +73 -24
- pygeodesy/geohash.py +2 -2
- pygeodesy/geoids.py +28 -27
- pygeodesy/internals.py +156 -85
- pygeodesy/interns.py +23 -20
- pygeodesy/karney.py +61 -12
- pygeodesy/latlonBase.py +13 -15
- pygeodesy/lazily.py +206 -214
- pygeodesy/mgrs.py +13 -13
- pygeodesy/named.py +11 -10
- pygeodesy/nvectorBase.py +1 -1
- pygeodesy/points.py +2 -2
- pygeodesy/props.py +34 -13
- pygeodesy/rhumb/bases.py +5 -5
- pygeodesy/rhumb/solve.py +7 -8
- pygeodesy/solveBase.py +7 -25
- pygeodesy/sphericalBase.py +20 -23
- pygeodesy/sphericalNvector.py +24 -23
- pygeodesy/sphericalTrigonometry.py +9 -8
- pygeodesy/streprs.py +11 -8
- pygeodesy/trf.py +6 -4
- pygeodesy/triaxials.py +46 -9
- pygeodesy/units.py +4 -3
- pygeodesy/ups.py +6 -6
- pygeodesy/utily.py +2 -2
- pygeodesy/utm.py +2 -2
- pygeodesy/vector3d.py +5 -5
- pygeodesy/vector3dBase.py +4 -5
- {PyGeodesy-24.9.29.dist-info → PyGeodesy-24.10.24.dist-info}/WHEEL +0 -0
- {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.
|
|
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
|
|
657
|
+
from pygeodesy.ellipsoidalVincenty import LatLon, fabs
|
|
658
658
|
from pygeodesy.internals import _fper, printf
|
|
659
|
-
from pygeodesy.
|
|
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
|
-
|
|
666
|
-
if
|
|
667
|
-
|
|
668
|
-
printf(' using: %s
|
|
669
|
-
|
|
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
|
-
|
|
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 =
|
|
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(
|
|
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,
|
|
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
|
-
|
|
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
|
|
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.
|
|
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 =
|
|
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_) #
|
|
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
|
|
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__,
|
|
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 =
|
|
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),
|
|
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
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.
|
|
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 (
|
|
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,
|
|
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_,
|
|
19
|
-
_not_, _SPACE_, _UNDER_
|
|
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.
|
|
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
|
-
|
|
657
|
-
name
|
|
658
|
-
|
|
659
|
-
|
|
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
|
-
@
|
|
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
|
|
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
|
|
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.
|
|
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=
|
|
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=
|
|
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=
|
|
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
|
|
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.
|
|
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 =
|
|
34
|
-
_Xable_path =
|
|
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
|
|
398
|
-
rS.RhumbSolve =
|
|
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,
|
|
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
|
|
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.
|
|
26
|
+
__version__ = '24.10.13'
|
|
29
27
|
|
|
30
|
-
_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
|
|
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
|
-
|
|
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:
|
pygeodesy/sphericalBase.py
CHANGED
|
@@ -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-
|
|
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.
|
|
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
|
|
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
|
|
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:
|
|
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
|
-
|
|
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
|
-
(
|
|
208
|
-
@arg point: A point on the (great circle) line (
|
|
209
|
-
@arg other: An other point I{on} (
|
|
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
|
|
220
|
-
|
|
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:
|
|
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
|
-
(
|
|
473
|
-
@arg point: The rhumb line's start point (
|
|
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:
|
|
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
|
-
|
|
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}).
|
pygeodesy/sphericalNvector.py
CHANGED
|
@@ -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-
|
|
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.
|
|
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
|
-
|
|
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 =
|
|
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
|
|
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
|
-
|
|
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}}
|
|
876
|
-
|
|
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 =
|
|
882
|
-
p =
|
|
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 =
|
|
970
|
-
p2 =
|
|
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 =
|
|
980
|
-
gc2, s2, e2 =
|
|
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 =
|
|
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 =
|
|
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(
|
|
1188
|
-
|
|
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(
|
|
1229
|
-
|
|
1230
|
-
|
|
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
|
|