pygeodesy 25.10.10__py2.py3-none-any.whl → 25.12.12__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 (126) hide show
  1. pygeodesy/__init__.py +25 -12
  2. pygeodesy/__main__.py +1 -1
  3. pygeodesy/albers.py +1 -1
  4. pygeodesy/angles.py +960 -0
  5. pygeodesy/auxilats/_CX_4.py +1 -1
  6. pygeodesy/auxilats/_CX_6.py +1 -1
  7. pygeodesy/auxilats/_CX_8.py +1 -1
  8. pygeodesy/auxilats/_CX_Rs.py +1 -1
  9. pygeodesy/auxilats/__init__.py +2 -2
  10. pygeodesy/auxilats/__main__.py +1 -1
  11. pygeodesy/auxilats/auxAngle.py +7 -8
  12. pygeodesy/auxilats/auxDLat.py +1 -1
  13. pygeodesy/auxilats/auxDST.py +1 -1
  14. pygeodesy/auxilats/auxLat.py +1 -1
  15. pygeodesy/auxilats/auxily.py +1 -1
  16. pygeodesy/azimuthal.py +6 -5
  17. pygeodesy/basics.py +14 -10
  18. pygeodesy/booleans.py +8 -33
  19. pygeodesy/cartesianBase.py +7 -7
  20. pygeodesy/clipy.py +17 -23
  21. pygeodesy/constants.py +86 -63
  22. pygeodesy/css.py +1 -1
  23. pygeodesy/datums.py +1 -1
  24. pygeodesy/deprecated/__init__.py +2 -2
  25. pygeodesy/deprecated/bases.py +1 -1
  26. pygeodesy/deprecated/classes.py +32 -2
  27. pygeodesy/deprecated/consterns.py +1 -1
  28. pygeodesy/deprecated/datum.py +1 -1
  29. pygeodesy/deprecated/functions.py +1 -1
  30. pygeodesy/deprecated/nvector.py +1 -1
  31. pygeodesy/deprecated/rhumbBase.py +1 -1
  32. pygeodesy/deprecated/rhumbaux.py +1 -1
  33. pygeodesy/deprecated/rhumbsolve.py +1 -1
  34. pygeodesy/deprecated/rhumbx.py +1 -1
  35. pygeodesy/dms.py +1 -1
  36. pygeodesy/ecef.py +1 -1
  37. pygeodesy/ecefLocals.py +1 -1
  38. pygeodesy/elevations.py +1 -1
  39. pygeodesy/ellipsoidalBase.py +1 -1
  40. pygeodesy/ellipsoidalBaseDI.py +1 -1
  41. pygeodesy/ellipsoidalExact.py +1 -1
  42. pygeodesy/ellipsoidalGeodSolve.py +1 -1
  43. pygeodesy/ellipsoidalKarney.py +1 -1
  44. pygeodesy/ellipsoidalNvector.py +1 -1
  45. pygeodesy/ellipsoidalVincenty.py +1 -1
  46. pygeodesy/ellipsoids.py +7 -6
  47. pygeodesy/elliptic.py +1 -1
  48. pygeodesy/epsg.py +1 -1
  49. pygeodesy/errors.py +8 -4
  50. pygeodesy/etm.py +1 -1
  51. pygeodesy/fmath.py +15 -8
  52. pygeodesy/formy.py +107 -5
  53. pygeodesy/frechet.py +1 -1
  54. pygeodesy/fstats.py +1 -1
  55. pygeodesy/fsums.py +1 -1
  56. pygeodesy/gars.py +1 -1
  57. pygeodesy/geod3solve.py +488 -0
  58. pygeodesy/geodesici.py +4 -4
  59. pygeodesy/geodesicw.py +1 -1
  60. pygeodesy/geodesicx/_C4_24.py +1 -1
  61. pygeodesy/geodesicx/_C4_27.py +1 -1
  62. pygeodesy/geodesicx/_C4_30.py +1 -1
  63. pygeodesy/geodesicx/__init__.py +1 -1
  64. pygeodesy/geodesicx/__main__.py +1 -1
  65. pygeodesy/geodesicx/gx.py +1 -1
  66. pygeodesy/geodesicx/gxarea.py +1 -1
  67. pygeodesy/geodesicx/gxbases.py +1 -1
  68. pygeodesy/geodesicx/gxline.py +1 -1
  69. pygeodesy/geodsolve.py +70 -102
  70. pygeodesy/geohash.py +1 -1
  71. pygeodesy/geoids.py +1 -1
  72. pygeodesy/hausdorff.py +1 -1
  73. pygeodesy/heights.py +1 -1
  74. pygeodesy/internals.py +3 -3
  75. pygeodesy/interns.py +3 -3
  76. pygeodesy/iters.py +1 -1
  77. pygeodesy/karney.py +132 -116
  78. pygeodesy/ktm.py +1 -1
  79. pygeodesy/latlonBase.py +1 -1
  80. pygeodesy/lazily.py +25 -13
  81. pygeodesy/lcc.py +1 -1
  82. pygeodesy/ltp.py +1 -1
  83. pygeodesy/ltpTuples.py +1 -1
  84. pygeodesy/mgrs.py +3 -3
  85. pygeodesy/named.py +14 -9
  86. pygeodesy/namedTuples.py +1 -1
  87. pygeodesy/nvectorBase.py +1 -1
  88. pygeodesy/osgr.py +1 -1
  89. pygeodesy/points.py +1 -1
  90. pygeodesy/props.py +1 -1
  91. pygeodesy/resections.py +1 -1
  92. pygeodesy/rhumb/__init__.py +8 -6
  93. pygeodesy/rhumb/aux_.py +1 -1
  94. pygeodesy/rhumb/bases.py +1 -1
  95. pygeodesy/rhumb/ekx.py +1 -1
  96. pygeodesy/rhumb/solve.py +91 -84
  97. pygeodesy/simplify.py +1 -1
  98. pygeodesy/solveBase.py +72 -49
  99. pygeodesy/sphericalBase.py +1 -1
  100. pygeodesy/sphericalNvector.py +1 -1
  101. pygeodesy/sphericalTrigonometry.py +1 -1
  102. pygeodesy/streprs.py +6 -4
  103. pygeodesy/trf.py +1 -1
  104. pygeodesy/triaxials/__init__.py +70 -0
  105. pygeodesy/triaxials/bases.py +935 -0
  106. pygeodesy/triaxials/conformal3.py +617 -0
  107. pygeodesy/triaxials/triaxial3.py +969 -0
  108. pygeodesy/triaxials/triaxial5.py +1220 -0
  109. pygeodesy/units.py +6 -1
  110. pygeodesy/unitsBase.py +1 -1
  111. pygeodesy/ups.py +2 -3
  112. pygeodesy/utily.py +19 -15
  113. pygeodesy/utm.py +1 -1
  114. pygeodesy/utmups.py +1 -1
  115. pygeodesy/utmupsBase.py +1 -1
  116. pygeodesy/vector2d.py +2 -2
  117. pygeodesy/vector3d.py +1 -1
  118. pygeodesy/vector3dBase.py +195 -51
  119. pygeodesy/webmercator.py +1 -1
  120. pygeodesy/wgrs.py +1 -1
  121. {pygeodesy-25.10.10.dist-info → pygeodesy-25.12.12.dist-info}/METADATA +13 -13
  122. pygeodesy-25.12.12.dist-info/RECORD +125 -0
  123. pygeodesy/triaxials.py +0 -1566
  124. pygeodesy-25.10.10.dist-info/RECORD +0 -119
  125. {pygeodesy-25.10.10.dist-info → pygeodesy-25.12.12.dist-info}/WHEEL +0 -0
  126. {pygeodesy-25.10.10.dist-info → pygeodesy-25.12.12.dist-info}/top_level.txt +0 -0
