pygeodesy 25.8.25__py2.py3-none-any.whl → 25.9.9__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/__init__.py +7 -6
- pygeodesy/auxilats/__init__.py +1 -1
- pygeodesy/auxilats/auxAngle.py +4 -3
- pygeodesy/auxilats/auxily.py +1 -1
- pygeodesy/basics.py +4 -4
- pygeodesy/booleans.py +25 -25
- pygeodesy/constants.py +37 -7
- pygeodesy/deprecated/functions.py +1 -0
- pygeodesy/dms.py +2 -2
- pygeodesy/ecef.py +3 -3
- pygeodesy/ellipsoidalExact.py +4 -4
- pygeodesy/ellipsoidalGeodSolve.py +3 -3
- pygeodesy/ellipsoids.py +52 -41
- pygeodesy/elliptic.py +8 -11
- pygeodesy/errors.py +18 -5
- pygeodesy/etm.py +8 -8
- pygeodesy/fmath.py +1 -1
- pygeodesy/geodesicx/__init__.py +1 -1
- pygeodesy/geodesicx/__main__.py +1 -0
- pygeodesy/geodesicx/gx.py +30 -37
- pygeodesy/geodesicx/gxbases.py +1 -5
- pygeodesy/geodesicx/gxline.py +43 -34
- pygeodesy/geodsolve.py +10 -17
- pygeodesy/internals.py +37 -13
- pygeodesy/karney.py +19 -18
- pygeodesy/ktm.py +1 -1
- pygeodesy/lazily.py +12 -11
- pygeodesy/lcc.py +5 -5
- pygeodesy/named.py +10 -13
- pygeodesy/rhumb/__init__.py +1 -1
- pygeodesy/rhumb/aux_.py +1 -1
- pygeodesy/rhumb/bases.py +7 -8
- pygeodesy/rhumb/ekx.py +9 -9
- pygeodesy/solveBase.py +14 -3
- pygeodesy/sphericalTrigonometry.py +4 -4
- pygeodesy/utily.py +200 -159
- pygeodesy/vector3dBase.py +6 -6
- {pygeodesy-25.8.25.dist-info → pygeodesy-25.9.9.dist-info}/METADATA +8 -7
- {pygeodesy-25.8.25.dist-info → pygeodesy-25.9.9.dist-info}/RECORD +41 -41
- {pygeodesy-25.8.25.dist-info → pygeodesy-25.9.9.dist-info}/WHEEL +0 -0
- {pygeodesy-25.8.25.dist-info → pygeodesy-25.9.9.dist-info}/top_level.txt +0 -0
pygeodesy/__init__.py
CHANGED
|
@@ -125,7 +125,7 @@ C{epydoc --html --no-private --no-source --name=pygeodesy --url=... -v pygeodesy
|
|
|
125
125
|
Tests
|
|
126
126
|
=====
|
|
127
127
|
|
|
128
|
-
The tests ran with Python 3.13.
|
|
128
|
+
The tests ran with Python 3.13.7 (with U{geographiclib<https://PyPI.org/project/geographiclib>} 2.1),
|
|
129
129
|
Python 3.12.7 (with U{geographiclib<https://PyPI.org/project/geographiclib>} 2.0,
|
|
130
130
|
U{numpy<https://PyPI.org/project/numpy>} 2.1.0, U{scipy<https://PyPI.org/project/scipy>} 1.14.1,
|
|
131
131
|
U{GeodSolve<https://GeographicLib.SourceForge.io/C++/doc/utilities.html>} 2.5,
|
|
@@ -150,13 +150,13 @@ env variable C{PYGEODESY_WARNINGS=on} for all Python versions. The results of t
|
|
|
150
150
|
the distribution files.
|
|
151
151
|
|
|
152
152
|
Test coverage has been measured with U{coverage<https://PyPI.org/project/coverage>} 7.6.1 using Python
|
|
153
|
-
3.13.
|
|
153
|
+
3.13.7, 3.12.7, 3.11.5 and 3.10.8. The complete coverage report in HTML and a PDF summary are included in
|
|
154
154
|
the distribution files.
|
|
155
155
|
|
|
156
|
-
Python 3.13.
|
|
156
|
+
Python 3.13.7, 3.12.7, 3.11.5 and 3.10.8 run on Apple M4 Si (C{arm64}), I{natively}. Python 2.7.18 runs
|
|
157
157
|
on Intel (C{x86_64}) or Intel I{emulation} ("C{arm64_x86_64}", see function L{machine<pygeodesy.machine>}).
|
|
158
158
|
|
|
159
|
-
The tests also ran with Python 3.13.
|
|
159
|
+
The tests also ran with Python 3.13.7 (and U{geographiclib<https://PyPI.org/project/geographiclib>} 2.1) on
|
|
160
160
|
U{Debian 12<https://Cirrus-CI.com/github/mrJean1/PyGeodesy/master>} in 64-bit only, with Python 3.12.8 (and
|
|
161
161
|
U{geographiclib<https://PyPI.org/project/geographiclib>} 2.0) on U{Windows 2019Server
|
|
162
162
|
<https://CI.AppVeyor.com/project/mrJean1/pygeodesy>} in 64-bit only and with Python 2.7.18 (and U{geographiclib
|
|
@@ -166,7 +166,7 @@ in 64- and 32-bit.
|
|
|
166
166
|
A single-File and single-Directory application with C{pygeodesy} has been bundled using U{PyInstaller
|
|
167
167
|
<https://PyPI.org/project/pyinstaller>} 3.4 and 64-bit Python 3.7.3 on macOS 10.13.6 High Sierra.
|
|
168
168
|
|
|
169
|
-
Previously, the tests were run with Python 3.13.0-
|
|
169
|
+
Previously, the tests were run with Python 3.13.0-5, 3.12.0-6, 3.11.2-4, 3.10.1-7, 3.9.6, 3.9.1, 3.8.7, 3.7.1, 2.7.15,
|
|
170
170
|
U{PyPy<https://PyPy.org>} 7.3.12 (Python 3.10.12), 7.3.1 (Python 3.6.9) and U{PyPy<https://PyPy.org>} 7.1.1 (Python
|
|
171
171
|
2.7.13) (and U{geographiclib <https://PyPI.org/project/geographiclib>} 1.52, U{numpy<https://PyPI.org/project/numpy>}
|
|
172
172
|
1.16.3, 1.16.4, 1.16.6, 1.19.0, 1.19.4, 1.19.5 or 1.22.4 and U{scipy<https://PyPI.org/project/scipy>} 1.2.1, 1.4.1,
|
|
@@ -329,6 +329,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.}
|
|
|
329
329
|
@var PI_3: One third PI, M{PI / 3} (C{float}).
|
|
330
330
|
@var PI4: Four PI, M{PI * 4} (C{float}).
|
|
331
331
|
@var PI_4: Quarter PI, M{PI / 4} (C{float}).
|
|
332
|
+
@var PI_6: One sixth PI, M{PI / 6} (C{float}).
|
|
332
333
|
|
|
333
334
|
@var R_MA: Equatorial earth radius (C{meter}), WGS84, EPSG:3785.
|
|
334
335
|
@var R_MB: Polar earth radius (C{meter}), WGS84, EPSG:3785.
|
|
@@ -604,7 +605,7 @@ else:
|
|
|
604
605
|
|
|
605
606
|
from pygeodesy.internals import _version2, _DOT_ # noqa: E402
|
|
606
607
|
# from pygeodesy.interns import _DOT_ # from .internals
|
|
607
|
-
__version__ = '25.
|
|
608
|
+
__version__ = '25.09.09'
|
|
608
609
|
# see setup.py for similar logic
|
|
609
610
|
version = _DOT_(*_version2(__version__, n=3))
|
|
610
611
|
|
pygeodesy/auxilats/__init__.py
CHANGED
|
@@ -29,7 +29,7 @@ from pygeodesy.lazily import _ALL_OTHER
|
|
|
29
29
|
# no modules: auxAngle, auxDLat, auxDST, auxily, auxLat
|
|
30
30
|
__all__ = _ALL_OTHER(Aux, AuxAngle, AuxDLat, AuxDST, AuxLat,
|
|
31
31
|
AuxBeta, AuxChi, AuxMu, AuxPhi, AuxTheta, AuxXi)
|
|
32
|
-
__version__ = '25.
|
|
32
|
+
__version__ = '25.08.28'
|
|
33
33
|
|
|
34
34
|
# **) MIT License
|
|
35
35
|
#
|
pygeodesy/auxilats/auxAngle.py
CHANGED
|
@@ -17,7 +17,7 @@ from __future__ import division as _; del _ # noqa: E702 ;
|
|
|
17
17
|
from pygeodesy.auxilats.auxily import Aux, _Aux2Greek, AuxError
|
|
18
18
|
from pygeodesy.basics import map1, map2, _xinstanceof
|
|
19
19
|
from pygeodesy.constants import EPS, _INF_NAN_NINF, MAX, NAN, _0_0, _0_5, _1_0, \
|
|
20
|
-
_copysign_1_0,
|
|
20
|
+
_copysign_1_0, isfinite, isnan, _over, _pos_self
|
|
21
21
|
# from pygeodesy.errors import AuxError # from .auxilats.auxily
|
|
22
22
|
from pygeodesy.fmath import hypot, unstr
|
|
23
23
|
from pygeodesy.fsums import _add_op_, _iadd_op_, _isub_op_, _sub_op_
|
|
@@ -32,7 +32,7 @@ from pygeodesy.utily import atan2, atan2d, sincos2, sincos2d
|
|
|
32
32
|
from math import asinh, copysign, degrees, fabs, radians, sinh
|
|
33
33
|
|
|
34
34
|
__all__ = ()
|
|
35
|
-
__version__ = '25.
|
|
35
|
+
__version__ = '25.08.31'
|
|
36
36
|
|
|
37
37
|
_0_INF_NAN_NINF = (0, _0_0) + _INF_NAN_NINF
|
|
38
38
|
_MAX_2 = MAX * _0_5 # PYCHOK used!
|
|
@@ -505,6 +505,7 @@ _AUXClass = {Aux.BETA: AuxBeta,
|
|
|
505
505
|
Aux.CHI: AuxChi,
|
|
506
506
|
Aux.MU: AuxMu,
|
|
507
507
|
Aux.PHI: AuxPhi,
|
|
508
|
+
# Aux.PSI: AuxPSI, # Isometric
|
|
508
509
|
Aux.THETA: AuxTheta,
|
|
509
510
|
Aux.XI: AuxXi}
|
|
510
511
|
|
|
@@ -525,7 +526,7 @@ def _yx2(yx):
|
|
|
525
526
|
return y, x
|
|
526
527
|
|
|
527
528
|
|
|
528
|
-
__all__ += _ALL_DOCS(AuxAngle,
|
|
529
|
+
__all__ += _ALL_DOCS(AuxAngle, *_AUXClass.values())
|
|
529
530
|
|
|
530
531
|
# **) MIT License
|
|
531
532
|
#
|
pygeodesy/auxilats/auxily.py
CHANGED
pygeodesy/basics.py
CHANGED
|
@@ -37,7 +37,7 @@ from math import copysign as _copysign
|
|
|
37
37
|
# import inspect as _inspect # _MODS
|
|
38
38
|
|
|
39
39
|
__all__ = _ALL_LAZY.basics
|
|
40
|
-
__version__ = '25.04
|
|
40
|
+
__version__ = '25.09.04'
|
|
41
41
|
|
|
42
42
|
_below_ = 'below'
|
|
43
43
|
_list_tuple_types = (list, tuple)
|
|
@@ -201,7 +201,7 @@ def copytype(x, y):
|
|
|
201
201
|
|
|
202
202
|
|
|
203
203
|
def _enumereverse(iterable):
|
|
204
|
-
'''(INTERNAL) Reversed C{
|
|
204
|
+
'''(INTERNAL) Reversed C{enumerate}.
|
|
205
205
|
'''
|
|
206
206
|
for j in _reverange(len(iterable)):
|
|
207
207
|
yield j, iterable[j]
|
|
@@ -714,11 +714,11 @@ def _reverange(n, stop=-1, step=-1):
|
|
|
714
714
|
|
|
715
715
|
|
|
716
716
|
def signBit(x):
|
|
717
|
-
'''Return C{signbit(B{x})}, like C
|
|
717
|
+
'''Return C{signbit(B{x})}, like C++, see also L{isneg}.
|
|
718
718
|
|
|
719
719
|
@return: C{True} if C{B{x} < 0} or C{NEG0} (C{bool}).
|
|
720
720
|
'''
|
|
721
|
-
return x
|
|
721
|
+
return (x or _copysign(1, x)) < 0
|
|
722
722
|
|
|
723
723
|
|
|
724
724
|
def _signOf(x, ref): # in .fsums
|
pygeodesy/booleans.py
CHANGED
|
@@ -45,7 +45,7 @@ from pygeodesy.utily import fabs, _unrollon, _Wrap
|
|
|
45
45
|
# from math import fabs # from .utily
|
|
46
46
|
|
|
47
47
|
__all__ = _ALL_LAZY.booleans
|
|
48
|
-
__version__ = '25.
|
|
48
|
+
__version__ = '25.09.04'
|
|
49
49
|
|
|
50
50
|
_0EPS = EPS # near-zero, positive
|
|
51
51
|
_EPS0 = -EPS # near-zero, negative
|
|
@@ -60,26 +60,26 @@ _corners_ = 'corners'
|
|
|
60
60
|
_open_ = 'open'
|
|
61
61
|
|
|
62
62
|
|
|
63
|
-
def
|
|
63
|
+
def _Cnum(txt, enum): # PYCHOK unused
|
|
64
64
|
return txt # NN(txt, _TILDE_, enum)
|
|
65
65
|
|
|
66
66
|
|
|
67
67
|
class _L(object): # Intersection labels
|
|
68
|
-
CROSSING =
|
|
69
|
-
CROSSING_D =
|
|
68
|
+
CROSSING = _Cnum(_X_, 1) # C++ enum
|
|
69
|
+
CROSSING_D = _Cnum(_X_ + _d_, 8)
|
|
70
70
|
CROSSINGs = (CROSSING, CROSSING_D)
|
|
71
|
-
BOUNCING =
|
|
72
|
-
BOUNCING_D =
|
|
71
|
+
BOUNCING = _Cnum(_B_, 2)
|
|
72
|
+
BOUNCING_D = _Cnum(_B_ + _d_, 9)
|
|
73
73
|
BOUNCINGs = (BOUNCING, BOUNCING_D) + CROSSINGs
|
|
74
|
-
LEFT_ON =
|
|
75
|
-
ON_ON =
|
|
76
|
-
ON_LEFT =
|
|
77
|
-
ON_RIGHT =
|
|
78
|
-
RIGHT_ON =
|
|
74
|
+
LEFT_ON = _Cnum('Lo', 3)
|
|
75
|
+
ON_ON = _Cnum('oo', 5)
|
|
76
|
+
ON_LEFT = _Cnum('oL', 6)
|
|
77
|
+
ON_RIGHT = _Cnum('oR', 7)
|
|
78
|
+
RIGHT_ON = _Cnum('Ro', 4)
|
|
79
79
|
RIGHT_LEFT_ON = (RIGHT_ON, LEFT_ON)
|
|
80
80
|
# Entry/Exit flags
|
|
81
|
-
ENTRY =
|
|
82
|
-
EXIT =
|
|
81
|
+
ENTRY = _Cnum(_e_, 1)
|
|
82
|
+
EXIT = _Cnum(_x_, 0)
|
|
83
83
|
Toggle = {ENTRY: EXIT,
|
|
84
84
|
EXIT: ENTRY,
|
|
85
85
|
None: None}
|
|
@@ -88,10 +88,10 @@ _L = _L() # PYCHOK singleton
|
|
|
88
88
|
|
|
89
89
|
|
|
90
90
|
class _RP(object): # RelativePositions
|
|
91
|
-
IS_Pm =
|
|
92
|
-
IS_Pp =
|
|
93
|
-
LEFT =
|
|
94
|
-
RIGHT =
|
|
91
|
+
IS_Pm = _Cnum('Pm', 2) # C++ enum
|
|
92
|
+
IS_Pp = _Cnum('Pp', 3)
|
|
93
|
+
LEFT = _Cnum('L', 0)
|
|
94
|
+
RIGHT = _Cnum(_R_, 1)
|
|
95
95
|
|
|
96
96
|
_RP = _RP() # PYCHOK singleton
|
|
97
97
|
|
|
@@ -1521,16 +1521,16 @@ class _CompositeGH(_CompositeBase):
|
|
|
1521
1521
|
class _EdgeFHP(object):
|
|
1522
1522
|
# An edge between two L{LatLonFHP} points.
|
|
1523
1523
|
|
|
1524
|
-
X_INTERSECT =
|
|
1525
|
-
X_OVERLAP =
|
|
1526
|
-
P_INTERSECT =
|
|
1527
|
-
P_OVERLAP =
|
|
1524
|
+
X_INTERSECT = _Cnum('Xi', 1) # C++ enum
|
|
1525
|
+
X_OVERLAP = _Cnum('Xo', 5)
|
|
1526
|
+
P_INTERSECT = _Cnum('Pi', 3)
|
|
1527
|
+
P_OVERLAP = _Cnum('Po', 7)
|
|
1528
1528
|
Ps = (P_INTERSECT, P_OVERLAP, X_OVERLAP)
|
|
1529
|
-
Q_INTERSECT =
|
|
1530
|
-
Q_OVERLAP =
|
|
1529
|
+
Q_INTERSECT = _Cnum('Qi', 2)
|
|
1530
|
+
Q_OVERLAP = _Cnum('Qo', 6)
|
|
1531
1531
|
Qs = (Q_INTERSECT, Q_OVERLAP, X_OVERLAP)
|
|
1532
|
-
V_INTERSECT =
|
|
1533
|
-
V_OVERLAP =
|
|
1532
|
+
V_INTERSECT = _Cnum('Vi', 4)
|
|
1533
|
+
V_OVERLAP = _Cnum('Vo', 8)
|
|
1534
1534
|
Vs = (V_INTERSECT, V_OVERLAP)
|
|
1535
1535
|
|
|
1536
1536
|
def __init__(self, p1, p2, **unused):
|
pygeodesy/constants.py
CHANGED
|
@@ -10,7 +10,7 @@ L{pygeodesy.isnon0} and L{pygeodesy.remainder}.
|
|
|
10
10
|
# make sure int/int division yields float quotient, see .basics
|
|
11
11
|
from __future__ import division as _; del _ # noqa: E702 ;
|
|
12
12
|
|
|
13
|
-
from pygeodesy.basics import _copysign, isbool, iscomplex, isint
|
|
13
|
+
from pygeodesy.basics import _copysign, isbool, iscomplex, isint, signBit
|
|
14
14
|
from pygeodesy.errors import _xError, _xError2, _xkwds_get1, _xkwds_item2
|
|
15
15
|
# from pygeodesy.fsums import _isFsum_2Tuple # _MODS
|
|
16
16
|
from pygeodesy.internals import _0_0, _100_0, typename
|
|
@@ -26,25 +26,31 @@ except ImportError: # Python 2-
|
|
|
26
26
|
_inf, _nan = float(_INF_), float(_NAN_)
|
|
27
27
|
|
|
28
28
|
__all__ = _ALL_LAZY.constants
|
|
29
|
-
__version__ = '25.
|
|
29
|
+
__version__ = '25.09.09'
|
|
30
30
|
|
|
31
31
|
|
|
32
32
|
def _copysign_0_0(y):
|
|
33
33
|
'''(INTERNAL) copysign(0.0, y), only C{float}.
|
|
34
34
|
'''
|
|
35
|
-
return _N_0_0 if y
|
|
35
|
+
return _N_0_0 if signBit(y) else _0_0
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
def _copysign_1_0(y):
|
|
39
39
|
'''(INTERNAL) copysign(1.0, y), only C{float}.
|
|
40
40
|
'''
|
|
41
|
-
return _N_1_0 if y
|
|
41
|
+
return _N_1_0 if signBit(y) else _1_0
|
|
42
42
|
|
|
43
43
|
|
|
44
44
|
def _copysignINF(y):
|
|
45
45
|
'''(INTERNAL) copysign(INF, y), only C{float}.
|
|
46
46
|
'''
|
|
47
|
-
return NINF if y
|
|
47
|
+
return NINF if signBit(y) else INF
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _flipsign(x, y):
|
|
51
|
+
'''(INTERNAL) Negate C{x} for negative C{y}.
|
|
52
|
+
'''
|
|
53
|
+
return (-x) if signBit(y) else x
|
|
48
54
|
|
|
49
55
|
|
|
50
56
|
def _Float(**name_arg):
|
|
@@ -137,7 +143,7 @@ def _naninf(p, *xs):
|
|
|
137
143
|
|
|
138
144
|
|
|
139
145
|
def _over(p, q):
|
|
140
|
-
'''(INTERNAL) Return C{B{p} / B{q}}
|
|
146
|
+
'''(INTERNAL) Return C{B{p} / B{q}} without C{ZeroDivisionError} exceptions.
|
|
141
147
|
'''
|
|
142
148
|
try:
|
|
143
149
|
return (p / q) # if p else _copysign_0_0(q)
|
|
@@ -145,6 +151,18 @@ def _over(p, q):
|
|
|
145
151
|
return (_copysignINF(p) if isfinite(p) else NAN) if p else p
|
|
146
152
|
|
|
147
153
|
|
|
154
|
+
def _over_1(p, q):
|
|
155
|
+
'''(INTERNAL) Return C{B{p} / B{q}} with exact C{1.0} and without C{ZeroDivisionError} exceptions.
|
|
156
|
+
'''
|
|
157
|
+
if fabs(p) != fabs(q):
|
|
158
|
+
r = _over(p, q)
|
|
159
|
+
else:
|
|
160
|
+
r = _flipsign(p, q)
|
|
161
|
+
if p:
|
|
162
|
+
r = _copysign_1_0(r)
|
|
163
|
+
return r
|
|
164
|
+
|
|
165
|
+
|
|
148
166
|
def _1_over(x):
|
|
149
167
|
'''(INTERNAL) Return reciprocal C{1 / B{x}} avoiding C{ZeroDivisionError} exceptions.
|
|
150
168
|
'''
|
|
@@ -245,7 +263,7 @@ _EPStol = _Float(_EPStol=_EPSqrt * _0_1) # PYCHOK = 1.49011611938e5-09 == sqr
|
|
|
245
263
|
|
|
246
264
|
_89_999 = _Float(_89_999=_90_0 * EPS1) # just below 90.0
|
|
247
265
|
# <https://Numbers.Computation.Free.FR/Constants/Miscellaneous/digits.html>
|
|
248
|
-
_1__90
|
|
266
|
+
# _1__90 = _Float(_1__90 =_1_0 / _90_0) # PYCHOK = 0.011_111_111_111_111_111_111_111_111_111_111_111_111_111_111_11111
|
|
249
267
|
_2__PI = _Float(_2__PI =_2_0 / _pi) # PYCHOK = 0.636_619_772_367_581_343_075_535_053_490_057_448_137_838_582_96182
|
|
250
268
|
|
|
251
269
|
_1_16th = _Float(_1_16th=_1_0 / _16_0) # PYCHOK in .ellipsoids, .karney
|
|
@@ -273,6 +291,7 @@ PI3_2 = _Float(PI3_2=_pi * _1_5) # PYCHOK PI and a half, M{PI * 3 / 2}
|
|
|
273
291
|
PI_3 = _Float(PI_3 =_pi / _3_0) # PYCHOK One third PI, M{PI / 3}
|
|
274
292
|
PI4 = _Float(PI4 =_pi * _4_0) # PYCHOK Four PI, M{PI * 4}
|
|
275
293
|
PI_4 = _Float(PI_4 =_pi / _4_0) # PYCHOK Quarter PI, M{PI / 4}
|
|
294
|
+
PI_6 = _Float(PI_6 =_pi / _6_0) # PYCHOK One sixth PI, M{PI / 6}
|
|
276
295
|
|
|
277
296
|
R_MA = _Radius(R_MA=6378137.0) # PYCHOK equatorial earth radius (C{meter}), WGS84, EPSG:3785
|
|
278
297
|
R_MB = _Radius(R_MB=6356752.3) # PYCHOK polar earth radius (C{meter}), WGS84, EPSG:3785
|
|
@@ -417,6 +436,17 @@ def isnear90(x, eps90=EPS0):
|
|
|
417
436
|
return bool(eps90 > (x - _90_0) > -eps90)
|
|
418
437
|
|
|
419
438
|
|
|
439
|
+
def isneg(x):
|
|
440
|
+
'''Check for negative C{x}, including L{NEG0}.
|
|
441
|
+
|
|
442
|
+
@arg x: Value (C{scalar}).
|
|
443
|
+
|
|
444
|
+
@return: C{True} if C{B{x} < 0 or NEG0},
|
|
445
|
+
C{False} otherwise.
|
|
446
|
+
'''
|
|
447
|
+
return signBit(x)
|
|
448
|
+
|
|
449
|
+
|
|
420
450
|
def isneg0(x):
|
|
421
451
|
'''Check for L{NEG0}, negative C{0.0}.
|
|
422
452
|
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
u'''DEPRECATED functions kept for backward compatibility.
|
|
5
5
|
'''
|
|
6
6
|
|
|
7
|
+
# from pygeodesy.basics import copysign0 # _MODS_
|
|
7
8
|
from pygeodesy.constants import EPS, R_M, float0_
|
|
8
9
|
from pygeodesy.deprecated.classes import ClipCS3Tuple, TriAngle4Tuple, _TriAngle5Tuple
|
|
9
10
|
from pygeodesy.interns import NN, _area_, _COMMASPACE_, _negative_, \
|
pygeodesy/dms.py
CHANGED
|
@@ -63,7 +63,7 @@ U{Vector-based geodesy<https://www.Movable-Type.co.UK/scripts/latlong-vectors.ht
|
|
|
63
63
|
|
|
64
64
|
from pygeodesy.basics import copysign0, isLatLon, isodd, issequence, isstr, \
|
|
65
65
|
neg as _neg, typename # in .ups
|
|
66
|
-
from pygeodesy.constants import
|
|
66
|
+
from pygeodesy.constants import _0_0, _0_5, _60_0, _360_0, _3600_0, _umod_360
|
|
67
67
|
from pygeodesy.errors import ParseError, RangeError, _TypeError, _ValueError, \
|
|
68
68
|
_parseX, rangerrors, _xError, _xkwds, _envPYGEODESY
|
|
69
69
|
# from pygeodesy.internals import _envPYGEODESY, typename # from .errors
|
|
@@ -86,7 +86,7 @@ except ImportError: # Python 3+
|
|
|
86
86
|
from string import ascii_letters as _LETTERS
|
|
87
87
|
|
|
88
88
|
__all__ = _ALL_LAZY.dms
|
|
89
|
-
__version__ = '25.
|
|
89
|
+
__version__ = '25.08.31'
|
|
90
90
|
|
|
91
91
|
_beyond_ = 'beyond'
|
|
92
92
|
_deg_min_ = 'deg+min'
|
pygeodesy/ecef.py
CHANGED
|
@@ -62,8 +62,8 @@ plane} as opposed to I{geocentric} (ECEF) ones.
|
|
|
62
62
|
from pygeodesy.basics import copysign0, _isin, isscalar, issubclassof, neg, map1, \
|
|
63
63
|
_xinstanceof, _xsubclassof, typename # _args_kwds_names
|
|
64
64
|
from pygeodesy.constants import EPS, EPS0, EPS02, EPS1, INT0, PI, PI_2, _0_0, \
|
|
65
|
-
_0_5, _1_0, _1_0_1T, _2_0, _3_0, _4_0, _6_0, \
|
|
66
|
-
|
|
65
|
+
_0_5, _1_0, _1_0_1T, _2_0, _3_0, _4_0, _6_0, _90_0, \
|
|
66
|
+
_copysign_1_0, isnon0 # PYCHOK used!
|
|
67
67
|
from pygeodesy.datums import _ellipsoidal_datum, _WGS84, a_f2Tuple, _EWGS84
|
|
68
68
|
from pygeodesy.ecefLocals import _EcefLocal
|
|
69
69
|
# from pygeodesy.ellipsoids import a_f2Tuple, _EWGS84 # from .datums
|
|
@@ -91,7 +91,7 @@ from pygeodesy.utily import atan1, atan1d, atan2, atan2d, degrees90, degrees180,
|
|
|
91
91
|
from math import cos, degrees, fabs, radians, sqrt
|
|
92
92
|
|
|
93
93
|
__all__ = _ALL_LAZY.ecef
|
|
94
|
-
__version__ = '25.08.
|
|
94
|
+
__version__ = '25.08.31'
|
|
95
95
|
|
|
96
96
|
_Ecef_ = 'Ecef'
|
|
97
97
|
_prolate_ = 'prolate'
|
pygeodesy/ellipsoidalExact.py
CHANGED
|
@@ -11,20 +11,20 @@ L{GeodesicExact}, L{GeodesicAreaExact} and L{GeodesicLineExact}.
|
|
|
11
11
|
|
|
12
12
|
# from pygeodesy.datums import _WGS84 # from .ellipsoidalBase
|
|
13
13
|
from pygeodesy.ellipsoidalBase import CartesianEllipsoidalBase, \
|
|
14
|
-
_nearestOn, _WGS84
|
|
14
|
+
_nearestOn, Property_RO, _WGS84
|
|
15
15
|
from pygeodesy.ellipsoidalBaseDI import LatLonEllipsoidalBaseDI, \
|
|
16
16
|
_intersection3, _intersections2, \
|
|
17
17
|
_TOL_M, intersecant2
|
|
18
18
|
# from pygeodesy.errors import _xkwds # from .karney
|
|
19
|
-
from pygeodesy.karney import _polygon, fabs,
|
|
19
|
+
from pygeodesy.karney import _polygon, fabs, _xkwds
|
|
20
20
|
from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS, _ALL_OTHER
|
|
21
21
|
from pygeodesy.points import _areaError, ispolar # PYCHOK exported
|
|
22
|
-
# from pygeodesy.props import Property_RO # from .
|
|
22
|
+
# from pygeodesy.props import Property_RO # from .ellipsoidalBase
|
|
23
23
|
|
|
24
24
|
# from math import fabs # from .karney
|
|
25
25
|
|
|
26
26
|
__all__ = _ALL_LAZY.ellipsoidalExact
|
|
27
|
-
__version__ = '25.
|
|
27
|
+
__version__ = '25.08.28'
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
class Cartesian(CartesianEllipsoidalBase):
|
|
@@ -12,11 +12,11 @@ L{geodsolve}, a wrapper invoking I{Karney}'s U{GeodSolve
|
|
|
12
12
|
|
|
13
13
|
# from pygeodesy.datums import _WGS84 # from .ellipsoidalBase
|
|
14
14
|
from pygeodesy.ellipsoidalBase import CartesianEllipsoidalBase, \
|
|
15
|
-
_nearestOn, _WGS84
|
|
15
|
+
_nearestOn, Property_RO, _WGS84
|
|
16
16
|
from pygeodesy.ellipsoidalBaseDI import LatLonEllipsoidalBaseDI, _TOL_M, \
|
|
17
17
|
_intersection3, _intersections2
|
|
18
18
|
# from pygeodesy.errors import _xkwds # from .karney
|
|
19
|
-
from pygeodesy.karney import fabs, _polygon,
|
|
19
|
+
from pygeodesy.karney import fabs, _polygon, _xkwds
|
|
20
20
|
from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS, _ALL_OTHER
|
|
21
21
|
from pygeodesy.points import _areaError, ispolar # PYCHOK exported
|
|
22
22
|
# from pygeodesy.props import Property_RO # from .karney
|
|
@@ -24,7 +24,7 @@ from pygeodesy.points import _areaError, ispolar # PYCHOK exported
|
|
|
24
24
|
# from math import fabs # from .karney
|
|
25
25
|
|
|
26
26
|
__all__ = _ALL_LAZY.ellipsoidalGeodSolve
|
|
27
|
-
__version__ = '25.
|
|
27
|
+
__version__ = '25.08.28'
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
class Cartesian(CartesianEllipsoidalBase):
|
pygeodesy/ellipsoids.py
CHANGED
|
@@ -67,8 +67,8 @@ from __future__ import division as _; del _ # noqa: E702 ;
|
|
|
67
67
|
# from pygeodesy.albers import AlbersEqualAreaCylindrical # _MODS
|
|
68
68
|
from pygeodesy.basics import copysign0, isbool, _isin, isint, typename
|
|
69
69
|
from pygeodesy.constants import EPS, EPS_2, EPS0, EPS02, EPS1, INF, NINF, \
|
|
70
|
-
_over, PI_2, PI_3, PI4, R_M, R_MA, R_FM, \
|
|
71
|
-
|
|
70
|
+
_over, PI_2, PI_3, PI4, R_M, R_MA, R_FM, _EPSqrt, \
|
|
71
|
+
_EPStol as _TOL, _floatuple as _T, _isfinite, \
|
|
72
72
|
_0_0s, _0_0, _0_5, _1_0, _1_EPS, _2_0, _4_0, _90_0, \
|
|
73
73
|
_0_25, _3_0 # PYCHOK used!
|
|
74
74
|
from pygeodesy.errors import _AssertionError, IntersectionError, _ValueError, _xattr, _xkwds_not
|
|
@@ -96,7 +96,7 @@ from pygeodesy.utily import atan1, atan1d, atan2b, degrees90, m2radians, radians
|
|
|
96
96
|
from math import asinh, atan, atanh, cos, degrees, exp, fabs, radians, sin, sinh, sqrt, tan # as _tan
|
|
97
97
|
|
|
98
98
|
__all__ = _ALL_LAZY.ellipsoids
|
|
99
|
-
__version__ = '25.08.
|
|
99
|
+
__version__ = '25.08.31'
|
|
100
100
|
|
|
101
101
|
_f_0_0 = Float(f =_0_0) # zero flattening
|
|
102
102
|
_f__0_0 = Float(f_=_0_0) # zero inverse flattening
|
|
@@ -443,7 +443,7 @@ class Ellipsoid(_NamedEnumItem):
|
|
|
443
443
|
eps=eps, f0=f0, **name_value))
|
|
444
444
|
|
|
445
445
|
def auxAuthalic(self, lat, inverse=False):
|
|
446
|
-
'''Compute the I{authalic} auxiliary latitude or the I{inverse} thereof.
|
|
446
|
+
'''Compute the I{authalic} auxiliary latitude (Xi) or the I{inverse} thereof.
|
|
447
447
|
|
|
448
448
|
@arg lat: The geodetic (or I{authalic}) latitude (C{degrees90}).
|
|
449
449
|
@kwarg inverse: If C{True}, B{C{lat}} is the I{authalic} and
|
|
@@ -463,7 +463,7 @@ class Ellipsoid(_NamedEnumItem):
|
|
|
463
463
|
return _aux(lat, inverse, Ellipsoid.auxAuthalic)
|
|
464
464
|
|
|
465
465
|
def auxConformal(self, lat, inverse=False):
|
|
466
|
-
'''Compute the I{conformal} auxiliary latitude or the I{inverse} thereof.
|
|
466
|
+
'''Compute the I{conformal} auxiliary latitude (Chi) or the I{inverse} thereof.
|
|
467
467
|
|
|
468
468
|
@arg lat: The geodetic (or I{conformal}) latitude (C{degrees90}).
|
|
469
469
|
@kwarg inverse: If C{True}, B{C{lat}} is the I{conformal} and
|
|
@@ -481,12 +481,13 @@ class Ellipsoid(_NamedEnumItem):
|
|
|
481
481
|
lat = atan1d(f(tan(Phid(lat)))) # PYCHOK attr
|
|
482
482
|
return _aux(lat, inverse, Ellipsoid.auxConformal)
|
|
483
483
|
|
|
484
|
-
def auxGeocentric(self, lat, inverse=False):
|
|
485
|
-
'''Compute the I{geocentric} auxiliary latitude or the I{inverse} thereof.
|
|
484
|
+
def auxGeocentric(self, lat, inverse=False, height=_0_0):
|
|
485
|
+
'''Compute the I{geocentric} auxiliary latitude (Theta) or the I{inverse} thereof.
|
|
486
486
|
|
|
487
487
|
@arg lat: The geodetic (or I{geocentric}) latitude (C{degrees90}).
|
|
488
488
|
@kwarg inverse: If C{True}, B{C{lat}} is the geocentric and
|
|
489
489
|
return the I{geocentric} latitude (C{bool}).
|
|
490
|
+
@kwarg height: Optional, ellipsoidal height (C{meter}).
|
|
490
491
|
|
|
491
492
|
@return: The I{geocentric} (or geodetic) latitude in C{degrees90}.
|
|
492
493
|
|
|
@@ -495,13 +496,24 @@ class Ellipsoid(_NamedEnumItem):
|
|
|
495
496
|
<https://WikiPedia.org/wiki/Latitude#Geocentric_latitude>}, and
|
|
496
497
|
U{Snyder<https://Pubs.USGS.gov/pp/1395/report.pdf>}, pp 17-18.
|
|
497
498
|
'''
|
|
498
|
-
if self.f:
|
|
499
|
-
|
|
500
|
-
|
|
499
|
+
if self.f: # and lat
|
|
500
|
+
t = tan(Phid(lat))
|
|
501
|
+
f = self.b2_a2
|
|
502
|
+
if height:
|
|
503
|
+
if inverse:
|
|
504
|
+
lat = atan1d(t * f) # geodetic n
|
|
505
|
+
d, f = f, _1_0
|
|
506
|
+
else:
|
|
507
|
+
d = _1_0
|
|
508
|
+
n = self.rocPrimeVertical(lat)
|
|
509
|
+
f = _over(n * f + height, n * d + height)
|
|
510
|
+
elif inverse:
|
|
511
|
+
f = self.a2_b2
|
|
512
|
+
lat = atan1d(t * f)
|
|
501
513
|
return _aux(lat, inverse, Ellipsoid.auxGeocentric)
|
|
502
514
|
|
|
503
515
|
def auxIsometric(self, lat, inverse=False):
|
|
504
|
-
'''Compute the I{isometric} auxiliary latitude or the I{inverse} thereof.
|
|
516
|
+
'''Compute the I{isometric} auxiliary latitude (Psi) or the I{inverse} thereof.
|
|
505
517
|
|
|
506
518
|
@arg lat: The geodetic (or I{isometric}) latitude (C{degrees}).
|
|
507
519
|
@kwarg inverse: If C{True}, B{C{lat}} is the I{isometric} and
|
|
@@ -510,8 +522,8 @@ class Ellipsoid(_NamedEnumItem):
|
|
|
510
522
|
@return: The I{isometric} (or geodetic) latitude in C{degrees}.
|
|
511
523
|
|
|
512
524
|
@note: The I{isometric} latitude for geodetic C{+/-90} is far
|
|
513
|
-
outside the C{[-90..+90]} range but the inverse
|
|
514
|
-
|
|
525
|
+
outside the C{[-90..+90]} range but the inverse thereof
|
|
526
|
+
is the original geodetic latitude.
|
|
515
527
|
|
|
516
528
|
@see: U{Inverse-/IsometricLatitude<https://GeographicLib.SourceForge.io/
|
|
517
529
|
C++/doc/classGeographicLib_1_1Ellipsoid.html>}, U{Isometric latitude
|
|
@@ -526,7 +538,7 @@ class Ellipsoid(_NamedEnumItem):
|
|
|
526
538
|
return _aux(lat, inverse, Ellipsoid.auxIsometric, clip=0)
|
|
527
539
|
|
|
528
540
|
def auxParametric(self, lat, inverse=False):
|
|
529
|
-
'''Compute the I{parametric} auxiliary latitude or the I{inverse} thereof.
|
|
541
|
+
'''Compute the I{parametric} auxiliary latitude (Beta) or the I{inverse} thereof.
|
|
530
542
|
|
|
531
543
|
@arg lat: The geodetic (or I{parametric}) latitude (C{degrees90}).
|
|
532
544
|
@kwarg inverse: If C{True}, B{C{lat}} is the I{parametric} and
|
|
@@ -546,7 +558,7 @@ class Ellipsoid(_NamedEnumItem):
|
|
|
546
558
|
auxReduced = auxParametric # synonymous
|
|
547
559
|
|
|
548
560
|
def auxRectifying(self, lat, inverse=False):
|
|
549
|
-
'''Compute the I{rectifying} auxiliary latitude or the I{inverse} thereof.
|
|
561
|
+
'''Compute the I{rectifying} auxiliary latitude (Mu) or the I{inverse} thereof.
|
|
550
562
|
|
|
551
563
|
@arg lat: The geodetic (or I{rectifying}) latitude (C{degrees90}).
|
|
552
564
|
@kwarg inverse: If C{True}, B{C{lat}} is the I{rectifying} and
|
|
@@ -692,23 +704,23 @@ class Ellipsoid(_NamedEnumItem):
|
|
|
692
704
|
'''
|
|
693
705
|
lat = Lat(lat)
|
|
694
706
|
if lat:
|
|
695
|
-
|
|
707
|
+
B = lat # beta
|
|
696
708
|
if fabs(lat) < _90_0:
|
|
697
709
|
if self.f:
|
|
698
|
-
|
|
699
|
-
z, r = sincos2d(
|
|
710
|
+
B = self._beta(lat)
|
|
711
|
+
z, r = sincos2d(B)
|
|
700
712
|
r *= self.a
|
|
701
713
|
z *= self.b
|
|
702
714
|
else: # near-polar
|
|
703
715
|
r, z = _0_0, copysign0(self.b, lat)
|
|
704
716
|
else: # equator
|
|
705
717
|
r = self.a
|
|
706
|
-
z = lat =
|
|
707
|
-
return Circle4Tuple(r, z, lat,
|
|
718
|
+
z = lat = B = _0_0
|
|
719
|
+
return Circle4Tuple(r, z, lat, B)
|
|
708
720
|
|
|
709
721
|
def degrees2m(self, deg, lat=0):
|
|
710
|
-
'''Convert an angle
|
|
711
|
-
|
|
722
|
+
'''Convert an angle along the equator or along a parallel
|
|
723
|
+
of (geodetic) latitude to the distance.
|
|
712
724
|
|
|
713
725
|
@arg deg: The angle (C{degrees}).
|
|
714
726
|
@kwarg lat: Parallel latitude (C{degrees90}, C{str}).
|
|
@@ -878,10 +890,10 @@ class Ellipsoid(_NamedEnumItem):
|
|
|
878
890
|
|
|
879
891
|
@raise ValueError: Invalid B{C{s}}.
|
|
880
892
|
'''
|
|
881
|
-
r = _1_0
|
|
882
|
-
if
|
|
893
|
+
r, e2 = _1_0, self.e2
|
|
894
|
+
if e2: # and s
|
|
883
895
|
try:
|
|
884
|
-
r -=
|
|
896
|
+
r -= e2 * Scalar(s=s)**2
|
|
885
897
|
if r < 0:
|
|
886
898
|
raise ValueError(_negative_)
|
|
887
899
|
except (TypeError, ValueError) as x:
|
|
@@ -1468,19 +1480,18 @@ class Ellipsoid(_NamedEnumItem):
|
|
|
1468
1480
|
@see: U{Geocentric Radius
|
|
1469
1481
|
<https://WikiPedia.org/wiki/Earth_radius#Geocentric_radius>}
|
|
1470
1482
|
'''
|
|
1471
|
-
r,
|
|
1472
|
-
if
|
|
1473
|
-
if fabs(
|
|
1474
|
-
s2, c2 = _s2_c2(
|
|
1475
|
-
b2_a2_s2 = self.b2_a2 * s2
|
|
1483
|
+
r, p = self.a, Phid(lat)
|
|
1484
|
+
if p and self.f:
|
|
1485
|
+
if fabs(p) < PI_2:
|
|
1486
|
+
s2, c2 = _s2_c2(p)
|
|
1476
1487
|
# R == sqrt((a2**2 * c2 + b2**2 * s2) / (a2 * c2 + b2 * s2))
|
|
1477
1488
|
# == sqrt(a2**2 * (c2 + (b2 / a2)**2 * s2) / (a2 * (c2 + b2 / a2 * s2)))
|
|
1478
1489
|
# == sqrt(a2 * (c2 + (b2 / a2)**2 * s2) / (c2 + (b2 / a2) * s2))
|
|
1479
1490
|
# == a * sqrt((c2 + b2_a2 * b2_a2 * s2) / (c2 + b2_a2 * s2))
|
|
1480
|
-
|
|
1481
|
-
r
|
|
1491
|
+
s2 *= self.b2_a2
|
|
1492
|
+
r *= sqrt((c2 + self.b2_a2 * s2) / (c2 + s2))
|
|
1482
1493
|
else:
|
|
1483
|
-
r
|
|
1494
|
+
r = self.b
|
|
1484
1495
|
return Radius(Rgeocentric=r)
|
|
1485
1496
|
|
|
1486
1497
|
@Property_RO
|
|
@@ -1653,18 +1664,18 @@ class Ellipsoid(_NamedEnumItem):
|
|
|
1653
1664
|
and the meridional and prime vertical U{Radii of Curvature
|
|
1654
1665
|
<https://WikiPedia.org/wiki/Earth_radius#Radii_of_curvature>}.
|
|
1655
1666
|
'''
|
|
1656
|
-
|
|
1667
|
+
p = fabs(Phi(phi))
|
|
1657
1668
|
if self.f:
|
|
1658
|
-
r = self.e2s2(sin(
|
|
1669
|
+
r = self.e2s2(sin(p))
|
|
1659
1670
|
if r > EPS02:
|
|
1660
|
-
n = self.
|
|
1661
|
-
m = n *
|
|
1671
|
+
n = sqrt(self.a2 / r)
|
|
1672
|
+
m = n * self.e21 / r
|
|
1662
1673
|
else:
|
|
1663
1674
|
m = n = _0_0
|
|
1664
1675
|
else:
|
|
1665
1676
|
m = n = self.a
|
|
1666
|
-
if scaled and
|
|
1667
|
-
n *= cos(
|
|
1677
|
+
if scaled and p:
|
|
1678
|
+
n *= cos(p) if p < PI_2 else _0_0
|
|
1668
1679
|
return Curvature2Tuple(m, n)
|
|
1669
1680
|
|
|
1670
1681
|
def rocAzimuth(self, lat, azimuth):
|
|
@@ -1795,8 +1806,8 @@ class Ellipsoid(_NamedEnumItem):
|
|
|
1795
1806
|
U{Radii of Curvature<https://WikiPedia.org/wiki/
|
|
1796
1807
|
Earth_radius#Radii_of_curvature>}.
|
|
1797
1808
|
'''
|
|
1798
|
-
r = self.
|
|
1799
|
-
return Radius(rocPrimeVertical=r
|
|
1809
|
+
r = self.roc1_(sin(Phid(lat))) if lat else self.a
|
|
1810
|
+
return Radius(rocPrimeVertical=r)
|
|
1800
1811
|
|
|
1801
1812
|
rocTransverse = rocPrimeVertical # synonymous
|
|
1802
1813
|
|