pygeodesy 24.5.15__py2.py3-none-any.whl → 24.6.1__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 (90) hide show
  1. {PyGeodesy-24.5.15.dist-info → PyGeodesy-24.6.1.dist-info}/METADATA +6 -5
  2. PyGeodesy-24.6.1.dist-info/RECORD +116 -0
  3. pygeodesy/__init__.py +4 -4
  4. pygeodesy/albers.py +41 -41
  5. pygeodesy/auxilats/__init__.py +1 -1
  6. pygeodesy/auxilats/__main__.py +2 -2
  7. pygeodesy/auxilats/auxAngle.py +32 -31
  8. pygeodesy/auxilats/auxLat.py +80 -51
  9. pygeodesy/azimuthal.py +123 -124
  10. pygeodesy/basics.py +46 -10
  11. pygeodesy/booleans.py +13 -14
  12. pygeodesy/cartesianBase.py +25 -23
  13. pygeodesy/clipy.py +3 -3
  14. pygeodesy/constants.py +3 -3
  15. pygeodesy/css.py +50 -42
  16. pygeodesy/datums.py +42 -41
  17. pygeodesy/deprecated/functions.py +9 -3
  18. pygeodesy/dms.py +6 -6
  19. pygeodesy/ecef.py +41 -41
  20. pygeodesy/ellipsoidalBase.py +41 -41
  21. pygeodesy/ellipsoidalBaseDI.py +3 -4
  22. pygeodesy/ellipsoidalGeodSolve.py +2 -2
  23. pygeodesy/ellipsoidalKarney.py +3 -3
  24. pygeodesy/ellipsoidalNvector.py +11 -12
  25. pygeodesy/ellipsoids.py +45 -38
  26. pygeodesy/elliptic.py +3 -4
  27. pygeodesy/epsg.py +4 -3
  28. pygeodesy/errors.py +52 -20
  29. pygeodesy/etm.py +68 -65
  30. pygeodesy/fmath.py +44 -49
  31. pygeodesy/formy.py +129 -115
  32. pygeodesy/frechet.py +118 -103
  33. pygeodesy/fstats.py +21 -14
  34. pygeodesy/fsums.py +124 -80
  35. pygeodesy/gars.py +10 -9
  36. pygeodesy/geodesicw.py +19 -17
  37. pygeodesy/geodesicx/__init__.py +1 -1
  38. pygeodesy/geodesicx/__main__.py +2 -2
  39. pygeodesy/geodesicx/gx.py +39 -33
  40. pygeodesy/geodesicx/gxarea.py +12 -9
  41. pygeodesy/geodesicx/gxbases.py +3 -4
  42. pygeodesy/geodesicx/gxline.py +6 -8
  43. pygeodesy/geodsolve.py +29 -28
  44. pygeodesy/geohash.py +60 -57
  45. pygeodesy/geoids.py +34 -32
  46. pygeodesy/hausdorff.py +114 -101
  47. pygeodesy/heights.py +137 -130
  48. pygeodesy/internals.py +16 -11
  49. pygeodesy/interns.py +3 -6
  50. pygeodesy/iters.py +19 -17
  51. pygeodesy/karney.py +21 -17
  52. pygeodesy/ktm.py +25 -18
  53. pygeodesy/latlonBase.py +12 -11
  54. pygeodesy/lazily.py +6 -6
  55. pygeodesy/lcc.py +24 -25
  56. pygeodesy/ltp.py +143 -113
  57. pygeodesy/ltpTuples.py +207 -150
  58. pygeodesy/mgrs.py +26 -26
  59. pygeodesy/named.py +172 -90
  60. pygeodesy/namedTuples.py +33 -25
  61. pygeodesy/nvectorBase.py +8 -8
  62. pygeodesy/osgr.py +40 -48
  63. pygeodesy/points.py +18 -18
  64. pygeodesy/props.py +29 -16
  65. pygeodesy/rhumb/__init__.py +1 -1
  66. pygeodesy/rhumb/aux_.py +13 -15
  67. pygeodesy/rhumb/bases.py +12 -5
  68. pygeodesy/rhumb/ekx.py +24 -18
  69. pygeodesy/rhumb/solve.py +13 -10
  70. pygeodesy/simplify.py +16 -16
  71. pygeodesy/solveBase.py +18 -18
  72. pygeodesy/sphericalBase.py +17 -21
  73. pygeodesy/sphericalTrigonometry.py +21 -21
  74. pygeodesy/streprs.py +5 -5
  75. pygeodesy/trf.py +13 -11
  76. pygeodesy/triaxials.py +68 -64
  77. pygeodesy/units.py +35 -35
  78. pygeodesy/unitsBase.py +24 -11
  79. pygeodesy/ups.py +66 -70
  80. pygeodesy/utily.py +3 -3
  81. pygeodesy/utm.py +183 -187
  82. pygeodesy/utmups.py +38 -38
  83. pygeodesy/utmupsBase.py +104 -106
  84. pygeodesy/vector2d.py +6 -7
  85. pygeodesy/vector3d.py +16 -17
  86. pygeodesy/vector3dBase.py +4 -5
  87. pygeodesy/webmercator.py +43 -51
  88. PyGeodesy-24.5.15.dist-info/RECORD +0 -116
  89. {PyGeodesy-24.5.15.dist-info → PyGeodesy-24.6.1.dist-info}/WHEEL +0 -0
  90. {PyGeodesy-24.5.15.dist-info → PyGeodesy-24.6.1.dist-info}/top_level.txt +0 -0