pygeodesy/errors.py CHANGED
@@ -28,7 +28,7 @@ from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS, _PYTHON_X_DEV
28
28
  from copy import copy as _copy
29
29
 
30
30
  __all__ = _ALL_LAZY.errors # _ALL_DOCS('_InvalidError', '_IsnotError') _under
31
- __version__ = '25.09.04'
31
+ __version__ = '25.12.02'
32
32
 
33
33
  _argument_ = 'argument'
34
34
  _basics = _MODS.into(basics=__name__)
@@ -214,7 +214,8 @@ class CrossError(_ValueError):
214
214
 
215
215
  class GeodesicError(_ValueError):
216
216
  '''Error raised for convergence or other issues in L{geodesicx<pygeodesy.geodesicx>},
217
- L{geodesicw<pygeodesy.geodesicw>} or L{karney<pygeodesy.karney>}.
217
+ L{geodesicw<pygeodesy.geodesicw>}, L{geodsolve<pygeodesy.geodsolve>} or
218
+ L{karney<pygeodesy.karney>}.
218
219
  '''
219
220
  pass
220
221
 
@@ -626,7 +627,10 @@ def _xattr(obj, **name_default):
626
627
  '''
627
628
  if len(name_default) == 1:
628
629
  for n, d in name_default.items():
629
- return getattr(obj, n, d)
630
+ try: # obj is tuple
631
+ return getattr(obj, n, d)
632
+ except ValueError:
633
+ return d
630
634
  raise _xAssertionError(_xattr, obj, **name_default)
631
635
 
632
636
 
@@ -928,7 +932,7 @@ def _xStrError(*Refs, **name_value_Error): # in .gars, .geohash, .wgrs
928
932
 
929
933
  # **) MIT License
930
934
  #
931
- # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
935
+ # Copyright (C) 2016-2026 -- mrJean1 at Gmail -- All Rights Reserved.
932
936
  #
933
937
  # Permission is hereby granted, free of charge, to any person obtaining a
934
938
  # copy of this software and associated documentation files (the "Software"),
pygeodesy/etm.py CHANGED
@@ -1197,7 +1197,7 @@ if __name__ == _DMAIN_: # MCCABE 16
1197
1197
 
1198
1198
  # **) MIT License
1199
1199
  #
1200
- # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
1200
+ # Copyright (C) 2016-2026 -- mrJean1 at Gmail -- All Rights Reserved.
1201
1201
  #
1202
1202
  # Permission is hereby granted, free of charge, to any person obtaining a
1203
1203
  # copy of this software and associated documentation files (the "Software"),
pygeodesy/fmath.py CHANGED
@@ -25,7 +25,7 @@ from math import fabs, sqrt # pow
25
25
  import operator as _operator # in .datums, .trf, .utm
26
26
 
27
27
  __all__ = _ALL_LAZY.fmath
28
- __version__ = '25.09.15'
28
+ __version__ = '25.12.02'
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
@@ -260,7 +260,6 @@ def bqrt(x):
260
260
 
261
261
  try:
262
262
  from math import cbrt as _cbrt # Python 3.11+
263
-
264
263
  except ImportError: # Python 3.10-
265
264
 
266
265
  def _cbrt(x):
@@ -314,8 +313,9 @@ def euclid(x, y):
314
313
  @see: Function L{euclid_}.
315
314
  '''
