pygeodesy 24.6.1__py2.py3-none-any.whl → 24.6.24__py2.py3-none-any.whl

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