pygeodesy/units.py CHANGED
@@ -12,7 +12,7 @@ from pygeodesy.constants import EPS, EPS1, PI, PI2, PI_2, _umod_360, _0_0, \
12
12
  from pygeodesy.dms import F__F, F__F_, S_NUL, S_SEP, parseDMS, parseRad, \
13
13
  _toDMS, toDMS
14
14
  from pygeodesy.errors import _AssertionError, _IsnotError, TRFError, UnitError, \
15
- _xkwds, _xkwds_item2
15
+ _xkwds
16
16
  from pygeodesy.interns import NN, _band_, _bearing_, _degrees_, _degrees2_, \
17
17
  _distance_, _E_, _easting_, _epoch_, _EW_, _feet_, \
18
18
  _height_, _lam_, _lat_, _LatLon_, _lon_, _meter_, \
@@ -23,13 +23,13 @@ from pygeodesy.interns import NN, _band_, _bearing_, _degrees_, _degrees2_, \
23
23
  from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS, _getenv
24
24
  from pygeodesy.props import Property_RO
25
25
  # from pygeodesy.streprs import Fmt, fstr # from .unitsBase
26
- from pygeodesy.unitsBase import _Error, Float, Fmt, fstr, Int, _NamedUnit, \
27
- Radius, Str # PYCHOK shared .namedTuples
26
+ from pygeodesy.unitsBase import _Error, Float, Fmt, fstr, Int, _arg_name_arg2, \
27
+ _NamedUnit, Radius, Str # PYCHOK shared .namedTuples
28
28
 
29
29
  from math import degrees, radians
30
30
 
31
31
  __all__ = _ALL_LAZY.units
32
- __version__ = '24.05.10'
32
+ __version__ = '24.05.20'
33
33
 
34
34
  _negative_falsed_ = 'negative, falsed'
35
35
 
@@ -46,15 +46,15 @@ class Float_(Float):
46
46
  @kwarg Error: Optional error to raise, overriding the default L{UnitError}.
47
47
  @kwarg low: Optional lower B{C{arg}} limit (C{float} or C{None}).
48
48
  @kwarg high: Optional upper B{C{arg}} limit (C{float} or C{None}).
49
- @kwarg name_arg: Optional C{name=arg} keyword argument, inlieu of B{C{name}}
50
- and B{C{arg}}.
49
+ @kwarg name_arg: Optional C{name=arg} keyword argument, inlieu of separate
50
+ B{C{arg}} and B{C{name}} ones.
51
51
 
52
52
  @returns: A C{Float_} instance.
53
53
 
54
54
  @raise Error: Invalid B{C{arg}} or B{C{arg}} below B{C{low}} or above B{C{high}}.
55
55
  '''
56
56
  if name_arg:
57
- name, arg = _xkwds_item2(name_arg)
57
+ name, arg = _arg_name_arg2(arg, **name_arg)
58
58
  self = Float.__new__(cls, arg=arg, name=name, Error=Error)
59
59
  if (low is not None) and self < low:
60
60
  txt = Fmt.limit(below=Fmt.g(low, prec=6, ints=isinstance(self, Epoch)))
@@ -77,15 +77,15 @@ class Int_(Int):
77
77
  @kwarg Error: Optional error to raise, overriding the default C{UnitError}.
78
78
  @kwarg low: Optional lower B{C{arg}} limit (C{int} or C{None}).
79
79
  @kwarg high: Optional upper B{C{arg}} limit (C{int} or C{None}).
80
- @kwarg name_arg: Optional C{name=arg} keyword argument, inlieu of B{C{name}}
81
- and B{C{arg}}.
80
+ @kwarg name_arg: Optional C{name=arg} keyword argument, inlieu of separate
81
+ B{C{arg}} and B{C{name}} ones.
82
82
 
83
83
  @returns: An L{Int_} instance.
84
84
 
85
85
  @raise Error: Invalid B{C{arg}} or B{C{arg}} below B{C{low}} or above B{C{high}}.
86
86
  '''
87
87
  if name_arg:
88
- name, arg = _xkwds_item2(name_arg)
88
+ name, arg = _arg_name_arg2(arg, **name_arg)
89
89
  self = Int.__new__(cls, arg=arg, name=name, Error=Error)
90
90
  if (low is not None) and self < low:
91
91
  txt = Fmt.limit(below=low)
@@ -118,7 +118,7 @@ class Bool(Int, _NamedUnit):
118
118
  @raise Error: Invalid B{C{arg}}.
119
119
  '''
120
120
  if name_arg:
121
- name, arg = _xkwds_item2(name_arg)
121
+ name, arg = _arg_name_arg2(arg, **name_arg)
122
122
  try:
123
123
  b = bool(arg)
124
124
  except Exception as x: # XXX not ... as x:
@@ -193,7 +193,7 @@ class Degrees(Float):
193
193
  range and L{pygeodesy.rangerrors} set to C{True}.
194
194
  '''
195
195
  if name_arg:
196
- name, arg = _xkwds_item2(name_arg)
196
+ name, arg = _arg_name_arg2(arg, **name_arg)
197
197
  try:
198
198
  d = Float.__new__(cls, parseDMS(arg, suffix=suffix, clip=clip),
199
199
  Error=Error, name=name)
@@ -253,15 +253,15 @@ class Degrees_(Degrees):
253
253
  @kwarg suffix: Optional, valid compass direction suffixes (C{NSEW}).
254
254
  @kwarg low: Optional lower B{C{arg}} limit (C{float} or C{None}).
255
255
  @kwarg high: Optional upper B{C{arg}} limit (C{float} or C{None}).
