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.
Files changed (54) hide show
  1. {PyGeodesy-24.10.24.dist-info → PyGeodesy-24.11.11.dist-info}/METADATA +4 -4
  2. {PyGeodesy-24.10.24.dist-info → PyGeodesy-24.11.11.dist-info}/RECORD +54 -54
  3. {PyGeodesy-24.10.24.dist-info → PyGeodesy-24.11.11.dist-info}/WHEEL +1 -1
  4. pygeodesy/__init__.py +2 -2
  5. pygeodesy/azimuthal.py +51 -61
  6. pygeodesy/basics.py +34 -33
  7. pygeodesy/booleans.py +36 -36
  8. pygeodesy/cartesianBase.py +5 -5
  9. pygeodesy/constants.py +4 -4
  10. pygeodesy/css.py +7 -8
  11. pygeodesy/deprecated/__init__.py +1 -1
  12. pygeodesy/deprecated/classes.py +9 -9
  13. pygeodesy/deprecated/functions.py +6 -6
  14. pygeodesy/ecef.py +11 -14
  15. pygeodesy/ellipsoidalBase.py +105 -120
  16. pygeodesy/ellipsoidalBaseDI.py +114 -118
  17. pygeodesy/ellipsoidalExact.py +35 -37
  18. pygeodesy/ellipsoids.py +3 -3
  19. pygeodesy/errors.py +24 -24
  20. pygeodesy/etm.py +80 -72
  21. pygeodesy/fmath.py +39 -37
  22. pygeodesy/formy.py +3 -2
  23. pygeodesy/fsums.py +51 -40
  24. pygeodesy/geodesicw.py +15 -14
  25. pygeodesy/geodesicx/__init__.py +2 -2
  26. pygeodesy/geodsolve.py +7 -16
  27. pygeodesy/geoids.py +5 -5
  28. pygeodesy/heights.py +2 -2
  29. pygeodesy/internals.py +63 -79
  30. pygeodesy/karney.py +2 -2
  31. pygeodesy/ktm.py +11 -13
  32. pygeodesy/latlonBase.py +6 -6
  33. pygeodesy/lazily.py +5 -5
  34. pygeodesy/lcc.py +4 -4
  35. pygeodesy/ltp.py +10 -10
  36. pygeodesy/ltpTuples.py +74 -75
  37. pygeodesy/mgrs.py +9 -10
  38. pygeodesy/named.py +4 -0
  39. pygeodesy/osgr.py +9 -12
  40. pygeodesy/props.py +2 -2
  41. pygeodesy/resections.py +9 -10
  42. pygeodesy/rhumb/__init__.py +1 -1
  43. pygeodesy/rhumb/solve.py +3 -3
  44. pygeodesy/simplify.py +5 -5
  45. pygeodesy/sphericalNvector.py +80 -123
  46. pygeodesy/sphericalTrigonometry.py +60 -66
  47. pygeodesy/units.py +2 -2
  48. pygeodesy/utm.py +6 -6
  49. pygeodesy/vector2d.py +13 -13
  50. pygeodesy/vector3d.py +19 -21
  51. pygeodesy/vector3dBase.py +18 -15
  52. pygeodesy/webmercator.py +4 -4
  53. pygeodesy/wgrs.py +4 -4
  54. {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, _1primed, \
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.10.11'
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._faddot(n, a, b, **kwds)
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(Fdot):
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, *cs[:1], **name_f2product_nonfinites_RESIDUAL)
145
+ Fsum.__init__(self, **name_f2product_nonfinites_RESIDUAL)
154
146
  n = len(cs) - 1
