pygeodesy 25.7.25__py2.py3-none-any.whl → 25.9.9__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 (44) hide show
  1. pygeodesy/__init__.py +10 -9
  2. pygeodesy/auxilats/__init__.py +1 -1
  3. pygeodesy/auxilats/auxAngle.py +4 -3
  4. pygeodesy/auxilats/auxily.py +1 -1
  5. pygeodesy/basics.py +4 -4
  6. pygeodesy/booleans.py +25 -25
  7. pygeodesy/cartesianBase.py +21 -20
  8. pygeodesy/constants.py +37 -7
  9. pygeodesy/deprecated/functions.py +1 -0
  10. pygeodesy/dms.py +2 -2
  11. pygeodesy/ecef.py +324 -260
  12. pygeodesy/ellipsoidalExact.py +4 -4
  13. pygeodesy/ellipsoidalGeodSolve.py +3 -3
  14. pygeodesy/ellipsoids.py +79 -52
  15. pygeodesy/elliptic.py +8 -11
  16. pygeodesy/errors.py +18 -5
  17. pygeodesy/etm.py +8 -8
  18. pygeodesy/fmath.py +1 -1
  19. pygeodesy/geodesicx/__init__.py +1 -1
  20. pygeodesy/geodesicx/__main__.py +1 -0
  21. pygeodesy/geodesicx/gx.py +30 -37
  22. pygeodesy/geodesicx/gxbases.py +1 -5
  23. pygeodesy/geodesicx/gxline.py +43 -34
  24. pygeodesy/geodsolve.py +10 -17
  25. pygeodesy/internals.py +39 -15
  26. pygeodesy/karney.py +19 -18
  27. pygeodesy/ktm.py +3 -3
  28. pygeodesy/latlonBase.py +4 -4
  29. pygeodesy/lazily.py +14 -13
  30. pygeodesy/lcc.py +5 -5
  31. pygeodesy/named.py +10 -13
  32. pygeodesy/nvectorBase.py +4 -4
  33. pygeodesy/rhumb/__init__.py +1 -1
  34. pygeodesy/rhumb/aux_.py +1 -1
  35. pygeodesy/rhumb/bases.py +7 -8
  36. pygeodesy/rhumb/ekx.py +9 -9
  37. pygeodesy/solveBase.py +14 -3
  38. pygeodesy/sphericalTrigonometry.py +8 -8
  39. pygeodesy/utily.py +200 -159
  40. pygeodesy/vector3dBase.py +10 -8
  41. {pygeodesy-25.7.25.dist-info → pygeodesy-25.9.9.dist-info}/METADATA +12 -11
  42. {pygeodesy-25.7.25.dist-info → pygeodesy-25.9.9.dist-info}/RECORD +44 -44
  43. {pygeodesy-25.7.25.dist-info → pygeodesy-25.9.9.dist-info}/WHEEL +0 -0
  44. {pygeodesy-25.7.25.dist-info → pygeodesy-25.9.9.dist-info}/top_level.txt +0 -0
pygeodesy/utily.py CHANGED
@@ -12,44 +12,48 @@ and published under the same MIT Licence**.
12
12
  from __future__ import division as _; del _ # noqa: E702 ;
13
13
 
14
14
  from pygeodesy.basics import _copysign, isinstanceof, isint, isstr
15
- from pygeodesy.constants import EPS, EPS0, INF, NAN, PI, PI2, PI_2, R_M, \
16
- _M_KM, _M_NM, _M_SM, _0_0, _1__90, _0_5, _2__PI, \
17
- _1_0, _N_1_0, _10_0, _90_0, _180_0, _360_0, \
18
- _copysign_0_0, _float, _isfinite, isnan, isnear0, \
19
- _over, _umod_360, _umod_PI2
20
- from pygeodesy.errors import _ValueError, _xkwds, _ALL_LAZY, _MODS
21
- from pygeodesy.internals import _passargs, typename
15
+ from pygeodesy.constants import EPS, EPS0, NAN, PI, PI2, PI_2, PI_4, PI_6, R_M, \
16
+ _M_KM, _M_NM, _M_SM, _0_0, _0_5, _1_0, _N_1_0, \
17
+ _10_0, _90_0, _180_0, _360_0, _copysign_0_0, \
18
+ _copysignINF, _float, _isfinite, isnan, isnear0, \
19
+ _over_1, _umod_360, _umod_PI2
20
+ from pygeodesy.errors import _ValueError, _xkwds, _xkwds_get
21
+ from pygeodesy.internals import _Enum, _passargs, typename
22
22
  from pygeodesy.interns import _edge_, _radians_, _semi_circular_, _SPACE_
23
- # from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS # from .errors
23
+ from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS
24
24
  from pygeodesy.units import Degrees, Degrees_, Feet, Float, Lam, Lamd, \
25
25
  Meter, Meter2, Radians # Radians_
26
26
 
27
- from math import acos, asin, atan2 as _atan2, cos, degrees, fabs, radians, \
28
- sin, tan as _tan # pow
27
+ from math import acos, asin, asinh, atan2 as _atan2, cos, degrees, fabs, \
28
+ radians, sin, sinh, tan as _tan # pow
29
29
 
30
30
  __all__ = _ALL_LAZY.utily