256
- @kwarg name_arg: Optional C{name=arg} keyword argument, inlieu of B{C{name}}
257
- and B{C{arg}}.
256
+ @kwarg name_arg: Optional C{name=arg} keyword argument, inlieu of separate
257
+ B{C{arg}} and B{C{name}} ones.
258
258
 
259
259
  @returns: A C{Degrees} instance.
260
260
 
261
261
  @raise Error: Invalid B{C{arg}} or B{C{arg}} below B{C{low}} or above B{C{high}}.
262
262
  '''
263
263
  if name_arg:
264
- name, arg = _xkwds_item2(name_arg)
264
+ name, arg = _arg_name_arg2(arg, **name_arg)
265
265
  self = Degrees.__new__(cls, arg=arg, name=name, Error=Error, suffix=suffix, clip=0)
266
266
  if (low is not None) and self < low:
267
267
  txt = Fmt.limit(below=low)
@@ -295,8 +295,8 @@ class Radians(Float):
295
295
  @kwarg suffix: Optional, valid compass direction suffixes (C{NSEW}).
296
296
  @kwarg clip: Optional B{C{arg}} range B{C{-clip..+clip}} (C{radians} or C{0}
297
297
  or C{None} for unclipped).
298
- @kwarg name_arg: Optional C{name=arg} keyword argument, inlieu of B{C{name}}
299
- and B{C{arg}}.
298
+ @kwarg name_arg: Optional C{name=arg} keyword argument, inlieu of separate
299
+ B{C{arg}} and B{C{name}} ones.
300
300
 
301
301
  @returns: A C{Radians} instance.
302
302
 
@@ -304,7 +304,7 @@ class Radians(Float):
304
304
  range and L{pygeodesy.rangerrors} set to C{True}.
305
305
  '''
306
306
  if name_arg:
307
- name, arg = _xkwds_item2(name_arg)
307
+ name, arg = _arg_name_arg2(arg, **name_arg)
308
308
  try:
309
309
  return Float.__new__(cls, parseRad(arg, suffix=suffix, clip=clip),
310
310
  Error=Error, name=name)
@@ -324,8 +324,8 @@ class Radians(Float):
324
324
  def toRepr(self, std=False, **prec_fmt_ints): # PYCHOK prec=8, ...
325
325
  '''Return a representation of this C{Radians}.
326
326
 
327
- @kwarg std: If C{True} return the standard C{repr},
328
- otherwise the named representation (C{bool}).
327
+ @kwarg std: If C{True} return the standard C{repr}, otherwise
328
+ the named representation (C{bool}).
329
329
 
330
330
  @see: Methods L{Radians.toStr}, L{Float.toRepr} and function
331
331
  L{pygeodesy.toDMS} for more documentation.
@@ -354,15 +354,15 @@ class Radians_(Radians):
354
354
  @kwarg suffix: Optional, valid compass direction suffixes (C{NSEW}).
355
355
  @kwarg low: Optional lower B{C{arg}} limit (C{float} or C{None}).
356
356
  @kwarg high: Optional upper B{C{arg}} limit (C{float} or C{None}).
357
- @kwarg name_arg: Optional C{name=arg} keyword argument, inlieu of B{C{name}}
358
- and B{C{arg}}.
357
+ @kwarg name_arg: Optional C{name=arg} keyword argument, inlieu of separate
358
+ B{C{arg}} and B{C{name}} ones.
359
359
 
360
360
  @returns: A C{Radians_} instance.
361
361
 
362
362
  @raise Error: Invalid B{C{arg}} or B{C{arg}} below B{C{low}} or above B{C{high}}.
363
363
  '''
364
364
  if name_arg:
365
- name, arg = _xkwds_item2(name_arg)
365
+ name, arg = _arg_name_arg2(arg, **name_arg)
366
366
  self = Radians.__new__(cls, arg=arg, name=name, Error=Error, suffix=suffix, clip=0)
367
367
  if (low is not None) and self < low:
368
368
  txt = Fmt.limit(below=low)
@@ -392,7 +392,7 @@ class Bearing(Degrees):
392
392
  '''New L{Bearing} instance, see L{Degrees}.
393
393
  '''
394
394
  if name_arg:
395
- name, arg = _xkwds_item2(name_arg)
395
+ name, arg = _arg_name_arg2(arg, **name_arg)
396
396
  d = Degrees.__new__(cls, arg=arg, name=name, Error=Error, suffix=_N_, clip=clip)
397
397
  b = _umod_360(d) # 0 <= b < 360
398
398
  return d if b == d else Degrees.__new__(cls, arg=b, name=name, Error=Error)
@@ -438,15 +438,15 @@ class Easting(Float):
438
438
  @kwarg Error: Optional error to raise, overriding the default L{UnitError}.
439
439
  @kwarg falsed: The B{C{arg}} value includes false origin (C{bool}).
440
440
  @kwarg high: Optional upper B{C{arg}} easting limit (C{scalar} or C{None}).
441
- @kwarg name_arg: Optional C{name=arg} keyword argument, inlieu of B{C{name}}
442
- and B{C{arg}}.
441
+ @kwarg name_arg: Optional C{name=arg} keyword argument, inlieu of separate
442
+ B{C{arg}} and B{C{name}} ones.
443
443
 
444
444
  @returns: An C{Easting} instance.
445
445
 
446
446
  @raise Error: Invalid B{C{arg}}, above B{C{high}} or negative, falsed B{C{arg}}.
