pygeodesy 24.6.9__py2.py3-none-any.whl → 24.7.7__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 (87) hide show
  1. {PyGeodesy-24.6.9.dist-info → PyGeodesy-24.7.7.dist-info}/METADATA +2 -2
  2. PyGeodesy-24.7.7.dist-info/RECORD +117 -0
  3. pygeodesy/__init__.py +39 -32
  4. pygeodesy/__main__.py +6 -1
  5. pygeodesy/albers.py +2 -2
  6. pygeodesy/auxilats/__init__.py +1 -1
  7. pygeodesy/auxilats/auxAngle.py +40 -39
  8. pygeodesy/auxilats/auxDLat.py +3 -2
  9. pygeodesy/auxilats/auxLat.py +16 -18
  10. pygeodesy/auxilats/auxily.py +1 -1
  11. pygeodesy/azimuthal.py +10 -10
  12. pygeodesy/basics.py +16 -4
  13. pygeodesy/booleans.py +4 -4
  14. pygeodesy/cartesianBase.py +11 -14
  15. pygeodesy/css.py +14 -18
  16. pygeodesy/datums.py +6 -6
  17. pygeodesy/deprecated/__init__.py +1 -1
  18. pygeodesy/deprecated/classes.py +25 -4
  19. pygeodesy/deprecated/datum.py +3 -3
  20. pygeodesy/deprecated/functions.py +6 -8
  21. pygeodesy/dms.py +23 -27
  22. pygeodesy/ecef.py +4 -4
  23. pygeodesy/elevations.py +4 -4
  24. pygeodesy/ellipsoidalBase.py +23 -28
  25. pygeodesy/ellipsoidalBaseDI.py +19 -23
  26. pygeodesy/ellipsoidalExact.py +3 -3
  27. pygeodesy/ellipsoidalGeodSolve.py +15 -23
  28. pygeodesy/ellipsoidalKarney.py +37 -60
  29. pygeodesy/ellipsoidalNvector.py +38 -44
  30. pygeodesy/ellipsoidalVincenty.py +11 -14
  31. pygeodesy/ellipsoids.py +107 -101
  32. pygeodesy/errors.py +109 -48
  33. pygeodesy/etm.py +32 -44
  34. pygeodesy/formy.py +55 -58
  35. pygeodesy/frechet.py +18 -20
  36. pygeodesy/fsums.py +3 -3
  37. pygeodesy/gars.py +3 -4
  38. pygeodesy/geodesici.py +1696 -0
  39. pygeodesy/geodesicw.py +15 -15
  40. pygeodesy/geodesicx/__init__.py +4 -4
  41. pygeodesy/geodesicx/gx.py +34 -55
  42. pygeodesy/geodesicx/gxbases.py +20 -8
  43. pygeodesy/geodesicx/gxline.py +93 -88
  44. pygeodesy/geodsolve.py +108 -59
  45. pygeodesy/geohash.py +26 -34
  46. pygeodesy/geoids.py +28 -37
  47. pygeodesy/hausdorff.py +17 -18
  48. pygeodesy/heights.py +2 -2
  49. pygeodesy/internals.py +46 -13
  50. pygeodesy/interns.py +2 -2
  51. pygeodesy/karney.py +78 -15
  52. pygeodesy/ktm.py +13 -16
  53. pygeodesy/latlonBase.py +17 -19
  54. pygeodesy/lazily.py +28 -25
  55. pygeodesy/lcc.py +28 -31
  56. pygeodesy/ltp.py +7 -8
  57. pygeodesy/ltpTuples.py +71 -73
  58. pygeodesy/mgrs.py +8 -9
  59. pygeodesy/named.py +19 -10
  60. pygeodesy/nvectorBase.py +9 -10
  61. pygeodesy/osgr.py +9 -9
  62. pygeodesy/points.py +6 -6
  63. pygeodesy/rhumb/__init__.py +1 -1
  64. pygeodesy/rhumb/aux_.py +5 -5
  65. pygeodesy/rhumb/bases.py +30 -31
  66. pygeodesy/rhumb/ekx.py +3 -4
  67. pygeodesy/rhumb/solve.py +21 -22
  68. pygeodesy/solveBase.py +177 -123
  69. pygeodesy/sphericalBase.py +10 -11
  70. pygeodesy/sphericalNvector.py +13 -13
  71. pygeodesy/sphericalTrigonometry.py +86 -97
  72. pygeodesy/streprs.py +4 -34
  73. pygeodesy/triaxials.py +48 -43
  74. pygeodesy/units.py +208 -275
  75. pygeodesy/unitsBase.py +115 -107
  76. pygeodesy/ups.py +26 -31
  77. pygeodesy/utily.py +8 -8
  78. pygeodesy/utm.py +35 -40
  79. pygeodesy/utmups.py +43 -46
  80. pygeodesy/utmupsBase.py +8 -9
  81. pygeodesy/vector3d.py +26 -27
  82. pygeodesy/vector3dBase.py +6 -7
  83. pygeodesy/webmercator.py +19 -21
  84. pygeodesy/wgrs.py +18 -20
  85. PyGeodesy-24.6.9.dist-info/RECORD +0 -116
  86. {PyGeodesy-24.6.9.dist-info → PyGeodesy-24.7.7.dist-info}/WHEEL +0 -0
  87. {PyGeodesy-24.6.9.dist-info → PyGeodesy-24.7.7.dist-info}/top_level.txt +0 -0
pygeodesy/units.py CHANGED
@@ -6,93 +6,74 @@ basic C{float}, C{int} respectively C{str} to named units as L{Degrees},
6
6
  L{Feet}, L{Meter}, L{Radians}, etc.
7
7
  '''
8
8
 
9
- from pygeodesy.basics import isscalar, isstr, issubclassof, signOf, _xsubclassof
9
+ from pygeodesy.basics import isscalar, issubclassof, signOf
10
10
  from pygeodesy.constants import EPS, EPS1, PI, PI2, PI_2, _umod_360, _0_0, \
11
11
  _0_001, _0_5, INT0 # PYCHOK for .mgrs, .namedTuples
12
12
  from pygeodesy.dms import F__F, F__F_, S_NUL, S_SEP, parseDMS, parseRad, _toDMS
13
- from pygeodesy.errors import _AssertionError, _IsnotError, TRFError, UnitError, \
14
- _xattr
15
- from pygeodesy.interns import NN, _band_, _bearing_, _degrees_, _degrees2_, \
16
- _distance_, _E_, _easting_, _epoch_, _EW_, _feet_, \
17
- _height_, _lam_, _lat_, _LatLon_, _lon_, _meter_, \
18
- _meter2_, _N_, _northing_, _NS_, _NSEW_, _number_, \
19
- _PERCENT_, _phi_, _precision_, _radians_, _radians2_, \
20
- _radius_, _S_, _scalar_, _units_, _W_, _zone_, \
21
- _std_ # PYCHOK used!
13
+ from pygeodesy.errors import _AssertionError, TRFError, UnitError, _xattr, _xcallable
14
+ from pygeodesy.interns import NN, _band_, _bearing_, _COMMASPACE_, _degrees_, \
15
+ _degrees2_, _distance_, _E_, _easting_, _epoch_, _EW_, \
16
+ _feet_, _height_, _lam_, _lat_, _LatLon_, _lon_, \
17
+ _meter_, _meter2_, _N_, _negative_, _northing_, _NS_, \
18
+ _NSEW_, _number_, _PERCENT_, _phi_, _precision_, \
19
+ _radians_, _radians2_, _radius_, _S_, _scalar_, \
20
+ _units_, _W_, _zone_, _std_ # PYCHOK used!
22
21
  from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS, _getenv
22
+ # from pygeodesy.named import _name__ # _MODS
23
23
  from pygeodesy.props import Property_RO
24
24
  # from pygeodesy.streprs import Fmt, fstr # from .unitsBase
25
- from pygeodesy.unitsBase import _Error, Float, Fmt, fstr, Int, _arg_name_arg2, \
26
- _NamedUnit, Radius, Str # PYCHOK shared .namedTuples
25
+ from pygeodesy.unitsBase import Float, Int, _NamedUnit, Radius, Str, Fmt, fstr
27
26
 
28
27
  from math import degrees, radians
29
28
 
30
29
  __all__ = _ALL_LAZY.units
31
- __version__ = '24.06.10'
32
-
33
- _negative_falsed_ = 'negative, falsed'
30
+ __version__ = '24.06.29'
34
31
 
35
32
 
36
33
  class Float_(Float):
37
34
  '''Named C{float} with optional C{low} and C{high} limit.