155
- if n > 0:
156
- self._faddot(n, cs[1:], _powers(x, n), **name_f2product_nonfinites_RESIDUAL)
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(a, *b, **start):
435
- '''Return the precision dot product M{sum(a[i] * b[i] for ni=0..len(a))}.
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 a: Iterable of values (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
438
- @arg b: Other values (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}), all
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 start: Optional bias C{B{start}=0} (C{scalar}, an L{Fsum} or
441
- L{Fsum2Tuple}).
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{a})} and C{len(B{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(a, nonfinites=True, *b, **start)
442
+ D = Fdot(xs, *ys, **_xkwds(start_f2product_nonfinites, nonfinites=True))
452
443
  return float(D)
453
444
 
454
445
 
455
- def fdot3(xs, ys, zs, start=0):
456
- '''Return the precision dot product M{start + sum(a[i] * b[i] * c[i]
457
- for i=0..len(a)-1)}.
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
- @kwarg start: Optional bias (C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
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, start=start)
473
- _f = Fsum(nonfinites=True) # f2product=True
474
- r = (_f(x).f2mul_(y, z) for x, y, z in zip(xs, ys, zs))
475
- D = D.fadd(_1primed(r) if n < 4 else r)
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
- i=0..n)} with in- or decreasing exponent M{sum(... i=n..0)},
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 # ellispoidalBaseDI
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, height=0, wrap=False)
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.10.22'
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): # like Python 3.13+ I{Modules/mathmodule.c}:
167
- # raise a ValueError for a NAN result from non-NAN C{a_b_c}s or an
168
- # OverflowError for a non-NAN non-finite from all finite C{a_b_c}s.
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(*two):
217
+ def f2product(two=None):
216
218
  '''Turn accurate I{TwoProduct} multiplication on or off.
217
219
 
218
- @arg two: If C{True}, turn I{TwoProduct} on, if C{False} off or
219
- if C{None} or omitted, keep the current setting.
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 and two[0] is not None:
230
- Fsum._f2product = bool(two[0])
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(*raiser):
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
- @arg raiser: If C{True}, throw exceptions, if C{False} handle
327
- I{non-finites} or if C{None} or omitted, leave
328
- the setting unchanged.
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 and raiser[0] is not None:
337
- Fsum._isfine = {} if bool(raiser[0]) else Fsum._nonfinites_isfine_kwds[True]
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_(*others, **raiser))
1510
+ return self._fset(self.f2mul_(others, **raiser))
1505
1511
 
1506
- def f2mul_(self, *others, **nonfinites): # in .fmath.f2mul
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>} set to C{True}.
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 nonfinites: Use C{B{nonfinites}=True} or C{False}, to override both
1513
- L{nonfinites<Fsum.nonfinites>} and the L{nonfiniterrors}
1514
- default (C{bool}).
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_, *others, **nonfinites)
1526
+ return self._f2mul(self.f2mul_, others, **f2product_nonfinites)
1521
1527
 
1522
- def _f2mul(self, where, *others, **nonfinites_raiser):
1528
+ def _f2mul(self, where, others, f2product=True, **nonfinites_raiser):
1523
1529
  '''(INTERNAL) See methods C{fma} and C{f2mul_}.
1524
1530
  '''
1525
- f = self._copy_2(where)
1526
- ps = f._ps
1527
- if ps and others:
1528
- op = where.__name__
1529
- try:
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
- pfs = _2products(p, _2split3s(ps))
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 f in _pfs(p, fs):
2313
- yield f if _isfine(f) else _nfError(f)
2323
+ for x in _pfs(p, fs):
2324
+ yield x if _isfine(x) else _nfError(x)
2314
2325
 
2315
- fs = _psfs(self._ps, factors, **self._isfine)
2316
- f = _Psum(self._ps_acc([], fs, up=False), name=op)
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 isinstance(x, _Fsum_2Tuple_types):
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.10.14'
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://geographiclib.sourceforge.io/Python/doc/code.html>}.
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://geographiclib.sourceforge.io/Python/doc/code.html>}.
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 _a(d.s12), P, d
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
- __2 = _0_5 # Rb > r > Rc
538
+ # Rb > r > Rc
540
539
  for i in range(_TRIPS): # 47-48
541
- s = (b + c) * __2
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
- t = _a(b - c)
548
- if t < tol: # or _a(R - r) < tol:
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, _a(R - r))
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 = _a(C.s02) # distance between centers
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 _a(p - q) < max(EPS, tol):
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)))
@@ -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://geographiclib.sourceforge.io/C++/doc/classGeographicLib_1_1GeodesicLine.html>}.
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.09.06'
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.10.14'
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 unused
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
- and the reference point or C{NAN}.
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}, more details below
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{>>> h0, h1, h2, ... = ginterpolator(ll0, ll1, ll2, ...)}
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.10.11'
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
- '''Issue parsing or cropping an C{egm*.pgm} geoid dataset.
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.08.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://geographiclib.sourceforge.io/Python/doc/code.html#
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):