pygeodesy 24.11.11__py2.py3-none-any.whl → 24.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 (118) hide show
  1. {PyGeodesy-24.11.11.dist-info → PyGeodesy-24.12.12.dist-info}/METADATA +4 -4
  2. PyGeodesy-24.12.12.dist-info/RECORD +118 -0
  3. {PyGeodesy-24.11.11.dist-info → PyGeodesy-24.12.12.dist-info}/WHEEL +1 -1
  4. pygeodesy/__init__.py +4 -4
  5. pygeodesy/__main__.py +1 -1
  6. pygeodesy/albers.py +5 -5
  7. pygeodesy/auxilats/_CX_4.py +1 -1
  8. pygeodesy/auxilats/_CX_6.py +1 -1
  9. pygeodesy/auxilats/_CX_8.py +1 -1
  10. pygeodesy/auxilats/_CX_Rs.py +1 -1
  11. pygeodesy/auxilats/__init__.py +1 -1
  12. pygeodesy/auxilats/__main__.py +1 -1
  13. pygeodesy/auxilats/auxAngle.py +5 -5
  14. pygeodesy/auxilats/auxDLat.py +6 -6
  15. pygeodesy/auxilats/auxDST.py +2 -2
  16. pygeodesy/auxilats/auxLat.py +5 -5
  17. pygeodesy/auxilats/auxily.py +2 -2
  18. pygeodesy/azimuthal.py +5 -5
  19. pygeodesy/basics.py +1 -1
  20. pygeodesy/booleans.py +1 -1
  21. pygeodesy/cartesianBase.py +22 -61
  22. pygeodesy/clipy.py +1 -1
  23. pygeodesy/constants.py +3 -3
  24. pygeodesy/css.py +1 -1
  25. pygeodesy/datums.py +1 -1
  26. pygeodesy/deprecated/__init__.py +2 -2
  27. pygeodesy/deprecated/bases.py +1 -1
  28. pygeodesy/deprecated/classes.py +1 -1
  29. pygeodesy/deprecated/consterns.py +1 -1
  30. pygeodesy/deprecated/datum.py +1 -1
  31. pygeodesy/deprecated/functions.py +18 -8
  32. pygeodesy/deprecated/nvector.py +1 -1
  33. pygeodesy/deprecated/rhumbBase.py +1 -1
  34. pygeodesy/deprecated/rhumbaux.py +1 -1
  35. pygeodesy/deprecated/rhumbsolve.py +1 -1
  36. pygeodesy/deprecated/rhumbx.py +1 -1
  37. pygeodesy/dms.py +1 -1
  38. pygeodesy/ecef.py +53 -56
  39. pygeodesy/elevations.py +1 -1
  40. pygeodesy/ellipsoidalBase.py +3 -3
  41. pygeodesy/ellipsoidalBaseDI.py +1 -1
  42. pygeodesy/ellipsoidalExact.py +1 -1
  43. pygeodesy/ellipsoidalGeodSolve.py +1 -1
  44. pygeodesy/ellipsoidalKarney.py +1 -1
  45. pygeodesy/ellipsoidalNvector.py +1 -1
  46. pygeodesy/ellipsoidalVincenty.py +6 -5
  47. pygeodesy/ellipsoids.py +4 -5
  48. pygeodesy/elliptic.py +6 -6
  49. pygeodesy/epsg.py +1 -1
  50. pygeodesy/errors.py +1 -1
  51. pygeodesy/etm.py +5 -5
  52. pygeodesy/fmath.py +17 -16
  53. pygeodesy/formy.py +71 -104
  54. pygeodesy/frechet.py +1 -1
  55. pygeodesy/fstats.py +1 -1
  56. pygeodesy/fsums.py +32 -33
  57. pygeodesy/gars.py +1 -1
  58. pygeodesy/geodesici.py +4 -4
  59. pygeodesy/geodesicw.py +1 -1
  60. pygeodesy/geodesicx/_C4_24.py +2 -2
  61. pygeodesy/geodesicx/_C4_27.py +2 -2
  62. pygeodesy/geodesicx/_C4_30.py +2 -2
  63. pygeodesy/geodesicx/__init__.py +1 -1
  64. pygeodesy/geodesicx/__main__.py +1 -1
  65. pygeodesy/geodesicx/gx.py +6 -5
  66. pygeodesy/geodesicx/gxarea.py +2 -2
  67. pygeodesy/geodesicx/gxbases.py +2 -2
  68. pygeodesy/geodesicx/gxline.py +16 -12
  69. pygeodesy/geodsolve.py +1 -1
  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 +1 -1
  75. pygeodesy/interns.py +2 -3
  76. pygeodesy/iters.py +1 -1
  77. pygeodesy/karney.py +3 -3
  78. pygeodesy/ktm.py +16 -15
  79. pygeodesy/latlonBase.py +291 -341
  80. pygeodesy/lazily.py +11 -11
  81. pygeodesy/lcc.py +1 -1
  82. pygeodesy/ltp.py +46 -50
  83. pygeodesy/ltpTuples.py +145 -128
  84. pygeodesy/mgrs.py +1 -1
  85. pygeodesy/named.py +149 -3
  86. pygeodesy/namedTuples.py +58 -7
  87. pygeodesy/nvectorBase.py +122 -105
  88. pygeodesy/osgr.py +1 -1
  89. pygeodesy/points.py +1 -1
  90. pygeodesy/props.py +1 -1
  91. pygeodesy/resections.py +18 -17
  92. pygeodesy/rhumb/__init__.py +1 -1
  93. pygeodesy/rhumb/aux_.py +2 -2
  94. pygeodesy/rhumb/bases.py +2 -2
  95. pygeodesy/rhumb/ekx.py +4 -4
  96. pygeodesy/rhumb/solve.py +1 -1
  97. pygeodesy/simplify.py +289 -401
  98. pygeodesy/solveBase.py +1 -1
  99. pygeodesy/sphericalBase.py +1 -1
  100. pygeodesy/sphericalNvector.py +5 -5
  101. pygeodesy/sphericalTrigonometry.py +7 -6
  102. pygeodesy/streprs.py +10 -5
  103. pygeodesy/trf.py +1 -1
  104. pygeodesy/triaxials.py +23 -16
  105. pygeodesy/units.py +16 -16
  106. pygeodesy/unitsBase.py +1 -1
  107. pygeodesy/ups.py +4 -4
  108. pygeodesy/utily.py +202 -145
  109. pygeodesy/utm.py +5 -5
  110. pygeodesy/utmups.py +1 -1
  111. pygeodesy/utmupsBase.py +1 -1
  112. pygeodesy/vector2d.py +5 -5
  113. pygeodesy/vector3d.py +14 -3
  114. pygeodesy/vector3dBase.py +5 -5
  115. pygeodesy/webmercator.py +1 -1
  116. pygeodesy/wgrs.py +1 -1
  117. PyGeodesy-24.11.11.dist-info/RECORD +0 -118
  118. {PyGeodesy-24.11.11.dist-info → PyGeodesy-24.12.12.dist-info}/top_level.txt +0 -0