447
447
  '''
448
448
  if name_arg:
449
- name, arg = _xkwds_item2(name_arg)
449
+ name, arg = _arg_name_arg2(arg, **name_arg)
450
450
  self = Float.__new__(cls, arg=arg, name=name, Error=Error)
451
451
  if high and (self < 0 or self > high): # like Veness
452
452
  raise _Error(cls, arg, name, Error)
@@ -465,7 +465,7 @@ class Epoch(Float_): # in .ellipsoidalBase, .trf
465
465
  '''New L{Epoch} instance, see L{Float_}.
466
466
  '''
467
467
  if name_arg:
468
- name, arg = _xkwds_item2(name_arg)
468
+ name, arg = _arg_name_arg2(arg, **name_arg)
469
469
  return arg if isinstance(arg, Epoch) else Float_.__new__(cls,
470
470
  arg=arg, name=name, Error=Error, low=low, high=high)
471
471
 
@@ -513,8 +513,8 @@ class FIx(Float_):
513
513
  @arg fi: The fractional index (C{float} or C{int}).
514
514
  @kwarg fin: Optional C{len}, the number of C{points}, the index
515
515
  C{[n]} wrapped to C{[0]} (C{int} or C{None}).
516
- @kwarg name_Error: Optional keyword argument C{B{name}=NN}
517
- and C{B{Error}=UnitError}.
516
+ @kwarg name_Error: Optional C{B{name}=NN} (C{str}) and keyword
517
+ argument C{B{Error}=UnitError}.
518
518
 
519
519
  @return: The B{C{fi}} (named L{FIx}).
520
520
 
@@ -629,7 +629,7 @@ class Lam_(Lam):
629
629
  '''New L{Lam_} instance, see L{Lam} and L{Radians}.
630
630
  '''
631
631
  if name_arg:
632
- name, arg = _xkwds_item2(name_arg)
632
+ name, arg = _arg_name_arg2(arg, **name_arg)
633
633
  d = Lam.__new__(cls, arg=arg, name=name, Error=Error, clip=clip)
634
634
  return Radians.__new__(cls, radians(d), name=name, Error=Error)
635
635
 
@@ -750,15 +750,15 @@ class Northing(Float):
750
750
  @kwarg Error: Optional error to raise, overriding the default L{UnitError}.
751
751
  @kwarg falsed: The B{C{arg}} value includes false origin (C{bool}).
752
752
  @kwarg high: Optional upper B{C{arg}} northing limit (C{scalar} or C{None}).
753
- @kwarg name_arg: Optional C{name=arg} keyword argument, inlieu of B{C{name}}
754
- and B{C{arg}}.
753
+ @kwarg name_arg: Optional C{name=arg} keyword argument, inlieu of separate
754
+ B{C{arg}} and B{C{name}} ones.
755
755
 
756
756
  @returns: A C{Northing} instance.
757
757
 
758
758
  @raise Error: Invalid B{C{arg}}, above B{C{high}} or negative, falsed B{C{arg}}.
759
759
  '''
760
760
  if name_arg:
761
- name, arg = _xkwds_item2(name_arg)
761
+ name, arg = _arg_name_arg2(arg, **name_arg)
762
762
  self = Float.__new__(cls, arg=arg, name=name, Error=Error)
763
763
  if high and (self < 0 or self > high):
764
764
  raise _Error(cls, arg, name, Error)
@@ -792,7 +792,7 @@ class Phi_(Phi):
792
792
  '''New L{Phi_} instance, see L{Phi} and L{Radians}.
793
793
  '''
794
794
  if name_arg:
795
- name, arg = _xkwds_item2(name_arg)
795
+ name, arg = _arg_name_arg2(arg, **name_arg)
796
796
  d = Phi.__new__(cls, arg=arg, name=name, Error=Error, clip=clip)
797
797
  return Radians.__new__(cls, arg=radians(d), name=name, Error=Error)
798
798
 
pygeodesy/unitsBase.py CHANGED
@@ -4,9 +4,9 @@
4
4
  u'''Basic C{Float}, C{Int} and C{Str}ing units classes.
5
5
  '''
6
6
 
7
- from pygeodesy.errors import UnitError, _XError, _xkwds_item2
7
+ from pygeodesy.errors import _UnexpectedError, UnitError, _XError
8
8
  from pygeodesy.interns import NN, _degrees_, _degrees2_, _invalid_, \
9
- _meter_, _radians_, _radians2_, \
9
+ _meter_, MISSING, _radians_, _radians2_, \
10
10
  _radius_, _UNDER_, _std_ # PYCHOK used!
11
11
  from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY
12
12
  from pygeodesy.named import modulename, _Named, property_doc_
@@ -14,7 +14,7 @@ from pygeodesy.named import modulename, _Named, property_doc_
14
14
  from pygeodesy.streprs import Fmt, fstr
15
15
 
16
16
  __all__ = _ALL_LAZY.unitsBase
17
- __version__ = '24.02.20'
17
+ __version__ = '24.05.20'
18
18
 
19
19
 
20
20
  class _NamedUnit(_Named):
@@ -69,14 +69,14 @@ class Float(float, _NamedUnit):
69
69
  @kwarg Error: Optional error to raise, overriding the default
70
70
  L{UnitError}.
71
71
  @kwarg name_arg: Optional C{name=arg} keyword argument, inlieu
72
- of B{C{name}} and B{C{arg}}.
72
+ of separate B{C{arg}} and B{C{name}} ones.
73
73
 
74
74
  @returns: A C{Float} instance.
75
75
 
76
76
  @raise Error: Invalid B{C{arg}}.