38
35
  '''
39
- def __new__(cls, arg=None, name=NN, Error=UnitError, low=EPS, high=None, **name_arg):
40
- '''New C{Float_} instance.
36
+ def __new__(cls, arg=None, name=NN, low=EPS, high=None, **Error_name_arg):
37
+ '''New, named C{Float_}, see L{Float}.
41
38
 
42
39
  @arg cls: This class (C{Float_} or sub-class).
43
40
  @kwarg arg: The value (any C{type} convertable to C{float}).
44
41
  @kwarg name: Optional instance name (C{str}).
45
- @kwarg Error: Optional error to raise, overriding the default L{UnitError}.
46
42
  @kwarg low: Optional lower B{C{arg}} limit (C{float} or C{None}).
47
43
  @kwarg high: Optional upper B{C{arg}} limit (C{float} or C{None}).
48
- @kwarg name_arg: Optional C{name=arg} keyword argument, inlieu of separate
49
- B{C{arg}} and B{C{name}} ones.
50
44
 
51
- @returns: A C{Float_} instance.
45
+ @returns: A named C{Float_}.
52
46
 
53
47
  @raise Error: Invalid B{C{arg}} or B{C{arg}} below B{C{low}} or above B{C{high}}.
54
48
  '''
55
- if name_arg:
56
- name, arg = _arg_name_arg2(arg, **name_arg)
57
- self = Float.__new__(cls, arg=arg, name=name, Error=Error)
58
- if (low is not None) and self < low:
59
- txt = Fmt.limit(below=Fmt.g(low, prec=6, ints=isinstance(self, Epoch)))
60
- elif (high is not None) and self > high:
61
- txt = Fmt.limit(above=Fmt.g(high, prec=6, ints=isinstance(self, Epoch)))
62
- else:
63
- return self
64
- raise _Error(cls, arg, name, Error, txt=txt)
49
+ self = Float.__new__(cls, arg=arg, name=name, **Error_name_arg)
50
+ t = _xlimits(self, low, high, g=True)
51
+ if t:
52
+ raise _NamedUnit._Error(cls, arg, name, txt=t, **Error_name_arg)
53
+ return self
65
54
 
66
55
 
67
56
  class Int_(Int):
68
57
  '''Named C{int} with optional limits C{low} and C{high}.
69
58
  '''
70
- def __new__(cls, arg=None, name=NN, Error=UnitError, low=0, high=None, **name_arg):
71
- '''New named C{int} instance with limits.
59
+ def __new__(cls, arg=None, name=NN, low=0, high=None, **Error_name_arg):
60
+ '''New, named C{int} instance with limits, see L{Int}.
72
61
 
73
62
  @kwarg cls: This class (C{Int_} or sub-class).
74
63
  @arg arg: The value (any C{type} convertable to C{int}).
75
64
  @kwarg name: Optional instance name (C{str}).
76
- @kwarg Error: Optional error to raise, overriding the default C{UnitError}.
77
65
  @kwarg low: Optional lower B{C{arg}} limit (C{int} or C{None}).
78
66
  @kwarg high: Optional upper B{C{arg}} limit (C{int} or C{None}).
79
- @kwarg name_arg: Optional C{name=arg} keyword argument, inlieu of separate
80
- B{C{arg}} and B{C{name}} ones.
81
67
 
82
- @returns: An L{Int_} instance.
68
+ @returns: A named L{Int_}.
83
69
 
84
70
  @raise Error: Invalid B{C{arg}} or B{C{arg}} below B{C{low}} or above B{C{high}}.
85
71
  '''
86
- if name_arg:
87
- name, arg = _arg_name_arg2(arg, **name_arg)
88
- self = Int.__new__(cls, arg=arg, name=name, Error=Error)
89
- if (low is not None) and self < low:
90
- txt = Fmt.limit(below=low)
91
- elif (high is not None) and self > high:
92
- txt = Fmt.limit(above=high)
93
- else:
94
- return self
95
- raise _Error(cls, arg, name, Error, txt=txt)
72
+ self = Int.__new__(cls, arg=arg, name=name, **Error_name_arg)
73
+ t = _xlimits(self, low, high)
74
+ if t:
75
+ raise _NamedUnit._Error(cls, arg, name, txt=t, **Error_name_arg)
76
+ return self
96
77
 
97
78
 
98
79
  class Bool(Int, _NamedUnit):
@@ -102,25 +83,25 @@ class Bool(Int, _NamedUnit):
102
83
  _bool_True_or_False = None
103
84
 
104
85
  def __new__(cls, arg=None, name=NN, Error=UnitError, **name_arg):
105
- '''New C{Bool} instance.
86
+ '''New, named C{Bool}.
106
87
 
107
88
  @kwarg cls: This class (C{Bool} or sub-class).
108
89
  @kwarg arg: The value (any C{type} convertable to C{bool}).
109
90
  @kwarg name: Optional instance name (C{str}).
110
91
  @kwarg Error: Optional error to raise, overriding the default L{UnitError}.
111
92
  @kwarg name_arg: Optional C{name=arg} keyword argument, inlieu of separate
112
- B{C{name}} and B{C{arg}}.
93
+ B{C{arg}} and B{C{name}} ones.
113
94
 
114
- @returns: A L{Bool}, a C{bool}-like instance.
95
+ @returns: A named L{Bool}, C{bool}-like.
115
96
 
116
97
  @raise Error: Invalid B{C{arg}}.
117
98
  '''
118
99
  if name_arg:
119
- name, arg = _arg_name_arg2(arg, **name_arg)
100
+ name, arg = _NamedUnit._arg_name_arg2(arg, **name_arg)
120
101
  try:
121
102
  b = bool(arg)
122
- except Exception as x: # XXX not ... as x:
123
- raise _Error(cls, arg, name, Error, x=x)
103
+ except Exception as x:
104
+ raise _NamedUnit._Error(cls, arg, name, Error, cause=x)
124
105
 
125
106
  self = Int.__new__(cls, b, name=name, Error=Error)
126
107
  self._bool_True_or_False = b
