pygeodesy 24.3.24__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 (115) hide show
  1. PyGeodesy-24.3.24.dist-info/METADATA +272 -0
  2. PyGeodesy-24.3.24.dist-info/RECORD +115 -0
  3. PyGeodesy-24.3.24.dist-info/WHEEL +6 -0
  4. PyGeodesy-24.3.24.dist-info/top_level.txt +1 -0
  5. pygeodesy/LICENSE +21 -0
  6. pygeodesy/__init__.py +615 -0
  7. pygeodesy/__main__.py +103 -0
  8. pygeodesy/albers.py +867 -0
  9. pygeodesy/auxilats/_CX_4.py +218 -0
  10. pygeodesy/auxilats/_CX_6.py +314 -0
  11. pygeodesy/auxilats/_CX_8.py +475 -0
  12. pygeodesy/auxilats/__init__.py +54 -0
  13. pygeodesy/auxilats/__main__.py +86 -0
  14. pygeodesy/auxilats/auxAngle.py +548 -0
  15. pygeodesy/auxilats/auxDLat.py +302 -0
  16. pygeodesy/auxilats/auxDST.py +296 -0
  17. pygeodesy/auxilats/auxLat.py +848 -0
  18. pygeodesy/auxilats/auxily.py +272 -0
  19. pygeodesy/azimuthal.py +1150 -0
  20. pygeodesy/basics.py +892 -0
  21. pygeodesy/booleans.py +2031 -0
  22. pygeodesy/cartesianBase.py +1062 -0
  23. pygeodesy/clipy.py +704 -0
  24. pygeodesy/constants.py +516 -0
  25. pygeodesy/css.py +660 -0
  26. pygeodesy/datums.py +752 -0
  27. pygeodesy/deprecated/__init__.py +61 -0
  28. pygeodesy/deprecated/bases.py +40 -0
  29. pygeodesy/deprecated/classes.py +262 -0
  30. pygeodesy/deprecated/consterns.py +54 -0
  31. pygeodesy/deprecated/datum.py +40 -0
  32. pygeodesy/deprecated/functions.py +375 -0
  33. pygeodesy/deprecated/nvector.py +48 -0
  34. pygeodesy/deprecated/rhumbBase.py +32 -0
  35. pygeodesy/deprecated/rhumbaux.py +33 -0
  36. pygeodesy/deprecated/rhumbsolve.py +33 -0
  37. pygeodesy/deprecated/rhumbx.py +33 -0
  38. pygeodesy/dms.py +986 -0
  39. pygeodesy/ecef.py +1348 -0
  40. pygeodesy/elevations.py +279 -0
  41. pygeodesy/ellipsoidalBase.py +1224 -0
  42. pygeodesy/ellipsoidalBaseDI.py +913 -0
  43. pygeodesy/ellipsoidalExact.py +343 -0
  44. pygeodesy/ellipsoidalGeodSolve.py +343 -0
  45. pygeodesy/ellipsoidalKarney.py +403 -0
  46. pygeodesy/ellipsoidalNvector.py +685 -0
  47. pygeodesy/ellipsoidalVincenty.py +590 -0
  48. pygeodesy/ellipsoids.py +2476 -0
  49. pygeodesy/elliptic.py +1198 -0
  50. pygeodesy/epsg.py +243 -0
  51. pygeodesy/errors.py +804 -0
  52. pygeodesy/etm.py +1190 -0
  53. pygeodesy/fmath.py +1013 -0
  54. pygeodesy/formy.py +1818 -0
  55. pygeodesy/frechet.py +865 -0
  56. pygeodesy/fstats.py +760 -0
  57. pygeodesy/fsums.py +1898 -0
  58. pygeodesy/gars.py +358 -0
  59. pygeodesy/geodesicw.py +581 -0
  60. pygeodesy/geodesicx/_C4_24.py +1699 -0
  61. pygeodesy/geodesicx/_C4_27.py +2395 -0
  62. pygeodesy/geodesicx/_C4_30.py +3301 -0
  63. pygeodesy/geodesicx/__init__.py +48 -0
  64. pygeodesy/geodesicx/__main__.py +91 -0
  65. pygeodesy/geodesicx/gx.py +1382 -0
  66. pygeodesy/geodesicx/gxarea.py +535 -0
  67. pygeodesy/geodesicx/gxbases.py +154 -0
  68. pygeodesy/geodesicx/gxline.py +669 -0
  69. pygeodesy/geodsolve.py +426 -0
  70. pygeodesy/geohash.py +914 -0
  71. pygeodesy/geoids.py +1884 -0
  72. pygeodesy/hausdorff.py +892 -0
  73. pygeodesy/heights.py +1155 -0
  74. pygeodesy/interns.py +687 -0
  75. pygeodesy/iters.py +545 -0
  76. pygeodesy/karney.py +919 -0
  77. pygeodesy/ktm.py +633 -0
  78. pygeodesy/latlonBase.py +1766 -0
  79. pygeodesy/lazily.py +960 -0
  80. pygeodesy/lcc.py +684 -0
  81. pygeodesy/ltp.py +1107 -0
  82. pygeodesy/ltpTuples.py +1563 -0
  83. pygeodesy/mgrs.py +721 -0
  84. pygeodesy/named.py +1324 -0
  85. pygeodesy/namedTuples.py +683 -0
  86. pygeodesy/nvectorBase.py +695 -0
  87. pygeodesy/osgr.py +781 -0
  88. pygeodesy/points.py +1686 -0
  89. pygeodesy/props.py +628 -0
  90. pygeodesy/resections.py +1048 -0
  91. pygeodesy/rhumb/__init__.py +46 -0
  92. pygeodesy/rhumb/aux_.py +397 -0
  93. pygeodesy/rhumb/bases.py +1148 -0
  94. pygeodesy/rhumb/ekx.py +563 -0
  95. pygeodesy/rhumb/solve.py +572 -0
  96. pygeodesy/simplify.py +647 -0
  97. pygeodesy/solveBase.py +472 -0
  98. pygeodesy/sphericalBase.py +724 -0
  99. pygeodesy/sphericalNvector.py +1264 -0
  100. pygeodesy/sphericalTrigonometry.py +1447 -0
  101. pygeodesy/streprs.py +627 -0
  102. pygeodesy/trf.py +2079 -0
  103. pygeodesy/triaxials.py +1484 -0
  104. pygeodesy/units.py +969 -0
  105. pygeodesy/unitsBase.py +349 -0
  106. pygeodesy/ups.py +538 -0
  107. pygeodesy/utily.py +1231 -0
  108. pygeodesy/utm.py +762 -0
  109. pygeodesy/utmups.py +318 -0
  110. pygeodesy/utmupsBase.py +517 -0
  111. pygeodesy/vector2d.py +785 -0
  112. pygeodesy/vector3d.py +968 -0
  113. pygeodesy/vector3dBase.py +1049 -0
  114. pygeodesy/webmercator.py +383 -0
  115. pygeodesy/wgrs.py +439 -0