77
77
  '''
78
78
  if name_arg:
79
- name, arg = _xkwds_item2(name_arg)
79
+ name, arg = _arg_name_arg2(arg, **name_arg)
80
80
  try:
81
81
  self = float.__new__(cls, arg)
82
82
  if name:
@@ -146,15 +146,15 @@ class Int(int, _NamedUnit):
146
146
  @kwarg name: Optional instance name (C{str}).
147
147
  @kwarg Error: Optional error to raise, overriding the
148
148
  default L{UnitError}.
149
- @kwarg name_arg: Optional C{name=arg} keyword argument,
150
- inlieu of B{C{name}} and B{C{arg}}.
149
+ @kwarg name_arg: Optional C{name=arg} keyword argument, inlieu
150
+ of separate B{C{arg}} and B{C{name}} ones.
151
151
 
152
152
  @returns: An C{Int} instance.
153
153
 
154
154
  @raise Error: Invalid B{C{arg}}.
155
155
  '''
156
156
  if name_arg:
157
- name, arg = _xkwds_item2(name_arg)
157
+ name, arg = _arg_name_arg2(arg, **name_arg)
158
158
  try:
159
159
  self = int.__new__(cls, arg)
160
160
  if name:
@@ -223,8 +223,8 @@ class Str(str, _NamedUnit):
223
223
  @kwarg name: Optional instance name (C{str}).
224
224
  @kwarg Error: Optional error to raise, overriding the
225
225
  default (C{ValueError}).
226
- @kwarg name_arg: Optional C{name=arg} keyword argument,
227
- inlieu of B{C{name}} and B{C{arg}}.
226
+ @kwarg name_arg: Optional C{name=arg} keyword argument, inlieu
227
+ of separate B{C{arg}} and B{C{name}} ones.
228
228
 
229
229
  @returns: A L{Str} instance.
230
230
 
@@ -233,7 +233,7 @@ class Str(str, _NamedUnit):
233
233
  @see: Callable, not-nameable class L{pygeodesy.Str_}.
234
234
  '''
235
235
  if name_arg:
236
- name, arg = _xkwds_item2(name_arg)
236
+ name, arg = _arg_name_arg2(arg, **name_arg)
237
237
  try:
238
238
  self = str.__new__(cls, arg)
239
239
  if name:
@@ -324,6 +324,19 @@ def _Error(clas, arg, name, Error, txt=_invalid_, x=None):
324
324
  return _XError(Error, n, arg, txt=txt, cause=x)
325
325
 
326
326
 
327
+ def _arg_name_arg2(arg, name__=None, **name_arg): # in .units
328
+ '''(INTERNAL) Get the 2-tuple C{(name, arg)}.
329
+ '''
330
+ if name__ is None:
331
+ t = name_arg.popitem() if len(name_arg) == 1 else \
332
+ (MISSING, arg)
333
+ else:
334
+ t = name__.__name__, arg
335
+ if name_arg:
336
+ raise _UnexpectedError(**name_arg)
337
+ return t
338
+
339
+
327
340
  __all__ += _ALL_DOCS(_NamedUnit)
328
341
 
329
342
  # **) MIT License
pygeodesy/ups.py CHANGED
@@ -26,14 +26,14 @@ from pygeodesy.constants import EPS, EPS0, _EPSmin as _Tol90, \
26
26
  isnear90, _0_0, _0_5, _1_0, _2_0
27
27
  from pygeodesy.datums import _ellipsoidal_datum, _WGS84
28
28
  from pygeodesy.dms import degDMS, _neg, parseDMS2
29
- from pygeodesy.errors import RangeError, _ValueError
29
+ from pygeodesy.errors import RangeError, _ValueError, _xkwds_pop2
30
30
  from pygeodesy.fmath import hypot, hypot1, sqrt0
31
31
  # from pygeodesy.internals import _under # from .named
32
32
  from pygeodesy.interns import NN, _COMMASPACE_, _inside_, _N_, \
33
33
  _pole_, _range_, _S_, _scale0_, \
34
34
  _SPACE_, _std_, _to_, _UTM_
35
35
  from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS, _getenv
36
- from pygeodesy.named import nameof, _xnamed, _under
36
+ from pygeodesy.named import nameof, _under
37
37
  from pygeodesy.namedTuples import EasNor2Tuple, UtmUps5Tuple, \
38
38
  UtmUps8Tuple, UtmUpsLatLon5Tuple
39
39
  from pygeodesy.props import deprecated_method, property_doc_, \
@@ -49,7 +49,7 @@ from pygeodesy.utmupsBase import Fmt, _LLEB, _hemi, _parseUTMUPS5, _to4lldn, \
49
49
  from math import atan2, fabs, radians, tan
50
50
 
51
51
  __all__ = _ALL_LAZY.ups
52
- __version__ = '25.05.13'
52
+ __version__ = '25.05.31'
53
53
 
54
54
  _BZ_UPS = _getenv('PYGEODESY_UPS_POLES', _std_) == _std_
55
55
  _Falsing = Meter(2000e3) # false easting and northing (C{meter})
@@ -57,18 +57,6 @@ _K0_UPS = Float(_K0_UPS= 0.994) # scale factor at central meridian
57
57
  _K1_UPS = Float(_K1_UPS=_1_0) # rescale point scale factor
58
58
 
59
59
 
60
- def _scale(E, rho, tau):
61
- # compute the point scale factor, ala Karney
62
- t = hypot1(tau)
63
- return Float(scale=(rho / E.a) * t * sqrt0(E.e21 + E.e2 / t**2))
64
-
65
-
66
- def _toBand(lat, lon): # see utm._toBand
67
- '''(INTERNAL) Get the I{polar} Band letter for a (lat, lon).
68
- '''
69
- return _Bands[(0 if lat < 0 else 2) + (0 if -180 < lon < 0 else 1)]
70
-
71
-
72
60
  class UPSError(_ValueError):
73
61
  '''Universal Polar Stereographic (UPS) parse or other L{Ups} issue.