@@ -154,7 +135,7 @@ class Band(Str):
154
135
  '''Named C{str} representing a UTM/UPS band letter, unchecked.
155
136
  '''
156
137
  def __new__(cls, arg=None, name=_band_, **Error_name_arg):
157
- '''New L{Band} instance, see L{Str}.
138
+ '''New, named L{Band}, see L{Str}.
158
139
  '''
159
140
  return Str.__new__(cls, arg=arg, name=name, **Error_name_arg)
160
141
 
@@ -166,39 +147,38 @@ class Degrees(Float):
166
147
  _sep_ = S_SEP
167
148
  _suf_ = (S_NUL,) * 3
168
149
 
169
- def __new__(cls, arg=None, name=_degrees_, Error=UnitError, suffix=_NSEW_, clip=0, wrap=None, **name_arg):
150
+ def __new__(cls, arg=None, name=_degrees_, suffix=_NSEW_, clip=0, wrap=None, Error=UnitError, **name_arg):
170
151
  '''New C{Degrees} instance, see L{Float}.
171
152
 
172
153
  @arg cls: This class (C{Degrees} or sub-class).
173
- @kwarg arg: The value (any scalar C{type} convertable to C{float} or parsable
174
- by L{pygeodesy.parseDMS}).
154
+ @kwarg arg: The value (any C{type} convertable to C{float} or parsable by
155
+ function L{parseDMS<pygeodesy.dms.parseDMS>}).
175
156
  @kwarg name: Optional instance name (C{str}).
176
- @kwarg Error: Optional error to raise, overriding the default L{UnitError}.
177
157
  @kwarg suffix: Optional, valid compass direction suffixes (C{NSEW}).
178
158
  @kwarg clip: Optional B{C{arg}} range B{C{-clip..+clip}} (C{degrees} or C{0}
179
159
  or C{None} for unclipped).
180
- @kwarg wrap: Optionally adjust the B{C{arg}} value (L{pygeodesy.wrap90},
181
- L{pygeodesy.wrap180} or L{pygeodesy.wrap360}).
160
+ @kwarg wrap: Optionally adjust the B{C{arg}} value (L{wrap90<pygeodesy.wrap90>},
161
+ L{wrap180<pygeodesy.wrap180>} or L{wrap360<pygeodesy.wrap360>}).
162
+ @kwarg Error: Optional error to raise, overriding the default L{UnitError}.
182
163
  @kwarg name_arg: Optional C{name=arg} keyword argument, inlieu of separate
183
- B{C{name}} and B{C{arg}}.
164
+ B{C{arg}} and B{C{name}} ones.
184
165
 
185
166
  @returns: A C{Degrees} instance.
186
167
 
187
168
  @raise Error: Invalid B{C{arg}} or B{C{abs(arg)}} outside the B{C{clip}}
188
- range and L{pygeodesy.rangerrors} set to C{True}.
169
+ range and L{rangerrors<pygeodesy.rangerrors>} is C{True}.
189
170
  '''
190
171
  if name_arg:
191
- name, arg = _arg_name_arg2(arg, **name_arg)
172
+ name, arg = _NamedUnit._arg_name_arg2(arg, name, **name_arg)
192
173
  try:
193
- d = Float.__new__(cls, parseDMS(arg, suffix=suffix, clip=clip),
194
- Error=Error, name=name)
174
+ arg = parseDMS(arg, suffix=suffix, clip=clip)
195
175
  if wrap:
196
- w = wrap(d)
197
- if w != d:
198
- d = Float.__new__(cls, arg=w, name=name, Error=Error)
176
+ _xcallable(wrap=wrap)
177
+ arg = wrap(arg)
178
+ self = Float.__new__(cls, arg=arg, name=name, Error=Error)
199
179
  except Exception as x:
200
- raise _Error(cls, arg, name, Error, x=x)
201
- return d
180
+ raise _NamedUnit._Error(cls, arg, name, Error, cause=x)
181
+ return self
202
182
 
203
183
  def toDegrees(self):
204
184
  '''Convert C{Degrees} to C{Degrees}.
@@ -237,34 +217,25 @@ class Degrees(Float):
237
217
  class Degrees_(Degrees):
238
218
  '''Named C{Degrees} representing a coordinate in C{degrees} with optional limits C{low} and C{high}.
239
219
  '''
240
- def __new__(cls, arg=None, name=_degrees_, Error=UnitError, suffix=_NSEW_, low=None, high=None, **name_arg):
241
- '''New C{Degrees_} instance, see L{Degrees} and L{Float}..
220
+ def __new__(cls, arg=None, name=_degrees_, low=None, high=None, **suffix_Error_name_arg):
221
+ '''New, named C{Degrees_}, see L{Degrees} and L{Float}.
242
222
 
243
223
  @arg cls: This class (C{Degrees_} or sub-class).
244
224
  @kwarg arg: The value (any C{type} convertable to C{float} or parsable by
245
- L{pygeodesy.parseDMS}).
225
+ function L{parseDMS<pygeodesy.dms.parseDMS>}).
246
226
  @kwarg name: Optional instance name (C{str}).
247
- @kwarg Error: Optional error to raise, overriding the default L{UnitError}.
248
- @kwarg suffix: Optional, valid compass direction suffixes (C{NSEW}).
249
227
  @kwarg low: Optional lower B{C{arg}} limit (C{float} or C{None}).
250
228
  @kwarg high: Optional upper B{C{arg}} limit (C{float} or C{None}).
251
- @kwarg name_arg: Optional C{name=arg} keyword argument, inlieu of separate
252
- B{C{arg}} and B{C{name}} ones.
253
229
 
254
- @returns: A C{Degrees} instance.
230
+ @returns: A named C{Degrees}.
255
231
 
256
232
  @raise Error: Invalid B{C{arg}} or B{C{arg}} below B{C{low}} or above B{C{high}}.
257
233
  '''
258
- if name_arg:
259
- name, arg = _arg_name_arg2(arg, **name_arg)
260
- self = Degrees.__new__(cls, arg=arg, name=name, Error=Error, suffix=suffix, clip=0)
261
- if (low is not None) and self < low:
262
- txt = Fmt.limit(below=low)
263
- elif (high is not None) and self > high:
264
- txt = Fmt.limit(above=high)
265
- else:
266
- return self
267
- raise _Error(cls, arg, name, Error, txt=txt)
234
+ self = Degrees.__new__(cls, arg=arg, name=name, clip=0, **suffix_Error_name_arg)
235
+ t = _xlimits(self, low, high)
236
+ if t:
237
+ raise _NamedUnit._Error(cls, arg, name, txt=t, **suffix_Error_name_arg)
238
+ return self
268
239
 
269
240
 
270
241
  class Degrees2(Float):
@@ -279,32 +250,32 @@ class Degrees2(Float):
279
250
  class Radians(Float):
280
251
  '''Named C{float} representing a coordinate in C{radians}, optionally clipped.