316
315
  x, y = abs(x), abs(y) # NOT fabs!
317
- return (x + y * _0_4142) if x > y else \
318
- (y + x * _0_4142) # * _0_5 before 20.10.02
316
+ if x < y:
317
+ x, y = y, x
318
+ return x + y * _0_4142 # * _0_5 before 20.10.02
319
319
 
320
320
 
321
321
  def euclid_(*xs):
@@ -332,10 +332,17 @@ def euclid_(*xs):
332
332
  e = _0_0
333
333
  for x in sorted(map(abs, xs)): # NOT fabs, reverse=True!
334
334
  # e = euclid(x, e)
335
- if e < x:
336
- e, x = x, e
337
335
  if x:
338
- e += x * _0_4142
336
+ if e < x:
337
+ e, x = x, e
338
+ x *= _0_4142
339
+ # s = e + x
340
+ # if e < x: # like .fsums._2sum
341
+ # x -= s # e = (x - s) + e
342
+ # else:
343
+ # e -= s # e = (e - s) + x
344
+ e += x
345
+ # e += s
339
346
  return e
340
347
 
341
348
 
@@ -1115,7 +1122,7 @@ def zqrt(x):
1115
1122
 
1116
1123
  # **) MIT License
1117
1124
  #
1118
- # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
1125
+ # Copyright (C) 2016-2026 -- mrJean1 at Gmail -- All Rights Reserved.
1119
1126
  #
1120
1127
  # Permission is hereby granted, free of charge, to any person obtaining a
1121
1128
  # copy of this software and associated documentation files (the "Software"),
pygeodesy/formy.py CHANGED
@@ -11,7 +11,7 @@ from pygeodesy.basics import _copysign, _isin # _args_kwds_count2
11
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
- _90_0, _180_0, _360_0
14
+ _90_0, _180_0, _360_0, MANT_DIG as _DIG53
15
15
  from pygeodesy.datums import Datum, Ellipsoid, _ellipsoidal_datum, \
16
16
  _mean_radius, _spherical_datum, _WGS84, _EWGS84
17
17
  # from pygeodesy.ellipsoids import Ellipsoid, _EWGS84 # from .datums
@@ -27,7 +27,7 @@ from pygeodesy.named import _name__, _name2__, _NamedTuple, _xnamed, typename
27
27
  from pygeodesy.namedTuples import Bearing2Tuple, Distance4Tuple, LatLon2Tuple, \
28
28
  Intersection3Tuple, PhiLam2Tuple
29
29
  # from pygeodesy.streprs import Fmt, unstr # from .fsums