74
62
  '''
@@ -88,7 +76,7 @@ class Ups(UtmUpsBase):
88
76
  def __init__(self, zone=0, pole=_N_, easting=_Falsing, # PYCHOK expected
89
77
  northing=_Falsing, band=NN, datum=_WGS84,
90
78
  falsed=True, gamma=None, scale=None,
91
- name=NN, **convergence):
79
+ **name_convergence):
92
80
  '''New L{Ups} UPS coordinate.
93
81
 
94
82
  @kwarg zone: UPS zone (C{int}, zero) or zone with/-out I{polar} Band
@@ -100,13 +88,13 @@ class Ups(UtmUpsBase):
100
88
  @kwarg band: Optional, I{polar} Band (C{str}, 'A'|'B'|'Y'|'Z').
101
89
  @kwarg datum: Optional, this coordinate's datum (L{Datum},
102
90
  L{Ellipsoid}, L{Ellipsoid2} or L{a_f2Tuple}).
103
- @kwarg falsed: If C{True}, both B{C{easting}} and B{C{northing}}
104
- are falsed (C{bool}).
105
- @kwarg gamma: Optional, meridian convergence to save (C{degrees}).
106
- @kwarg scale: Optional, computed scale factor k to save
107
- (C{scalar}).
108
- @kwarg name: Optional name (C{str}).
109
- @kwarg convergence: DEPRECATED, use keyword argument C{B{gamma}=None}.
91
+ @kwarg falsed: If C{True}, both B{C{easting}} and B{C{northing}} are
92
+ falsed (C{bool}).
93
+ @kwarg gamma: Optional meridian convergence, bearing off grid North,
94
+ clockwise from true North to save (C{degrees}) or C{None}.
95
+ @kwarg scale: Optional grid scale factor to save (C{scalar}) or C{None}.
96
+ @kwarg name_convergence: Optional C{B{name}=NN} (C{str}) and DEPRECATED
97
+ keyword argument C{B{convergence}=None}, use B{C{gamma}}.
110
98
 
111
99
  @raise TypeError: Invalid B{C{datum}}.
112
100
 
@@ -114,18 +102,19 @@ class Ups(UtmUpsBase):
114
102
  B{C{northing}}, B{C{band}}, B{C{convergence}}
115
103
  or B{C{scale}}.
116
104
  '''
117
- if name:
118
- self.name = name
119
-
105
+ if name_convergence:
106
+ gamma, name = _xkwds_pop2(name_convergence, convergence=gamma)
107
+ if name:
108
+ self.name = name
120
109
  try:
121
- z, B, p = _to3zBhp(zone, band, hemipole=pole)
110
+ z, B, self._pole = _to3zBhp(zone, band, hemipole=pole)
122
111
  if z != _UPS_ZONE or (B and (B not in _Bands)):
123
112
  raise ValueError
124
113
  except (TypeError, ValueError) as x:
125
114
  raise UPSError(zone=zone, pole=pole, band=band, cause=x)
126
- self._pole = p
115
+
127
116
  UtmUpsBase.__init__(self, easting, northing, band=B, datum=datum, falsed=falsed,
128
- gamma=gamma, scale=scale, **convergence)
117
+ gamma=gamma, scale=scale)
129
118
 
130
119
  def __eq__(self, other):
131
120
  return isinstance(other, Ups) and other.zone == self.zone \
@@ -161,13 +150,11 @@ class Ups(UtmUpsBase):
161
150
  f = _Falsing if self.falsed else 0
162
151
  return EasNor2Tuple(f, f)
163
152
 
164
- def parse(self, strUPS, name=NN):
153
+ def parse(self, strUPS, **name):
165
154
  '''Parse a string to a similar L{Ups} instance.
166
155
 
167
- @arg strUPS: The UPS coordinate (C{str}),
168
- see function L{parseUPS5}.
169
- @kwarg name: Optional instance name (C{str}),
170
- overriding this name.
156
+ @arg strUPS: The UPS coordinate (C{str}), see function L{parseUPS5}.
157
+ @kwarg name: Optional C{B{name}=NN} (C{str}), overriding this name.
171
158
 
172
159
  @return: The similar instance (L{Ups}).
173
160
 
@@ -176,7 +163,7 @@ class Ups(UtmUpsBase):
176
163
  @see: Functions L{parseUTM5} and L{pygeodesy.parseUTMUPS5}.
177
164
  '''
178
165
  return parseUPS5(strUPS, datum=self.datum, Ups=self.classof,
179
- name=name or self.name)
166
+ name=self._name__(name))
180
167
 
181
168
  @deprecated_method
182
169
  def parseUPS(self, strUPS): # PYCHOK no cover
@@ -250,9 +237,8 @@ class Ups(UtmUpsBase):
250
237
  b, g, a = atan2(x, y), -1, _neg(a)
251
238
  ll = _LLEB(a, degrees180(b), datum=self._datum, name=self.name)
252
239
 
253
- ll._gamma = b * g
254
- ll._scale = _scale(E, r, t) if r > 0 else self.scale0
255
- self._latlon5args(ll, _toBand, unfalse)
240
+ k = _scale(E, r, t) if r > 0 else self.scale0
241
+ self._latlon5args(ll, g * b, k, _toBand, unfalse)
256
242
 
257
243
  def toRepr(self, prec=0, fmt=Fmt.SQUARE, sep=_COMMASPACE_, B=False, cs=False, **unused): # PYCHOK expected
258
244
  '''Return a string representation of this UPS coordinate.