281
252
  '''
282
- def __new__(cls, arg=None, name=_radians_, Error=UnitError, suffix=_NSEW_, clip=0, **name_arg):
283
- '''New C{Radians} instance, see L{Float}.
253
+ def __new__(cls, arg=None, name=_radians_, suffix=_NSEW_, clip=0, Error=UnitError, **name_arg):
254
+ '''New, named C{Radians}, see L{Float}.
284
255
 
285
256
  @arg cls: This class (C{Radians} or sub-class).
286
257
  @kwarg arg: The value (any C{type} convertable to C{float} or parsable by
287
258
  L{pygeodesy.parseRad}).
288
259
  @kwarg name: Optional instance name (C{str}).
289
- @kwarg Error: Optional error to raise, overriding the default L{UnitError}.
290
260
  @kwarg suffix: Optional, valid compass direction suffixes (C{NSEW}).
291
261
  @kwarg clip: Optional B{C{arg}} range B{C{-clip..+clip}} (C{radians} or C{0}
292
262
  or C{None} for unclipped).
263
+ @kwarg Error: Optional error to raise, overriding the default L{UnitError}.
293
264
  @kwarg name_arg: Optional C{name=arg} keyword argument, inlieu of separate
294
265
  B{C{arg}} and B{C{name}} ones.
295
266
 
296
- @returns: A C{Radians} instance.
267
+ @returns: A named C{Radians}.
297
268
 
298
269
  @raise Error: Invalid B{C{arg}} or B{C{abs(arg)}} outside the B{C{clip}}
299
- range and L{pygeodesy.rangerrors} set to C{True}.
270
+ range and L{rangerrors<pygeodesy.rangerrors>} is C{True}.
300
271
  '''
301
272
  if name_arg:
302
- name, arg = _arg_name_arg2(arg, **name_arg)
273
+ name, arg = _NamedUnit._arg_name_arg2(arg, name, **name_arg)
303
274
  try:
304
- return Float.__new__(cls, parseRad(arg, suffix=suffix, clip=clip),
305
- Error=Error, name=name)
275
+ arg = parseRad(arg, suffix=suffix, clip=clip)
276
+ return Float.__new__(cls, arg, name=name, Error=Error)
306
277
  except Exception as x:
307
- raise _Error(cls, arg, name, Error, x=x)
278
+ raise _NamedUnit._Error(cls, arg, name, Error, cause=x)
308
279
 
309
280
  def toDegrees(self):
310
281
  '''Convert C{Radians} to C{Degrees}.
@@ -338,41 +309,32 @@ class Radians(Float):
338
309
  class Radians_(Radians):
339
310
  '''Named C{float} representing a coordinate in C{radians} with optional limits C{low} and C{high}.
340
311
  '''
341
- def __new__(cls, arg=None, name=_radians_, Error=UnitError, suffix=_NSEW_, low=_0_0, high=PI2, **name_arg):
342
- '''New C{Radians_} instance.
312
+ def __new__(cls, arg=None, name=_radians_, low=_0_0, high=PI2, **suffix_Error_name_arg):
313
+ '''New, named C{Radians_}, see L{Radians}.
343
314
 
344
315
  @arg cls: This class (C{Radians_} or sub-class).
345
316
  @kwarg arg: The value (any C{type} convertable to C{float} or parsable by
346
- L{pygeodesy.parseRad}).
347
- @kwarg name: Optional instance name (C{str}).
348
- @kwarg Error: Optional error to raise, overriding the default L{UnitError}.
349
- @kwarg suffix: Optional, valid compass direction suffixes (C{NSEW}).
317
+ function L{parseRad<pygeodesy.dms.parseRad>}).
318
+ @kwarg name: Optional name (C{str}).
350
319
  @kwarg low: Optional lower B{C{arg}} limit (C{float} or C{None}).
351
320
  @kwarg high: Optional upper B{C{arg}} limit (C{float} or C{None}).
352
- @kwarg name_arg: Optional C{name=arg} keyword argument, inlieu of separate
353
- B{C{arg}} and B{C{name}} ones.
354
321
 
355
- @returns: A C{Radians_} instance.
322
+ @returns: A named C{Radians_}.
356
323
 
357
324
  @raise Error: Invalid B{C{arg}} or B{C{arg}} below B{C{low}} or above B{C{high}}.
358
325
  '''
359
- if name_arg:
360
- name, arg = _arg_name_arg2(arg, **name_arg)
361
- self = Radians.__new__(cls, arg=arg, name=name, Error=Error, suffix=suffix, clip=0)
362
- if (low is not None) and self < low:
363
- txt = Fmt.limit(below=low)
364
- elif (high is not None) and self > high:
365
- txt = Fmt.limit(above=high)
366
- else:
367
- return self
368
- raise _Error(cls, arg, name, Error, txt=txt)
326
+ self = Radians.__new__(cls, arg=arg, name=name, **suffix_Error_name_arg)
327
+ t = _xlimits(self, low, high)
328
+ if t:
329
+ raise _NamedUnit._Error(cls, arg, name, txt=t, **suffix_Error_name_arg)
330
+ return self
369
331
 
370
332
 
371
333
  class Radians2(Float_):
372
334
  '''Named C{float} representing a distance in C{radians squared}.
373
335
  '''
374
336
  def __new__(cls, arg=None, name=_radians2_, **Error_name_arg):
375
- '''New L{Radians2} instance, see L{Float_}.
337
+ '''New, named L{Radians2}, see L{Float_}.
376
338
  '''
377
339
  return Float_.__new__(cls, arg=arg, name=name, low=_0_0, **Error_name_arg)
378
340
 
@@ -383,31 +345,29 @@ class Bearing(Degrees):
383
345
  _ddd_ = 1
384
346
  _suf_ = _N_ * 3 # always suffix N
385
347
 
386
- def __new__(cls, arg=None, name=_bearing_, Error=UnitError, clip=0, **name_arg):
387
- '''New L{Bearing} instance, see L{Degrees}.
348
+ def __new__(cls, arg=None, name=_bearing_, clip=0, **Error_name_arg):
349
+ '''New, named L{Bearing}, see L{Degrees}.
388
350
  '''
389
- if name_arg:
390
- name, arg = _arg_name_arg2(arg, **name_arg)
391
- d = Degrees.__new__(cls, arg=arg, name=name, Error=Error, suffix=_N_, clip=clip)
351
+ d = Degrees.__new__(cls, arg=arg, name=name, suffix=_N_, clip=clip, **Error_name_arg)
392
352
  b = _umod_360(d) # 0 <= b < 360
393
- return d if b == d else Degrees.__new__(cls, arg=b, name=name, Error=Error)
353
+ return d if b == d else Degrees.__new__(cls, arg=b, name=d.name)
394
354
 
395
355
 
396
356
  class Bearing_(Radians):
397
357
  '''Named C{float} representing a bearing in C{radians} from compass C{degrees} from (true) North.
398
358
  '''
399
- def __new__(cls, arg=None, name=_bearing_, clip=0, **Error_name_arg):
400
- '''New L{Bearing_} instance, see L{Bearing} and L{Radians}.
359
+ def __new__(cls, arg=None, **name_clip_Error_name_arg):
360
+ '''New, named L{Bearing_}, see L{Bearing} and L{Radians}.
401
361
  '''
402
- d = Bearing.__new__(cls, arg=arg, name=name, clip=clip, **Error_name_arg)
403
- return Radians.__new__(cls, radians(d), name=name)
362
+ d = Bearing.__new__(cls, arg=arg, **name_clip_Error_name_arg)
363
+ return Radians.__new__(cls, radians(d), name=d.name)
404
364
 
405
365
 
406
366
  class Distance(Float):
407
367
  '''Named C{float} representing a distance, conventionally in C{meter}.
