pygeodesy 25.12.31__py2.py3-none-any.whl → 26.1.16__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 +9 -9
- pygeodesy/albers.py +5 -5
- pygeodesy/cartesianBase.py +2 -2
- pygeodesy/constants.py +6 -1
- pygeodesy/datums.py +5 -8
- pygeodesy/ellipsoids.py +9 -8
- pygeodesy/elliptic.py +532 -139
- pygeodesy/fmath.py +2 -2
- pygeodesy/formy.py +10 -249
- pygeodesy/fsums.py +9 -3
- pygeodesy/geod3solve.py +18 -3
- pygeodesy/internals.py +10 -3
- pygeodesy/lazily.py +13 -6
- pygeodesy/lcc.py +3 -7
- pygeodesy/named.py +13 -9
- pygeodesy/trf.py +1 -1
- pygeodesy/triaxials/bases.py +64 -42
- pygeodesy/triaxials/triaxial3.py +40 -43
- pygeodesy/triaxials/triaxial5.py +17 -49
- pygeodesy/utily.py +7 -7
- {pygeodesy-25.12.31.dist-info → pygeodesy-26.1.16.dist-info}/METADATA +9 -9
- {pygeodesy-25.12.31.dist-info → pygeodesy-26.1.16.dist-info}/RECORD +24 -24
- {pygeodesy-25.12.31.dist-info → pygeodesy-26.1.16.dist-info}/WHEEL +0 -0
- {pygeodesy-25.12.31.dist-info → pygeodesy-26.1.16.dist-info}/top_level.txt +0 -0
pygeodesy/fmath.py
CHANGED
|
@@ -22,10 +22,10 @@ from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS
|
|
|
22
22
|
from pygeodesy.units import Int_, _isHeight, _isRadius
|
|
23
23
|
|
|
24
24
|
from math import fabs, sqrt # pow
|
|
25
|
-
import operator as _operator # in .datums, .trf, .utm
|
|
25
|
+
import operator as _operator # in .datums, .elliptic, .trf, .utm
|
|
26
26
|
|
|
27
27
|
__all__ = _ALL_LAZY.fmath
|
|
28
|
-
__version__ = '
|
|
28
|
+
__version__ = '26.01.06'
|
|
29
29
|
|
|
30
30
|
# sqrt(2) - 1 <https://WikiPedia.org/wiki/Square_root_of_2>
|
|
31
31
|
_0_4142 = 0.41421356237309504880 # ~ 3_730_904_090_310_553 / 9_007_199_254_740_992
|
pygeodesy/formy.py
CHANGED
|
@@ -8,28 +8,25 @@ from __future__ import division as _; del _ # noqa: E702 ;
|
|
|
8
8
|
|
|
9
9
|
from pygeodesy.basics import _copysign, _isin # _args_kwds_count2
|
|
10
10
|
# from pygeodesy.cartesianBase import CartesianBase # _MODS
|
|
11
|
-
from pygeodesy.constants import EPS, EPS0, EPS1,
|
|
11
|
+
from pygeodesy.constants import EPS, EPS0, EPS1, PI, PI2, PI3, PI_2, R_M, \
|
|
12
12
|
_0_0s, float0_, isnon0, remainder, _umod_PI2, \
|
|
13
13
|
_0_0, _0_125, _0_25, _0_5, _1_0, _2_0, _4_0, \
|
|
14
14
|
_90_0, _180_0, _360_0
|
|
15
|
-
from pygeodesy.constants import _3_0, _10_0, MANT_DIG as _DIG53 # PYCHOK used!
|
|
16
15
|
from pygeodesy.datums import Datum, Ellipsoid, _ellipsoidal_datum, \
|
|
17
16
|
_mean_radius, _spherical_datum, _WGS84, _EWGS84
|
|
18
17
|
# from pygeodesy.ellipsoids import Ellipsoid, _EWGS84 # from .datums
|
|
19
|
-
# from pygeodesy.elliptic import Elliptic # _MODS
|
|
20
18
|
from pygeodesy.errors import IntersectionError, LimitError, limiterrors, \
|
|
21
19
|
_TypeError, _ValueError, _xattr, _xError, \
|
|
22
20
|
_xcallable, _xkwds, _xkwds_pop2
|
|
23
|
-
from pygeodesy.fmath import euclid, fdot_,
|
|
24
|
-
from pygeodesy.fsums import
|
|
21
|
+
from pygeodesy.fmath import euclid, fdot_, fprod, hypot, hypot2, sqrt0
|
|
22
|
+
from pygeodesy.fsums import fsumf_, Fmt, unstr
|
|
25
23
|
# from pygeodesy.internals import typename # from .named
|
|
26
|
-
from pygeodesy.interns import _delta_, _distant_,
|
|
27
|
-
from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS
|
|
28
|
-
from pygeodesy.named import
|
|
29
|
-
|
|
24
|
+
from pygeodesy.interns import _delta_, _distant_, _inside_, _SPACE_, _too_
|
|
25
|
+
from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS
|
|
26
|
+
from pygeodesy.named import _name__, _name2__, _NamedTuple, _xnamed, \
|
|
27
|
+
typename
|
|
30
28
|
from pygeodesy.namedTuples import Bearing2Tuple, Distance4Tuple, LatLon2Tuple, \
|
|
31
29
|
Intersection3Tuple, PhiLam2Tuple
|
|
32
|
-
from pygeodesy.props import property_ROnce
|
|
33
30
|
# from pygeodesy.streprs import Fmt, unstr # from .fsums
|
|
34
31
|
# from pygeodesy.triaxials.triaxial5 import _hartzell3 # _MODS
|
|
35
32
|
from pygeodesy.units import _isDegrees, _isHeight, _isRadius, Bearing, Degrees_, \
|
|
@@ -46,241 +43,13 @@ from contextlib import contextmanager
|
|
|
46
43
|
from math import atan, cos, degrees, fabs, radians, sin, sqrt # pow
|
|
47
44
|
|
|
48
45
|
__all__ = _ALL_LAZY.formy
|
|
49
|
-
__version__ = '
|
|
46
|
+
__version__ = '26.01.06'
|
|
50
47
|
|
|
51
48
|
_RADIANS2 = radians(_1_0)**2 # degree to radians-squared
|
|
52
49
|
_ratio_ = 'ratio'
|
|
53
50
|
_xline_ = 'xline'
|
|
54
51
|
|
|
55
52
|
|
|
56
|
-
class Elliperim(object):
|
|
57
|
-
'''Singleton with various methods to compute the perimeter of an ellipse.
|
|
58
|
-
'''
|
|
59
|
-
_TOL53 = sqrt(EPS_2) # sqrt(pow(_0_5, _DIG53))
|
|
60
|
-
_TOL53_53 = _TOL53 / _DIG53 # "flat" b/a tolerance, 1.9e-10
|
|
61
|
-
# assert _DIG53 == 53
|
|
62
|
-
|
|
63
|
-
def AGM(self, a, b, maxit=_DIG53):
|
|
64
|
-
'''Return the perimeter of an ellipse with semi-axes C{a} and C{b} using the U{AGM
|
|
65
|
-
<https://PaulBourke.net/geometry/ellipsecirc>} (Arithmetic-Geometric Mean) method.
|
|
66
|
-
|
|
67
|
-
@kwarg maxit: Number of iterations (C{int}).
|
|
68
|
-
|
|
69
|
-
@raise ValueError: No convergence for B{C{maxit}} iterations.
|
|
70
|
-
'''
|
|
71
|
-
_, p, a, b = self._pab4(a, b)
|
|
72
|
-
if p is None:
|
|
73
|
-
c_ = []
|
|
74
|
-
ts = self._AGMs(a, b, max(maxit, _DIG53), c_)
|
|
75
|
-
p = fsum(ts, nonfinites=True)
|
|
76
|
-
p *= PI / c_[0]
|
|
77
|
-
return p
|
|
78
|
-
|
|
79
|
-
def _AGMs(self, a, b, maxit, c_):
|
|
80
|
-
'''(INTERNAL) Yield the C{AGM} terms and final C{c}.
|
|
81
|
-
'''
|
|
82
|
-
c = a + b
|
|
83
|
-
yield c**2
|
|
84
|
-
m = -1
|
|
85
|
-
t = self._TOL53
|
|
86
|
-
for _ in range(maxit): # 4..5 trips
|
|
87
|
-
b = sqrt(a * b)
|
|
88
|
-
a = c * _0_5
|
|
89
|
-
c = a + b
|
|
90
|
-
d = a - b
|
|
91
|
-
m *= 2
|
|
92
|
-
yield d**2 * m
|
|
93
|
-
if d <= (b * t):
|
|
94
|
-
break
|
|
95
|
-
else:
|
|
96
|
-
raise self._Error(maxit, d, b * t)
|
|
97
|
-
c_.append(c) # kludge
|
|
98
|
-
|
|
99
|
-
def Arc43(self, a, b):
|
|
100
|
-
'''Return the perimeter (and arcs) of an ellipse with semi-axes C{a} and C{b}
|
|
101
|
-
with the U{4-Arc<https://PaulBourke.net/geometry/ellipsecirc>} approximation.
|
|
102
|
-
|
|
103
|
-
@return: 3-Tuple C{(p, Ra, Rb)} with perimeter C{p}, arc radius C{Ra} at the
|
|
104
|
-
major and arc radius C{Rb} at the minor semi-axis.
|
|
105
|
-
'''
|
|
106
|
-
_r, p, a, b = self._pab4(a, b)
|
|
107
|
-
if p is None:
|
|
108
|
-
h = hypot(a, b)
|
|
109
|
-
p = atan2(b, a)
|
|
110
|
-
s, c = sincos2(p)
|
|
111
|
-
L = (h - b) * _0_5
|
|
112
|
-
Ra = L / c
|
|
113
|
-
Rb = (h - L) / s
|
|
114
|
-
p = Rb * p + Ra * (PI_2 - p)
|
|
115
|
-
p *= _4_0
|
|
116
|
-
else: # circle or flat
|
|
117
|
-
Ra, Rb = a, b
|
|
118
|
-
return (p, Rb, Ra) if _r else (p, Ra, Rb)
|
|
119
|
-
|
|
120
|
-
# def CR(self, a, b):
|
|
121
|
-
# '''Return the perimeter of an ellipse with semi-axes C{a} and C{b} using U{Rackauckas'
|
|
122
|
-
# <https://www.ChrisRackauckas.com/assets/Papers/ChrisRackauckas-The_Circumference_of_an_Ellipse.pdf>}
|
|
123
|
-
# approximation, also U{here<https://ExtremeLearning.com.AU/a-formula-for-the-perimeter-of-an-ellipse>}.
|
|
124
|
-
# '''
|
|
125
|
-
# _, p, a, b = self._pab4(a, b)
|
|
126
|
-
# if p is None:
|
|
127
|
-
# p = a + b
|
|
128
|
-
# h = ((a - b) / p)**2
|
|
129
|
-
# p *= (fhorner(h, 135168, -85760, -5568, 3867) /
|
|
130
|
-
# fhorner(h, 135168, -119552, 22208, 345)) * PI
|
|
131
|
-
# return p
|
|
132
|
-
|
|
133
|
-
def E2k(self, a, b):
|
|
134
|
-
'''Return the perimeter of an ellipse with semi-axes C{a} and C{b} from the complete
|
|
135
|
-
elliptic integral of the 2nd kind L{E(k)<pygeodesy.elliptic.Elliptic.cE>}.
|
|
136
|
-
'''
|
|
137
|
-
return self._ellip2k(a, b, self._ellipE)
|
|
138
|
-
|
|
139
|
-
def e2k(self, a, b, E_alt=None):
|
|
140
|
-
'''Return the perimeter of an ellipse with semi-axes C{a} and C{b} using U{SciPy's
|
|
141
|
-
ellipe<https://www.JohnDCook.com/perimeter_ellipse.html>} function or method
|
|
142
|
-
C{E_alt}, otherwise C{None}.
|
|
143
|
-
|
|
144
|
-
@kwarg E_alt: An other C{Elliperim}C{(a, b)} method to use in case C{SciPy's
|
|
145
|
-
ellipe} is not available.
|
|
146
|
-
'''
|
|
147
|
-
p = self._ellipe
|
|
148
|
-
if p is not None: # i.e. callable
|
|
149
|
-
p = self._ellip2k(a, b, p)
|
|
150
|
-
elif callable(E_alt): # and E_alt is not Elliperim.e2k
|
|
151
|
-
p = E_alt(a, b)
|
|
152
|
-
return p
|
|
153
|
-
|
|
154
|
-
def _ellipE(self, k):
|
|
155
|
-
'''(INTERNAL) Get the complete C{elliptic} integeral C{E(k)}.
|
|
156
|
-
'''
|
|
157
|
-
return _MODS.elliptic.Elliptic(k).cE
|
|
158
|
-
|
|
159
|
-
@property_ROnce
|
|
160
|
-
def _ellipe(self):
|
|
161
|
-
'''(INTERNAL) Wrap function C{scipy.special.ellipe}, I{once}.
|
|
162
|
-
'''
|
|
163
|
-
try:
|
|
164
|
-
from scipy.special import ellipe
|
|
165
|
-
|
|
166
|
-
def _ellipe(k):
|
|
167
|
-
return float(ellipe(k))
|
|
168
|
-
|
|
169
|
-
except (AttributeError, ImportError):
|
|
170
|
-
_ellipe = None
|
|
171
|
-
return _ellipe # overwrite property_ROnce
|
|
172
|
-
|
|
173
|
-
def _ellip2k(self, a, b, _ellip):
|
|
174
|
-
'''(INTERNAL) Helper for methods C{E2k} and C{e2k}.
|
|
175
|
-
'''
|
|
176
|
-
_, p, a, b = self._pab4(a, b)
|
|
177
|
-
if p is None: # see .ellipsoids.Ellipsoid.L
|
|
178
|
-
k = _1_0 - (b / a)**2
|
|
179
|
-
p = _ellip(k) * a * _4_0
|
|
180
|
-
return p
|
|
181
|
-
|
|
182
|
-
def _Error(self, maxit, d, t):
|
|
183
|
-
return _ValueError(maxit=maxit, txt=Fmt.no_convergence(d, t))
|
|
184
|
-
|
|
185
|
-
def GK(self, a, b):
|
|
186
|
-
'''Return the perimeter of an ellipse with semi-axes C{a} and C{b} using the U{Gauss-Kummer
|
|
187
|
-
<https://www.JohnDCook.com/blog/2023/05/28/approximate-ellipse-perimeter>} series, and
|
|
188
|
-
U{here<https://www.MathsIsFun.com/geometry/ellipse-perimeter.html>}, C{B{b / a} > 0.75}.
|
|
189
|
-
'''
|
|
190
|
-
_, p, a, b = self._pab4(a, b)
|
|
191
|
-
if p is None:
|
|
192
|
-
p = a + b
|
|
193
|
-
h = (a - b) / p
|
|
194
|
-
p *= fhorner(h**2, *self._GKs) * PI
|
|
195
|
-
return p
|
|
196
|
-
|
|
197
|
-
@property_ROnce
|
|
198
|
-
def _GKs(self):
|
|
199
|
-
'''(INTERNAL) Compute the Gauss-Kummer coefficients, I{once}.
|
|
200
|
-
'''
|
|
201
|
-
return (1, 1 / 4, 1 / 64, 1 / 256, 25 / 16384, 49 / 65536,
|
|
202
|
-
441 / 1048576, 1089 / 4194304) # overwrite property_ROnce
|
|
203
|
-
|
|
204
|
-
def HG(self, a, b, maxit=_DIG53):
|
|
205
|
-
'''Return the perimeter of an ellipse with semi-axes C{a} and C{b} using the U{HG
|
|
206
|
-
<https://web.Tecnico.ULisboa.PT/~mcasquilho/compute/com/,ellips/PerimeterOfEllipse.pdf>}
|
|
207
|
-
(HyperGeometric Gauss-Kummer) series.
|
|
208
|
-
|
|
209
|
-
@kwarg maxit: Number of iterations (C{int}), sufficient for C{B{b / a} > 0.125}.
|
|
210
|
-
|
|
211
|
-
@raise ValueError: No convergence for B{C{maxit}} iterations.
|
|
212
|
-
'''
|
|
213
|
-
_, p, a, b = self._pab4(a, b)
|
|
214
|
-
if p is None:
|
|
215
|
-
p = a + b
|
|
216
|
-
h = (a - b) / p
|
|
217
|
-
ts = self._HGs(h, max(maxit, _DIG53))
|
|
218
|
-
p *= fsum(ts, nonfinites=True) * PI
|
|
219
|
-
return p
|
|
220
|
-
|
|
221
|
-
def _HGs(self, h, maxit):
|
|
222
|
-
'''(INTERNAL) Yield the C{HG} terms.
|
|
223
|
-
'''
|
|
224
|
-
t = s_ = -1
|
|
225
|
-
s = _1_0
|
|
226
|
-
yield s
|
|
227
|
-
for u in range(-1, maxit * 2, 2):
|
|
228
|
-
t *= u / (u + 3) * h
|
|
229
|
-
t2 = t**2
|
|
230
|
-
s += t2
|
|
231
|
-
yield t2
|
|
232
|
-
if s == s_:
|
|
233
|
-
break
|
|
234
|
-
s_ = s
|
|
235
|
-
else:
|
|
236
|
-
s -= s_ - t2
|
|
237
|
-
raise self._Error(maxit, t2, s)
|
|
238
|
-
|
|
239
|
-
# def LS(self, a, b):
|
|
240
|
-
# '''Return the perimeter of an ellipse with semi-axes C{a} and C{b} using the U{Linderholm-Segal
|
|
241
|
-
# <https://www.JohnDCook.com/blog/2021/03/24/perimeter-of-an-ellipse>} formula, aka C{3/2 norm}.
|
|
242
|
-
# '''
|
|
243
|
-
# _, p, a, b = self._pab4(a, b)
|
|
244
|
-
# if p is None:
|
|
245
|
-
# p = pow(a, _1_5) + pow(b, _1_5)
|
|
246
|
-
# p = pow(p * _0_5, _2_3rd) * PI2
|
|
247
|
-
# return p
|
|
248
|
-
|
|
249
|
-
def _pab4(self, a, b):
|
|
250
|
-
_r = a < b
|
|
251
|
-
if _r:
|
|
252
|
-
a, b = b, a
|
|
253
|
-
if a > b:
|
|
254
|
-
if b > (a * self._TOL53_53):
|
|
255
|
-
p = None
|
|
256
|
-
elif b < 0:
|
|
257
|
-
t = callername() # underOK=True
|
|
258
|
-
t = _DOT_(typename(self), t)
|
|
259
|
-
raise _ValueError(unstr(t, a, b))
|
|
260
|
-
else: # "flat"
|
|
261
|
-
p = a * _4_0
|
|
262
|
-
else: # circle
|
|
263
|
-
p = a * PI2
|
|
264
|
-
return _r, p, a, b
|
|
265
|
-
|
|
266
|
-
def R2(self, a, b):
|
|
267
|
-
'''Return the perimeter of an ellipse with semi-axes C{a} and C{b} using U{Ramanujan's
|
|
268
|
-
2nd<https://PaulBourke.net/geometry/ellipsecirc>} approximation, C{B{b / a} > 0.9}.
|
|
269
|
-
'''
|
|
270
|
-
_, p, a, b = self._pab4(a, b)
|
|
271
|
-
if p is None:
|
|
272
|
-
p = a + b
|
|
273
|
-
h = (a - b) / p
|
|
274
|
-
h *= _3_0 * h
|
|
275
|
-
h /= sqrt(_4_0 - h) + _10_0 # /= chokes PyChecker?
|
|
276
|
-
p *= (h + _1_0) * PI
|
|
277
|
-
return p
|
|
278
|
-
|
|
279
|
-
if not _FOR_DOCS: # PYCHOK force epydoc
|
|
280
|
-
Elliperim = Elliperim() # singleton
|
|
281
|
-
del _FOR_DOCS
|
|
282
|
-
|
|
283
|
-
|
|
284
53
|
def angle2chord(rad, radius=R_M):
|
|
285
54
|
'''Get the chord length of a (central) angle or I{angular} distance.
|
|
286
55
|
|
|
@@ -599,15 +368,6 @@ def _dS(fun_, radius, wrap, *lls, **adjust):
|
|
|
599
368
|
return r * radius
|
|
600
369
|
|
|
601
370
|
|
|
602
|
-
def elliperim(a, b):
|
|
603
|
-
'''Compute the perimeter of an ellipse with semi-axes C{a} and C{b}
|
|
604
|
-
using the C{Elliperim.e2k} or C{Elliperim.AGM} method.
|
|
605
|
-
|
|
606
|
-
@return: The perimeter (C{scalar}, same units as C{a} and C{b}).
|
|
607
|
-
'''
|
|
608
|
-
return Elliperim.e2k(a, b, Elliperim.E2k)
|
|
609
|
-
|
|
610
|
-
|
|
611
371
|
def _ellipsoidal(earth, where):
|
|
612
372
|
'''(INTERNAL) Helper for distances.
|
|
613
373
|
'''
|
|
@@ -1167,7 +927,8 @@ def hartzell(pov, los=False, earth=_WGS84, **name_LatLon_and_kwds):
|
|
|
1167
927
|
n, kwds = _name2__(name_LatLon_and_kwds, name__=hartzell)
|
|
1168
928
|
try:
|
|
1169
929
|
D = _spherical_datum(earth, name__=hartzell)
|
|
1170
|
-
|
|
930
|
+
m = _MODS._triaxials_triaxial5
|
|
931
|
+
r, h, i = m._hartzell3(pov, los, D.ellipsoid._triaxial)
|
|
1171
932
|
|
|
1172
933
|
C = _MODS.cartesianBase.CartesianBase
|
|
1173
934
|
if kwds:
|
pygeodesy/fsums.py
CHANGED
|
@@ -62,7 +62,7 @@ from math import fabs, isinf, isnan, \
|
|
|
62
62
|
ceil as _ceil, floor as _floor # PYCHOK used! .ltp
|
|
63
63
|
|
|
64
64
|
__all__ = _ALL_LAZY.fsums
|
|
65
|
-
__version__ = '
|
|
65
|
+
__version__ = '26.01.16'
|
|
66
66
|
|
|
67
67
|
from pygeodesy.interns import (
|
|
68
68
|
_PLUS_ as _add_op_, # in .auxilats.auxAngle
|
|
@@ -1449,6 +1449,12 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1449
1449
|
override L{nonfinites<Fsum.nonfinites>} and
|
|
1450
1450
|
the L{nonfiniterrors} default (C{bool}).
|
|
1451
1451
|
'''
|
|
1452
|
+
f = self._fma(other1, other2, **nonfinites)
|
|
1453
|
+
return self._fset(f)
|
|
1454
|
+
|
|
1455
|
+
def _fma(self, other1, other2, **nonfinites): # in .elliptic
|
|
1456
|
+
'''(INTERNAL) Return C{self * B{other1} + B{other2}}.
|
|
1457
|
+
'''
|
|
1452
1458
|
op = typename(self.fma)
|
|
1453
1459
|
_fs = self._ps_other
|
|
1454
1460
|
try:
|
|
@@ -1459,7 +1465,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1459
1465
|
elif _residue(other1) or _residue(other2):
|
|
1460
1466
|
fs = _2split3s(_fs(op, other1))
|
|
1461
1467
|
fs = _2products(s, fs, *_fs(op, other2))
|
|
1462
|
-
f =
|
|
1468
|
+
f = Fsum(fs, name=op, **nonfinites)
|
|
1463
1469
|
else:
|
|
1464
1470
|
f = _fma(s, other1, other2)
|
|
1465
1471
|
f = _2finite(f, **self._isfine)
|
|
@@ -1469,7 +1475,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1469
1475
|
f = self._mul_reduce(s, other1) # INF, NAN, NINF
|
|
1470
1476
|
f += sum(_fs(op, other2))
|
|
1471
1477
|
f = self._nonfiniteX(X, op, f, **nonfinites)
|
|
1472
|
-
return
|
|
1478
|
+
return f
|
|
1473
1479
|
|
|
1474
1480
|
def fma_(self, *xys, **nonfinites):
|
|
1475
1481
|
'''Fused-multiply-accumulate C{for i in range(0, len(xys), B{2}):
|
pygeodesy/geod3solve.py
CHANGED
|
@@ -26,7 +26,7 @@ from pygeodesy.units import Degrees, Meter
|
|
|
26
26
|
# from pygeodesy.utily import sincos2d # from .karney
|
|
27
27
|
|
|
28
28
|
__all__ = _ALL_LAZY.geod3solve
|
|
29
|
-
__version__ = '
|
|
29
|
+
__version__ = '26.01.04'
|
|
30
30
|
|
|
31
31
|
_Triaxial3_WGS84 = Triaxial3s.WGS84_3r # a=6378172, b=6378102, c=6356752
|
|
32
32
|
|
|
@@ -48,16 +48,31 @@ class Geod3Solve8Tuple(_GTuple):
|
|
|
48
48
|
_Names_ = ('bet1', 'omg1', 'alp1', 'bet2', 'omg2', 'alp2', _s12_, _a12_)
|
|
49
49
|
_Units_ = ( Deg, Deg, Deg, Deg, Deg, Deg, Meter, Deg)
|
|
50
50
|
|
|
51
|
+
# @Property_RO
|
|
52
|
+
# def A12(self):
|
|
53
|
+
# '''Approximate arc C{A12} as C{Deg}.
|
|
54
|
+
# '''
|
|
55
|
+
# t = self
|
|
56
|
+
# d = t.s12 or _0_0
|
|
57
|
+
# if d:
|
|
58
|
+
# a = hypot(Deg(t.bet2 - t.bet1).degrees,
|
|
59
|
+
# Deg(t.omg2 - t.omg1).degrees)
|
|
60
|
+
# d = (-a) if d < 0 else a
|
|
61
|
+
# return Deg(d)
|
|
62
|
+
|
|
51
63
|
|
|
52
64
|
class _Geodesic3SolveBase(_Solve3Base):
|
|
53
65
|
'''(INTERNAL) Base class for L{Geodesic3Solve} and L{GeodesicLine3Solve}.
|
|
54
66
|
'''
|
|
67
|
+
_a12x = Geod3Solve8Tuple._Names_.index(_a12_) # last
|
|
55
68
|
_Error = Geodesic3Error
|
|
56
69
|
_Names_Direct = _Names_Distance = \
|
|
57
|
-
_Names_Inverse = Geod3Solve8Tuple._Names_[:
|
|
70
|
+
_Names_Inverse = Geod3Solve8Tuple._Names_[:_a12x] # 7 only, always
|
|
58
71
|
_triaxial3 = _Triaxial3_WGS84
|
|
59
72
|
_Xable_name = _Xables.Geod3Solve.__name__ # typename
|
|
60
73
|
_Xable_path = _Xables.Geod3Solve()
|
|
74
|
+
# assert _a12x == len(Geod3Solve8Tuple._Names_) - 1
|
|
75
|
+
del _a12x
|
|
61
76
|
|
|
62
77
|
@Property_RO
|
|
63
78
|
def a(self):
|
|
@@ -162,7 +177,7 @@ class Geodesic3Solve(_Geodesic3SolveBase):
|
|
|
162
177
|
'''
|
|
163
178
|
a = r.s12 or _0_0
|
|
164
179
|
if a:
|
|
165
|
-
t =
|
|
180
|
+
t = self.triaxial3
|
|
166
181
|
z = _toAzi(r.alp1) + _toAzi(r.alp2)
|
|
167
182
|
s, c = sincos2d(z * _0_5)
|
|
168
183
|
a *= hypot(_over(s, t.perimeter4ab), # azimuth!
|
pygeodesy/internals.py
CHANGED
|
@@ -6,8 +6,8 @@ u'''Mostly INTERNAL functions, except L{machine}, L{print_} and L{printf}.
|
|
|
6
6
|
# from pygeodesy.basics import isiterablen, ubstr # _MODS
|
|
7
7
|
# from pygeodesy.errors import _AttributeError, _error_init, _ImmutableError, _UnexpectedError, _xError2 # _MODS
|
|
8
8
|
from pygeodesy.interns import _BAR_, _COLON_, _DASH_, _DMAIN_, _DOT_, _ELLIPSIS_, _NL_, NN, \
|
|
9
|
-
_pygeodesy_, _PyPy__, _python_, _QUOTE1_, _QUOTE2_,
|
|
10
|
-
_SPACE_, _UNDER_
|
|
9
|
+
_NLATvar_, _pygeodesy_, _PyPy__, _python_, _QUOTE1_, _QUOTE2_, \
|
|
10
|
+
_s_, _sys, _SPACE_, _UNDER_
|
|
11
11
|
from pygeodesy.interns import _COMMA_, _Python_ # PYCHOK used!
|
|
12
12
|
# from pygeodesy.streprs import anstr, pairs, unstr # _MODS
|
|
13
13
|
|
|
@@ -459,6 +459,13 @@ def _popen2(cmd, stdin=None): # in .mgrs, .solveBase, .testMgrs
|
|
|
459
459
|
return _MODS.basics.ub2str(r).strip(), p.returncode
|
|
460
460
|
|
|
461
461
|
|
|
462
|
+
def _pregistry(registry):
|
|
463
|
+
'''(INTERNAL) Print all items of a C{registry}.
|
|
464
|
+
'''
|
|
465
|
+
t = [NN] + registry.toRepr(all=True, asorted=True).split(_NL_)
|
|
466
|
+
printf(_NLATvar_.join(i.strip(_COMMA_) for i in t))
|
|
467
|
+
|
|
468
|
+
|
|
462
469
|
def print_(*args, **nl_nt_prec_prefix__end_file_flush_sep__kwds): # PYCHOK no cover
|
|
463
470
|
'''Python 3+ C{print}-like formatting and printing.
|
|
464
471
|
|
|
@@ -709,7 +716,7 @@ def _versions(sep=_SPACE_):
|
|
|
709
716
|
|
|
710
717
|
|
|
711
718
|
__all__ = tuple(map(typename, (machine, print_, printf, typename)))
|
|
712
|
-
__version__ = '
|
|
719
|
+
__version__ = '26.01.13'
|
|
713
720
|
|
|
714
721
|
if __name__ == _DMAIN_:
|
|
715
722
|
|
pygeodesy/lazily.py
CHANGED
|
@@ -30,8 +30,8 @@ and line number.
|
|
|
30
30
|
from pygeodesy import internals as _internals, interns as _interns, \
|
|
31
31
|
_isfrozen # DON'T _lazy_import2
|
|
32
32
|
# from pygeodesy.errors import _error_init, _ImmutableError, _xkwds_item2 # _ALL_MODS
|
|
33
|
-
from pygeodesy.internals import _caller3, _envPYGEODESY, _headof, printf,
|
|
34
|
-
|
|
33
|
+
from pygeodesy.internals import _caller3, _envPYGEODESY, _headof, printf, _Property_RO, \
|
|
34
|
+
_tailof, typename, _versions # _getenv, _PYGEODESY_ENV, \
|
|
35
35
|
# _MODS_Base, _MODS.sys_version_info2
|
|
36
36
|
from pygeodesy.interns import _attribute_, _by_, _COLONSPACE_, _COMMASPACE_, _DALL_, \
|
|
37
37
|
_DMAIN_, _doesn_t_exist_, _DOT_, _EQUALSPACED_, _from_, \
|
|
@@ -234,7 +234,8 @@ _ALL_LAZY = _NamedEnum_RO(_name='_ALL_LAZY',
|
|
|
234
234
|
'a_f2b', 'a_f_2b', 'b_f2a', 'b_f_2a',
|
|
235
235
|
'e2f', 'e22f',
|
|
236
236
|
'f2e2', 'f2e22', 'f2e32', 'f_2f', 'f2f_', 'f2f2', 'f2n', 'n2e2', 'n2f', 'n2f_'),
|
|
237
|
-
elliptic=_a('Elliptic', 'EllipticError', 'Elliptic3Tuple'
|
|
237
|
+
elliptic=_a('Elliperim', 'Elliptic', 'EllipticError', 'Elliptic3Tuple',
|
|
238
|
+
'elliperim', 'elliperim_'),
|
|
238
239
|
epsg=_a('Epsg', 'EPSGError'),
|
|
239
240
|
errors=_a('AuxError', 'ClipError', 'CrossError', 'GeodesicError', 'IntersectionError',
|
|
240
241
|
'NumPyError', 'LenError', 'LimitError', 'MGRSError',
|
|
@@ -250,10 +251,10 @@ _ALL_LAZY = _NamedEnum_RO(_name='_ALL_LAZY',
|
|
|
250
251
|
'fpolynomial', 'fpowers', 'fprod', 'frandoms', 'frange', 'freduce', 'fremainder',
|
|
251
252
|
'hypot', 'hypot_', 'hypot1', 'hypot2', 'hypot2_',
|
|
252
253
|
'norm2', 'norm_', 'sqrt0', 'sqrt3', 'sqrt_a', 'zcrt', 'zqrt'),
|
|
253
|
-
formy=_a('
|
|
254
|
+
formy=_a('Radical2Tuple',
|
|
254
255
|
'angle2chord', 'antipode', 'antipode_', 'bearing', 'bearing_',
|
|
255
256
|
'chord2angle', 'compassAngle', 'cosineLaw', 'cosineLaw_',
|
|
256
|
-
'
|
|
257
|
+
'equirectangular', 'equirectangular4', 'euclidean', 'euclidean_',
|
|
257
258
|
'excessAbc_', 'excessCagnoli_', 'excessGirard_', 'excessLHuilier_',
|
|
258
259
|
'excessKarney', 'excessKarney_', 'excessQuad', 'excessQuad_',
|
|
259
260
|
'flatLocal', 'flatLocal_', 'flatPolar', 'flatPolar_',
|
|
@@ -517,10 +518,16 @@ class _ALL_MODS(_internals._MODS_Base):
|
|
|
517
518
|
if _headof(n) == _pygeodesy_:
|
|
518
519
|
yield n, m
|
|
519
520
|
|
|
521
|
+
@_Property_RO
|
|
522
|
+
def _triaxials_triaxial5(self):
|
|
523
|
+
'''(INTERNAL) Get module C{triaxial.triaxials}.
|
|
524
|
+
'''
|
|
525
|
+
return self.triaxials.triaxial5
|
|
526
|
+
|
|
520
527
|
_internals._MODS = _ALL_MODS = _ALL_MODS() # PYCHOK singleton
|
|
521
528
|
|
|
522
529
|
__all__ = _ALL_LAZY.lazily
|
|
523
|
-
__version__ = '
|
|
530
|
+
__version__ = '26.01.06'
|
|
524
531
|
|
|
525
532
|
|
|
526
533
|
def _ALL_OTHER(*objs):
|
pygeodesy/lcc.py
CHANGED
|
@@ -651,13 +651,9 @@ def toLcc(latlon, conic=Conics.WRF_Lb, height=None, Lcc=Lcc,
|
|
|
651
651
|
|
|
652
652
|
|
|
653
653
|
if __name__ == _DMAIN_:
|
|
654
|
-
|
|
655
|
-
from pygeodesy.
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
# __doc__ of this file, force all into registery
|
|
659
|
-
t = _NL_ + Conics.toRepr(all=True, asorted=True)
|
|
660
|
-
printf(_NLATvar_.join(t.split(_NL_)))
|
|
654
|
+
# __doc__ of this file, force all into registry
|
|
655
|
+
from pygeodesy.internals import _pregistry
|
|
656
|
+
_pregistry(Conics)
|
|
661
657
|
|
|
662
658
|
# **) MIT License
|
|
663
659
|
#
|
pygeodesy/named.py
CHANGED
|
@@ -35,7 +35,7 @@ from pygeodesy.streprs import attrs, Fmt, lrstrip, pairs, reprs, unstr
|
|
|
35
35
|
# from pygeodesy.units import _toUnit # _MODS
|
|
36
36
|
|
|
37
37
|
__all__ = _ALL_LAZY.named
|
|
38
|
-
__version__ = '
|
|
38
|
+
__version__ = '26.01.14'
|
|
39
39
|
|
|
40
40
|
_COMMANL_ = _COMMA_ + _NL_
|
|
41
41
|
_COMMASPACEDOT_ = _COMMASPACE_ + _DOT_
|
|
@@ -658,18 +658,24 @@ class _NamedEnum(_NamedDict):
|
|
|
658
658
|
'''(INTERNAL) Check attribute name against given, registered name.
|
|
659
659
|
'''
|
|
660
660
|
pypy = _isPyPy()
|
|
661
|
-
_isa = isinstance
|
|
662
661
|
for n, v in kwds.items():
|
|
663
|
-
if
|
|
662
|
+
if isinstance(v, _LazyNamedEnumItem): # property
|
|
664
663
|
assert (n == v.name) if pypy else (n is v.name)
|
|
665
664
|
# assert not hasattr(self.__class__, n)
|
|
666
665
|
setattr(self.__class__, n, v)
|
|
667
|
-
elif
|
|
666
|
+
elif isinstance(v, self._item_Classes): # PYCHOK no cover
|
|
668
667
|
assert self[n] is v and getattr(self, n) \
|
|
669
668
|
and self.find(v) == n
|
|
670
669
|
else:
|
|
671
670
|
raise _TypeError(v, name=n)
|
|
672
671
|
|
|
672
|
+
def _asserts(self): # in .triaxials.triaxial3
|
|
673
|
+
'''(INTERNAL) Yield all asserted items.
|
|
674
|
+
'''
|
|
675
|
+
for n, p in tuple(type(self).__dict__.items()):
|
|
676
|
+
if isinstance(p, _LazyNamedEnumItem):
|
|
677
|
+
yield n, p
|
|
678
|
+
|
|
673
679
|
def find(self, item, dflt=None, all=False):
|
|
674
680
|
'''Find a registered item.
|
|
675
681
|
|
|
@@ -707,10 +713,8 @@ class _NamedEnum(_NamedDict):
|
|
|
707
713
|
case-insensitive} order (C{bool}).
|
|
708
714
|
'''
|
|
709
715
|
if all: # instantiate any remaining L{_LazyNamedEnumItem}
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
if _isa(p, _LazyNamedEnumItem):
|
|
713
|
-
_ = getattr(self, n)
|
|
716
|
+
for n, _ in self._asserts():
|
|
717
|
+
_ = getattr(self, n)
|
|
714
718
|
return itemsorted(self) if asorted else ADict.items(self)
|
|
715
719
|
|
|
716
720
|
def keys(self, **all_asorted):
|
|
@@ -857,7 +861,7 @@ def _lazyNamedEnumItem(name, *args, **kwds):
|
|
|
857
861
|
|
|
858
862
|
|
|
859
863
|
class _NamedEnumItem(_NamedBase):
|
|
860
|
-
'''(INTERNAL) Base class for items in a C{_NamedEnum}
|
|
864
|
+
'''(INTERNAL) Base class for items in a C{_NamedEnum} registry.
|
|
861
865
|
'''
|
|
862
866
|
_enum = None
|
|
863
867
|
|
pygeodesy/trf.py
CHANGED
|
@@ -1754,7 +1754,7 @@ if __name__ == _DMAIN_:
|
|
|
1754
1754
|
t = '%d,%3d,%3d' % t
|
|
1755
1755
|
printf('# %s = %s = %s %s', f, e, t, x)
|
|
1756
1756
|
|
|
1757
|
-
# __doc__ of this file, force all into
|
|
1757
|
+
# __doc__ of this file, force all into registry
|
|
1758
1758
|
def _RFs():
|
|
1759
1759
|
yield NN
|
|
1760
1760
|
for t in RefFrames.toRepr(all=True).split(_NL_):
|