31
- __version__ = '25.05.12'
32
-
33
- _G_DEG = _float( 400.0 / _360_0) # grades per degree
34
- _G_RAD = _float( 400.0 / PI2) # grades per radian
35
- _M_ACRE = _float( 4046.8564224) # square meter per acre, chain2m(1) * furlong2m(1)
36
- _M_CHAIN = _float( 20.1168) # meter per yard2m(1) * 22
37
- _M_FATHOM = _float( 1.8288) # meter per yard2m(1) * 2 or _M_NM * 1e-3
38
- _M_FOOT = _float( 0.3048) # meter per Int'l foot, 1 / 3.280_839_895_0131 = 10_000 / (254 * 12)
39
- _M_FOOT_GE = _float( 0.31608) # meter per German Fuss, 1 / 3.163_756_011_1364
40
- _M_FOOT_FR = _float( 0.3248406) # meter per French Pied-du-Roi or pied, 1 / 3.078_432_929_8739
41
- _M_FOOT_US = _float( 0.3048006096012192) # meter per US Survey foot, 1_200 / 3_937
42
- _M_FURLONG = _float( 201.168) # meter per furlong, 220 * yard2m(1) = 10 * m2chain(1)
43
- _M_HA = _float(10000.0) # square meter per hectare, 100 * 100
44
- # _M_KM = _float( 1000.0) # meter per kilo meter
45
- # _M_NM = _float( 1852.0) # meter per nautical mile
46
- # _M_SM = _float( 1609.344) # meter per statute mile
47
- _M_TOISE = _float( 1.9490436) # meter per French toise, 6 pieds = 6 / 3.078_432_929_8739
48
- _M_YARD_UK = _float( 0.9144) # meter per yard, 254 * 12 * 3 / 10_000 = 3 * _M_FOOT
31
+ __version__ = '25.09.09'
32
+
49
33
  # sqrt(3) <https://WikiPedia.org/wiki/Square_root_of_3>
50
34
  _COS_30, _SIN_30 = 0.86602540378443864676, _0_5 # sqrt(3) / 2
51
35
  _COS_45 = _SIN_45 = 0.70710678118654752440 # sqrt(2) / 2
52
36
 
37
+ _G = _Enum( # grades per ...
38
+ DEG = _float( 400.0 / _360_0), # degree
39
+ RAD = _float( 400.0 / PI2)) # radian
40
+
41
+ _M = _Enum( # meter per ...
42
+ ACRE = _float( 4046.8564224), # acre, chain2m(1) * furlong2m(1), squared
43
+ CHAIN = _float( 20.1168), # yard2m(1) * 22
44
+ FATHOM = _float( 1.8288), # yard2m(1) * 2 or _M.NM * 1e-3
45
+ FOOT = _float( 0.3048), # Int'l foot, 1 / 3.280_839_895_0131 = 10_000 / (254 * 12)
46
+ FOOT_GE = _float( 0.31608), # German Fuss, 1 / 3.163_756_011_1364
47
+ FOOT_FR = _float( 0.3248406), # French Pied-du-Roi or pied, 1 / 3.078_432_929_8739
48
+ FOOT_US = _float( 0.3048006096012192), # US Survey foot, 1_200 / 3_937
49
+ FURLONG = _float( 201.168), # furlong, 220 * yard2m(1) = 10 * m2chain(1)
50
+ HA = _float(10000.0), # hectare, 100 * 100, squared
51
+ KM = _M_KM, # kilo meter
52
+ NM = _M_NM, # nautical mile
53
+ SM = _M_SM, # statute mile
54
+ TOISE = _float( 1.9490436), # French toise, 6 pieds = 6 / 3.078_432_929_8739
55
+ YARD_UK = _float( 0.9144)) # yard, 254 * 12 * 3 / 10_000 = 3 * _M.FOOT
56
+
53
57
 
54
58
  def _abs1nan(x):
55
59
  '''(INTERNAL) Bracket C{x}.
@@ -84,7 +88,20 @@ def acre2m2(acres):
84
88
 
85
89
  @raise ValueError: Invalid B{C{acres}}.
86
90
  '''
87
- return Meter2(Float(acres=acres) * _M_ACRE)
91
+ return Meter2(Float(acres=acres) * _M.ACRE)
92
+
93
+
94
+ def agdf(phi):
95
+ '''Inverse U{Gudermannian function
96
+ <https://WikiPedia.org/wiki/Gudermannian_function>}.
97
+
98
+ @arg phi: Angle (C{radians}).
99
+
100
+ @return: Gudermannian (psi, C{float}).
101
+
102
+ @see: Function L{gdf}.
103
+ '''
104
+ return asinh(tan(phi))
88
105
 
89
106
 
90
107
  def asin1(x):
@@ -163,13 +180,13 @@ def chain2m(chains):
163
180
 
164
181
  @raise ValueError: Invalid B{C{chains}}.
165
182
  '''
166
- return Meter(Float(chains=chains) * _M_CHAIN)
183
+ return Meter(Float(chains=chains) * _M.CHAIN)
167
184
 
168
185
 
169
186
  def circle4(earth, lat):
170
187
  '''Get the equatorial or a parallel I{circle of latitude}.
171
188
 
172
- @arg earth: The earth radius (C{meter}), ellipsoid or datum
189
+ @arg earth: The earth radius (C{meter}) or an ellipsoid or datum
173
190
  (L{Ellipsoid}, L{Ellipsoid2}, L{Datum} or L{a_f2Tuple}).
174
191
  @arg lat: Geodetic latitude (C{degrees90}, C{str}).
175
192
 
@@ -180,18 +197,25 @@ def circle4(earth, lat):
180
197
 
181
198
  @raise TypeError: Invalid B{C{earth}}.
182
199
 
183
- @raise ValueError: B{C{earth}} or B{C{lat}}.
200
+ @raise ValueError: invalid B{C{earth}} or B{C{lat}}.
184
201
  '''
185
202
  E = _MODS.datums._earth_ellipsoid(earth)
186
203
  return E.circle4(lat)
187
204
 
188
205
 
206
+ def _circle4radius(earth, lat, **radius):
207
+ '''(INTERNAL) Get C{circle4(earth, lat).radius}.
208
+ '''
209
+ e = _xkwds_get(radius, radius=earth) if radius else earth
210
+ return e if e is R_M and not lat else circle4(e, lat).radius
211
+
212
+
189
213
  def cot(rad, **raiser_kwds):
190
214
  '''Return the C{cotangent} of an angle in C{radians}.
191
215
 
192
216
  @arg rad: Angle (C{radians}).
193
217
  @kwarg raiser_kwds: Use C{B{raiser}=False} to avoid
194
- ValueErrors or optionally, additional
218
+ ValueErrors and optional, additional
195
219
  ValueError keyword argments.
196
220
 
197
221
  @return: C{cot(B{rad})}.
@@ -199,9 +223,9 @@ def cot(rad, **raiser_kwds):
199
223
  @raise Error: If L{pygeodesy.isnear0}C{(sin(B{rad})}.
200
224
  '''
201
225
  try:
202
- return _cotu(*sincos2(rad), **raiser_kwds)
226
+ return _cotu(*sincos2(rad))
203
227
  except ZeroDivisionError:
204
- raise _valueError(cot, rad, **raiser_kwds)
228
+ return _nonfinite(cot, rad, **raiser_kwds)
205
229
 
206
230
 
207
231
  def cot_(*rads, **raiser_kwds):
@@ -215,9 +239,9 @@ def cot_(*rads, **raiser_kwds):
215
239
  '''
216
240
  try:
217
241
  for r in rads:
218
- yield _cotu(*sincos2(r), **raiser_kwds)
242
+ yield _cotu(*sincos2(r))
219
243
  except ZeroDivisionError:
220
- raise _valueError(cot_, r, **raiser_kwds)
244
+ yield _nonfinite(cot_, r, **raiser_kwds)
221
245
 
222
246
 
223
247
  def cotd(deg, **raiser_kwds):
@@ -225,7 +249,7 @@ def cotd(deg, **raiser_kwds):
225
249
 
226
250
  @arg deg: Angle (C{degrees}).
227
251
  @kwarg raiser_kwds: Use C{B{raiser}=False} to avoid
228
- ValueErrors or optionally, additional
252
+ ValueErrors and optional, additional
229
253
  ValueError keyword argments.
230
254
 
231
255
  @return: C{cot(B{deg})}.
@@ -233,9 +257,9 @@ def cotd(deg, **raiser_kwds):
233
257
  @raise Error: If L{pygeodesy.isnear0}C{(sin(B{deg})}.
234
258
  '''
235
259
  try:
236
- return _cotu(*sincos2d(deg), **raiser_kwds)
260
+ return _cotu(*sincos2d(deg))
237
261
  except ZeroDivisionError:
238
- raise _valueError(cotd, deg, **raiser_kwds)
262
+ return _nonfinite(cotd, deg, **raiser_kwds)
239
263
 
240
264
 
241
265
  def cotd_(*degs, **raiser_kwds):
@@ -249,15 +273,15 @@ def cotd_(*degs, **raiser_kwds):
249
273
  '''
250
274
  try:
251
275
  for d in degs:
252
- yield _cotu(*sincos2d(d), **raiser_kwds)
276
+ yield _cotu(*sincos2d(d))
253
277
  except ZeroDivisionError:
254
- raise _valueError(cotd_, d, **raiser_kwds)
278
+ yield _nonfinite(cotd_, d, **raiser_kwds)
255
279
 
256
280
 
257
- def _cotu(s, c, **raiser_kwds):
281
+ def _cotu(s, c):
258
282
  '''(INTERNAL) Helper for functions C{cot}, C{cotd}, C{cot_} and C{cotd_}.
259
283
  '''
260
- return _tanu(c, s, **raiser_kwds)
284
+ return _tanu(c, s)
261
285
 
262
286
 
263
287
  def degrees90(rad):
@@ -297,31 +321,33 @@ def degrees2grades(deg):
297
321
 
298
322
  @return: Angle (C{grades}).
299
323
  '''
300
- return Float(grades=Degrees(deg) * _G_DEG)
324
+ return Float(grades=Degrees(deg) * _G.DEG)
301
325
 
302
326
 
303
- def degrees2m(deg, radius=R_M, lat=0):
327
+ def degrees2m(deg, earth=R_M, lat=0, **radius):
304
328
  '''Convert an angle to a distance along the equator or along a parallel
305
329
  at (geodetic) latitude.
306
330
 
307
331
  @arg deg: The angle (C{degrees}).
308
- @kwarg radius: Mean earth radius (C{meter}), an ellipsoid or datum
309
- (L{Ellipsoid}, L{Ellipsoid2}, L{Datum} or L{a_f2Tuple}).
332
+ @arg earth: The earth radius (C{meter}) or an ellipsoid or datum
333
+ (L{Ellipsoid}, L{Ellipsoid2}, L{Datum} or L{a_f2Tuple}).
310
334
  @kwarg lat: Parallel latitude (C{degrees90}, C{str}).
335
+ @kwarg radius: For backward compatibility C{B{radius}=B{earth}}.
311
336
 
312
- @return: Distance (C{meter}, same units as B{C{radius}} or polar and
337
+ @return: Distance (C{meter}, same units as B{C{earth}} or polar and
313
338
  equatorial radii) or C{0.0} for near-polar B{C{lat}}.
314
339
 
315
340
  @raise RangeError: Latitude B{C{lat}} outside valid range and
316
341
  L{rangerrors<pygeodesy.rangerrors>} is C{True}.
317
342
 
318
- @raise TypeError: Invalid B{C{radius}}.
343
+ @raise TypeError: Invalid B{C{earth}} or B{C{radius}}.
319
344
 
320
- @raise ValueError: Invalid B{C{deg}}, B{C{radius}} or B{C{lat}}.
345
+ @raise ValueError: Invalid B{C{deg}}, B{C{earth}} or B{C{lat}}.
321
346
 
322
347
  @see: Function L{radians2m} and L{m2degrees}.
323
348
  '''
324
- return _Radians2m(Lamd(deg=deg, clip=0), radius, lat)
349
+ m = _circle4radius(earth, lat, **radius)
350
+ return _Radians2m(Lamd(deg=deg, clip=0), m)
325
351
 
326
352
 
327
353
  def fathom2m(fathoms):
@@ -336,7 +362,7 @@ def fathom2m(fathoms):
336
362
  @see: Function L{toise2m}, U{Fathom<https://WikiPedia.org/wiki/Fathom>}
337
363
  and U{Klafter<https://WikiPedia.org/wiki/Klafter>}.
338
364
  '''
339
- return Meter(Float(fathoms=fathoms) * _M_FATHOM)
365
+ return Meter(Float(fathoms=fathoms) * _M.FATHOM)
340
366
 
341
367
 
342
368
  def ft2m(feet, usurvey=False, pied=False, fuss=False):
@@ -353,9 +379,9 @@ def ft2m(feet, usurvey=False, pied=False, fuss=False):
353
379
 
354
380
  @raise ValueError: Invalid B{C{feet}}.
355
381
  '''
356
- return Meter(Feet(feet) * (_M_FOOT_US if usurvey else
357
- (_M_FOOT_FR if pied else
358
- (_M_FOOT_GE if fuss else _M_FOOT))))
382
+ return Meter(Feet(feet) * (_M.FOOT_US if usurvey else
383
+ (_M.FOOT_FR if pied else
384
+ (_M.FOOT_GE if fuss else _M.FOOT))))
359
385
 
360
386
 
361
387
  def furlong2m(furlongs):
@@ -367,7 +393,20 @@ def furlong2m(furlongs):
367
393
 
368
394
  @raise ValueError: Invalid B{C{furlongs}}.
369
395
  '''
370
- return Meter(Float(furlongs=furlongs) * _M_FURLONG)
396
+ return Meter(Float(furlongs=furlongs) * _M.FURLONG)
397
+
398
+
399
+ def gdf(psi):
400
+ '''U{Gudermannian function
401
+ <https://WikiPedia.org/wiki/Gudermannian_function>}.
402
+
403
+ @arg psi: Gudermannian (C{float}).
404
+
405
+ @return: Angle (C{radians}).
406
+
407
+ @see: Function L{agdf}.
408
+ '''
409
+ return atan1(sinh(psi))
371
410
 
372
411
 
373
412
  def grades(rad):
@@ -377,7 +416,7 @@ def grades(rad):
377
416
 
378
417
  @return: Angle (C{grades}).
379
418
  '''
380
- return Float(grades=Radians(rad) * _G_RAD)
419
+ return Float(grades=Radians(rad) * _G.RAD)
381
420
 
382
421
 
383
422
  def grades400(rad):
@@ -387,7 +426,7 @@ def grades400(rad):
387
426
 
388
427
  @return: Angle, wrapped (C{grades}).
389
428
  '''
390
- return Float(grades400=wrapPI2(rad) * _G_RAD)
429
+ return Float(grades400=wrapPI2(rad) * _G.RAD)
391
430
 
392
431
 
393
432
  def grades2degrees(gon):
@@ -397,7 +436,7 @@ def grades2degrees(gon):
397
436
 
398
437
  @return: Angle (C{degrees}).
399
438
  '''
400
- return Degrees(Float(gon=gon) / _G_DEG)
439
+ return Degrees(Float(gon=gon) / _G.DEG)
401
440
 
402
441
 
403
442
  def grades2radians(gon):
@@ -407,7 +446,7 @@ def grades2radians(gon):
407
446
 
408
447
  @return: Angle (C{radians}).
409
448
  '''
410
- return Radians(Float(gon=gon) / _G_RAD)
449
+ return Radians(Float(gon=gon) / _G.RAD)
411
450
 
412
451
 
413
452
  def ha2acre(ha):
@@ -431,7 +470,7 @@ def ha2m2(ha):
431
470
 
432
471
  @raise ValueError: Invalid B{C{ha}}.
433
472
  '''
434
- return Meter2(Float(ha=ha) * _M_HA)
473
+ return Meter2(Float(ha=ha) * _M.HA)
435
474
 
436
475
 
437
476
  def hav(rad):
@@ -453,7 +492,7 @@ def km2m(km):
453
492
 
454
493
  @raise ValueError: Invalid B{C{km}}.
455
494
  '''
456
- return Meter(Float(km=km) * _M_KM)
495
+ return Meter(Float(km=km) * _M.KM)
457
496
 
458
497
 
459
498
  def _loneg(lon):
@@ -471,7 +510,7 @@ def m2acre(meter2):
471
510
 
472
511
  @raise ValueError: Invalid B{C{meter2}}.
473
512
  '''
474
- return Float(acre=Meter2(meter2) / _M_ACRE)
513
+ return Float(acre=Meter2(meter2) / _M.ACRE)
475
514
 
476
515
 
477
516
  def m2chain(meter):
@@ -483,30 +522,31 @@ def m2chain(meter):
483
522
 
484
523
  @raise ValueError: Invalid B{C{meter}}.
485
524
  '''
486
- return Float(chain=Meter(meter) / _M_CHAIN) # * 0.049_709_695_378_986_715
525
+ return Float(chain=Meter(meter) / _M.CHAIN) # * 0.049_709_695_378_986_715
487
526
 
488
527
 
489
- def m2degrees(distance, radius=R_M, lat=0):
528
+ def m2degrees(distance, earth=R_M, lat=0, **radius):
490
529
  '''Convert a distance to an angle along the equator or along a parallel
491
530
  at (geodetic) latitude.
492
531
 
493
532
  @arg distance: Distance (C{meter}, same units as B{C{radius}}).
494
- @kwarg radius: Mean earth radius (C{meter}), an ellipsoid or datum
495
- (L{Ellipsoid}, L{Ellipsoid2}, L{Datum} or L{a_f2Tuple}).
533
+ @kwarg earth: Mean earth radius (C{meter}) or an ellipsoid or datum
534
+ (L{Ellipsoid}, L{Ellipsoid2}, L{Datum} or L{a_f2Tuple}).
496
535
  @kwarg lat: Parallel latitude (C{degrees90}, C{str}).
536
+ @kwarg radius: For backward compatibility C{B{radius}=B{earth}}.
497
537
 
498
- @return: Angle (C{degrees}) or C{INF} for near-polar B{C{lat}}.
538
+ @return: Angle (C{degrees}) or C{INF} or C{NINF} for near-polar B{C{lat}}.
499
539
 
500
540
  @raise RangeError: Latitude B{C{lat}} outside valid range and
501
541
  L{rangerrors<pygeodesy.rangerrors>} is C{True}.
502
542
 
503
- @raise TypeError: Invalid B{C{radius}}.
543
+ @raise TypeError: Invalid B{C{earth}} or B{C{radius}}.
504
544
 
505
- @raise ValueError: Invalid B{C{distance}}, B{C{radius}} or B{C{lat}}.
545
+ @raise ValueError: Invalid B{C{distance}}, B{C{earth}} or B{C{lat}}.
506
546
 
507
547
  @see: Function L{m2radians} and L{degrees2m}.
508
548
  '''
509
- return degrees(m2radians(distance, radius=radius, lat=lat))
549
+ return degrees(m2radians(distance, earth=earth, lat=lat, **radius))
510
550
 
511
551
 
512
552
  def m2fathom(meter):
@@ -521,7 +561,7 @@ def m2fathom(meter):
521
561
  @see: Function L{m2toise}, U{Fathom<https://WikiPedia.org/wiki/Fathom>}
522
562
  and U{Klafter<https://WikiPedia.org/wiki/Klafter>}.
523
563
  '''
524
- return Float(fathom=Meter(meter) / _M_FATHOM) # * 0.546_806_649
564
+ return Float(fathom=Meter(meter) / _M.FATHOM) # * 0.546_806_649
525
565
 
526
566
 
527
567
  def m2ft(meter, usurvey=False, pied=False, fuss=False):
@@ -540,9 +580,9 @@ def m2ft(meter, usurvey=False, pied=False, fuss=False):
540
580
  '''
541
581
  # * 3.280_833_333_333_3333, US Survey 3_937 / 1_200
542
582
  # * 3.280_839_895_013_1235, Int'l 10_000 / (254 * 12)
543
- return Float(feet=Meter(meter) / (_M_FOOT_US if usurvey else
544
- (_M_FOOT_FR if pied else
545
- (_M_FOOT_GE if fuss else _M_FOOT))))
583
+ return Float(feet=Meter(meter) / (_M.FOOT_US if usurvey else
584
+ (_M.FOOT_FR if pied else
585
+ (_M.FOOT_GE if fuss else _M.FOOT))))
546
586
 
547
587
 
548
588
  def m2furlong(meter):
@@ -554,7 +594,7 @@ def m2furlong(meter):
554
594
 
555
595
  @raise ValueError: Invalid B{C{meter}}.
556
596
  '''
557
- return Float(furlong=Meter(meter) / _M_FURLONG) # * 0.004_970_969_54
597
+ return Float(furlong=Meter(meter) / _M.FURLONG) # * 0.004_970_969_54
558
598
 
559
599
 
560
600
  def m2ha(meter2):
@@ -566,7 +606,7 @@ def m2ha(meter2):
566
606
 
567
607
  @raise ValueError: Invalid B{C{meter2}}.
568
608
  '''
569
- return Float(ha=Meter2(meter2) / _M_HA)
609
+ return Float(ha=Meter2(meter2) / _M.HA)
570
610
 
571
611
 
572
612
  def m2km(meter):
@@ -578,7 +618,7 @@ def m2km(meter):
578
618
 
579
619
  @raise ValueError: Invalid B{C{meter}}.
580
620
  '''
581
- return Float(km=Meter(meter) / _M_KM)
621
+ return Float(km=Meter(meter) / _M.KM)
582
622
 
583
623
 
584
624
  def m2NM(meter):
@@ -590,31 +630,33 @@ def m2NM(meter):
590
630
 
591
631
  @raise ValueError: Invalid B{C{meter}}.
592
632
  '''
593
- return Float(NM=Meter(meter) / _M_NM) # * 5.399_568_04e-4
633
+ return Float(NM=Meter(meter) / _M.NM) # * 5.399_568_04e-4
594
634
 
595
635
 
596
- def m2radians(distance, radius=R_M, lat=0):
636
+ def m2radians(distance, earth=R_M, lat=0, **radius):
597
637
  '''Convert a distance to an angle along the equator or along a parallel
598
638
  at (geodetic) latitude.
599
639
 
600
640
  @arg distance: Distance (C{meter}, same units as B{C{radius}}).
601
- @kwarg radius: Mean earth radius (C{meter}, an ellipsoid or datum
602
- (L{Ellipsoid}, L{Ellipsoid2}, L{Datum} or L{a_f2Tuple}).
641
+ @kwarg earth: Mean earth radius (C{meter}) or an ellipsoid or datum
642
+ (L{Ellipsoid}, L{Ellipsoid2}, L{Datum} or L{a_f2Tuple}).
603
643
  @kwarg lat: Parallel latitude (C{degrees90}, C{str}).
644
+ @kwarg radius: For backward compatibility C{B{radius}=B{earth}}.
604
645
 
605
- @return: Angle (C{radians}) or C{INF} for near-polar B{C{lat}}.
646
+ @return: Angle (C{radians}) or C{INF} or C{NINF} for near-polar B{C{lat}}.
606
647
 
607
648
  @raise RangeError: Latitude B{C{lat}} outside valid range and
608
649
  L{rangerrors<pygeodesy.rangerrors>} is C{True}.
609
650
 
610
- @raise TypeError: Invalid B{C{radius}}.
651
+ @raise TypeError: Invalid B{C{earth}} or B{C{radius}}.
611
652
 
612
- @raise ValueError: Invalid B{C{distance}}, B{C{radius}} or B{C{lat}}.
653
+ @raise ValueError: Invalid B{C{distance}}, B{C{earth}} or B{C{lat}}.
613
654
 
614
655
  @see: Function L{m2degrees} and L{radians2m}.
615
656
  '''
616
- m = circle4(radius, lat).radius
617
- return INF if m < EPS0 else Radians(Float(distance=distance) / m)
657
+ m = _circle4radius(earth, lat, **radius)
658
+ return _copysign_0_0(distance) if m < EPS0 else \
659
+ Radians(Float(distance=distance) / m)
618
660
 
619
661
 
620
662
  def m2SM(meter):
@@ -626,7 +668,7 @@ def m2SM(meter):
626
668
 
627
669
  @raise ValueError: Invalid B{C{meter}}.
628
670
  '''
629
- return Float(SM=Meter(meter) / _M_SM) # * 6.213_699_49e-4 == 1 / 1_609.344
671
+ return Float(SM=Meter(meter) / _M.SM) # * 6.213_699_49e-4 == 1 / 1_609.344
630
672
 
631
673
 
632
674
  def m2toise(meter):
@@ -640,7 +682,7 @@ def m2toise(meter):
640
682
 
641
683
  @see: Function L{m2fathom}.
642
684
  '''
643
- return Float(toise=Meter(meter) / _M_TOISE) # * 0.513_083_632_632_119
685
+ return Float(toise=Meter(meter) / _M.TOISE) # * 0.513_083_632_632_119
644
686
 
645
687
 
646
688
  def m2yard(meter):
@@ -652,7 +694,7 @@ def m2yard(meter):
652
694
 
653
695
  @raise ValueError: Invalid B{C{meter}}.
654
696
  '''
655
- return Float(yard=Meter(meter) / _M_YARD_UK) # * 1.093_613_298_337_707_8
697
+ return Float(yard=Meter(meter) / _M.YARD_UK) # * 1.093_613_298_337_707_8
656
698
 
657
699
 
658
700
  def NM2m(nm):
@@ -664,38 +706,49 @@ def NM2m(nm):
664
706
 
665
707
  @raise ValueError: Invalid B{C{nm}}.
666
708
  '''
667
- return Meter(Float(nm=nm) * _M_NM)
709
+ return Meter(Float(nm=nm) * _M.NM)
710
+
668
711
 
712
+ def _nonfinite(where, x, raiser=True, **kwds): # PYCHOK no cover
713
+ '''(INTERNAL) Raise a C{_ValueError} or return C{INF} or C{NINF}.
714
+ '''
715
+ if raiser:
716
+ t = typename(where)
717
+ t = _MODS.streprs.Fmt.PAREN(t, x)
718
+ raise _ValueError(t, **kwds)
719
+ return _copysignINF(x)
669
720
 
670
- def radians2m(rad, radius=R_M, lat=0):
721
+
722
+ def radians2m(rad, earth=R_M, lat=0, **radius):
671
723
  '''Convert an angle to a distance along the equator or along a parallel
672
724
  at (geodetic) latitude.
673
725
 
674
726
  @arg rad: The angle (C{radians}).
675
- @kwarg radius: Mean earth radius (C{meter}) or an ellipsoid or datum
676
- (L{Ellipsoid}, L{Ellipsoid2}, L{Datum} or L{a_f2Tuple}).
727
+ @kwarg earth: Mean earth radius (C{meter}) or an ellipsoid or datum
728
+ (L{Ellipsoid}, L{Ellipsoid2}, L{Datum} or L{a_f2Tuple}).
677
729
  @kwarg lat: Parallel latitude (C{degrees90}, C{str}).
730
+ @kwarg radius: For backward compatibility C{B{radius}=B{earth}}.
678
731
 
679
- @return: Distance (C{meter}, same units as B{C{radius}} or polar and
732
+ @return: Distance (C{meter}, same units as B{C{earth}} or polar and
680
733
  equatorial radii) or C{0.0} for near-polar B{C{lat}}.
681
734
 
682
735
  @raise RangeError: Latitude B{C{lat}} outside valid range and
683
736
  L{rangerrors<pygeodesy.rangerrors>} is C{True}.
684
737
 
685
- @raise TypeError: Invalid B{C{radius}}.
738
+ @raise TypeError: Invalid B{C{earth}} or B{C{radius}}.
686
739
 
687
- @raise ValueError: Invalid B{C{rad}}, B{C{radius}} or B{C{lat}}.
740
+ @raise ValueError: Invalid B{C{rad}}, B{C{earth}} or B{C{lat}}.
688
741
 
689
742
  @see: Function L{degrees2m} and L{m2radians}.
690
743
  '''
691
- return _Radians2m(Lam(rad=rad, clip=0), radius, lat)
744
+ m = _circle4radius(earth, lat, **radius)
745
+ return _Radians2m(Lam(rad=rad, clip=0), m)
692
746
 
693
747
 
694
- def _Radians2m(rad, radius, lat):
748
+ def _Radians2m(rad, m):
695
749
  '''(INTERNAL) Helper for C{degrees2m} and C{radians2m}.
696
750
  '''
697
- m = circle4(radius, lat).radius
698
- return _0_0 if m < EPS0 else (rad * m)
751
+ return _copysign_0_0(rad) if m < EPS0 else (rad * m)
699
752
 
700
753
 
701
754
  def radiansPI(deg):
@@ -728,25 +781,29 @@ def radiansPI_2(deg):
728
781
  return wrapPI_2(radians(deg))
729
782
 
730
783
 
731
- def _sin0cos2(q, r, sign, a, Q): # Quarter turn
784
+ def _sin0cos2(q, r, sign):
732
785
  '''(INTERNAL) 2-tuple (C{sin(r), cos(r)}) in quadrant C{0 <= B{q} <= 3} and
733
786
  C{sin} zero I{signed} with B{C{sign}}, like Karney's U{Math.sind and .cosd
734
787
  <https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1Math.html>}
735
788
  '''
736
- if r < PI_2:
737
- s = sin(r)
738
- if (a * 2) == Q:
739
- s, c = _copysign(_SIN_45, s), _COS_45
740
- elif (a * 3) == Q:
741
- s, c = _copysign(_SIN_30, s), _COS_30
789
+ q &= 3 # -1: 3, -2: 2, -3: 1, -4: 0 ...
790
+ if r < PI_2: # Quarter turn
791
+ a = fabs(r)
792
+ if a:
793
+ s = sin(r)
794
+ if a == PI_4:
795
+ s, c = _copysign(_SIN_45, s), _COS_45
796
+ elif a == PI_6:
797
+ s, c = _copysign(_SIN_30, s), _COS_30
798
+ else:
799
+ c = cos(r)
742
800
  else:
743
- c = cos(r)
801
+ s, c = _0_0, _1_0
744
802
  else:
745
803
  s, c = _1_0, _0_0
746
- t = s, c, -s, -c, s
747
- # q &= 3
748
- s = t[q] or _copysign_0_0(sign)
749
- c = t[q + 1] or _0_0
804
+ t = s, c, -s, -c, s
805
+ s = t[q] or _copysign_0_0(sign)
806
+ c = t[q + 1] or _0_0
750
807
  return s, c
751
808
 
752
809
 
@@ -777,11 +834,8 @@ def sincos2(rad):
777
834
  include/GeographicLib/Math.hpp#l558>}.
778
835
  '''
779
836
  if _isfinite(rad):
780
- q = int(rad * _2__PI) # int(math.floor)
781
- if q < 0:
782
- q -= 1
783
- r = rad - q * PI_2
784
- t = _sin0cos2(q & 3, r, rad, fabs(r), PI_2)
837
+ q, r = divmod(rad, PI_2)
838
+ t = _sin0cos2(int(q), r, rad)
785
839
  else:
786
840
  t = NAN, NAN
787
841
  return t
@@ -808,7 +862,7 @@ def sincos2d(deg, adeg=_0_0):
808
862
  @arg deg: Angle (C{degrees}).
809
863
  @kwarg adeg: Optional correction (C{degrees}).
810
864
 
811
- @return: 2-Tuple (C{sin(B{deg_})}, C{cos(B{deg_})}, C{B{deg_} =
865
+ @return: 2-Tuple (C{sin(B{deg_})}, C{cos(B{deg_})} with C{B{deg_} =
812
866
  B{deg} + B{adeg}}).
813
867
 
814
868
  @see: U{GeographicLib<https://GeographicLib.SourceForge.io/C++/doc/
@@ -819,13 +873,10 @@ def sincos2d(deg, adeg=_0_0):
819
873
  include/GeographicLib/Math.hpp#l558>}.
820
874
  '''
821
875
  if _isfinite(deg):
822
- q = int(deg * _1__90) # int(math.floor)
823
- if q < 0:
824
- q -= 1
825
- d = deg - q * _90_0
876
+ q, d = divmod(deg, _90_0)
826
877
  if adeg:
827
878
  d = _MODS.karney._around(d + adeg)
828
- t = _sin0cos2(q & 3, radians(d), deg, fabs(d), _90_0)
879
+ t = _sin0cos2(int(q), radians(d), deg)
829
880
  else:
830
881
  t = NAN, NAN
831
882
  return t
@@ -861,7 +912,7 @@ def sincostan3(rad):
861
912
  def _sincostan3(s, c):
862
913
  '''(INTERNAL) Helper for C{sincostan3} and C{sincostan3d}.
863
914
  '''
864
- return s, c, _tanu(s, c, raiser=False)
915
+ return s, c, _over_1(s, c) # _tanu(s, c, raiser=False)
865
916
 
866
917
 
867
918
  def sincostan3d(deg):
@@ -885,7 +936,7 @@ def SM2m(sm):
885
936
 
886
937
  @raise ValueError: Invalid B{C{sm}}.
887
938
  '''
888
- return Meter(Float(sm=sm) * _M_SM)
939
+ return Meter(Float(sm=sm) * _M.SM)
889
940
 
890
941
 
891
942
  def tan_2(rad, **semi): # edge=1
@@ -916,7 +967,7 @@ def tan(rad, **raiser_kwds):
916
967
 
917
968
  @arg rad: Angle (C{radians}).
918
969
  @kwarg raiser_kwds: Use C{B{raiser}=False} to avoid
919
- ValueErrors or optionally, additional
970
+ ValueErrors and optional, additional
920
971
  ValueError keyword argments.
921
972
 
922
973
  @return: C{tan(B{rad})}.
@@ -924,9 +975,9 @@ def tan(rad, **raiser_kwds):
924
975
  @raise Error: If L{pygeodesy.isnear0}C{(cos(B{rad})}.
925
976
  '''
926
977
  try:
927
- return _tanu(*sincos2(rad), **raiser_kwds)
978
+ return _tanu(*sincos2(rad))
928
979
  except ZeroDivisionError:
929
- raise _valueError(tan, rad, **raiser_kwds)
980
+ return _nonfinite(tan, rad, **raiser_kwds)
930
981
 
931
982
 
932
983
  def tan_(*rads, **raiser_kwds):
@@ -940,9 +991,9 @@ def tan_(*rads, **raiser_kwds):
940
991
  '''
941
992
  try:
942
993
  for r in rads:
943
- yield _tanu(*sincos2(r), **raiser_kwds)
994
+ yield _tanu(*sincos2(r))
944
995
  except ZeroDivisionError:
945
- raise _valueError(tan_, r, **raiser_kwds)
996
+ yield _nonfinite(tan_, r, **raiser_kwds)
946
997
 
947
998
 
948
999
  def tand(deg, **raiser_kwds):
@@ -950,7 +1001,7 @@ def tand(deg, **raiser_kwds):
950
1001
 
951
1002
  @arg deg: Angle (C{degrees}).
952
1003
  @kwarg raiser_kwds: Use C{B{raiser}=False} to avoid
953
- ValueErrors or optionally, additional
1004
+ ValueErrors and optional, additional
954
1005
  ValueError keyword argments.
955
1006
 
956
1007
  @return: C{tan(B{deg})}.
@@ -958,9 +1009,9 @@ def tand(deg, **raiser_kwds):
958
1009
  @raise Error: If L{pygeodesy.isnear0}C{(cos(B{deg})}.
959
1010
  '''
960
1011
  try:
961
- return _tanu(*sincos2d(deg), **raiser_kwds)
1012
+ return _tanu(*sincos2d(deg))
962
1013
  except ZeroDivisionError:
963
- raise _valueError(tand, deg, **raiser_kwds)
1014
+ return _nonfinite(tand, deg, **raiser_kwds)
964
1015
 
965
1016
 
966
1017
  def tand_(*degs, **raiser_kwds):
@@ -974,9 +1025,9 @@ def tand_(*degs, **raiser_kwds):
974
1025
  '''
975
1026
  try:
976
1027
  for d in degs:
977
- yield _tanu(*sincos2d(d), **raiser_kwds)
1028
+ yield _tanu(*sincos2d(d))
978
1029
  except ZeroDivisionError:
979
- raise _valueError(tand_, d, **raiser_kwds)
1030
+ yield _nonfinite(tand_, d, **raiser_kwds)
980
1031
 
981
1032
 
982
1033
  def tanPI_2_2(rad):
@@ -990,20 +1041,17 @@ def tanPI_2_2(rad):
990
1041
  NAN if isnan(rad) else _copysign(_90_0, rad))
991
1042
 
992
1043
 
993
- def _tanu(s, c, raiser=True, **unused):
1044
+ def _tanu(s, c):
994
1045
  '''(INTERNAL) Helper for functions C{_cotu}, C{sincostan3},
995
1046
  C{sincostan3d}, C{tan}, C{tan_}, C{tand} and C{tand_}.
996
1047
  '''
997
1048
  if s is NAN or isnan(s):
998
- s = NAN
999
- elif s:
1000
- if raiser and isnear0(c):
1001
- raise ZeroDivisionError()
1002
- s = _over(s, c) if fabs(s) != fabs(c) else \
1003
- _copysign(_1_0, (-s) if c < 0 else s)
1004
- elif c < 0:
1005
- s = -s # negate-0
1006
- return s
1049
+ t = NAN
1050
+ elif isnear0(c):
1051
+ raise ZeroDivisionError()
1052
+ else:
1053
+ t = _over_1(s, c)
1054
+ return t
1007
1055
 
1008
1056
 
1009
1057
  def toise2m(toises):
@@ -1017,7 +1065,7 @@ def toise2m(toises):
1017
1065
 
1018
1066
  @see: Function L{fathom2m}.
1019
1067
  '''
1020
- return Meter(Float(toises=toises) * _M_TOISE)
1068
+ return Meter(Float(toises=toises) * _M.TOISE)
1021
1069
 
1022
1070
 
1023
1071
  def truncate(x, ndigits=None):
@@ -1076,7 +1124,7 @@ def _unrollon3(p1, p2, p3, wrap=False):
1076
1124
  '''(INTERNAL) Wrap/normalize, unroll 2 points.
1077
1125
  '''
1078
1126
  w = wrap
1079
- if w:
1127
+ if w: # PYCHOK no cover
1080
1128
  w = _Wrap.normal
1081
1129
  p2 = _unrollon(p1, p2, wrap=w)
1082
1130
  p3 = _unrollon(p1, p3, wrap=w)
@@ -1106,13 +1154,6 @@ def unrollPI(rad1, rad2, wrap=True):
1106
1154
  return r, rad2
1107
1155
 
1108
1156
 
1109
- def _valueError(where, x, raiser=True, **kwds):
1110
- '''(INTERNAL) Return a C{_ValueError} or C{None}.
1111
- '''
1112
- t = _MODS.streprs.Fmt.PAREN(typename(where), x)
1113
- return _ValueError(t, **kwds) if raiser else None
1114
-
1115
-
1116
1157
  class _Wrap(object):
1117
1158
 
1118
1159
  _normal = False # default
@@ -1125,7 +1166,7 @@ class _Wrap(object):
1125
1166
  return self._normal
1126
1167
 
1127
1168
  @normal.setter # PYCHOK setter!
1128
- def normal(self, setting):
1169
+ def normal(self, setting): # PYCHOK no cover
1129
1170
  '''Set L{normal} to C{True}, C{False} or C{None}.
1130
1171
  '''
1131
1172
  m = _MODS.formy
@@ -1136,7 +1177,7 @@ class _Wrap(object):
1136
1177
  self.latlon, self.philam = t
1137
1178
  self._normal = setting
1138
1179
 
1139
- def latlonDMS2(self, lat, lon, **DMS2_kwds):
1180
+ def latlonDMS2(self, lat, lon, **DMS2_kwds): # PYCHOK no cover
1140
1181
  if isstr(lat) or isstr(lon):
1141
1182
  kwds = _xkwds(DMS2_kwds, clipLon=0, clipLat=0)
1142
1183
  lat, lon = _MODS.dms.parseDMS2(lat, lon, **kwds)
@@ -1338,7 +1379,7 @@ def yard2m(yards):
1338
1379
 
1339
1380
  @raise ValueError: Invalid B{C{yards}}.
1340
1381
  '''
1341
- return Float(yards=yards) * _M_YARD_UK
1382
+ return Float(yards=yards) * _M.YARD_UK
1342
1383
 
1343
1384
  # **) MIT License
1344
1385
  #