408
368
  '''
409
369
  def __new__(cls, arg=None, name=_distance_, **Error_name_arg):
410
- '''New L{Distance} instance, see L{Float}.
370
+ '''New, named L{Distance}, see L{Float}.
411
371
  '''
412
372
  return Float.__new__(cls, arg=arg, name=name, **Error_name_arg)
413
373
 
@@ -421,33 +381,38 @@ class Distance_(Float_):
421
381
  return Float_.__new__(cls, arg=arg, name=name, **low_high_Error_name_arg)
422
382
 
423
383
 
424
- class Easting(Float):
384
+ class _EasNorBase(Float):
385
+ '''(INTERNAL) L{Easting} and L{Northing} base class.
386
+ '''
387
+ def __new__(cls, arg, name, falsed, high, **Error_name_arg):
388
+ self = Float.__new__(cls, arg=arg, name=name, **Error_name_arg)
389
+ low = self < 0
390
+ if (high is not None) and (low or self > high): # like Veness
391
+ t = _negative_ if low else Fmt.limit(above=high)
392
+ elif low and falsed:
393
+ t = _COMMASPACE_(_negative_, 'falsed')
394
+ else:
395
+ return self
396
+ raise _NamedUnit._Error(cls, arg, name, txt=t, **Error_name_arg)
397
+
398
+
399
+ class Easting(_EasNorBase):
425
400
  '''Named C{float} representing an easting, conventionally in C{meter}.
426
401
  '''
427
- def __new__(cls, arg=None, name=_easting_, Error=UnitError, falsed=False, high=None, **name_arg):
428
- '''New named C{Easting} or C{Easting of Point} instance.
402
+ def __new__(cls, arg=None, name=_easting_, falsed=False, high=None, **Error_name_arg):
403
+ '''New, named C{Easting} or C{Easting of Point}, see L{Float}.
429
404
 
430
405
  @arg cls: This class (C{Easting} or sub-class).
431
406
  @kwarg arg: The value (any C{type} convertable to C{float}).
432
- @kwarg name: Optional instance name (C{str}).
433
- @kwarg Error: Optional error to raise, overriding the default L{UnitError}.
434
- @kwarg falsed: The B{C{arg}} value includes false origin (C{bool}).
435
- @kwarg high: Optional upper B{C{arg}} easting limit (C{scalar} or C{None}).
436
- @kwarg name_arg: Optional C{name=arg} keyword argument, inlieu of separate
437
- B{C{arg}} and B{C{name}} ones.
407
+ @kwarg name: Optional name (C{str}).
408
+ @kwarg falsed: If C{True}, the B{C{arg}} value is falsed (C{bool}).
409
+ @kwarg high: Optional upper B{C{arg}} limit (C{scalar} or C{None}).
438
410
 
439
- @returns: An C{Easting} instance.
411
+ @returns: A named C{Easting}.
440
412
 
441
413
  @raise Error: Invalid B{C{arg}}, above B{C{high}} or negative, falsed B{C{arg}}.
442
414
  '''
443
- if name_arg:
444
- name, arg = _arg_name_arg2(arg, **name_arg)
445
- self = Float.__new__(cls, arg=arg, name=name, Error=Error)
446
- if high and (self < 0 or self > high): # like Veness
447
- raise _Error(cls, arg, name, Error)
448
- elif falsed and self < 0:
449
- raise _Error(cls, arg, name, Error, txt=_negative_falsed_)
450
- return self
415
+ return _EasNorBase.__new__(cls, arg, name, falsed, high, **Error_name_arg)
451
416
 
452
417
 
453
418
  class Epoch(Float_): # in .ellipsoidalBase, .trf
@@ -456,11 +421,11 @@ class Epoch(Float_): # in .ellipsoidalBase, .trf
456
421
  '''
457
422
  _std_repr = False
458
423
 
459
- def __new__(cls, arg=None, name=_epoch_, Error=TRFError, low=1900, high=9999, **name_arg):
460
- '''New L{Epoch} instance, see L{Float_}.
424
+ def __new__(cls, arg=None, name=_epoch_, low=1900, high=9999, Error=TRFError, **name_arg):
425
+ '''New, named L{Epoch}, see L{Float_}.
461
426
  '''
462
427
  if name_arg:
463
- name, arg = _arg_name_arg2(arg, **name_arg)
428
+ name, arg = _NamedUnit._arg_name_arg2(arg, name, **name_arg)
464
429
  return arg if isinstance(arg, Epoch) else Float_.__new__(cls,
465
430
  arg=arg, name=name, Error=Error, low=low, high=high)
466
431
 
@@ -474,7 +439,7 @@ class Epoch(Float_): # in .ellipsoidalBase, .trf
474
439
  '''
475
440
  return Float_.toRepr(self, prec=prec, std=std) # fmt=Fmt.F, ints=True
476
441
 
477
- def toStr(self, prec=3, **unused): # PYCHOK fmt=Fmt.F, ints=True
442
+ def toStr(self, prec=3, **unused): # PYCHOK fmt=Fmt.F, nts=True
478
443
  '''Format this C{Epoch} as C{str}.
479
444
 
480
445
  @see: Function L{pygeodesy.fstr} for more documentation.
@@ -488,44 +453,44 @@ class Feet(Float):
488
453
  '''Named C{float} representing a distance or length in C{feet}.
489
454
  '''
490
455
  def __new__(cls, arg=None, name=_feet_, **Error_name_arg):
491
- '''New L{Feet} instance, see L{Float}.
456
+ '''New, named L{Feet}, see L{Float}.
492
457
  '''
493
458
  return Float.__new__(cls, arg=arg, name=name, **Error_name_arg)
494
459
 
495
460
 
496
461
  class FIx(Float_):
497
- '''A named I{Fractional Index}, an C{int} or C{float} index into
498
- a C{list} or C{tuple} of C{points}, typically. A C{float}
499
- I{Fractional Index} C{fi} represents a location on the edge
500
- between C{points[int(fi)]} and C{points[(int(fi) + 1) %
501
- len(points)]}.
462
+ '''A named I{Fractional Index}, an C{int} or C{float} index into a C{list}
463
+ or C{tuple} of C{points}, typically. A C{float} I{Fractional Index}
464
+ C{fi} represents a location on the edge between C{points[int(fi)]} and
465
+ C{points[(int(fi) + 1) % len(points)]}.
502
466
  '''
503
467
  _fin = 0
504
468
 
505
- def __new__(cls, fi, fin=None, **name_Error):
506
- '''New I{Fractional Index} in a C{list} or C{tuple} of points.
469
+ def __new__(cls, fi, fin=None, Error=UnitError, **name):
470
+ '''New, named I{Fractional Index} in a C{list} or C{tuple} of points.
507
471
 
508
472
  @arg fi: The fractional index (C{float} or C{int}).
509
473
  @kwarg fin: Optional C{len}, the number of C{points}, the index
510
474
  C{[n]} wrapped to C{[0]} (C{int} or C{None}).
511
- @kwarg name_Error: Optional C{B{name}=NN} (C{str}) and keyword
512
- argument C{B{Error}=UnitError}.
475
+ @kwarg Error: Optional error to raise.
476
+ @kwarg name: Optional C{B{name}=NN} (C{str}).
513
477
 
514
- @return: The B{C{fi}} (named L{FIx}).
478
+ @return: A named B{C{fi}} (L{FIx}).
515
479
 
516
- @note: The returned B{C{fi}} may exceed the B{C{flen}} of
517
- the original C{points} in certain open/closed cases.
480
+ @note: The returned B{C{fi}} may exceed the B{C{len}}, number of
481
+ original C{points} in certain open/closed cases.
518
482
 
519
483
  @see: Method L{fractional} or function L{pygeodesy.fractional}.
520
484
  '''
521
- n = Int_(fin=fin, low=0) if fin else None
522
- f = Float_.__new__(cls, fi, low=_0_0, high=n, **name_Error)
523
- i = int(f)
524
- r = f - float(i)
485
+ _ = _MODS.named._name__(name) if name else NN # check error
486
+ n = Int_(fin=fin, low=0) if fin else None
487
+ f = Float_.__new__(cls, fi, low=_0_0, high=n, Error=Error, **name)
488
+ i = int(f)
489
+ r = f - float(i)
525
490
  if r < EPS: # see .points._fractional
526
- f = Float_.__new__(cls, i, low=_0_0)
491
+ f = Float_.__new__(cls, i, low=_0_0, Error=Error, **name)
527
492
  elif r > EPS1:
528
- f = Float_.__new__(cls, i + 1, high=n, **name_Error)
493
+ f = Float_.__new__(cls, i + 1, high=n, Error=Error, **name)
529
494
  if n: # non-zero and non-None
530
495
  f._fin = n
531
496
  return f
@@ -536,37 +501,30 @@ class FIx(Float_):
536
501
  '''
537
502
  return self._fin
538
503
 
539
- def fractional(self, points, wrap=None, LatLon=None, Vector=None, **kwds):
504
+ def fractional(self, points, wrap=None, **LatLon_or_Vector_and_kwds):
540
505
  '''Return the point at this I{Fractional Index}.
541
506
 
542
- @arg points: The points (C{LatLon}[], L{Numpy2LatLon}[],
543
- L{Tuple2LatLon}[] or C{other}[]).
544
- @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the
545
- B{C{points}} (C{bool}) or C{None} for backward
546
- compatible L{LatLon2Tuple} or B{C{LatLon}} with
547
- I{averaged} lat- and longitudes.
548
- @kwarg LatLon: Optional class to return the I{intermediate},
549
- I{fractional} point (C{LatLon}) or C{None}.
550
- @kwarg Vector: Optional class to return the I{intermediate},
551
- I{fractional} point (C{Cartesian}, C{Vector3d})
552
- or C{None}.
553
- @kwarg kwds: Optional, additional B{C{LatLon}} I{or} B{C{Vector}}
554
- keyword arguments, ignored if both C{B{LatLon}} and
555
- C{B{Vector}} are C{None}.
556
-
557
- @return: See function L{pygeodesy.fractional}.
558
-
559
- @raise IndexError: This fractional index invalid or B{C{points}}
560
- not subscriptable or not closed.
561
-
562
- @raise TypeError: Invalid B{C{LatLon}}, B{C{Vector}} or B{C{kwds}}
563
- argument.
507
+ @arg points: The points (C{LatLon}[], L{Numpy2LatLon}[], L{Tuple2LatLon}[] or
508
+ C{other}[]).
509
+ @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the B{C{points}}
510
+ (C{bool}) or C{None} for backward compatible L{LatLon2Tuple} or
511
+ B{C{LatLon}} with I{averaged} lat- and longitudes.
512
+ @kwarg LatLon_or_Vector_and_kwds: Optional C{B{LatLon}=None} I{or} C{B{Vector}=None}
513
+ to return the I{intermediate}, I{fractional} point and optional,
514
+ additional B{C{LatLon}} I{or} B{C{Vector}} keyword arguments, see
515
+ function L{fractional<pygeodesy.points.fractional>}.
516
+
517
+ @return: See function L{fractional<pygeodesy.points.fractional>}.
518
+
519
+ @raise IndexError: In fractional index invalid or B{C{points}} not
520
+ subscriptable or not closed.
521
+
522
+ @raise TypeError: Invalid B{C{LatLon}}, B{C{Vector}} or B{C{kwds}} argument.
564
523
 
565
524
  @see: Function L{pygeodesy.fractional}.
566
525
  '''
567
526
  # fi = 0 if self == self.fin else self
568
- return _MODS.points.fractional(points, self, wrap=wrap,
569
- LatLon=LatLon, Vector=Vector, **kwds)
527
+ return _MODS.points.fractional(points, self, wrap=wrap, **LatLon_or_Vector_and_kwds)
570
528
 
571
529
 
572
530
  def _fi_j2(f, n): # PYCHOK in .ellipsoidalBaseDI, .vector3d
@@ -581,7 +539,7 @@ class Height(Float): # here to avoid circular import
581
539
  '''Named C{float} representing a height, conventionally in C{meter}.
582
540
  '''
583
541
  def __new__(cls, arg=None, name=_height_, **Error_name_arg):
584
- '''New L{Height} instance, see L{Float}.
542
+ '''New, named L{Height}, see L{Float}.
585
543
  '''
586
544
  return Float.__new__(cls, arg=arg, name=name, **Error_name_arg)
587
545
 
@@ -590,7 +548,7 @@ class Height_(Float_): # here to avoid circular import
590
548
  '''Named C{float} with optional C{low} and C{high} limits representing a height, conventionally in C{meter}.
591
549
  '''
592
550
  def __new__(cls, arg=None, name=_height_, **low_high_Error_name_arg):
593
- '''New L{Height} instance, see L{Float}.
551
+ '''New, named L{Height}, see L{Float}.
594
552
  '''
595
553
  return Float_.__new__(cls, arg=arg, name=name, **low_high_Error_name_arg)
596
554
 
@@ -612,21 +570,19 @@ class Lam(Radians):
612
570
  '''Named C{float} representing a longitude in C{radians}.
613
571
  '''
614
572
  def __new__(cls, arg=None, name=_lam_, clip=PI, **Error_name_arg):
615
- '''New L{Lam} instance, see L{Radians}.
573
+ '''New, named L{Lam}, see L{Radians}.
616
574
  '''
617
575
  return Radians.__new__(cls, arg=arg, name=name, suffix=_EW_, clip=clip, **Error_name_arg)
618
576
 
619
577
 
620
- class Lam_(Lam):
578
+ class Lamd(Lam):
621
579
  '''Named C{float} representing a longitude in C{radians} converted from C{degrees}.
622
580
  '''
623
- def __new__(cls, arg=None, name=_lon_, Error=UnitError, clip=180, **name_arg):
624
- '''New L{Lam_} instance, see L{Lam} and L{Radians}.
581
+ def __new__(cls, arg=None, name=_lon_, clip=180, **Error_name_arg):
582
+ '''New, named L{Lamd}, see L{Lam} and L{Radians}.
625
583
  '''
626
- if name_arg:
627
- name, arg = _arg_name_arg2(arg, **name_arg)
628
- d = Lam.__new__(cls, arg=arg, name=name, Error=Error, clip=clip)
629
- return Radians.__new__(cls, radians(d), name=name, Error=Error)
584
+ d = Degrees(arg=arg, name=name, clip=clip, **Error_name_arg)
585
+ return Lam.__new__(cls, radians(d), clip=radians(clip), name=d.name)
630
586
 
631
587
 
632
588
  class Lat(Degrees):
@@ -636,7 +592,7 @@ class Lat(Degrees):
636
592
  _suf_ = _S_, S_NUL, _N_ # no zero suffix
637
593
 
638
594
  def __new__(cls, arg=None, name=_lat_, clip=90, **Error_name_arg):
639
- '''New L{Lat} instnace, see L{Degrees}.
595
+ '''New, named L{Lat}, see L{Degrees}.
640
596
  '''