30
- # from pygeodesy.triaxials import _hartzell3 # _MODS
30
+ # from pygeodesy.triaxials.triaxial5 import _hartzell3 # _MODS
31
31
  from pygeodesy.units import _isDegrees, _isHeight, _isRadius, Bearing, Degrees_, \
32
32
  Distance, Distance_, Height, Lamd, Lat, Lon, Meter_, \
33
33
  Phid, Radians, Radians_, Radius, Radius_, Scalar, _100km
@@ -42,10 +42,11 @@ from contextlib import contextmanager
42
42
  from math import atan, cos, degrees, fabs, radians, sin, sqrt # pow
43
43
 
44
44
  __all__ = _ALL_LAZY.formy
45
- __version__ = '25.05.12'
45
+ __version__ = '25.12.12'
46
46
 
47
47
  _RADIANS2 = radians(_1_0)**2 # degree to radians-squared
48
48
  _ratio_ = 'ratio'
49
+ _TOL53 = sqrt(pow(_0_5, _DIG53)) # elliperim
49
50
  _xline_ = 'xline'
50
51
 
51
52
 
@@ -367,6 +368,107 @@ def _dS(fun_, radius, wrap, *lls, **adjust):
367
368
  return r * radius
368
369
 
369
370
 
371
+ def elliperim(a, b):
372
+ '''Compute the perimeter of an ellipse with semi-axes C{a} and C{b} using U{SciPy's
373
+ ellipe<https://www.JohnDCook.com/perimeter_ellipse.html>} function or the U{AGM
374
+ <https://PaulBourke.net/geometry/ellipsecirc>} (Arithmetic Geometric Mean) method.
375
+
376
+ @return: The perimeter (C{scalar}, same units as C{a} and C{b}).
377
+ '''
378
+ if a < b:
379
+ a, b = b, a
380
+ if 0 < b < a:
381
+ try:
382
+ from scipy.special import ellipe
383
+ a *= float(ellipe(_1_0 - (b / a)**2)) * _4_0
384
+ except (AttributeError, ImportError):
385
+ # relative accuracy is about _TOL53**2
386
+ if (b * _DIG53) > (a * _TOL53):
387
+ c = a + b
388
+ d = a - b
389
+ m, s = -1, [c**2]
390
+ _s = s.append
391
+ while d > (b * _TOL53) and len(s) < 32: # 4..5 trips
392
+ b = sqrt(a * b)
393
+ a = c * _0_5
394
+ c = a + b
395
+ d = a - b
396
+ m *= 2
397
+ _s(m * d**2)
398
+ a = fsumf_(*s) * PI / c
399
+ else: # near flat
400
+ a *= _4_0
401
+ elif b < 0:
402
+ raise _ValueError(unstr(elliperim, a, b))
403
+ else: # circle or flat
404
+ a *= PI2 if b else _4_0
405
+ return a
406
+
407
+
408
+ # def elliperimR2(a, b):
409
+ # '''Compute the perimeter of an ellipse with semi-axes C{a} and C{b} using
410
+ # Ramanujan's U{2nd approximation<https://PaulBourke.net/geometry/ellipsecirc>}.
411
+ # '''
412
+ # if a < 0 or b < 0:
413
+ # raise ValueError(unstr(elliperimR2, a, b))
414
+ # p = a + b
415
+ # if p:
416
+ # t = ((a - b) / p)**2 * _3_0
417
+ # t = t / (_10_0 + sqrt(_4_0 - t)) + _1_0
418
+ # p *= t * PI
419
+ # return p
420
+
421
+
422
+ # def elliperim4arc3(a, b):
423
+ # '''Compute the perimeter of an ellipse with semi-axes C{a} and C{b} using
424
+ # the U{4 arc approximation<https://PaulBourke.net/geometry/ellipsecirc>}.
425
+ #
426
+ # @return: 3-Tuple C{(p, ra, rb)} with perimeter C{p}, arc radius C{ra}
427
+ # at the major and arc radius C{rb} at the minor semi-axes.
428
+ # '''
429
+ # _r = a < b
430
+ # if _r:
431
+ # a, b = b, a
432
+ # if 0 < b < a:
433
+ # h = hypot(a, b)
434
+ # L = (h - b) * _0_5
435
+ # p = atan2(b, a)
436
+ # s, c = sincos2(p)
437
+ # ra = L / c
438
+ # rb = (h - L) / s
439
+ # p = rb * p + ra * (PI_2 - p)
440
+ # elif b < 0:
441
+ # raise ValueError(unstr(elliperim4arc3, a, b))
442
+ # elif b == a:
443
+ # ra = rb = a
444
+ # p = a * PI_2
445
+ # else: # b == 0
446
+ # ra, rb = _0_0, a
447
+ # p = a
448
+ # p *= _4_0
449
+ # if _r:
450
+ # ra, rb = rb, ra
451
+ # return p, ra, rb
452
+
453
+
454
+ # def elliperimGKS(a, b):
455
+ # '''Compute the perimeter of an ellipse with semi-axes C{a} and C{b} using the U{Gauss-Kummer
456
+ # Series<https://www.JohnDCook.com/blog/2023/05/28/approximate-ellipse-perimeter/>}.
457
+ # '''
458
+ # if a < b:
459
+ # a, b = b, a
460
+ # if b < 0:
461
+ # raise ValueError(unstr(elliperimGKS, a, b))
462
+ # if b:
463
+ # p = a + b
464
+ # h = (a - b) / p
465
+ # h *= h
466
+ # p *= (1 + h * (1 / 4 + h * (1 / 64 + h * (1 / 256 + h * (25 / 16384 + h * (49 / 65536)))))) * PI
467
+ # else:
468
+ # p = _4_0 * a
469
+ # return p
470
+
471
+
370
472
  def _ellipsoidal(earth, where):
