pygeodesy 24.10.24__py2.py3-none-any.whl → 24.11.11__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {PyGeodesy-24.10.24.dist-info → PyGeodesy-24.11.11.dist-info}/METADATA +4 -4
- {PyGeodesy-24.10.24.dist-info → PyGeodesy-24.11.11.dist-info}/RECORD +54 -54
- {PyGeodesy-24.10.24.dist-info → PyGeodesy-24.11.11.dist-info}/WHEEL +1 -1
- pygeodesy/__init__.py +2 -2
- pygeodesy/azimuthal.py +51 -61
- pygeodesy/basics.py +34 -33
- pygeodesy/booleans.py +36 -36
- pygeodesy/cartesianBase.py +5 -5
- pygeodesy/constants.py +4 -4
- pygeodesy/css.py +7 -8
- pygeodesy/deprecated/__init__.py +1 -1
- pygeodesy/deprecated/classes.py +9 -9
- pygeodesy/deprecated/functions.py +6 -6
- pygeodesy/ecef.py +11 -14
- pygeodesy/ellipsoidalBase.py +105 -120
- pygeodesy/ellipsoidalBaseDI.py +114 -118
- pygeodesy/ellipsoidalExact.py +35 -37
- pygeodesy/ellipsoids.py +3 -3
- pygeodesy/errors.py +24 -24
- pygeodesy/etm.py +80 -72
- pygeodesy/fmath.py +39 -37
- pygeodesy/formy.py +3 -2
- pygeodesy/fsums.py +51 -40
- pygeodesy/geodesicw.py +15 -14
- pygeodesy/geodesicx/__init__.py +2 -2
- pygeodesy/geodsolve.py +7 -16
- pygeodesy/geoids.py +5 -5
- pygeodesy/heights.py +2 -2
- pygeodesy/internals.py +63 -79
- pygeodesy/karney.py +2 -2
- pygeodesy/ktm.py +11 -13
- pygeodesy/latlonBase.py +6 -6
- pygeodesy/lazily.py +5 -5
- pygeodesy/lcc.py +4 -4
- pygeodesy/ltp.py +10 -10
- pygeodesy/ltpTuples.py +74 -75
- pygeodesy/mgrs.py +9 -10
- pygeodesy/named.py +4 -0
- pygeodesy/osgr.py +9 -12
- pygeodesy/props.py +2 -2
- pygeodesy/resections.py +9 -10
- pygeodesy/rhumb/__init__.py +1 -1
- pygeodesy/rhumb/solve.py +3 -3
- pygeodesy/simplify.py +5 -5
- pygeodesy/sphericalNvector.py +80 -123
- pygeodesy/sphericalTrigonometry.py +60 -66
- pygeodesy/units.py +2 -2
- pygeodesy/utm.py +6 -6
- pygeodesy/vector2d.py +13 -13
- pygeodesy/vector3d.py +19 -21
- pygeodesy/vector3dBase.py +18 -15
- pygeodesy/webmercator.py +4 -4
- pygeodesy/wgrs.py +4 -4
- {PyGeodesy-24.10.24.dist-info → PyGeodesy-24.11.11.dist-info}/top_level.txt +0 -0
pygeodesy/fmath.py
CHANGED
|
@@ -12,9 +12,8 @@ from pygeodesy.constants import EPS0, EPS02, EPS1, NAN, PI, PI_2, PI_4, \
|
|
|
12
12
|
_0_0, _0_125, _1_6th, _0_25, _1_3rd, _0_5, _1_0, \
|
|
13
13
|
_1_5, _copysign_0_0, isfinite, remainder
|
|
14
14
|
from pygeodesy.errors import _IsnotError, LenError, _TypeError, _ValueError, \
|
|
15
|
-
_xError, _xkwds_pop2, _xsError
|
|
16
|
-
from pygeodesy.fsums import _2float, Fsum, fsum, _isFsum_2Tuple,
|
|
17
|
-
Fmt, unstr
|
|
15
|
+
_xError, _xkwds, _xkwds_pop2, _xsError
|
|
16
|
+
from pygeodesy.fsums import _2float, Fsum, fsum, _isFsum_2Tuple, Fmt, unstr
|
|
18
17
|
from pygeodesy.interns import MISSING, _negative_, _not_scalar_
|
|
19
18
|
from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS
|
|
20
19
|
# from pygeodesy.streprs import Fmt, unstr # from .fsums
|
|
@@ -24,7 +23,7 @@ from math import fabs, sqrt # pow
|
|
|
24
23
|
import operator as _operator # in .datums, .trf, .utm
|
|
25
24
|
|
|
26
25
|
__all__ = _ALL_LAZY.fmath
|
|
27
|
-
__version__ = '24.
|
|
26
|
+
__version__ = '24.11.08'
|
|
28
27
|
|
|
29
28
|
# sqrt(2) - 1 <https://WikiPedia.org/wiki/Square_root_of_2>
|
|
30
29
|
_0_4142 = 0.41421356237309504880 # ... ~ 3730904090310553 / 9007199254740992
|
|
@@ -62,14 +61,7 @@ class Fdot(Fsum):
|
|
|
62
61
|
n = len(b)
|
|
63
62
|
if len(a) != n: # PYCHOK no cover
|
|
64
63
|
raise LenError(Fdot, a=len(a), b=n)
|
|
65
|
-
self.
|
|
66
|
-
|
|
67
|
-
def _faddot(self, n, xs, ys, **kwds):
|
|
68
|
-
if n > 0:
|
|
69
|
-
_f = Fsum(**kwds)
|
|
70
|
-
r = (_f(x).fmul(y) for x, y in zip(xs, ys)) # PYCHOK attr?
|
|
71
|
-
self.fadd(_1primed(r) if n < 4 else r) # PYCHOK attr?
|
|
72
|
-
return self
|
|
64
|
+
self._facc_dot(n, a, b, **kwds)
|
|
73
65
|
|
|
74
66
|
|
|
75
67
|
class Fhorner(Fsum):
|
|
@@ -129,7 +121,7 @@ class Fhypot(Fsum):
|
|
|
129
121
|
raise self._ErrorXs(X, xs, root=r)
|
|
130
122
|
|
|
131
123
|
|
|
132
|
-
class Fpolynomial(
|
|
124
|
+
class Fpolynomial(Fsum):
|
|
133
125
|
'''Precision polynomial evaluation.
|
|
134
126
|
'''
|
|
135
127
|
def __init__(self, x, *cs, **name_f2product_nonfinites_RESIDUAL):
|
|
@@ -150,12 +142,10 @@ class Fpolynomial(Fdot):
|
|
|
150
142
|
|
|
151
143
|
@see: Class L{Fhorner}, function L{fpolynomial} and method L{Fsum.fadd}.
|
|
152
144
|
'''
|
|
153
|
-
Fsum.__init__(self,
|
|
145
|
+
Fsum.__init__(self, **name_f2product_nonfinites_RESIDUAL)
|
|
154
146
|
n = len(cs) - 1
|
|
155
|
-
if n
|
|
156
|
-
|
|
157
|
-
elif n < 0:
|
|
158
|
-
self(_0_0)
|
|
147
|
+
self(_0_0 if n < 0 else cs[0])
|
|
148
|
+
self._facc_dot(n, cs[1:], _powers(x, n), **name_f2product_nonfinites_RESIDUAL)
|
|
159
149
|
|
|
160
150
|
|
|
161
151
|
class Fpowers(Fsum):
|
|
@@ -431,35 +421,48 @@ def favg(a, b, f=_0_5, nonfinites=True):
|
|
|
431
421
|
return float(F)
|
|
432
422
|
|
|
433
423
|
|
|
434
|
-
def fdot(
|
|
435
|
-
'''Return the precision dot product M{sum(
|
|
424
|
+
def fdot(xs, *ys, **start_f2product_nonfinites):
|
|
425
|
+
'''Return the precision dot product M{sum(xs[i] * ys[i] for i in range(len(xs)))}.
|
|
436
426
|
|
|
437
|
-
@arg
|
|
438
|
-
@arg
|
|
427
|
+
@arg xs: Iterable of values (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
|
|
428
|
+
@arg ys: Other values (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}), all
|
|
439
429
|
positional.
|
|
440
|
-
@kwarg
|
|
441
|
-
|
|
430
|
+
@kwarg start_f2product_nonfinites: Optional bias C{B{start}=0} (C{scalar}, an
|
|
431
|
+
L{Fsum} or L{Fsum2Tuple}) and settings C{B{f2product}=None} (C{bool})
|
|
432
|
+
and C{B{nonfinites=True}} (C{bool}), see class L{Fsum<Fsum.__init__>}.
|
|
442
433
|
|
|
443
434
|
@return: Dot product (C{float}).
|
|
444
435
|
|
|
445
|
-
@raise LenError: Unequal C{len(B{
|
|
436
|
+
@raise LenError: Unequal C{len(B{xs})} and C{len(B{ys})}.
|
|
446
437
|
|
|
447
438
|
@see: Class L{Fdot}, U{Algorithm 5.10 B{DotK}
|
|
448
439
|
<https://www.TUHH.De/ti3/paper/rump/OgRuOi05.pdf>} and function
|
|
449
440
|
C{math.sumprod} in Python 3.12 and later.
|
|
450
441
|
'''
|
|
451
|
-
D = Fdot(
|
|
442
|
+
D = Fdot(xs, *ys, **_xkwds(start_f2product_nonfinites, nonfinites=True))
|
|
452
443
|
return float(D)
|
|
453
444
|
|
|
454
445
|
|
|
455
|
-
def
|
|
456
|
-
'''Return the precision dot product M{
|
|
457
|
-
|
|
446
|
+
def fdot_(*xys, **start_f2product_nonfinites):
|
|
447
|
+
'''Return the (precision) dot product M{sum(xys[i] * xys[i+1] for i in range(0, len(xys), B{2}))}.
|
|
448
|
+
|
|
449
|
+
@arg xys: Pairwise values (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}), all positional.
|
|
450
|
+
|
|
451
|
+
@see: Function L{fdot} for further details.
|
|
452
|
+
|
|
453
|
+
@return: Dot product (C{float}).
|
|
454
|
+
'''
|
|
455
|
+
return fdot(xys[0::2], *xys[1::2], **start_f2product_nonfinites)
|
|
456
|
+
|
|
457
|
+
|
|
458
|
+
def fdot3(xs, ys, zs, **start_f2product_nonfinites):
|
|
459
|
+
'''Return the (precision) dot product M{start + sum(xs[i] * ys[i] * zs[i] for i in range(len(xs)))}.
|
|
458
460
|
|
|
459
461
|
@arg xs: Iterable (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
|
|
460
462
|
@arg ys: Iterable (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
|
|
461
463
|
@arg zs: Iterable (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
|
|
462
|
-
|
|
464
|
+
|
|
465
|
+
@see: Function L{fdot} for further details.
|
|
463
466
|
|
|
464
467
|
@return: Dot product (C{float}).
|
|
465
468
|
|
|
@@ -469,17 +472,16 @@ def fdot3(xs, ys, zs, start=0):
|
|
|
469
472
|
if not n == len(ys) == len(zs):
|
|
470
473
|
raise LenError(fdot3, xs=n, ys=len(ys), zs=len(zs))
|
|
471
474
|
|
|
472
|
-
D = Fdot((), nonfinites=True
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
D = D.
|
|
475
|
+
D = Fdot((), **_xkwds(start_f2product_nonfinites, nonfinites=True))
|
|
476
|
+
kwds = dict(f2product=D.f2product(), nonfinites=D.nonfinites())
|
|
477
|
+
_f = Fsum(**kwds)
|
|
478
|
+
D = D._facc(_f(x).f2mul_(y, z, **kwds) for x, y, z in zip(xs, ys, zs))
|
|
476
479
|
return float(D)
|
|
477
480
|
|
|
478
481
|
|
|
479
482
|
def fhorner(x, *cs, **incx):
|
|
480
|
-
'''Horner form evaluation of polynomial M{sum(cs[i] * x**i for
|
|
481
|
-
|
|
482
|
-
where C{n = len(cs) - 1}.
|
|
483
|
+
'''Horner form evaluation of polynomial M{sum(cs[i] * x**i for i=0..n)} as
|
|
484
|
+
in- or decreasing exponent M{sum(... i=n..0)}, where C{n = len(cs) - 1}.
|
|
483
485
|
|
|
484
486
|
@return: Horner sum (C{float}).
|
|
485
487
|
|
pygeodesy/formy.py
CHANGED
|
@@ -1156,7 +1156,7 @@ class _idllmn6(object): # see also .geodesicw._wargs, .latlonBase._toCartesian3
|
|
|
1156
1156
|
m = _MODS.ellipsoidalKarney
|
|
1157
1157
|
except ImportError:
|
|
1158
1158
|
m = _MODS.ellipsoidalExact
|
|
1159
|
-
_i = m._intersections2 if s else m._intersection3 #
|
|
1159
|
+
_i = m._intersections2 if s else m._intersection3 # ellipsoidalBaseDI
|
|
1160
1160
|
else:
|
|
1161
1161
|
raise _TypeError(datum=datum)
|
|
1162
1162
|
yield _i, d, lat2, lon2, m, n
|
|
@@ -1231,7 +1231,8 @@ def intersection2(lat1, lon1, bearing1,
|
|
|
1231
1231
|
|
|
1232
1232
|
else:
|
|
1233
1233
|
t = _i(m.LatLon(lat1, lon1, datum=d), b1,
|
|
1234
|
-
m.LatLon(lat2, lon2, datum=d), b2,
|
|
1234
|
+
m.LatLon(lat2, lon2, datum=d), b2,
|
|
1235
|
+
LatLon=None, height=0, wrap=False)
|
|
1235
1236
|
if isinstance(t, Intersection3Tuple): # ellipsoidal
|
|
1236
1237
|
t, _, _ = t
|
|
1237
1238
|
t = LatLon2Tuple(t.lat, t.lon, name=n)
|
pygeodesy/fsums.py
CHANGED
|
@@ -64,7 +64,7 @@ from math import fabs, isinf, isnan, \
|
|
|
64
64
|
ceil as _ceil, floor as _floor # PYCHOK used! .ltp
|
|
65
65
|
|
|
66
66
|
__all__ = _ALL_LAZY.fsums
|
|
67
|
-
__version__ = '24.
|
|
67
|
+
__version__ = '24.11.11'
|
|
68
68
|
|
|
69
69
|
from pygeodesy.interns import (
|
|
70
70
|
_PLUS_ as _add_op_, # in .auxilats.auxAngle
|
|
@@ -163,9 +163,11 @@ except ImportError: # PYCHOK DSPACE! Python 3.12-
|
|
|
163
163
|
|
|
164
164
|
_2n_d = None # redef
|
|
165
165
|
|
|
166
|
-
def _fmaX(r, *a_b_c): #
|
|
167
|
-
#
|
|
168
|
-
#
|
|
166
|
+
def _fmaX(r, *a_b_c): # PYCHOK no cover
|
|
167
|
+
# handle non-finite as Python 3.13+ C-function U{math_fma_impl<https://
|
|
168
|
+
# GitHub.com/python/cpython/blob/main/Modules/mathmodule.c#L2305>}:
|
|
169
|
+
# raise a ValueError for a NAN result from non-NAN C{a_b_c}s or an
|
|
170
|
+
# OverflowError for a non-NAN non-finite from all finite C{a_b_c}s.
|
|
169
171
|
if isnan(r):
|
|
170
172
|
def _x(x):
|
|
171
173
|
return not isnan(x)
|
|
@@ -212,11 +214,11 @@ except ImportError: # PYCHOK DSPACE! Python 3.12-
|
|
|
212
214
|
return map(_2split3, xs)
|
|
213
215
|
|
|
214
216
|
|
|
215
|
-
def f2product(
|
|
217
|
+
def f2product(two=None):
|
|
216
218
|
'''Turn accurate I{TwoProduct} multiplication on or off.
|
|
217
219
|
|
|
218
|
-
@
|
|
219
|
-
|
|
220
|
+
@kwarg two: If C{True}, turn I{TwoProduct} on, if C{False} off or
|
|
221
|
+
if C{None} or omitted, keep the current setting.
|
|
220
222
|
|
|
221
223
|
@return: The previous setting (C{bool}).
|
|
222
224
|
|
|
@@ -226,8 +228,8 @@ def f2product(*two):
|
|
|
226
228
|
equivalent, slower implementation when not available.
|
|
227
229
|
'''
|
|
228
230
|
t = Fsum._f2product
|
|
229
|
-
if two
|
|
230
|
-
Fsum._f2product = bool(two
|
|
231
|
+
if two is not None:
|
|
232
|
+
Fsum._f2product = bool(two)
|
|
231
233
|
return t
|
|
232
234
|
|
|
233
235
|
|
|
@@ -318,14 +320,14 @@ def _NonfiniteError(x):
|
|
|
318
320
|
_ValueError if isnan(x) else _AssertionError)
|
|
319
321
|
|
|
320
322
|
|
|
321
|
-
def nonfiniterrors(
|
|
323
|
+
def nonfiniterrors(raiser=None):
|
|
322
324
|
'''Throw C{OverflowError} and C{ValueError} exceptions for or
|
|
323
325
|
handle I{non-finite} C{float}s as C{inf}, C{INF}, C{NINF},
|
|
324
326
|
C{nan} and C{NAN} in summations and multiplications.
|
|
325
327
|
|
|
326
|
-
@
|
|
327
|
-
|
|
328
|
-
|
|
328
|
+
@kwarg raiser: If C{True}, throw exceptions, if C{False} handle
|
|
329
|
+
I{non-finites} or if C{None} or omitted, leave
|
|
330
|
+
the setting unchanged.
|
|
329
331
|
|
|
330
332
|
@return: Previous setting (C{bool}).
|
|
331
333
|
|
|
@@ -333,8 +335,8 @@ def nonfiniterrors(*raiser):
|
|
|
333
335
|
C{nan} and C{NAN} a C{ValueError}.
|
|
334
336
|
'''
|
|
335
337
|
d = Fsum._isfine
|
|
336
|
-
if raiser
|
|
337
|
-
Fsum._isfine = {} if bool(raiser
|
|
338
|
+
if raiser is not None:
|
|
339
|
+
Fsum._isfine = {} if bool(raiser) else Fsum._nonfinites_isfine_kwds[True]
|
|
338
340
|
return (False if d is Fsum._nonfinites_isfine_kwds[True] else
|
|
339
341
|
_xkwds_get1(d, _isfine=_isfinite) is _isfinite) if d else True
|
|
340
342
|
|
|
@@ -645,10 +647,6 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
645
647
|
f = self._copy_2(self.__floordiv__)
|
|
646
648
|
return f._floordiv(other, _floordiv_op_)
|
|
647
649
|
|
|
648
|
-
def __format__(self, *other): # PYCHOK no cover
|
|
649
|
-
'''Not implemented.'''
|
|
650
|
-
return _NotImplemented(self, *other)
|
|
651
|
-
|
|
652
650
|
def __ge__(self, other):
|
|
653
651
|
'''Return C{(B{self} >= B{other})}, see C{__eq__}.
|
|
654
652
|
'''
|
|
@@ -1171,6 +1169,14 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1171
1169
|
return self._fadd(xs[0], **up) if len(xs) == 1 else \
|
|
1172
1170
|
self._facc(xs, **up) # origin=1?
|
|
1173
1171
|
|
|
1172
|
+
def _facc_dot(self, n, xs, ys, **kwds): # in .fmath
|
|
1173
|
+
'''(INTERNAL) Accumulate C{fdot(B{xs}, *B{ys})}.
|
|
1174
|
+
'''
|
|
1175
|
+
if n > 0:
|
|
1176
|
+
_f = Fsum(**kwds)
|
|
1177
|
+
self._facc(_f(x).fmul(y) for x, y in zip(xs, ys)) # PYCHOK attr?
|
|
1178
|
+
return self
|
|
1179
|
+
|
|
1174
1180
|
def _facc_neg(self, xs, **up_origin):
|
|
1175
1181
|
'''(INTERNAL) Accumulate more C{xs}, negated.
|
|
1176
1182
|
'''
|
|
@@ -1462,7 +1468,7 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1462
1468
|
try:
|
|
1463
1469
|
s, r = self._fprs2
|
|
1464
1470
|
if r:
|
|
1465
|
-
f = self._f2mul(self.fma, other1, **nonfinites)
|
|
1471
|
+
f = self._f2mul(self.fma, (other1,), **nonfinites)
|
|
1466
1472
|
f += other2
|
|
1467
1473
|
elif _residue(other1) or _residue(other2):
|
|
1468
1474
|
fs = _2split3s(_fs(op, other1))
|
|
@@ -1501,36 +1507,41 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
1501
1507
|
@deprecated_method
|
|
1502
1508
|
def f2mul(self, *others, **raiser):
|
|
1503
1509
|
'''DEPRECATED on 2024.09.13, use method L{f2mul_<Fsum.f2mul_>}.'''
|
|
1504
|
-
return self._fset(self.f2mul_(
|
|
1510
|
+
return self._fset(self.f2mul_(others, **raiser))
|
|
1505
1511
|
|
|
1506
|
-
def f2mul_(self, *others, **
|
|
1512
|
+
def f2mul_(self, *others, **f2product_nonfinites): # in .fmath.f2mul
|
|
1507
1513
|
'''Return C{B{self} * B{other} * B{other} ...} for all B{C{others}} using cascaded,
|
|
1508
|
-
accurate multiplication like with L{f2product<Fsum.f2product>}
|
|
1514
|
+
accurate multiplication like with L{f2product<Fsum.f2product>}C{(B{True})}.
|
|
1509
1515
|
|
|
1510
1516
|
@arg others: Multipliers (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}), all
|
|
1511
1517
|
positional.
|
|
1512
|
-
@kwarg
|
|
1513
|
-
|
|
1514
|
-
|
|
1518
|
+
@kwarg f2product_nonfinites: Use C{B{f2product=False}} to override the default
|
|
1519
|
+
C{True} and C{B{nonfinites}=True} or C{False}, to override
|
|
1520
|
+
settings L{nonfinites<Fsum.nonfinites>} and L{nonfiniterrors}.
|
|
1515
1521
|
|
|
1516
1522
|
@return: The cascaded I{TwoProduct} (L{Fsum} or C{float}).
|
|
1517
1523
|
|
|
1518
1524
|
@see: U{Equations 2.3<https://www.TUHH.De/ti3/paper/rump/OzOgRuOi06.pdf>}
|
|
1519
1525
|
'''
|
|
1520
|
-
return self._f2mul(self.f2mul_,
|
|
1526
|
+
return self._f2mul(self.f2mul_, others, **f2product_nonfinites)
|
|
1521
1527
|
|
|
1522
|
-
def _f2mul(self, where,
|
|
1528
|
+
def _f2mul(self, where, others, f2product=True, **nonfinites_raiser):
|
|
1523
1529
|
'''(INTERNAL) See methods C{fma} and C{f2mul_}.
|
|
1524
1530
|
'''
|
|
1525
|
-
f
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1531
|
+
f = _Psum(self._ps, f2product=f2product, name=where.__name__)
|
|
1532
|
+
if others and f:
|
|
1533
|
+
if f.f2product():
|
|
1534
|
+
def _pfs(f, ps):
|
|
1535
|
+
return _2products(f, _2split3s(ps))
|
|
1536
|
+
else:
|
|
1537
|
+
def _pfs(f, ps): # PYCHOK redef
|
|
1538
|
+
return (f * p for p in ps)
|
|
1539
|
+
|
|
1540
|
+
op, ps = where.__name__, f._ps
|
|
1541
|
+
try: # as if self.f2product(True)
|
|
1530
1542
|
for other in others: # to pinpoint errors
|
|
1531
1543
|
for p in self._ps_other(op, other):
|
|
1532
|
-
|
|
1533
|
-
ps[:] = f._ps_acc([], pfs, up=False)
|
|
1544
|
+
ps[:] = f._ps_acc([], _pfs(p, ps), update=False)
|
|
1534
1545
|
f._update()
|
|
1535
1546
|
except TypeError as X:
|
|
1536
1547
|
raise self._ErrorX(X, op, other)
|
|
@@ -2309,11 +2320,11 @@ class Fsum(_Named): # sync __methods__ with .vector3dBase.Vector3dBase, .fstats
|
|
|
2309
2320
|
return (p * f for f in fs)
|
|
2310
2321
|
|
|
2311
2322
|
for p in ps:
|
|
2312
|
-
for
|
|
2313
|
-
yield
|
|
2323
|
+
for x in _pfs(p, fs):
|
|
2324
|
+
yield x if _isfine(x) else _nfError(x)
|
|
2314
2325
|
|
|
2315
|
-
|
|
2316
|
-
f = _Psum(self._ps_acc([],
|
|
2326
|
+
xs = _psfs(self._ps, factors, **self._isfine)
|
|
2327
|
+
f = _Psum(self._ps_acc([], xs, up=False), name=op)
|
|
2317
2328
|
return f
|
|
2318
2329
|
|
|
2319
2330
|
@property_RO
|
|
@@ -2784,7 +2795,7 @@ def _xs(xs, _X=_X_ps, _x=float, _isfine=_isfinite, # defaults for Fsum._facc
|
|
|
2784
2795
|
i, x = 0, xs
|
|
2785
2796
|
try:
|
|
2786
2797
|
for i, x in enumerate(_xiterable(xs)):
|
|
2787
|
-
if
|
|
2798
|
+
if _isFsum_2Tuple(x):
|
|
2788
2799
|
for p in _X(x):
|
|
2789
2800
|
yield p if _isfine(p) else _nfError(p)
|
|
2790
2801
|
else:
|
pygeodesy/geodesicw.py
CHANGED
|
@@ -39,7 +39,7 @@ from contextlib import contextmanager
|
|
|
39
39
|
# from math import fabs # from .utily
|
|
40
40
|
|
|
41
41
|
__all__ = _ALL_LAZY.geodesicw
|
|
42
|
-
__version__ = '24.
|
|
42
|
+
__version__ = '24.11.02'
|
|
43
43
|
|
|
44
44
|
_plumb_ = 'plumb'
|
|
45
45
|
_TRIPS = 65
|
|
@@ -94,14 +94,14 @@ class _gWrapped(_kWrapped):
|
|
|
94
94
|
if name:
|
|
95
95
|
self._name, _ = _name2__(name, _or_nameof=E)
|
|
96
96
|
|
|
97
|
-
def ArcDirect(self, lat1, lon1, azi1, a12, outmask=Caps._STD):
|
|
97
|
+
def ArcDirect(self, lat1, lon1, azi1, a12, outmask=Caps._STD): # PYCHOK no cover
|
|
98
98
|
'''Return the C{_Geodesic.ArcDirect} result as L{GDict}.
|
|
99
99
|
'''
|
|
100
100
|
with _wargs(self, lat1, lon1, azi1, a12, outmask) as args:
|
|
101
101
|
d = _Geodesic.ArcDirect(self, *args)
|
|
102
102
|
return GDict(d)
|
|
103
103
|
|
|
104
|
-
def ArcDirectLine(self, lat1, lon1, azi1, a12, caps=Caps._STD_LINE, **name):
|
|
104
|
+
def ArcDirectLine(self, lat1, lon1, azi1, a12, caps=Caps._STD_LINE, **name): # PYCHOK no cover
|
|
105
105
|
'''Return the C{_Geodesic.ArcDirectLine} as I{wrapped} C{GeodesicLine}.
|
|
106
106
|
'''
|
|
107
107
|
return self._GenDirectLine(lat1, lon1, azi1, True, a12, caps, **name)
|
|
@@ -445,7 +445,7 @@ _wrapped = _gWrapped() # PYCHOK singleton, .ellipsoids, .test/base.py
|
|
|
445
445
|
|
|
446
446
|
class Geodesic(_gWrapped): # overwritten by 1st instance
|
|
447
447
|
'''I{Wrapper} around I{Karney}'s class U{geographiclib.geodesic.Geodesic
|
|
448
|
-
<https://
|
|
448
|
+
<https://GeographicLib.SourceForge.io/Python/doc/code.html>}.
|
|
449
449
|
'''
|
|
450
450
|
def __new__(unused, a_ellipsoid=_EWGS84, f=None, **name):
|
|
451
451
|
'''Return a I{wrapped} C{geodesic.Geodesic} instance from I{Karney}'s
|
|
@@ -465,7 +465,7 @@ class Geodesic(_gWrapped): # overwritten by 1st instance
|
|
|
465
465
|
|
|
466
466
|
class GeodesicLine(_gWrapped): # overwritten by 1st instance
|
|
467
467
|
'''I{Wrapper} around I{Karney}'s class U{geographiclib.geodesicline.GeodesicLine
|
|
468
|
-
<https://
|
|
468
|
+
<https://GeographicLib.SourceForge.io/Python/doc/code.html>}.
|
|
469
469
|
'''
|
|
470
470
|
def __new__(unused, geodesic, lat1, lon1, azi1, caps=Caps._STD_LINE, **name):
|
|
471
471
|
'''Return a I{wrapped} C{geodesicline.GeodesicLine} instance from I{Karney}'s
|
|
@@ -519,13 +519,12 @@ def _Intersecant2(gl, lat0, lon0, radius, tol=_TOL, form=F_D): # MCCABE in LatL
|
|
|
519
519
|
n = _DUNDER_nameof(_Intersecant2)[1:]
|
|
520
520
|
_P = gl.Position
|
|
521
521
|
_I = gl.geodesic.Inverse
|
|
522
|
-
_a = fabs
|
|
523
522
|
|
|
524
523
|
def _R3(s):
|
|
525
524
|
# radius, intersection, etc. at distance C{s}
|
|
526
525
|
P = _P(s)
|
|
527
526
|
d = _I(lat0, lon0, P.lat2, P.lon2)
|
|
528
|
-
return
|
|
527
|
+
return fabs(d.s12), P, d
|
|
529
528
|
|
|
530
529
|
def _bisect2(s, c, Rc, r, tol, _R3):
|
|
531
530
|
_s = Fsum(c).fsumf_
|
|
@@ -536,18 +535,20 @@ def _Intersecant2(gl, lat0, lon0, radius, tol=_TOL, form=F_D): # MCCABE in LatL
|
|
|
536
535
|
break
|
|
537
536
|
else: # b >>> s and c >>> s
|
|
538
537
|
raise ValueError(Fmt.no_convergence(b, s))
|
|
539
|
-
|
|
538
|
+
# Rb > r > Rc
|
|
540
539
|
for i in range(_TRIPS): # 47-48
|
|
541
|
-
s = (b + c) *
|
|
540
|
+
s = (b + c) * _0_5
|
|
542
541
|
R, P, d = _R3(s)
|
|
543
542
|
if Rb > R > r:
|
|
544
543
|
b, Rb = s, R
|
|
545
544
|
elif Rc < R < r:
|
|
546
545
|
c, Rc = s, R
|
|
547
|
-
|
|
548
|
-
|
|
546
|
+
# else:
|
|
547
|
+
# break
|
|
548
|
+
t = fabs(b - c)
|
|
549
|
+
if t < tol: # or fabs(R - r) < tol:
|
|
549
550
|
break
|
|
550
|
-
else: # t = min(t,
|
|
551
|
+
else: # t = min(t, fabs(R - r))
|
|
551
552
|
raise ValueError(Fmt.no_convergence(t, tol))
|
|
552
553
|
i += C.iteration # combine iterations
|
|
553
554
|
P.set_(lat0=lat0, lon0=lon0, azi0=d.azi1, iteration=i,
|
|
@@ -558,13 +559,13 @@ def _Intersecant2(gl, lat0, lon0, radius, tol=_TOL, form=F_D): # MCCABE in LatL
|
|
|
558
559
|
# one the plumb, pseudo-rhumb line to the other
|
|
559
560
|
C = _PlumbTo(gl, lat0, lon0, tol=tol)
|
|
560
561
|
try:
|
|
561
|
-
a =
|
|
562
|
+
a = fabs(C.s02) # distance between centers
|
|
562
563
|
if a < r:
|
|
563
564
|
c = C.s12 # distance along pseudo-rhumb line
|
|
564
565
|
h = _copysign(r, c) # past half chord length
|
|
565
566
|
P, p = _bisect2( h, c, a, r, tol, _R3)
|
|
566
567
|
Q, q = _bisect2(-h, c, a, r, tol, _R3)
|
|
567
|
-
if
|
|
568
|
+
if fabs(p - q) < max(EPS, tol):
|
|
568
569
|
Q = P
|
|
569
570
|
elif a > r:
|
|
570
571
|
raise ValueError(_too_(Fmt.distant(a)))
|
pygeodesy/geodesicx/__init__.py
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
u'''A pure Python version of I{Karney}'s C++ classes U{GeodesicExact
|
|
5
5
|
<https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1GeodesicExact.html>}
|
|
6
6
|
and U{GeodesicLineExact
|
|
7
|
-
<https://
|
|
7
|
+
<https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1GeodesicLine.html>}.
|
|
8
8
|
|
|
9
9
|
For more details, see the C++ U{GeographicLib<https://GeographicLib.SourceForge.io/C++/doc/index.html>}
|
|
10
10
|
documentation, especially the U{Class List<https://GeographicLib.SourceForge.io/C++/doc/annotated.html>}
|
|
@@ -23,7 +23,7 @@ from pygeodesy.karney import Caps, GeodesicError
|
|
|
23
23
|
from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY
|
|
24
24
|
|
|
25
25
|
__all__ = _ALL_LAZY.geodesicx + _ALL_DOCS(Caps, GeodesicError)
|
|
26
|
-
__version__ = '24.
|
|
26
|
+
__version__ = '24.11.02'
|
|
27
27
|
|
|
28
28
|
# **) MIT License
|
|
29
29
|
#
|
pygeodesy/geodsolve.py
CHANGED
|
@@ -23,7 +23,7 @@ from pygeodesy.solveBase import _SolveGDictBase, _SolveGDictLineBase
|
|
|
23
23
|
from pygeodesy.utily import _unrollon, _Wrap, wrap360
|
|
24
24
|
|
|
25
25
|
__all__ = _ALL_LAZY.geodsolve
|
|
26
|
-
__version__ = '24.
|
|
26
|
+
__version__ = '24.11.02'
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
class _GeodesicSolveBase(_SolveGDictBase):
|
|
@@ -181,15 +181,6 @@ class GeodesicSolve(_GeodesicSolveBase):
|
|
|
181
181
|
ll2 = _unrollon(ll1, _Wrap.point(ll2))
|
|
182
182
|
return self.InverseLine(ll1.lat, ll1.lon, ll2.lat, ll2.lon, **caps_name)
|
|
183
183
|
|
|
184
|
-
# def _InverseLine2(self, lat1, lon1, lat2, lon2, **caps_name): # in .geodesici
|
|
185
|
-
# '''(INTERNAL) Helper for L{InverseLine} and L{_InverseLine}.
|
|
186
|
-
# '''
|
|
187
|
-
# r = self.Inverse(lat1, lon1, lat2, lon2)
|
|
188
|
-
# gl = GeodesicLineSolve(self, lat1, lon1, r.azi1, **_name1__(caps_name, _or_nameof=self))
|
|
189
|
-
# gl._a13 = r.a12 # gl.SetArc(r.a12)
|
|
190
|
-
# gl._s13 = r.s12 # gl.SetDistance(r.s12)
|
|
191
|
-
# return gl, r
|
|
192
|
-
|
|
193
184
|
def InverseLine(self, lat1, lon1, lat2, lon2, **caps_name): # PYCHOK no cover
|
|
194
185
|
'''Set up a L{GeodesicLineSolve} to compute several points
|
|
195
186
|
on a single geodesic.
|
|
@@ -270,14 +261,14 @@ class GeodesicLineSolve(_GeodesicSolveBase, _SolveGDictLineBase):
|
|
|
270
261
|
'''
|
|
271
262
|
return self._a13
|
|
272
263
|
|
|
273
|
-
def Arc(self):
|
|
264
|
+
def Arc(self): # PYCHOK no cover
|
|
274
265
|
'''Return the arc length to reference point 3 (C{degrees} or C{NAN}).
|
|
275
266
|
|
|
276
267
|
@see: Method L{SetArc} and property L{a13}.
|
|
277
268
|
'''
|
|
278
269
|
return self.a13
|
|
279
270
|
|
|
280
|
-
def ArcPosition(self, a12, outmask=Caps.STANDARD): # PYCHOK
|
|
271
|
+
def ArcPosition(self, a12, outmask=Caps.STANDARD): # PYCHOK no cover
|
|
281
272
|
'''Find the position on the line given B{C{a12}}.
|
|
282
273
|
|
|
283
274
|
@arg a12: Spherical arc length from the first point to the
|
|
@@ -347,7 +338,7 @@ class GeodesicLineSolve(_GeodesicSolveBase, _SolveGDictLineBase):
|
|
|
347
338
|
'''
|
|
348
339
|
return self._s13
|
|
349
340
|
|
|
350
|
-
def SetArc(self, a13):
|
|
341
|
+
def SetArc(self, a13): # PYCHOK no cover
|
|
351
342
|
'''Set reference point 3 in terms relative to the first point.
|
|
352
343
|
|
|
353
344
|
@arg a13: Spherical arc length from the first to the reference
|
|
@@ -362,13 +353,13 @@ class GeodesicLineSolve(_GeodesicSolveBase, _SolveGDictLineBase):
|
|
|
362
353
|
# _update_all(self)
|
|
363
354
|
return self._s13
|
|
364
355
|
|
|
365
|
-
def SetDistance(self, s13):
|
|
356
|
+
def SetDistance(self, s13): # PYCHOK no cover
|
|
366
357
|
'''Set reference point 3 in terms relative to the first point.
|
|
367
358
|
|
|
368
359
|
@arg s13: Distance from the first to the reference point (C{meter}).
|
|
369
360
|
|
|
370
|
-
@return: The arc length C{a13} (C{degrees}) between the first
|
|
371
|
-
|
|
361
|
+
@return: The arc length C{a13} (C{degrees}) between the first and
|
|
362
|
+
the reference point or C{NAN}.
|
|
372
363
|
'''
|
|
373
364
|
if self._s13 != s13:
|
|
374
365
|
self._s13 = s13
|
pygeodesy/geoids.py
CHANGED
|
@@ -15,7 +15,7 @@ The L{GeoidG2012B} and L{GeoidPGM} interpolators both depend on U{scipy
|
|
|
15
15
|
require those packages to be installed.
|
|
16
16
|
|
|
17
17
|
In addition, each geoid interpolator needs C{grid knots} (down)loaded from
|
|
18
|
-
a C{geoid} model file, I{specific to the interpolator}
|
|
18
|
+
a C{geoid} model file, I{specific to the interpolator}. More details below
|
|
19
19
|
and in the documentation of the interpolator class. For each interpolator,
|
|
20
20
|
there are several interpolation choices, like I{linear}, I{cubic}, etc.
|
|
21
21
|
|
|
@@ -42,7 +42,7 @@ C{>>> h = ginterpolator(ll)}
|
|
|
42
42
|
|
|
43
43
|
or
|
|
44
44
|
|
|
45
|
-
C{>>>
|
|
45
|
+
C{>>> h1, h2, h3, ... = ginterpolator(ll1, ll2, ll3, ...)}
|
|
46
46
|
|
|
47
47
|
or a list, tuple, generator, etc. of C{LatLon}s
|
|
48
48
|
|
|
@@ -118,7 +118,7 @@ except ImportError: # Python 3+
|
|
|
118
118
|
from io import BytesIO as _BytesIO # PYCHOK expected
|
|
119
119
|
|
|
120
120
|
__all__ = _ALL_LAZY.geoids
|
|
121
|
-
__version__ = '24.
|
|
121
|
+
__version__ = '24.11.05'
|
|
122
122
|
|
|
123
123
|
_assert_ = 'assert'
|
|
124
124
|
_bHASH_ = b'#'
|
|
@@ -159,7 +159,7 @@ class _GeoidBase(_HeightBase):
|
|
|
159
159
|
_smooth = 0 # used only for RectBivariateSpline
|
|
160
160
|
_stdev = None # fixed in GeoidKarney
|
|
161
161
|
_u2B = 0 # np.itemsize or undefined
|
|
162
|
-
_yx_hits = None # cache hits, ala Karney
|
|
162
|
+
_yx_hits = None # cache hits, ala Karney's
|
|
163
163
|
|
|
164
164
|
# _lat_d = _0_0 # increment, +tive
|
|
165
165
|
# _lat_lo = _0_0 # lower lat, south
|
|
@@ -1621,7 +1621,7 @@ class _PGM(_Gpars):
|
|
|
1621
1621
|
|
|
1622
1622
|
|
|
1623
1623
|
class PGMError(GeoidError):
|
|
1624
|
-
'''
|
|
1624
|
+
'''An issue while parsing or cropping an C{egm*.pgm} geoid dataset.
|
|
1625
1625
|
'''
|
|
1626
1626
|
pass
|
|
1627
1627
|
|
pygeodesy/heights.py
CHANGED
|
@@ -91,7 +91,7 @@ from pygeodesy.units import _isDegrees, Float_, Int_
|
|
|
91
91
|
# from math import radians # from .points
|
|
92
92
|
|
|
93
93
|
__all__ = _ALL_LAZY.heights
|
|
94
|
-
__version__ = '24.
|
|
94
|
+
__version__ = '24.11.02'
|
|
95
95
|
|
|
96
96
|
_error_ = 'error'
|
|
97
97
|
_formy = _MODS.into(formy=__name__)
|
|
@@ -1031,7 +1031,7 @@ class HeightIDWkarney(_HeightIDW):
|
|
|
1031
1031
|
<https://WikiPedia.org/wiki/Inverse_distance_weighting>} (IDW) and the
|
|
1032
1032
|
I{angular} distance in C{degrees} from I{Karney}'s U{geographiclib
|
|
1033
1033
|
<https://PyPI.org/project/geographiclib>} method U{Geodesic.Inverse
|
|
1034
|
-
<https://
|
|
1034
|
+
<https://GeographicLib.SourceForge.io/Python/doc/code.html#
|
|
1035
1035
|
geographiclib.geodesic.Geodesic.Inverse>}.
|
|
1036
1036
|
'''
|
|
1037
1037
|
def __init__(self, knots, beta=2, datum=None, **name__wrap):
|