641
597
  return Degrees.__new__(cls, arg=arg, name=name, suffix=_NS_, clip=clip, **Error_name_arg)
642
598
 
@@ -660,7 +616,7 @@ class Lon(Degrees):
660
616
  _suf_ = _W_, S_NUL, _E_ # no zero suffix
661
617
 
662
618
  def __new__(cls, arg=None, name=_lon_, clip=180, **Error_name_arg):
663
- '''New L{Lon} instance, see L{Degrees}.
619
+ '''New, named L{Lon}, see L{Degrees}.
664
620
  '''
665
621
  return Degrees.__new__(cls, arg=arg, name=name, suffix=_EW_, clip=clip, **Error_name_arg)
666
622
 
@@ -672,7 +628,7 @@ class Lon_(Degrees_):
672
628
  _suf_ = _W_, S_NUL, _E_ # no zero suffix
673
629
 
674
630
  def __new__(cls, arg=None, name=_lon_, low=-180, high=180, **Error_name_arg):
675
- '''New L{Lon_} instance, see L{Lon} and L{Degrees_}.
631
+ '''New, named L{Lon_}, see L{Lon} and L{Degrees_}.
676
632
  '''
677
633
  return Degrees_.__new__(cls, arg=arg, name=name, suffix=_EW_, low=low, high=high, **Error_name_arg)
678
634
 
@@ -681,7 +637,7 @@ class Meter(Float):
681
637
  '''Named C{float} representing a distance or length in C{meter}.
682
638
  '''
683
639
  def __new__(cls, arg=None, name=_meter_, **Error_name_arg):
684
- '''New L{Meter} instance, see L{Float}.
640
+ '''New, named L{Meter}, see L{Float}.
685
641
  '''
686
642
  return Float.__new__(cls, arg=arg, name=name, **Error_name_arg)
687
643
 
@@ -709,7 +665,7 @@ class Meter_(Float_):
709
665
  '''Named C{float} representing a distance or length in C{meter}.
710
666
  '''
711
667
  def __new__(cls, arg=None, name=_meter_, low=_0_0, **high_Error_name_arg):
712
- '''New L{Meter_} instance, see L{Meter} and L{Float_}.
668
+ '''New, named L{Meter_}, see L{Meter} and L{Float_}.
713
669
  '''
714
670
  return Float_.__new__(cls, arg=arg, name=name, low=low, **high_Error_name_arg)
715
671
 
@@ -717,55 +673,45 @@ class Meter_(Float_):
717
673
  class Meter2(Float_):
718
674
  '''Named C{float} representing an area in C{meter squared}.
719
675
  '''
720
- def __new__(cls, arg=None, name=_meter2_, Error=UnitError, **name_arg):
721
- '''New L{Meter2} instance, see L{Float_}.
676
+ def __new__(cls, arg=None, name=_meter2_, **Error_name_arg):
677
+ '''New, named L{Meter2}, see L{Float_}.
722
678
  '''
723
- return Float_.__new__(cls, arg=arg, name=name, Error=Error, low=_0_0, **name_arg)
679
+ return Float_.__new__(cls, arg=arg, name=name, low=_0_0, **Error_name_arg)
724
680
 
725
681
 
726
682
  class Meter3(Float_):
727
683
  '''Named C{float} representing a volume in C{meter cubed}.
728
684
  '''
729
685
  def __new__(cls, arg=None, name='meter3', **Error_name_arg):
730
- '''New L{Meter3} instance, see L{Float_}.
686
+ '''New, named L{Meter3}, see L{Float_}.
731
687
  '''
732
688
  return Float_.__new__(cls, arg=arg, name=name, low=_0_0, **Error_name_arg)
733
689
 
734
690
 
735
- class Northing(Float):
691
+ class Northing(_EasNorBase):
736
692
  '''Named C{float} representing a northing, conventionally in C{meter}.
737
693
  '''
738
- def __new__(cls, arg=None, name=_northing_, Error=UnitError, falsed=False, high=None, **name_arg):
739
- '''New C{Northing} or C{Northing of point} instance.
694
+ def __new__(cls, arg=None, name=_northing_, falsed=False, high=None, **Error_name_arg):
695
+ '''New, named C{Northing} or C{Northing of point}, see L{Float}.
740
696
 
741
697
  @arg cls: This class (C{Northing} or sub-class).
742
698
  @kwarg arg: The value (any C{type} convertable to C{float}).
743
- @kwarg name: Optional instance name (C{str}).
744
- @kwarg Error: Optional error to raise, overriding the default L{UnitError}.
745
- @kwarg falsed: The B{C{arg}} value includes false origin (C{bool}).
746
- @kwarg high: Optional upper B{C{arg}} northing limit (C{scalar} or C{None}).
747
- @kwarg name_arg: Optional C{name=arg} keyword argument, inlieu of separate
748
- B{C{arg}} and B{C{name}} ones.
699
+ @kwarg name: Optional name (C{str}).
700
+ @kwarg falsed: If C{True}, the B{C{arg}} value is falsed (C{bool}).
701
+ @kwarg high: Optional upper B{C{arg}} limit (C{scalar} or C{None}).
749
702
 
750
- @returns: A C{Northing} instance.
703
+ @returns: A named C{Northing}.
751
704
 
752
705
  @raise Error: Invalid B{C{arg}}, above B{C{high}} or negative, falsed B{C{arg}}.
753
706
  '''
754
- if name_arg:
755
- name, arg = _arg_name_arg2(arg, **name_arg)
756
- self = Float.__new__(cls, arg=arg, name=name, Error=Error)
757
- if high and (self < 0 or self > high):
758
- raise _Error(cls, arg, name, Error)
759
- elif falsed and self < 0:
760
- raise _Error(cls, arg, name, Error, txt=_negative_falsed_)
761
- return self
707
+ return _EasNorBase.__new__(cls, arg, name, falsed, high, **Error_name_arg)
762
708
 
763
709
 
764
710
  class Number_(Int_):
765
711
  '''Named C{int} representing a non-negative number.
766
712
  '''
767
713
  def __new__(cls, arg=None, name=_number_, **low_high_Error_name_arg):
768
- '''New L{Number_} instance, see L{Int_}.
714
+ '''New, named L{Number_}, see L{Int_}.
769
715
  '''
770
716
  return Int_.__new__(cls, arg=arg, name=name, **low_high_Error_name_arg)
771
717
 
@@ -774,28 +720,26 @@ class Phi(Radians):
774
720
  '''Named C{float} representing a latitude in C{radians}.
775
721
  '''
776
722
  def __new__(cls, arg=None, name=_phi_, clip=PI_2, **Error_name_arg):
777
- '''New L{Phi} instance, see L{Radians}.
723
+ '''New, named L{Phi}, see L{Radians}.
778
724
  '''
779
725
  return Radians.__new__(cls, arg=arg, name=name, suffix=_NS_, clip=clip, **Error_name_arg)
780
726
 
781
727
 
782
- class Phi_(Phi):
728
+ class Phid(Phi):
783
729
  '''Named C{float} representing a latitude in C{radians} converted from C{degrees}.