371
473
  '''(INTERNAL) Helper for distances.
372
474
  '''
@@ -926,7 +1028,7 @@ def hartzell(pov, los=False, earth=_WGS84, **name_LatLon_and_kwds):
926
1028
  n, kwds = _name2__(name_LatLon_and_kwds, name__=hartzell)
927
1029
  try:
928
1030
  D = _spherical_datum(earth, name__=hartzell)
929
- r, h, i = _MODS.triaxials._hartzell3(pov, los, D.ellipsoid._triaxial)
1031
+ r, h, i = _MODS.triaxials.triaxial5._hartzell3(pov, los, D.ellipsoid._triaxial)
930
1032
 
931
1033
  C = _MODS.cartesianBase.CartesianBase
932
1034
  if kwds:
@@ -1663,7 +1765,7 @@ def vincentys_(phi2, phi1, lam21):
1663
1765
 
1664
1766
  # **) MIT License
1665
1767
  #
1666
- # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
1768
+ # Copyright (C) 2016-2026 -- mrJean1 at Gmail -- All Rights Reserved.
1667
1769
  #
1668
1770
  # Permission is hereby granted, free of charge, to any person obtaining a
1669
1771
  # copy of this software and associated documentation files (the "Software"),
pygeodesy/frechet.py CHANGED
@@ -906,7 +906,7 @@ if __name__ == _DMAIN_:
906
906
 
907
907
  # **) MIT License
908
908
  #
909
- # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
909
+ # Copyright (C) 2016-2026 -- mrJean1 at Gmail -- All Rights Reserved.
910
910
  #
911
911
  # Permission is hereby granted, free of charge, to any person obtaining a
912
912
  # copy of this software and associated documentation files (the "Software"),
pygeodesy/fstats.py CHANGED
@@ -804,7 +804,7 @@ __all__ += _ALL_DOCS(_FstatsBase, _FstatsNamed)
804
804
 
805
805
  # **) MIT License
806
806
  #
807
- # Copyright (C) 2021-2025 -- mrJean1 at Gmail -- All Rights Reserved.
807
+ # Copyright (C) 2021-2026 -- mrJean1 at Gmail -- All Rights Reserved.
808
808
  #
809
809
  # Permission is hereby granted, free of charge, to any person obtaining a
810
810
  # copy of this software and associated documentation files (the "Software"),
pygeodesy/fsums.py CHANGED
@@ -2863,7 +2863,7 @@ if __name__ == _DMAIN_:
2863
2863
 
2864
2864
  # **) MIT License
2865
2865
  #
2866
- # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
2866
+ # Copyright (C) 2016-2026 -- mrJean1 at Gmail -- All Rights Reserved.
2867
2867
  #
2868
2868
  # Permission is hereby granted, free of charge, to any person obtaining a
2869
2869
  # copy of this software and associated documentation files (the "Software"),
pygeodesy/gars.py CHANGED
@@ -344,7 +344,7 @@ __all__ += _ALL_DOCS(decode3, # functions
344
344
 
345
345
  # **) MIT License
346
346
  #
347
- # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
347
+ # Copyright (C) 2016-2026 -- mrJean1 at Gmail -- All Rights Reserved.
348
348
  #
349
349
  # Permission is hereby granted, free of charge, to any person obtaining a
350
350
  # copy of this software and associated documentation files (the "Software"),