pygeodesy/constants.py ADDED
@@ -0,0 +1,516 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ u'''Single-instance C{float} and C{int} constants across C{pygeodesy} modules and
4
+ related functions L{pygeodesy.float_}, L{pygeodesy.isclose}, L{pygeodesy.isfinite},
5
+ L{pygeodesy.isinf}, L{pygeodesy.isint0}, L{pygeodesy.isnan}, L{pygeodesy.isnear0},
6
+ L{pygeodesy.isnear1}, L{pygeodesy.isnear90}, L{pygeodesy.isneg0}, L{pygeodesy.isninf},
7
+ L{pygeodesy.isnon0} and L{pygeodesy.remainder}.
8
+ '''
9
+ # make sure int/int division yields float quotient, see .basics
10
+ from __future__ import division as _; del _ # PYCHOK semicolon
11
+
12
+ from pygeodesy.basics import _0_0, _copysign, isbool, iscomplex, isint, _ALL_LAZY
13
+ from pygeodesy.errors import _xError, _xError2, _xkwds_get, _xkwds_item2
14
+ from pygeodesy.interns import _INF_, _NAN_, _UNDER_
15
+ # from pygeodesy.lazily import _ALL_LAZY # from .basics
16
+ # from pygeodesy.streprs import Fmt # from .unitsBase
17
+ from pygeodesy.unitsBase import Float, Int, Radius, Fmt
18
+
19
+ from math import fabs, isinf, isnan, pi as _PI, sqrt
20
+ try:
21
+ from math import inf as _inf, nan as _nan # PYCHOK Python 3+
22
+ except ImportError: # Python 2-
23
+ _inf, _nan = float(_INF_), float(_NAN_)
24
+
25
+ __all__ = _ALL_LAZY.constants
26
+ __version__ = '24.03.15'
27
+
28
+
29
+ def _copysign_0_0(y):
30
+ '''(INTERNAL) copysign(0.0, y), only C{float}.
31
+ '''
32
+ return _N_0_0 if y < 0 else _0_0
33
+
34
+
35
+ def _copysign_1_0(y):
36
+ '''(INTERNAL) copysign(1.0, y), only C{float}.
37
+ '''
38
+ return _N_1_0 if y < 0 else _1_0
39
+
40
+
41
+ def _copysignINF(y):
42
+ '''(INTERNAL) copysign(INF, y), only C{float}.
43
+ '''
44
+ return NINF if y < 0 else INF
45
+
46
+
47
+ def _Float(**name_arg):
48
+ '''(INTERNAL) New named, cached C{Float}.
49
+ '''
50
+ n, arg = _xkwds_item2(name_arg)
51
+ return Float(_float(arg), name=n)
52
+
53
+
54
+ def _Radius(**name_arg):
55
+ '''(INTERNAL) New named, cached C{Radius}.
56
+ '''
57
+ n, arg = _xkwds_item2(name_arg)
58
+ return Radius(_float(arg), name=n)
59
+
60
+
61
+ def float_(*fs, **sets): # sets=False
62
+ '''Get scalars as C{float} or I{intern}'ed C{float}.
63
+
64
+ @arg fs: One more values (C{scalar}), all positional.
65
+ @kwarg sets: Use C{B{sets}=True} to C{intern} each
66
+ B{C{fs}}, otherwise don't C{intern}.
67
+
68
+ @return: A single C{float} if only one B{C{fs}} is
69
+ given, otherwise a tuple of C{float}s.
70
+
71
+ @raise TypeError: Some B{C{fs}} is not C{scalar}.
72
+ '''
73
+ fl = []
74
+ _a = fl.append
75
+ _f = _floats.setdefault if _xkwds_get(sets, sets=False) else \
76
+ _floats.get
77
+ try:
78
+ for i, f in enumerate(fs):
79
+ f = float(f)
80
+ _a(_f(f, f))
81
+ except Exception as x:
82
+ E, t = _xError2(x)
83
+ fs_i = Fmt.SQUARE(fs=i)
84
+ raise E(fs_i, f, txt=t)
85
+ return fl[0] if len(fl) == 1 else tuple(fl)
86
+
87
+
88
+ def _float(f): # in .datums, .ellipsoids, ...
89
+ '''(INTERNAL) Cache initial C{float}s.
90
+ '''
91
+ f = float(f)
92
+ return _floats.setdefault(f, f) # PYCHOK del _floats
93
+
94
+
95
+ def float0_(*xs):
96
+ '''Yield C{B{x}s} as a non-NEG0 C{float}.
97
+ '''
98
+ for x in xs:
99
+ yield float(x) if x else _0_0
100
+
101
+
102
+ def _float0(f): # in .resections, .vector3dBase, ...
103
+ '''(INTERNAL) Return C{float(B{f})} or C{INT0}.
104
+ '''
105
+ if f:
106
+ f = float(f)
107
+ f = _floats.get(f, f)
108
+ elif f is not INT0:
109
+ f = float(f) or _0_0 # force None, NN error
110
+ return f
111
+
112
+
113
+ def _floatuple(*fs):
114
+ '''(INTERNAL) Cache a tuple of C{float}s.
115
+ '''
116
+ return tuple(map(_float, fs))
117
+
118
+
119
+ try:
120
+ from math import log2 as _log2
121
+ except ImportError: # Python 3.3-
122
+ from math import log as _log
123
+
124
+ def _log2(x): # in .rhumb.aux_, .auxilats.auxLat
125
+ return _log(x, 2)
126
+
127
+
128
+ def _naninf(p, *xs):
129
+ '''(INTERNAL) Return C{NAN}, C{NINF} or C{INF}.
130
+ '''
131
+ for x in xs:
132
+ p *= x # fmath.fprod(xs)
133
+ return _copysignINF(p) if isfinite(p) else p
134
+
135
+
136
+ def _over(p, q):
137
+ '''(INTERNAL) Return C{B{p} / B{q}} avoiding C{ZeroDivisionError} exceptions.
138
+ '''
139
+ try:
140
+ return (p / q)
141
+ except ZeroDivisionError:
142
+ return (_copysignINF(p) if isfinite(p) else NAN) if p else p
143
+
144
+
145
+ def _1_over(x):
146
+ '''(INTERNAL) Return reciprocal C{1 / B{x}} avoiding C{ZeroDivisionError} exceptions.
147
+ '''
148
+ try:
149
+ return _1_0 / float(x)
150
+ except ZeroDivisionError:
151
+ return NINF if isneg0(x) else INF
152
+
153
+
154
+ _floats = {} # PYCHOK floats cache, in .__main__
155
+ # _float = float # PYCHOK expected
156
+ # del _floats # XXX zap floats cache never
157
+
158
+ _0_0 = _float( _0_0) # PYCHOK expected
159
+ _0_0_1T = _0_0, # PYCHOK 1-tuple
160
+ _0_0_9T = _0_0_1T * 9 # PYCHOK 9-tuple
161
+ _0_0001 = _float( 0.0001) # PYCHOK expected
162
+ _0_001 = _float( 0.001) # PYCHOK expected
163
+ _0_01 = _float( 0.01) # PYCHOK expected
164
+ _0_1 = _float( 0.1) # PYCHOK expected
165
+ _0_125 = _float( 0.125) # PYCHOK expected
166
+ _0_25 = _float( 0.25) # PYCHOK expected
167
+ _0_5 = _float( 0.5) # PYCHOK expected
168
+ _1_0 = _float( 1) # PYCHOK expected
169
+ _1_0_1T = _1_0, # PYCHOK 1-tuple
170
+ _1_5 = _float( 1.5) # PYCHOK expected
171
+ _1_75 = _float( 1.75) # PYCHOK expected
172
+ _2_0 = _float( 2) # PYCHOK expected
173
+ _3_0 = _float( 3) # PYCHOK expected
174
+ _4_0 = _float( 4) # PYCHOK expected
175
+ _5_0 = _float( 5) # PYCHOK expected
176
+ _6_0 = _float( 6) # PYCHOK expected
177
+ _8_0 = _float( 8) # PYCHOK expected
178
+ _9_0 = _float( 9) # PYCHOK expected
179
+ _10_0 = _float( 10) # PYCHOK expected
180
+ _16_0 = _float( 16) # PYCHOK expected
181
+ _32_0 = _float( 32) # PYCHOK expected
182
+ _60_0 = _float( 60) # PYCHOK expected
183
+ _90_0 = _float( 90) # PYCHOK expected
184
+ _100_0 = _float( 100) # PYCHOK expected
185
+ _180_0 = _float( 180) # PYCHOK expected
186
+ _270_0 = _float( 270) # PYCHOK expected
187
+ _360_0 = _float( 360) # PYCHOK expected
188
+ _400_0 = _float( 400) # PYCHOK expected
189
+ _720_0 = _float( 720) # PYCHOK expected
190
+ _1000_0 = _float(1000) # PYCHOK expected
191
+ _3600_0 = _float(3600) # PYCHOK expected
192
+
193
+ _N_0_0 = float( '-0.0') # PYCHOK NOT _float!
194
+ _N_0_5 = _float( -_0_5) # PYCHOK expected
195
+ _N_1_0 = _float( -_1_0) # PYCHOK expected
196
+ _N_2_0 = _float( -_2_0) # PYCHOK expected
197
+ _N_90_0 = _float( -_90_0) # PYCHOK expected
198
+ _N_180_0 = _float(-_180_0) # PYCHOK expected
199
+
200
+ _M_KM = _1000_0 # meter per Kilo meter, see .utily
201
+ _M_NM = _float(1852.0) # meter per Nautical Mile, exactly
202
+ _M_SM = _float(1609.344) # meter per Statute Mile
203
+
204
+ try:
205
+ from sys import float_info as _f_i
206
+ # @see: <https://NumPy.org/doc/stable/reference/generated/numpy.finfo.html>
207
+ DIG = Int( DIG =_f_i.dig) # PYCHOK system's float decimal digits
208
+ EPS = _Float(EPS =_f_i.epsilon) # PYCHOK system's EPSilon
209
+ MANT_DIG = Int( MANT_DIG=_f_i.mant_dig) # PYCHOK system's float mantissa bits
210
+ MAX = _Float(MAX =_f_i.max) # PYCHOK system's MAX float 1.7976931348623157e+308
211
+ MAX_EXP = Int( MAX_EXP =_f_i.max_exp) # PYTHON system's max base 2 exponent
212
+ MIN = _Float(MIN =_f_i.min) # PYCHOK system's MIN float 2.2250738585072014e-308
213
+ MIN_EXP = Int( MIN_EXP =_f_i.min_exp) # PYTHON system's min base 2 exponent
214
+ # RADIX = Int( RADIX =_f_i.radix) # PYTHON system's float base
215
+ del _f_i
216
+ except ImportError: # PYCHOK no cover
217
+ DIG = Int( DIG =15) # PYCHOK system's 64-bit float decimal digits
218
+ EPS = _Float(EPS =2.220446049250313e-16) # PYCHOK EPSilon 2**-52, M{EPS +/- 1 != 1}
219
+ MANT_DIG = Int( MANT_DIG=53) # PYCHOK float mantissa bits ≈ 53 (C{int})
220
+ MAX = _Float(MAX =pow(_2_0, 1023) * (_2_0 - EPS)) # PYCHOK ≈ 10**308
221
+ MAX_EXP = Int( MAX_ESP =_log2(MAX)) # 308 base 10
222
+ MIN = _Float(MIN =pow(_2_0, -1021)) # PYCHOK ≈ 10**-308
223
+ MIN_EXP = Int(MIN_EXP =_log2(MIN)) # -307 base 10
224
+ # RADIX = Int(Radix =2) # base
225
+
226
+ EPS0 = _Float( EPS0 = EPS**2) # PYCHOK near-/non-zero comparison 4.930381e-32, or EPS or EPS_2
227
+ EPS02 = _Float( EPS02 = EPS**4) # PYCHOK near-zero-squared comparison 2.430865e-63
228
+ EPS_2 = _Float( EPS_2 = EPS / _2_0) # PYCHOK ≈ 1.110223024625e-16
229
+ EPS1 = _Float( EPS1 =_1_0 - EPS) # PYCHOK ≈ 0.9999999999999998
230
+ EPS2 = _Float( EPS2 = EPS * _2_0) # PYCHOK ≈ 4.440892098501e-16
231
+ EPS4 = _Float( EPS4 = EPS * _4_0) # PYCHOK ≈ 8.881784197001e-16
232
+ # _1EPS = _Float(_1EPS =_1_0 + EPS) # PYCHOK ≈ 1.0000000000000002
233
+ _1_EPS = _Float(_1_EPS =_1_0 / EPS) # PYCHOK = 4503599627370496.0
234
+ # _2_EPS = _Float(_2_EPS =_2_0 / EPS) # PYCHOK = 9007199254740992.0
235
+ _EPS2e4 = _Float(_EPS2e4 = EPS2 * 1.e4) # PYCHOK ≈ 4.440892098501e-12
236
+ _EPS4e8 = _Float(_EPS4e8 = EPS4 * 1.e8) # PYCHOK ≈ 8.881784197001e-08
237
+ _EPSmin = _Float(_EPSmin = sqrt(MIN)) # PYCHOK = 1.49166814624e-154
238
+ _EPSqrt = _Float(_EPSqrt = sqrt(EPS)) # PYCHOK = 1.49011611938e5-08
239
+ _EPStol = _Float(_EPStol =_EPSqrt * _0_1) # PYCHOK = 1.49011611938e5-09 == sqrt(EPS * _0_01)
240
+
241
+ _89_999_ = _Float(_89_999_= EPS1 * _90_0) # just below 90.0
242
+ # <https://Numbers.Computation.Free.FR/Constants/Miscellaneous/digits.html>
243
+ _1__90 = _Float(_1__90 =_1_0 / _90_0) # PYCHOK = 0.011_111_111_111_111_111_111_111_111_111_111_111_111_111_111_11111
244
+ _2__PI = _Float(_2__PI =_2_0 / _PI) # PYCHOK = 0.636_619_772_367_581_343_075_535_053_490_057_448_137_838_582_96182
245
+
246
+ _1_16th = _Float(_1_16th =_1_0 / _16_0) # PYCHOK in .ellipsoids, .karney
247
+ _1_64th = _Float(_1_64th =_1_0 / 64) # PYCHOK in .elliptic, pow(2.0, -6)
248
+ _1_3rd = _Float(_1_3rd =_1_0 / _3_0) # PYCHOK in .fmath
249
+ _1_6th = _Float(_1_6th =_1_0 / _6_0) # PYCHOK in .fmath
250
+ _2_3rd = _Float(_2_3rd =_2_0 / _3_0) # PYCHOK in .fmath
251
+
252
+ _K0_UTM = _Float(_K0_UTM = 0.9996) # PYCHOK in .etm, .ktm, .utm, UTM scale at central meridian
253
+ # sqrt(2) <https://WikiPedia.org/wiki/Square_root_of_2>
254
+ # 1.414213562373095_048_801_688_724_209_698_078_569_671_875_376_948_073_176_679_737_99
255
+ # _1SQRT2= _Float(_1SQRT2 =sqrt(_2_0) + 1)
256
+ _SQRT2_2 = _Float(_SQRT2_2=sqrt(_0_5)) # PYCHOK = 0.707106781186547_6 == sqrt(2) / 2
257
+
258
+ INF = Float(INF =_inf) # PYCHOK INFinity, see function L{isinf}, L{isfinite}, NOT _Float!
259
+ INT0 = Int( INT0= 0) # PYCHOK unique int(0) instance, see .fsums, useZ=False
260
+ NAN = Float(NAN =_nan) # PYCHOK Not-A-Number, see function L{isnan}, NOT _Float!
261
+ NEG0 = Float(NEG0=_N_0_0) # PYCHOK NEGative 0.0, see function L{isneg0}, NOT _Float!
262
+ NINF = Float(NINF=-INF) # PYCHOK Negative INFinity, NOT _Float!
263
+
264
+ PI = _Float(PI =_PI) # 3.1415_9265_3589_7932_3846_2643_3832_795
265
+ PI2 = _Float(PI2 =_PI * _2_0) # PYCHOK Two PI, M{PI * 2} aka I{Tau}
266
+ PI_2 = _Float(PI_2 =_PI / _2_0) # PYCHOK Half PI, M{PI / 2}
267
+ PI3 = _Float(PI3 =_PI * _3_0) # PYCHOK Three PI, M{PI * 3}
268
+ PI3_2 = _Float(PI3_2=_PI * _1_5) # PYCHOK PI and a half, M{PI * 3 / 2}
269
+ PI_3 = _Float(PI_3 =_PI / _3_0) # PYCHOK One third PI, M{PI / 3}
270
+ PI4 = _Float(PI4 =_PI * _4_0) # PYCHOK Four PI, M{PI * 4}
271
+ PI_4 = _Float(PI_4 =_PI / _4_0) # PYCHOK Quarter PI, M{PI / 4}
272
+
273
+ R_MA = _Radius(R_MA=6378137.0) # PYCHOK equatorial earth radius (C{meter}), WGS84, EPSG:3785
274
+ R_MB = _Radius(R_MB=6356752.3) # PYCHOK polar earth radius (C{meter}), WGS84, EPSG:3785
275
+ R_M = _Radius(R_M =6371008.771415) # PYCHOK mean, spherical earth radius (C{meter})
276
+ R_KM = _Radius(R_KM=R_M / _M_KM) # PYCHOK mean, spherical earth radius (C{KM}, Kilo meter)
277
+ R_NM = _Radius(R_NM=R_M / _M_NM) # PYCHOK mean, spherical earth radius (C{NM}, nautical miles)
278
+ R_SM = _Radius(R_SM=R_M / _M_SM) # PYCHOK mean, spherical earth radius (C{SM}, statute miles)
279
+ # See <https://www.EdWilliams.org/avform.htm>, <https://www.DTIC.mil/dtic/tr/fulltext/u2/a216843.pdf>
280
+ # and <https://GitHub.com/NASA/MultiDop/blob/master/src/share/man/man3/geog_lib.3> based on the
281
+ # International Standard Nautical Mile of 1,852 meter (1' latitude)
282
+ R_FM = _Radius(R_FM=6371000.0) # PYCHOK former FAI Sphere earth radius (C{meter})
283
+ R_GM = _Radius(R_GM=6371230.0) # PYCHOK avg. radius, distance to geoid surface (C{meter})
284
+ # <http://Wiki.GIS.com/wiki/index.php/Ellipsoidal_quadratic_mean_radius>
285
+ R_QM = _Radius(R_QM=6372797.560856) # PYCHOK earth' quadratic mean radius (C{meter})
286
+ # Rtri= _Radius(Rtri=6372797.5559594) # PYCHOK Rtriaxial quadratic mean radius (C{meter}), WGS84
287
+ # Rbi = _Radius(Rbi =6367453.6345163) # PYCHOK Rbiaxial quadratic mean radius (C{meter}), WGS84
288
+ R_VM = _Radius(R_VM=6366707.0194937) # PYCHOK aViation/naVigation earth radius (C{meter})
289
+ # R_AU= Meter( R_AU=149597870700.0) # PYCHOK <https://WikiPedia.org/wiki/Astronomical_unit>
290
+
291
+ _INF_NAN_NINF = INF, NAN, NINF
292
+ _pos_self = _1_0.__pos__() is _1_0 # PYCHOK in .fsums, .vector3dBase
293
+
294
+
295
+ def _0_0s(n):
296
+ '''(INTERNAL) Return an C{B{n}-tuple} of C{_0_0} zeros.
297
+ '''
298
+ return _0_0_9T[:n] if 0 <= n <= len(_0_0_9T) else (_0_0_1T * n)
299
+
300
+
301
+ try:
302
+ from math import isclose as _isclose
303
+ except ImportError: # Python 3.4-
304
+
305
+ def _isclose(a, b, rel_tol=1e-9, abs_tol=0):
306
+ '''Mimick Python 3.5+ C{math.isclose}.
307
+ '''
308
+ t, d = abs_tol, fabs(a - b)
309
+ if d > t:
310
+ r = max(fabs(a), fabs(b)) * rel_tol
311
+ t = max(r, t)
312
+ return d <= t
313
+
314
+
315
+ def isclose(a, b, rel_tol=1e-12, abs_tol=EPS0):
316
+ '''Like C{math.isclose}, but with defaults such
317
+ that C{isclose(0, EPS0)} is C{True} by default.
318
+ '''
319
+ return _isclose(a, b, rel_tol=rel_tol, abs_tol=abs_tol)
320
+
321
+
322
+ try:
323
+ from math import isfinite as _isfinite # in .ellipsoids, ...
324
+ except ImportError: # Python 3.1-
325
+
326
+ def _isfinite(x):
327
+ '''Mimick Python 3.2+ C{math.isfinite}.
328
+ '''
329
+ return not (isinf(x) or isnan(x))
330
+
331
+
332
+ def isfinite(obj):
333
+ '''Check a finite C{scalar} or C{complex} value.
334
+
335
+ @arg obj: Value (C{scalar} or C{complex}).
336
+
337
+ @return: C{False} if B{C{obj}} is C{INF}, C{NINF}
338
+ or C{NAN}, C{True} otherwise.
339
+
340
+ @raise TypeError: Non-scalar and non-complex B{C{obj}}.
341
+ '''
342
+ try:
343
+ return (obj not in _INF_NAN_NINF) and _isfinite(obj)
344
+ except Exception as x:
345
+ if iscomplex(obj): # _isfinite(complex) thows TypeError
346
+ return isfinite(obj.real) and isfinite(obj.imag)
347
+ raise _xError(x, Fmt.PAREN(isfinite.__name__, obj))
348
+
349
+
350
+ def isint0(obj, both=False):
351
+ '''Check for L{INT0} or C{int(0)} value.
352
+
353
+ @arg obj: The object (any C{type}).
354
+ @kwarg both: If C{true}, also check C{float(0)} (C{bool}).
355
+
356
+ @return: C{True} if B{C{obj}} is L{INT0}, C{int(0)} or
357
+ C{float(0)}, C{False} otherwise.
358
+ '''
359
+ return (obj is INT0 or obj is int(0) or bool(both and
360
+ (not obj) and isint(obj, both=True))) and not isbool(obj)
361
+
362
+
363
+ def isnear0(x, eps0=EPS0):
364
+ '''Is B{C{x}} near I{zero} within a tolerance?
365
+
366
+ @arg x: Value (C{scalar}).
367
+ @kwarg eps0: Near-I{zero} tolerance (C{EPS0}).
368
+
369
+ @return: C{True} if C{abs(B{x}) < B{eps0}},
370
+ C{False} otherwise.
371
+
372
+ @see: Function L{isnon0}.
373
+ '''
374
+ return bool(eps0 > x > -eps0)
375
+
376
+
377
+ def isnear1(x, eps1=EPS0):
378
+ '''Is B{C{x}} near I{one} within a tolerance?
379
+
380
+ @arg x: Value (C{scalar}).
381
+ @kwarg eps1: Near-I{one} tolerance (C{EPS0}).
382
+
383
+ @return: C{isnear0(B{x} - 1, eps0=B{eps1})}.
384
+
385
+ @see: Function L{isnear0}.
386
+ '''
387
+ return bool(eps1 > (x - _1_0) > -eps1)
388
+
389
+
390
+ def isnear90(x, eps90=EPS0):
391
+ '''Is B{C{x}} near I{90} within a tolerance?
392
+
393
+ @arg x: Value (C{scalar}).
394
+ @kwarg eps90: Near-I{90} tolerance (C{EPS0}).
395
+
396
+ @return: C{isnear0(B{x} - 90, eps0=eps90)}.
397
+
398
+ @see: Function L{isnear0}.
399
+ '''
400
+ return bool(eps90 > (x - _90_0) > -eps90)
401
+
402
+
403
+ def isneg0(x):
404
+ '''Check for L{NEG0}, negative C{0.0}.
405
+
406
+ @arg x: Value (C{scalar}).
407
+
408
+ @return: C{True} if B{C{x}} is C{NEG0} or C{-0.0},
409
+ C{False} otherwise.
410
+ '''
411
+ return (not x) and _copysign(1, x) < 0
412
+ # and str(x).startswith(_MINUS_)
413
+
414
+
415
+ def isninf(x):
416
+ '''Check for L{NINF}, negative C{INF}.
417
+
418
+ @arg x: Value (C{scalar}).
419
+
420
+ @return: C{True} if B{C{x}} is C{NINF} or C{-inf},
421
+ C{False} otherwise.
422
+ '''
423
+ return x is NINF or (x < 0 and not isfinite(x))
424
+
425
+
426
+ def isnon0(x, eps0=EPS0):
427
+ '''Is B{C{x}} non-zero with a tolerance?
428
+
429
+ @arg x: Value (C{scalar}).
430
+ @kwarg eps0: Non-zero tolerance (C{EPS0}).
431
+
432
+ @return: C{True} if C{abs(B{x}) > B{eps0}},
433
+ C{False} otherwise.
434
+
435
+ @see: Function L{isnear0}.
436
+ '''
437
+ return not bool(eps0 > x > -eps0) # not isnear0
438
+
439
+
440
+ def _off90(lat):
441
+ '''(INTERNAL) Off 90.0 for .gars and .wgrs.
442
+ '''
443
+ return max(min(lat, _89_999_), -_89_999_)
444
+
445
+
446
+ try:
447
+ from math import remainder
448
+ except ImportError: # Python 3.6-
449
+ from math import fmod as _fmod
450
+
451
+ def remainder(x, y):
452
+ '''Mimick Python 3.7+ C{math.remainder}.
453
+ '''
454
+ if isnan(y):
455
+ x = NAN
456
+ elif x and not isnan(x):
457
+ y = fabs(y)
458
+ x = _fmod(x, y)
459
+ h = _0_5 * y
460
+ if x >= h:
461
+ x -= y
462
+ elif x < -h:
463
+ x += y
464
+ return x # keep signed 0.0
465
+
466
+
467
+ def _umod_360(deg):
468
+ '''(INTERNAL) Non-negative C{deg} modulo 360, basic C{.utily.wrap360}.
469
+ '''
470
+ return (deg % _360_0) or _0_0
471
+
472
+
473
+ def _umod_PI2(rad):
474
+ '''(INTERNAL) Non-negative C{rad} modulo PI2, basic C{.utily.wrapPI2}.
475
+ '''
476
+ return (rad % PI2) or _0_0
477
+
478
+
479
+ if __name__ == '__main__':
480
+
481
+ from pygeodesy import itemsorted, printf
482
+
483
+ t = n = v = []
484
+ for n, v in itemsorted(locals()):
485
+ if isinstance(v, (Float, Int, Radius)):
486
+ printf('%9s: %r', n, v.toRepr(std=False))
487
+ if v.name != n:
488
+ raise AssertionError('%r != %r' % (n, v))
489
+ if v.name is not n:
490
+ raise AssertionError('%r is not %r' % (n, v))
491
+ if not n.startswith(_UNDER_):
492
+ t.append(n)
493
+ t.append(float_.__name__)
494
+ printf('__all__ = %r', tuple(t))
495
+
496
+ # **) MIT License
497
+ #
498
+ # Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
499
+ #
500
+ # Permission is hereby granted, free of charge, to any person obtaining a
501
+ # copy of this software and associated documentation files (the "Software"),
502
+ # to deal in the Software without restriction, including without limitation
503
+ # the rights to use, copy, modify, merge, publish, distribute, sublicense,
504
+ # and/or sell copies of the Software, and to permit persons to whom the
505
+ # Software is furnished to do so, subject to the following conditions:
506
+ #
507
+ # The above copyright notice and this permission notice shall be included
508
+ # in all copies or substantial portions of the Software.
509
+ #
510
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
511
+ # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
512
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
513
+ # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
514
+ # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
515
+ # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
516
+ # OTHER DEALINGS IN THE SOFTWARE.