@@ -353,7 +339,7 @@ class _Ups_K1(Ups):
353
339
  _scale0 = _K1_UPS
354
340
 
355
341
 
356
- def parseUPS5(strUPS, datum=_WGS84, Ups=Ups, falsed=True, name=NN):
342
+ def parseUPS5(strUPS, datum=_WGS84, Ups=Ups, falsed=True, **name):
357
343
  '''Parse a string representing a UPS coordinate, consisting of
358
344
  C{"[zone][band] pole easting northing"} where B{C{zone}} is
359
345
  pseudo zone C{"00"|"0"|""} and C{band} is C{'A'|'B'|'Y'|'Z'|''}.
@@ -362,8 +348,9 @@ def parseUPS5(strUPS, datum=_WGS84, Ups=Ups, falsed=True, name=NN):
362
348
  @kwarg datum: Optional datum to use (L{Datum}).
363
349
  @kwarg Ups: Optional class to return the UPS coordinate (L{Ups})
364
350
  or C{None}.
365
- @kwarg falsed: Both B{C{easting}} and B{C{northing}} are falsed (C{bool}).
366
- @kwarg name: Optional B{C{Ups}} name (C{str}).
351
+ @kwarg falsed: If C{True}, both B{C{easting}} and B{C{northing}}
352
+ are falsed (C{bool}).
353
+ @kwarg name: Optional B{C{Ups}} C{B{name}=NN} (C{str}).
367
354
 
368
355
  @return: The UPS coordinate (B{C{Ups}}) or a
369
356
  L{UtmUps5Tuple}C{(zone, hemipole, easting, northing,
@@ -376,43 +363,54 @@ def parseUPS5(strUPS, datum=_WGS84, Ups=Ups, falsed=True, name=NN):
376
363
  if z != _UPS_ZONE or (B and B not in _Bands):
377
364
  raise UPSError(strUPS=strUPS, zone=z, band=B)
378
365
 
379
- r = UtmUps5Tuple(z, p, e, n, B, Error=UPSError) if Ups is None \
380
- else Ups(z, p, e, n, band=B, falsed=falsed, datum=datum)
381
- return _xnamed(r, name)
366
+ r = UtmUps5Tuple(z, p, e, n, B, Error=UPSError, **name) if Ups is None \
367
+ else Ups(z, p, e, n, band=B, falsed=falsed, datum=datum, **name)
368
+ return r
369
+
370
+
371
+ def _scale(E, rho, tau):
372
+ # compute the point scale factor, ala Karney
373
+ t = hypot1(tau)
374
+ return Float(scale=(rho / E.a) * t * sqrt0(E.e21 + E.e2 / t**2))
375
+
376
+
377
+ def _toBand(lat, lon): # see utm._toBand
378
+ '''(INTERNAL) Get the I{polar} Band letter for a (lat, lon).
379
+ '''
380
+ return _Bands[(0 if lat < 0 else 2) + (0 if -180 < lon < 0 else 1)]
382
381
 
383
382
 
384
383
  def toUps8(latlon, lon=None, datum=None, Ups=Ups, pole=NN,
385
- falsed=True, strict=True, name=NN):
384
+ falsed=True, strict=True, **name):
386
385
  '''Convert a lat-/longitude point to a UPS coordinate.
387
386
 
388
- @arg latlon: Latitude (C{degrees}) or an (ellipsoidal)
389
- geodetic C{LatLon} point.
387
+ @arg latlon: Latitude (C{degrees}) or an (ellipsoidal) geodetic
388
+ C{LatLon} point.
390
389
  @kwarg lon: Optional longitude (C{degrees}) or C{None} if
391
390
  B{C{latlon}} is a C{LatLon}.
392
- @kwarg datum: Optional datum for this UPS coordinate,
393
- overriding B{C{latlon}}'s datum (C{Datum},
394
- L{Ellipsoid}, L{Ellipsoid2} or L{a_f2Tuple}).
395
- @kwarg Ups: Optional class to return the UPS coordinate
396
- (L{Ups}) or C{None}.
391
+ @kwarg datum: Optional datum for this UPS coordinate, overriding
392
+ B{C{latlon}}'s datum (C{Datum}, L{Ellipsoid},
393
+ L{Ellipsoid2} or L{a_f2Tuple}).
394
+ @kwarg Ups: Optional class to return the UPS coordinate (L{Ups})
395
+ or C{None}.
397
396
  @kwarg pole: Optional top/center of (stereographic) projection
398
397
  (C{str}, C{'N[orth]'} or C{'S[outh]'}).
399
- @kwarg falsed: False both easting and northing (C{bool}).
398
+ @kwarg falsed: If C{True}, false both easting and northing (C{bool}).
400
399
  @kwarg strict: Restrict B{C{lat}} to UPS ranges (C{bool}).
401
- @kwarg name: Optional B{C{Ups}} name (C{str}).
400
+ @kwarg name: Optional B{C{Ups}} C{B{name}=NN} (C{str}).
402
401
 
403
- @return: The UPS coordinate (B{C{Ups}}) or a
404
- L{UtmUps8Tuple}C{(zone, hemipole, easting, northing,
405
- band, datum, gamma, scale)} if B{C{Ups}} is C{None}.
406
- The C{hemipole} is the C{'N'|'S'} pole, the UPS
407
- projection top/center.
402
+ @return: The UPS coordinate (B{C{Ups}}) or a L{UtmUps8Tuple}C{(zone,
403
+ hemipole, easting, northing, band, datum, gamma, scale)} if
404
+ B{C{Ups}} is C{None}. The C{hemipole} is the C{'N'|'S'}
405
+ pole, the UPS projection top/center.
408
406
 