784
730
  '''
785
- def __new__(cls, arg=None, name=_lat_, Error=UnitError, clip=90, **name_arg):
786
- '''New L{Phi_} instance, see L{Phi} and L{Radians}.
731
+ def __new__(cls, arg=None, name=_lat_, clip=90, **Error_name_arg):
732
+ '''New, named L{Phid}, see L{Phi} and L{Radians}.
787
733
  '''
788
- if name_arg:
789
- name, arg = _arg_name_arg2(arg, **name_arg)
790
- d = Phi.__new__(cls, arg=arg, name=name, Error=Error, clip=clip)
791
- return Radians.__new__(cls, arg=radians(d), name=name, Error=Error)
734
+ d = Degrees(arg=arg, name=name, clip=clip, **Error_name_arg)
735
+ return Phi.__new__(cls, arg=radians(d), clip=radians(clip), name=d.name)
792
736
 
793
737
 
794
738
  class Precision_(Int_):
795
739
  '''Named C{int} with optional C{low} and C{high} limits representing a precision.
796
740
  '''
797
741
  def __new__(cls, arg=None, name=_precision_, **low_high_Error_name_arg):
798
- '''New L{Precision_} instance, see L{Int_}.
742
+ '''New, named L{Precision_}, see L{Int_}.
799
743
  '''
800
744
  return Int_.__new__(cls, arg=arg, name=name, **low_high_Error_name_arg)
801
745
 
@@ -804,7 +748,7 @@ class Radius_(Float_):
804
748
  '''Named C{float} with optional C{low} and C{high} limits representing a radius, conventionally in C{meter}.
805
749
  '''
806
750
  def __new__(cls, arg=None, name=_radius_, **low_high_Error_name_arg):
807
- '''New L{Radius_} instance, see L{Radius} and L{Float}.
751
+ '''New, named L{Radius_}, see L{Radius} and L{Float}.
808
752
  '''
809
753
  return Float_.__new__(cls, arg=arg, name=name, **low_high_Error_name_arg)
810
754
 
@@ -813,7 +757,7 @@ class Scalar(Float):
813
757
  '''Named C{float} representing a factor, fraction, scale, etc.
814
758
  '''
815
759
  def __new__(cls, arg=None, name=_scalar_, **Error_name_arg):
816
- '''New L{Scalar} instance, see L{Float}.
760
+ '''New, named L{Scalar}, see L{Float}.
817
761
  '''
818
762
  return Float.__new__(cls, arg=arg, name=name, **Error_name_arg)
819
763
 
@@ -822,7 +766,7 @@ class Scalar_(Float_):
822
766
  '''Named C{float} with optional C{low} and C{high} limits representing a factor, fraction, scale, etc.
823
767
  '''
824
768
  def __new__(cls, arg=None, name=_scalar_, low=_0_0, **high_Error_name_arg):
825
- '''New L{Scalar_} instance, see L{Scalar} and L{Float_}.
769
+ '''New, named L{Scalar_}, see L{Scalar} and L{Float_}.
826
770
  '''
827
771
  return Float_.__new__(cls, arg=arg, name=name, low=low, **high_Error_name_arg)
828
772
 
@@ -831,16 +775,16 @@ class Zone(Int):
831
775
  '''Named C{int} representing a UTM/UPS zone number.
832
776
  '''
833
777
  def __new__(cls, arg=None, name=_zone_, **Error_name_arg):
834
- '''New L{Zone} instance, see L{Int}
778
+ '''New, named L{Zone}, see L{Int}
835
779
  '''
836
780
  # usually low=_UTMUPS_ZONE_MIN, high=_UTMUPS_ZONE_MAX
837
781
  return Int_.__new__(cls, arg=arg, name=name, **Error_name_arg)
838
782
 
839
783
 
840
- _Scalars = Float, Float_, Scalar, Scalar_
841
- _Degrees = (Bearing, Bearing_, Degrees, Degrees_) + _Scalars
842
- _Meters = (Distance, Distance_, Meter, Meter_) + _Scalars
843
- _Radians = (Radians, Radians_) + _Scalars # PYCHOK unused
784
+ _ScalarU = Float, Float_, Scalar, Scalar_
785
+ _Degrees = (Bearing, Bearing_, Degrees, Degrees_) + _ScalarU
786
+ _Meters = (Distance, Distance_, Meter, Meter_) + _ScalarU
787
+ _Radians = (Radians, Radians_) + _ScalarU # PYCHOK unused
844
788
  _Radii = _Meters + (Radius, Radius_)
845
789
 
846
790
 
@@ -873,36 +817,25 @@ def _toUnit(Unit, arg, name=NN, **Error):
873
817
  '''(INTERNAL) Wrap C{arg} in a C{name}d C{Unit}.
874
818
  '''
875
819
  if not (issubclassof(Unit, _NamedUnit) and isinstance(arg, Unit) and
876
- _xattr(arg, name=NN) == name):
820
+ _xattr(arg, name=NN) == name):
877
821
  arg = Unit(arg, name=name, **Error)
878
822
  return arg
879
823
 
880
824
 
881
- def _xStrError(*Refs, **name_value_Error):
882
- '''(INTERNAL) Create a C{TypeError} for C{Garef}, C{Geohash}, C{Wgrs}.
883
- '''
884
- r = tuple(r.__name__ for r in Refs) + (Str.__name__, _LatLon_, 'LatLon*Tuple')
885
- return _IsnotError(*r, **name_value_Error)
886
-
887
-
888
- def _xUnit(units, Base): # in .frechet, .hausdorff
889
- '''(INTERNAL) Get C{Unit} from C{Unit} or C{name}, ortherwise C{Base}.
890
- '''
891
- _xsubclassof(_NamedUnit, Base=Base)
892
- U = globals().get(units.capitalize(), Base) if isstr(units) else (
893
- units if issubclassof(units, Base) else Base)
894
- return U if issubclassof(U, Base) else Base
895
-
896
-
897
- def _xUnits(units, Base=_NamedUnit): # in .frechet, .hausdorff
898
- '''(INTERNAL) Set property C{units} as C{Unit} or C{Str}.
899
- '''
900
- _xsubclassof(_NamedUnit, Base=Base)
901
- if issubclassof(units, Base):
902
- return units
903
- elif isstr(units):
904
- return Str(units, name=_units_) # XXX Str to _Pass and for backward compatibility
905
- raise _IsnotError(*(_.__name__ for _ in (Base, Str, str)), units=units)
825
+ def _xlimits(arg, low, high, g=False):
826
+ '''(INTERNAL) Check C{low <= unit <= high}.
827
+ '''
828
+ if (low is not None) and arg < low:
829
+ if g:
830
+ low = Fmt.g(low, prec=6, ints=isinstance(arg, Epoch))
831
+ t = Fmt.limit(below=low)
832
+ elif (high is not None) and arg > high:
833
+ if g:
834
+ high = Fmt.g(high, prec=6, ints=isinstance(arg, Epoch))
835
+ t = Fmt.limit(above=high)
836
+ else:
837
+ t = NN
838
+ return t
906
839
 
907
840
 
908
841
  def _std_repr(*Classes):