@@ -885,7 +885,7 @@ del _1_0, _0_01
885
885
 
886
886
  # **) MIT License
887
887
  #
888
- # Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
888
+ # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
889
889
  #
890
890
  # Permission is hereby granted, free of charge, to any person obtaining a
891
891
  # copy of this software and associated documentation files (the "Software"),
@@ -320,7 +320,7 @@ __all__ += _ALL_OTHER(Cartesian, LatLon, # classes
320
320
 
321
321
  # **) MIT License
322
322
  #
323
- # Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
323
+ # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
324
324
  #
325
325
  # Permission is hereby granted, free of charge, to any person obtaining a
326
326
  # copy of this software and associated documentation files (the "Software"),
@@ -314,7 +314,7 @@ __all__ += _ALL_OTHER(Cartesian, LatLon, # classes
314
314
 
315
315
  # **) MIT License
316
316
  #
317
- # Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
317
+ # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
318
318
  #
319
319
  # Permission is hereby granted, free of charge, to any person obtaining a
320
320
  # copy of this software and associated documentation files (the "Software"),
@@ -359,7 +359,7 @@ __all__ += _ALL_OTHER(Cartesian, LatLon, # classes
359
359
 
360
360
  # **) MIT License
361
361
  #
362
- # Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
362
+ # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
363
363
  #
364
364
  # Permission is hereby granted, free of charge, to any person obtaining a
365
365
  # copy of this software and associated documentation files (the "Software"),
@@ -657,7 +657,7 @@ __all__ += _ALL_OTHER(Cartesian, LatLon, Ned, Nvector, # classes
657
657
 
658
658
  # **) MIT License
659
659
  #
660
- # Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
660
+ # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
661
661
  #
662
662
  # Permission is hereby granted, free of charge, to any person obtaining a
663
663
  # copy of this software and associated documentation files (the "Software"),
@@ -67,12 +67,13 @@ from pygeodesy.props import deprecated_function, deprecated_method, \
67
67
  property_doc_, property_RO
68
68
  # from pygeodesy.streprs import Fmt # from .points
69
69
  from pygeodesy.units import Number_, Scalar_
70
- from pygeodesy.utily import atan2b, atan2d, sincos2, sincos2d, unroll180, wrap180
70
+ from pygeodesy.utily import atan2, atan2b, atan2d, sincos2, sincos2d, \
71
+ unroll180, wrap180
71
72
 
72
- from math import atan2, cos, degrees, fabs, radians, tan
73
+ from math import cos, degrees, fabs, radians, tan as _tan
73
74
 
74
75
  __all__ = _ALL_LAZY.ellipsoidalVincenty
75
- __version__ = '24.10.12'
76
+ __version__ = '24.11.26'
76
77
 
77
78
  _antipodal_to_ = _SPACE_(_antipodal_, _to_)
78
79
 
@@ -383,7 +384,7 @@ def _sincos22(sa):
383
384
  def _sincostan3r(a, f):
384
385
  # I{Reduced} 3-tuple C{(sin(B{a}), cos(B{a}), tan(B{a}))}
385
386
  if a: # see L{sincostan3}
386
- t = (_1_0 - f) * tan(a)
387
+ t = (_1_0 - f) * _tan(a)
387
388
  if t:
388
389
  c = _1_0 / hypot1(t)
389
390
  s = c * t
@@ -567,7 +568,7 @@ __all__ += _ALL_DOCS(Cartesian, LatLon, intersecant2, # from .ellipsoidalBaseDI
567
568
 
568
569
  # **) MIT License
569
570
  #
570
- # Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
571
+ # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
571
572
  #
572
573
  # Permission is hereby granted, free of charge, to any person obtaining a
573
574
  # copy of this software and associated documentation files (the "Software"),
pygeodesy/ellipsoids.py CHANGED
@@ -90,10 +90,10 @@ from pygeodesy.units import Bearing_, Distance, Float, Float_, Height, Lamd, Lat
90
90
  Meter2, Meter3, Phi, Phid, Radius, Radius_, Scalar
91
91
  from pygeodesy.utily import atan1, atan1d, atan2b, degrees90, m2radians, radians2m, sincos2d
92
92
 
93
- from math import asinh, atan, atanh, cos, degrees, exp, fabs, radians, sin, sinh, sqrt, tan
93
+ from math import asinh, atan, atanh, cos, degrees, exp, fabs, radians, sin, sinh, sqrt, tan # as _tan
94
94
 
95
95
  __all__ = _ALL_LAZY.ellipsoids
96
- __version__ = '24.10.15'
96
+ __version__ = '24.11.26'
97
97
 
98
98
  _f_0_0 = Float(f =_0_0) # zero flattening
99
99
  _f__0_0 = Float(f_=_0_0) # zero inverse flattening
@@ -660,8 +660,7 @@ class Ellipsoid(_NamedEnumItem):
660
660
 
661
661
  @arg lat: Geodetic latitude (C{degrees90}, C{str}).
662
662
 
663
- @return: A L{Circle4Tuple}C{(radius, height, lat, beta)}
664
- instance.
663
+ @return: A L{Circle4Tuple}C{(radius, height, lat, beta)}.
665
664
 
666
665
  @raise RangeError: Latitude B{C{lat}} outside valid range and
667
666
  L{rangerrors<pygeodesy.rangerrors>} is C{True}.
@@ -2427,7 +2426,7 @@ if __name__ == '__main__':
2427
2426
 
2428
2427
  # **) MIT License
2429
2428
  #
2430
- # Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
2429
+ # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
2431
2430
  #
2432
2431
  # Permission is hereby granted, free of charge, to any person obtaining a
2433
2432
  # copy of this software and associated documentation files (the "Software"),
pygeodesy/elliptic.py CHANGED
@@ -24,7 +24,7 @@ Following is a copy of I{Karney}'s U{EllipticFunction.hpp
24
24
  <https://GeographicLib.SourceForge.io/C++/doc/EllipticFunction_8hpp_source.html>}
25
25
  file C{Header}.
26
26
 
27
- Copyright (C) U{Charles Karney<mailto:Karney@Alum.MIT.edu>} (2008-2023)
27
+ Copyright (C) U{Charles Karney<mailto:Karney@Alum.MIT.edu>} (2008-2024)
28
28
  and licensed under the MIT/X11 License. For more information, see the
29
29
  U{GeographicLib<https://GeographicLib.SourceForge.io>} documentation.
30
30
 
@@ -93,13 +93,13 @@ from pygeodesy.named import _Named, _NamedTuple, _ALL_LAZY, Fmt, unstr
93
93
  from pygeodesy.props import _allPropertiesOf_n, Property_RO, _update_all
94
94
  # from pygeodesy.streprs import Fmt, unstr # from .named
95
95
  from pygeodesy.units import Scalar, Scalar_
96
- # from pygeodesy.utily import sincos2 as _sincos2 # from .karney
96
+ from pygeodesy.utily import atan2 # sincos2 as _sincos2
97
97
 
98
- from math import asin, asinh, atan, atan2, ceil, cosh, fabs, floor, \
99
- radians, sin, sinh, sqrt, tan, tanh
98
+ from math import asin, asinh, atan, ceil, cosh, fabs, floor, radians, \
99
+ sin, sinh, sqrt, tan, tanh # tan as _tan
100
100
 
101
101
  __all__ = _ALL_LAZY.elliptic
102
- __version__ = '24.10.14'
102
+ __version__ = '24.11.26'
103
103
 
104
104
  _TolRD = zqrt(EPS * 0.002)
105
105
  _TolRF = zqrt(EPS * 0.030)
@@ -1246,7 +1246,7 @@ def _RJ(inst, x, y, z, p, *over):
1246
1246
 
1247
1247
  # **) MIT License
1248
1248
  #
1249
- # Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
1249
+ # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
1250
1250
  #
1251
1251
  # Permission is hereby granted, free of charge, to any person obtaining a
1252
1252
  # copy of this software and associated documentation files (the "Software"),
pygeodesy/epsg.py CHANGED
@@ -223,7 +223,7 @@ __all__ += _ALL_DOCS(decode2, encode)
223
223
 
224
224
  # **) MIT License
225
225
  #
226
- # Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
226
+ # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
227
227
  #
228
228
  # Permission is hereby granted, free of charge, to any person obtaining a
229
229
  # copy of this software and associated documentation files (the "Software"),
pygeodesy/errors.py CHANGED
@@ -914,7 +914,7 @@ def _xStrError(*Refs, **name_value_Error): # in .gars, .geohash, .wgrs
914
914
 
915
915
  # **) MIT License
916
916
  #
917
- # Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
917
+ # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
918
918
  #
919
919
  # Permission is hereby granted, free of charge, to any person obtaining a
920
920
  # copy of this software and associated documentation files (the "Software"),
pygeodesy/etm.py CHANGED
@@ -17,7 +17,7 @@ Following is a copy of I{Karney}'s U{TransverseMercatorExact.hpp
17
17
  <https://GeographicLib.SourceForge.io/C++/doc/TransverseMercatorExact_8hpp_source.html>}
18
18
  file C{Header}.
19
19
 
20
- Copyright (C) U{Charles Karney<mailto:Karney@Alum.MIT.edu>} (2008-2023) and licensed
20
+ Copyright (C) U{Charles Karney<mailto:Karney@Alum.MIT.edu>} (2008-2024) and licensed
21
21
  under the MIT/X11 License. For more information, see the U{GeographicLib<https://
22
22
  GeographicLib.SourceForge.io>} documentation.
23
23
 
@@ -86,14 +86,14 @@ from pygeodesy.props import deprecated_method, deprecated_property_RO, \
86
86
  property_doc_, _allPropertiesOf_n
87
87
  from pygeodesy.streprs import Fmt, pairs, unstr
88
88
  from pygeodesy.units import Degrees, Scalar_
89
- from pygeodesy.utily import atan1d, atan2d, _loneg, sincos2
89
+ from pygeodesy.utily import atan1d, atan2, atan2d, _loneg, sincos2
90
90
  from pygeodesy.utm import _cmlon, _LLEB, _parseUTM5, _toBand, _toXtm8, \
91
91
  _to7zBlldfn, Utm, UTMError
92
92
 
93
- from math import asinh, atan2, degrees, radians, sinh, sqrt
93
+ from math import asinh, degrees, radians, sinh, sqrt
94
94
 
95
95
  __all__ = _ALL_LAZY.etm
96
- __version__ = '24.11.04'
96
+ __version__ = '24.11.24'
97
97
 
98
98
  _OVERFLOW = _1_EPS**2 # ~2e+31
99
99
  _TAYTOL = pow(EPS, 0.6)
@@ -1197,7 +1197,7 @@ if __name__ == '__main__': # MCCABE 16
1197
1197
 
1198
1198
  # **) MIT License
1199
1199
  #
1200
- # Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
1200
+ # Copyright (C) 2016-2025 -- 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
@@ -23,7 +23,7 @@ from math import fabs, sqrt # pow
23
23
  import operator as _operator # in .datums, .trf, .utm
24
24
 
25
25
  __all__ = _ALL_LAZY.fmath
26
- __version__ = '24.11.08'
26
+ __version__ = '24.12.02'
27
27
 
28
28
  # sqrt(2) - 1 <https://WikiPedia.org/wiki/Square_root_of_2>
29
29
  _0_4142 = 0.41421356237309504880 # ... ~ 3730904090310553 / 9007199254740992
@@ -107,16 +107,18 @@ class Fhypot(Fsum):
107
107
  other settings, see class L{Fsum<Fsum.__init__>} and method
108
108
  L{root<Fsum.root>}.
109
109
  '''
110
+ def _r_X_kwds(power=None, raiser=True, root=2, **kwds):
111
+ # DEPRECATED keyword argument C{power=2}, use C{root=2}
112
+ return (root if power is None else power), raiser, kwds
113
+
110
114
  r = None # _xkwds_pop2 error
111
115
  try:
112
- r, kwds = _xkwds_pop2(root_name_f2product_nonfinites_RESIDUAL_raiser, root=2)
113
- r, kwds = _xkwds_pop2(kwds, power=r) # for backward compatibility
114
- t, kwds = _xkwds_pop2(kwds, raiser=True)
116
+ r, X, kwds = _r_X_kwds(**root_name_f2product_nonfinites_RESIDUAL_raiser)
115
117
  Fsum.__init__(self, **kwds)
116
118
  self(_0_0)
117
119
  if xs:
118
- self._facc_power(r, xs, Fhypot, raiser=t)
119
- self._fset(self.root(r, raiser=t))
120
+ self._facc_power(r, xs, Fhypot, raiser=X)
121
+ self._fset(self.root(r, raiser=X))
120
122
  except Exception as X:
121
123
  raise self._ErrorXs(X, xs, root=r)
122
124
 
@@ -163,11 +165,11 @@ class Fpowers(Fsum):
163
165
  L{fpow<Fsum.fpow>}.
164
166
  '''
165
167
  try:
166
- t, kwds = _xkwds_pop2(name_f2product_nonfinites_RESIDUAL_raiser, raiser=True)
168
+ X, kwds = _xkwds_pop2(name_f2product_nonfinites_RESIDUAL_raiser, raiser=True)
167
169
  Fsum.__init__(self, **kwds)
168
170
  self(_0_0)
169
171
  if xs:
170
- self._facc_power(power, xs, Fpowers, raiser=t) # x**0 == 1
172
+ self._facc_power(power, xs, Fpowers, raiser=X) # x**0 == 1
171
173
  except Exception as X:
172
174
  raise self._ErrorXs(X, xs, power=power)
173
175
 
@@ -187,12 +189,12 @@ class Froot(Fsum):
187
189
  L{fpow<Fsum.fpow>}.
188
190
  '''
189
191
  try:
190
- raiser, kwds = _xkwds_pop2(name_f2product_nonfinites_RESIDUAL_raiser, raiser=True)
192
+ X, kwds = _xkwds_pop2(name_f2product_nonfinites_RESIDUAL_raiser, raiser=True)
191
193
  Fsum.__init__(self, **kwds)
192
194
  self(_0_0)
193
195
  if xs:
194
196
  self.fadd(xs)
195
- self(self.root(root, raiser=raiser))
197
+ self(self.root(root, raiser=X))
196
198
  except Exception as X:
197
199
  raise self._ErrorXs(X, xs, root=root)
198
200
 
@@ -425,8 +427,7 @@ def fdot(xs, *ys, **start_f2product_nonfinites):
425
427
  '''Return the precision dot product M{sum(xs[i] * ys[i] for i in range(len(xs)))}.
426
428
 
427
429
  @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
429
- positional.
430
+ @arg ys: Other values (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}), all positional.
430
431
  @kwarg start_f2product_nonfinites: Optional bias C{B{start}=0} (C{scalar}, an
431
432
  L{Fsum} or L{Fsum2Tuple}) and settings C{B{f2product}=None} (C{bool})
432
433
  and C{B{nonfinites=True}} (C{bool}), see class L{Fsum<Fsum.__init__>}.
@@ -458,9 +459,9 @@ def fdot_(*xys, **start_f2product_nonfinites):
458
459
  def fdot3(xs, ys, zs, **start_f2product_nonfinites):
459
460
  '''Return the (precision) dot product M{start + sum(xs[i] * ys[i] * zs[i] for i in range(len(xs)))}.
460
461
 
461
- @arg xs: Iterable (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
462
- @arg ys: Iterable (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
463
- @arg zs: Iterable (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
462
+ @arg xs: X values iterable (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
463
+ @arg ys: Y values iterable (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
464
+ @arg zs: Z values iterable (each C{scalar}, an L{Fsum} or L{Fsum2Tuple}).
464
465
 
465
466
  @see: Function L{fdot} for further details.
466
467
 
@@ -1094,7 +1095,7 @@ def zqrt(x):
1094
1095
 
1095
1096
  # **) MIT License
1096
1097
  #
1097
- # Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
1098
+ # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
1098
1099
  #
1099
1100
  # Permission is hereby granted, free of charge, to any person obtaining a
1100
1101
  # copy of this software and associated documentation files (the "Software"),
pygeodesy/formy.py CHANGED
@@ -6,12 +6,12 @@ u'''Formulary of basic geodesy functions and approximations.
6
6
  # make sure int/int division yields float quotient, see .basics
7
7
  from __future__ import division as _; del _ # PYCHOK semicolon
8
8
 
9
- # from pygeodesy.basics import W_args_kwds_count2
9
+ # from pygeodesy.basics import _args_kwds_count2, _copysign # from .constants
10
10
  # from pygeodesy.cartesianBase import CartesianBase # _MODS
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
- _32_0, _90_0, _180_0, _360_0
14
+ _32_0, _90_0, _180_0, _360_0, _copysign
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
@@ -26,30 +26,47 @@ from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS
26
26
  from pygeodesy.named import _name__, _name2__, _NamedTuple, _xnamed, \
27
27
  _DUNDER_nameof
28
28
  from pygeodesy.namedTuples import Bearing2Tuple, Distance4Tuple, LatLon2Tuple, \
29
- Intersection3Tuple, PhiLam2Tuple, Vector3Tuple
29
+ Intersection3Tuple, PhiLam2Tuple
30
30
  # from pygeodesy.streprs import Fmt, unstr # from .fsums
31
31
  # from pygeodesy.triaxials import _hartzell3 # _MODS
32
- from pygeodesy.units import _isHeight, _isRadius, Bearing, Degrees_, Distance, \
33
- Distance_, Height, Lamd, Lat, Lon, Meter_, Phid, \
34
- Radians, Radians_, Radius, Radius_, Scalar, _100km
35
- from pygeodesy.utily import acos1, atan2b, atan2d, degrees2m, _loneg, m2degrees, \
36
- tan_2, sincos2, sincos2_, sincos2d_, _Wrap
32
+ from pygeodesy.units import _isDegrees, _isHeight, _isRadius, Bearing, Degrees_, \
33
+ Distance, Distance_, Height, Lamd, Lat, Lon, Meter_, \
34
+ Phid, Radians, Radians_, Radius, Radius_, Scalar, _100km
35
+ from pygeodesy.utily import acos1, atan2, atan2b, degrees2m, _loneg, m2degrees, \
36
+ tan_2, sincos2, sincos2_, _Wrap
37
37
  # from pygeodesy.vector3d import _otherV3d # _MODS
38
38
  # from pygeodesy.vector3dBase import _xyz_y_z3 # _MODS
39
39
  # from pygeodesy import ellipsoidalExact, ellipsoidalKarney, vector3d, \
40
40
  # sphericalNvector, sphericalTrigonometry # _MODS
41
41
 
42
42
  from contextlib import contextmanager
43
- from math import asin, atan, atan2, cos, degrees, fabs, radians, sin, sqrt # pow
43
+ from math import asin, atan, cos, degrees, fabs, radians, sin, sqrt # pow
44
44
 
45
45
  __all__ = _ALL_LAZY.formy
46
- __version__ = '24.10.14'
46
+ __version__ = '24.12.06'
47
47
 
48
48
  _RADIANS2 = (PI / _180_0)**2 # degrees- to radians-squared
49
49
  _ratio_ = 'ratio'
50
50
  _xline_ = 'xline'
51
51
 
52
52
 
53
+ def angle2chord(rad, radius=R_M):
54
+ '''Get the chord length of a (central) angle or I{angular} distance.
55
+
56
+ @arg rad: Central angle (C{radians}).
57
+ @kwarg radius: Mean earth radius (C{meter}, conventionally), datum (L{Datum}) or ellipsoid
58
+ (L{Ellipsoid}, L{Ellipsoid2} or L{a_f2Tuple}) to use or C{None}.
59
+
60
+ @return: Chord length (C{meter}, same units as B{C{radius}} or if C{B{radius} is None}, C{radians}).
61
+
62
+ @see: Function L{chord2angle}, method L{intermediateChordTo<sphericalNvector.LatLon.intermediateChordTo>} and
63
+ U{great-circle-distance<https://WikiPedia.org/wiki/Great-circle_distance#Relation_between_central_angle_and_chord_length>}.
64
+ '''
65
+ d = _isDegrees(rad, iscalar=False)
66
+ r = sin((radians(rad) if d else rad) / _2_0) * _2_0
67
+ return (degrees(r) if d else r) if radius is None else (_mean_radius(radius) * r)
68
+
69
+
53
70
  def _anti2(a, b, n_2, n, n2):
54
71
  '''(INTERNAL) Helper for C{antipode} and C{antipode_}.
55
72
  '''
@@ -161,6 +178,30 @@ def _bearingTo2(p1, p2, wrap=False): # for points.ispolar, sphericalTrigonometr
161
178
  name__=_bearingTo2)
162
179
 
163
180
 
181
+ def chord2angle(chord, radius=R_M):
182
+ '''Get the (central) angle from a chord length or distance.
183
+
184
+ @arg chord: Length or distance (C{meter}, same units as B{C{radius}}).
185
+ @kwarg radius: Mean earth radius (C{meter}, conventionally), datum (L{Datum}) or
186
+ ellipsoid (L{Ellipsoid}, L{Ellipsoid2} or L{a_f2Tuple}) to use.
187
+
188
+ @return: Angle (C{radians} with sign of B{C{chord}}) or C{0} if C{B{radius}=0}.
189
+
190
+ @note: The angle will exceed C{PI} if C{B{chord} > B{radius} * 2}.
191
+
192
+ @see: Function L{angle2chord}.
193
+ '''
194
+ m = _mean_radius(radius)
195
+ r = fabs(chord / (m * _2_0)) if m > 0 else _0_0
196
+ if r:
197
+ i = int(r)
198
+ if i > 0:
199
+ r -= i
200
+ i *= PI
201
+ r = asin(r) + i
202
+ return _copysign(r * _2_0, chord)
203
+
204
+
164
205
  def compassAngle(lat1, lon1, lat2, lon2, adjust=True, wrap=False):
165
206
  '''Return the angle from North for the direction vector M{(lon2 - lon1,
166
207
  lat2 - lat1)} between two points.
@@ -424,7 +465,7 @@ def _ellipsoidal(earth, where):
424
465
 
425
466
 
426
467
  def equirectangular(lat1, lon1, lat2, lon2, radius=R_M, **adjust_limit_wrap):
427
- '''Compute the distance between two points using the U{Equirectangular Approximation
468
+ '''Approximate the distance between two points using the U{Equirectangular Approximation
428
469
  / Projection<https://www.Movable-Type.co.UK/scripts/latlong.html#equirectangular>}.
429
470
 
430
471
  @arg lat1: Start latitude (C{degrees}).
@@ -449,14 +490,14 @@ def equirectangular(lat1, lon1, lat2, lon2, radius=R_M, **adjust_limit_wrap):
449
490
 
450
491
 
451
492
  def _equirectangular(lat1, lon1, lat2, lon2, **adjust_limit_wrap):
452
- '''(INTERNAL) Helper for the L{frechet._FrechetMeterRadians}
453
- and L{hausdorff._HausdorffMeterRedians} classes.
493
+ '''(INTERNAL) Helper for classes L{frechet._FrechetMeterRadians} and
494
+ L{hausdorff._HausdorffMeterRedians}.
454
495
  '''
455
496
  return equirectangular4(lat1, lon1, lat2, lon2, **adjust_limit_wrap).distance2 * _RADIANS2
456
497
 
457
498
 
458
499
  def equirectangular4(lat1, lon1, lat2, lon2, adjust=True, limit=45, wrap=False):
459
- '''Compute the distance between two points using the U{Equirectangular Approximation
500
+ '''Approximate the distance between two points using the U{Equirectangular Approximation
460
501
  / Projection<https://www.Movable-Type.co.UK/scripts/latlong.html#equirectangular>}.
461
502
 
462
503
  This approximation is valid for short distance of several hundred Km or Miles, see
@@ -473,10 +514,10 @@ def equirectangular4(lat1, lon1, lat2, lon2, adjust=True, limit=45, wrap=False):
473
514
  @kwarg wrap: If C{True}, wrap or I{normalize} and unroll B{C{lat2}} and B{C{lon2}}
474
515
  (C{bool}).
475
516
 
476
- @return: A L{Distance4Tuple}C{(distance2, delta_lat, delta_lon, unroll_lon2)}
477
- in C{degrees squared}.
517
+ @return: A L{Distance4Tuple}C{(distance2, delta_lat, delta_lon, unroll_lon2)} with
518
+ C{distance2} in C{degrees squared}.
478
519
 
479
- @raise LimitError: If the lat- and/or longitudinal delta exceeds the B{C{-limit..limit}}
520
+ @raise LimitError: The lat- or longitudinal delta exceeds the B{C{-limit..limit}}
480
521
  range and L{limiterrors<pygeodesy.limiterrors>} is C{True}.
481
522
 
482
523
  @see: U{Local, flat earth approximation<https://www.EdWilliams.org/avform.htm#flat>},
@@ -485,7 +526,10 @@ def equirectangular4(lat1, lon1, lat2, lon2, adjust=True, limit=45, wrap=False):
485
526
  L{thomas} and L{vincentys} and methods L{Ellipsoid.distance2}, C{LatLon.distanceTo*}
486
527
  and C{LatLon.equirectangularTo}.
487
528
  '''
488
- d_lon, lat2, ulon2 = _Wrap.latlon3(lon1, lat2, lon2, wrap)
529
+ if wrap:
530
+ d_lon, lat2, ulon2 = _Wrap.latlon3(lon1, lat2, lon2, wrap)
531
+ else:
532
+ d_lon, ulon2 = (lon2 - lon1), lon2
489
533
  d_lat = lat2 - lat1
490
534
 
491
535
  if limit and limit > 0 and limiterrors():
@@ -996,18 +1040,16 @@ def hartzell(pov, los=False, earth=_WGS84, **name_LatLon_and_kwds):
996
1040
 
997
1041
  def haversine(lat1, lon1, lat2, lon2, radius=R_M, wrap=False):
998
1042
  '''Compute the distance between two (spherical) points using the
999
- U{Haversine<https://www.Movable-Type.co.UK/scripts/latlong.html>}
1000
- formula.
1043
+ U{Haversine<https://www.Movable-Type.co.UK/scripts/latlong.html>} formula.
1001
1044
 
1002
1045
  @arg lat1: Start latitude (C{degrees}).
1003
1046
  @arg lon1: Start longitude (C{degrees}).
1004
1047
  @arg lat2: End latitude (C{degrees}).
1005
1048
  @arg lon2: End longitude (C{degrees}).
1006
- @kwarg radius: Mean earth radius (C{meter}), datum (L{Datum})
1007
- or ellipsoid (L{Ellipsoid}, L{Ellipsoid2} or
1008
- L{a_f2Tuple}) to use.
1009
- @kwarg wrap: If C{True}, wrap or I{normalize} and unroll
1010
- B{C{lat2}} and B{C{lon2}} (C{bool}).
1049
+ @kwarg radius: Mean earth radius (C{meter}), datum (L{Datum}) or ellipsoid
1050
+ (L{Ellipsoid}, L{Ellipsoid2} or L{a_f2Tuple}) to use.
1051
+ @kwarg wrap: If C{True}, wrap or I{normalize} and unroll B{C{lat2}} and
1052
+ B{C{lon2}} (C{bool}).
1011
1053
 
1012
1054
  @return: Distance (C{meter}, same units as B{C{radius}}).
1013
1055
 
@@ -1026,9 +1068,8 @@ def haversine(lat1, lon1, lat2, lon2, radius=R_M, wrap=False):
1026
1068
 
1027
1069
 
1028
1070
  def haversine_(phi2, phi1, lam21):
1029
- '''Compute the I{angular} distance between two (spherical) points
1030
- using the U{Haversine<https://www.Movable-Type.co.UK/scripts/latlong.html>}
1031
- formula.
1071
+ '''Compute the I{angular} distance between two (spherical) points using the
1072
+ U{Haversine<https://www.Movable-Type.co.UK/scripts/latlong.html>} formula.
1032
1073
 
1033
1074
  @arg phi2: End latitude (C{radians}).
1034
1075
  @arg phi1: Start latitude (C{radians}).
@@ -1395,24 +1436,6 @@ def isnormal_(phi, lam, eps=0):
1395
1436
  return (PI_2 - fabs(phi)) >= eps and (PI - fabs(lam)) >= eps
1396
1437
 
1397
1438
 
1398
- def latlon2n_xyz(lat, lon, **name):
1399
- '''Convert lat-, longitude to C{n-vector} (I{normal} to the
1400
- earth's surface) X, Y and Z components.
1401
-
1402
- @arg lat: Latitude (C{degrees}).
1403
- @arg lon: Longitude (C{degrees}).
1404
- @kwarg name: Optional C{B{name}=NN} (C{str}).
1405
-
1406
- @return: A L{Vector3Tuple}C{(x, y, z)}.
1407
-
1408
- @see: Function L{philam2n_xyz}.
1409
-
1410
- @note: These are C{n-vector} x, y and z components,
1411
- I{NOT} geocentric ECEF x, y and z coordinates!
1412
- '''
1413
- return _2n_xyz(name, *sincos2d_(lat, lon))
1414
-
1415
-
1416
1439
  def _normal2(a, b, n_2, n, n2):
1417
1440
  '''(INTERNAL) Helper for C{normal} and C{normal_}.
1418
1441
  '''
@@ -1458,44 +1481,6 @@ def normal_(phi, lam, **name):
1458
1481
  name=_name__(name, name__=normal_))
1459
1482
 
1460
1483
 
1461
- def _2n_xyz(name, sa, ca, sb, cb): # name always **name
1462
- '''(INTERNAL) Helper for C{latlon2n_xyz} and C{philam2n_xyz}.
1463
- '''
1464
- # Kenneth Gade eqn 3, but using right-handed
1465
- # vector x -> 0°E,0°N, y -> 90°E,0°N, z -> 90°N
1466
- return Vector3Tuple(ca * cb, ca * sb, sa, **name)
1467
-
1468
-
1469
- def n_xyz2latlon(x, y, z, **name):
1470
- '''Convert C{n-vector} components to lat- and longitude in C{degrees}.
1471
-
1472
- @arg x: X component (C{scalar}).
1473
- @arg y: Y component (C{scalar}).
1474
- @arg z: Z component (C{scalar}).
1475
- @kwarg name: Optional C{B{name}=NN} (C{str}).
1476
-
1477
- @return: A L{LatLon2Tuple}C{(lat, lon)}.
1478
-
1479
- @see: Function L{n_xyz2philam}.
1480
- '''
1481
- return LatLon2Tuple(atan2d(z, hypot(x, y)), atan2d(y, x), **name)
1482
-
1483
-
1484
- def n_xyz2philam(x, y, z, **name):
1485
- '''Convert C{n-vector} components to lat- and longitude in C{radians}.
1486
-
1487
- @arg x: X component (C{scalar}).
1488
- @arg y: Y component (C{scalar}).
1489
- @arg z: Z component (C{scalar}).
1490
- @kwarg name: Optional C{B{name}=NN} (C{str}).
1491
-
1492
- @return: A L{PhiLam2Tuple}C{(phi, lam)}.
1493
-
1494
- @see: Function L{n_xyz2latlon}.
1495
- '''
1496
- return PhiLam2Tuple(atan2(z, hypot(x, y)), atan2(y, x), **name)
1497
-
1498
-
1499
1484
  def _opposes(d, m, n, n2):
1500
1485
  '''(INTERNAL) Helper for C{opposing} and C{opposing_}.
1501
1486
  '''
@@ -1536,24 +1521,6 @@ def opposing_(radians1, radians2, margin=PI_2):
1536
1521
  return _opposes(radians2 - radians1, m, PI, PI2)
1537
1522
 
1538
1523
 
1539
- def philam2n_xyz(phi, lam, **name):
1540
- '''Convert lat-, longitude to C{n-vector} (I{normal} to the
1541
- earth's surface) X, Y and Z components.
1542
-
1543
- @arg phi: Latitude (C{radians}).
1544
- @arg lam: Longitude (C{radians}).
1545
- @kwarg name: Optional name (C{str}).
1546
-
1547
- @return: A L{Vector3Tuple}C{(x, y, z)}.
1548
-
1549
- @see: Function L{latlon2n_xyz}.
1550
-
1551
- @note: These are C{n-vector} x, y and z components,
1552
- I{NOT} geocentric ECEF x, y and z coordinates!
1553
- '''
1554
- return _2n_xyz(name, *sincos2_(phi, lam))
1555
-
1556
-
1557
1524
  def _Propy(func, nargs, kwds):
1558
1525
  '''(INTERNAL) Helper for the C{frechet.[-]Frechet**} and
1559
1526
  C{hausdorff.[-]Hausdorff*} classes.
@@ -1649,7 +1616,7 @@ def _radistance(inst):
1649
1616
  def _scale_deg(lat1, lat2): # degrees
1650
1617
  # scale factor cos(mean of lats) for delta lon
1651
1618
  m = fabs(lat1 + lat2) * _0_5
1652
- return cos(radians(m)) if m < 90 else _0_0
1619
+ return cos(radians(m)) if m < _90_0 else _0_0
1653
1620
 
1654
1621
 
1655
1622
  def _scale_rad(phi1, phi2): # radians, by .frechet, .hausdorff, .heights
@@ -1810,7 +1777,7 @@ def vincentys_(phi2, phi1, lam21):
1810
1777
 
1811
1778
  # **) MIT License
1812
1779
  #
1813
- # Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
1780
+ # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
1814
1781
  #
1815
1782
  # Permission is hereby granted, free of charge, to any person obtaining a
1816
1783
  # copy of this software and associated documentation files (the "Software"),
pygeodesy/frechet.py CHANGED
@@ -856,7 +856,7 @@ class Frechet6Tuple(_NamedTuple):
856
856
 
857
857
  # **) MIT License
858
858
  #
859
- # Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
859
+ # Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
860
860
  #
861
861
  # Permission is hereby granted, free of charge, to any person obtaining a
862
862
  # copy of this software and associated documentation files (the "Software"),
pygeodesy/fstats.py CHANGED
@@ -803,7 +803,7 @@ __all__ += _ALL_DOCS(_FstatsBase, _FstatsNamed)
803
803
 
804
804
  # **) MIT License
805
805
  #
806
- # Copyright (C) 2021-2024 -- mrJean1 at Gmail -- All Rights Reserved.
806
+ # Copyright (C) 2021-2025 -- mrJean1 at Gmail -- All Rights Reserved.
807
807
  #
808
808
  # Permission is hereby granted, free of charge, to any person obtaining a
809
809
  # copy of this software and associated documentation files (the "Software"),