409
407
  @raise RangeError: If B{C{strict}} and B{C{lat}} outside the valid
410
408
  UPS bands or if B{C{lat}} or B{C{lon}} outside
411
409
  the valid range and L{pygeodesy.rangerrors} set
412
410
  to C{True}.
413
411
 
414
- @raise TypeError: If B{C{latlon}} is not ellipsoidal or
415
- B{C{datum}} invalid.
412
+ @raise TypeError: If B{C{latlon}} is not ellipsoidal or if B{C{datum}}
413
+ is invalid.
416
414
 
417
415
  @raise ValueError: If B{C{lon}} value is missing or if B{C{latlon}}
418
416
  is invalid.
@@ -463,9 +461,7 @@ def toUps8(latlon, lon=None, datum=None, Ups=Ups, pole=NN,
463
461
  r = Ups(z, p, x, y, band=B, datum=d, falsed=falsed,
464
462
  gamma=g, scale=k, name=n)
465
463
  if isinstance(latlon, _LLEB) and d is latlon.datum: # see utm._toXtm8
466
- r._latlon5args(latlon, _toBand, falsed) # XXX weakref(latlon)?
467
- latlon._gamma = g
468
- latlon._scale = k
464
+ r._latlon5args(latlon, g, k, _toBand, falsed) # XXX weakref(latlon)?
469
465
  else:
470
466
  r._hemisphere = _hemi(lat)
471
467
  if not r._band:
@@ -473,18 +469,18 @@ def toUps8(latlon, lon=None, datum=None, Ups=Ups, pole=NN,
473
469
  return r
474
470
 
475
471
 
476
- def upsZoneBand5(lat, lon, strict=True, name=NN):
472
+ def upsZoneBand5(lat, lon, strict=True, **name):
477
473
  '''Return the UTM/UPS zone number, I{polar} Band letter, pole and
478
474
  clipped lat- and longitude for a given location.
479
475
 
480
476
  @arg lat: Latitude in degrees (C{scalar} or C{str}).
481
477
  @arg lon: Longitude in degrees (C{scalar} or C{str}).
482
478
  @kwarg strict: Restrict B{C{lat}} to UPS ranges (C{bool}).
483
- @kwarg name: Optional name (C{str}).
479
+ @kwarg name: Optional B{C{Ups}} C{B{name}=NN} (C{str}).
484
480
 
485
- @return: A L{UtmUpsLatLon5Tuple}C{(zone, band, hemipole,
486
- lat, lon)} where C{hemipole} is the C{'N'|'S'} pole,
487
- the UPS projection top/center and C{lon} [-180..180).
481
+ @return: A L{UtmUpsLatLon5Tuple}C{(zone, band, hemipole, lat,
482
+ lon)} where C{hemipole} is the C{'N'|'S'} pole, the
483
+ UPS projection top/center and C{lon} [-180..180).
488
484
 
489
485
  @note: The C{lon} is set to C{0} if B{C{lat}} is C{-90} or
490
486
  C{90}, see env variable C{PYGEODESY_UPS_POLES} in
@@ -514,7 +510,7 @@ def upsZoneBand5(lat, lon, strict=True, name=NN):
514
510
 
515
511
  else:
516
512
  B, p = NN, _hemi(lat)
517
- return UtmUpsLatLon5Tuple(z, B, p, lat, lon, Error=UPSError, name=name)
513
+ return UtmUpsLatLon5Tuple(z, B, p, lat, lon, Error=UPSError, **name)
518
514
 
519
515
  # **) MIT License
520
516
  #
pygeodesy/utily.py CHANGED
@@ -17,7 +17,7 @@ from pygeodesy.constants import EPS, EPS0, INF, NAN, PI, PI2, PI_2, R_M, \
17
17
  _N_180_0, _360_0, _400_0, _copysign_0_0, \
18
18
  _float as _F, _isfinite, isnan, isnear0, \
19
19
  _over, _umod_360, _umod_PI2
20
- from pygeodesy.errors import _ValueError, _xkwds, _xkwds_get, _ALL_LAZY, _MODS
20
+ from pygeodesy.errors import _ValueError, _xkwds, _xkwds_get1, _ALL_LAZY, _MODS
21
21
  from pygeodesy.internals import _passargs # , _MODS?
22
22
  from pygeodesy.interns import _edge_, _radians_, _semi_circular_, _SPACE_
23
23
  # from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS # from .errors
@@ -27,7 +27,7 @@ from pygeodesy.units import Degrees, Degrees_, Feet, Float, Lam, Lam_, \
27
27
  from math import acos, asin, atan2, cos, degrees, fabs, radians, sin, tan # pow
28
28
 
29
29
  __all__ = _ALL_LAZY.utily
30
- __version__ = '24.05.14'
30
+ __version__ = '24.05.29'
31
31
 
32
32
  # read constant name "_M_Unit" as "meter per Unit"
33
33
  _M_CHAIN = _F( 20.1168) # yard2m(1) * 22
@@ -763,7 +763,7 @@ def sincos2d(deg, **adeg):
763
763
  q -= 1
764
764
  d = deg - q * _90_0
765
765
  if adeg:
766
- t = _xkwds_get(adeg, adeg=_0_0)
766
+ t = _xkwds_get1(adeg, adeg=_0_0)
767
767
  d = _MODS.karney._around(d + t)
768
768
  t = _sin0cos2(q & 3, radians(d), deg)
769
769
  else: