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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. {PyGeodesy-24.5.15.dist-info → PyGeodesy-24.6.1.dist-info}/METADATA +6 -5
  2. PyGeodesy-24.6.1.dist-info/RECORD +116 -0
  3. pygeodesy/__init__.py +4 -4
  4. pygeodesy/albers.py +41 -41
  5. pygeodesy/auxilats/__init__.py +1 -1
  6. pygeodesy/auxilats/__main__.py +2 -2
  7. pygeodesy/auxilats/auxAngle.py +32 -31
  8. pygeodesy/auxilats/auxLat.py +80 -51
  9. pygeodesy/azimuthal.py +123 -124
  10. pygeodesy/basics.py +46 -10
  11. pygeodesy/booleans.py +13 -14
  12. pygeodesy/cartesianBase.py +25 -23
  13. pygeodesy/clipy.py +3 -3
  14. pygeodesy/constants.py +3 -3
  15. pygeodesy/css.py +50 -42
  16. pygeodesy/datums.py +42 -41
  17. pygeodesy/deprecated/functions.py +9 -3
  18. pygeodesy/dms.py +6 -6
  19. pygeodesy/ecef.py +41 -41
  20. pygeodesy/ellipsoidalBase.py +41 -41
  21. pygeodesy/ellipsoidalBaseDI.py +3 -4
  22. pygeodesy/ellipsoidalGeodSolve.py +2 -2
  23. pygeodesy/ellipsoidalKarney.py +3 -3
  24. pygeodesy/ellipsoidalNvector.py +11 -12
  25. pygeodesy/ellipsoids.py +45 -38
  26. pygeodesy/elliptic.py +3 -4
  27. pygeodesy/epsg.py +4 -3
  28. pygeodesy/errors.py +52 -20
  29. pygeodesy/etm.py +68 -65
  30. pygeodesy/fmath.py +44 -49
  31. pygeodesy/formy.py +129 -115
  32. pygeodesy/frechet.py +118 -103
  33. pygeodesy/fstats.py +21 -14
  34. pygeodesy/fsums.py +124 -80
  35. pygeodesy/gars.py +10 -9
  36. pygeodesy/geodesicw.py +19 -17
  37. pygeodesy/geodesicx/__init__.py +1 -1
  38. pygeodesy/geodesicx/__main__.py +2 -2
  39. pygeodesy/geodesicx/gx.py +39 -33
  40. pygeodesy/geodesicx/gxarea.py +12 -9
  41. pygeodesy/geodesicx/gxbases.py +3 -4
  42. pygeodesy/geodesicx/gxline.py +6 -8
  43. pygeodesy/geodsolve.py +29 -28
  44. pygeodesy/geohash.py +60 -57
  45. pygeodesy/geoids.py +34 -32
  46. pygeodesy/hausdorff.py +114 -101
  47. pygeodesy/heights.py +137 -130
  48. pygeodesy/internals.py +16 -11
  49. pygeodesy/interns.py +3 -6
  50. pygeodesy/iters.py +19 -17
  51. pygeodesy/karney.py +21 -17
  52. pygeodesy/ktm.py +25 -18
  53. pygeodesy/latlonBase.py +12 -11
  54. pygeodesy/lazily.py +6 -6
  55. pygeodesy/lcc.py +24 -25
  56. pygeodesy/ltp.py +143 -113
  57. pygeodesy/ltpTuples.py +207 -150
  58. pygeodesy/mgrs.py +26 -26
  59. pygeodesy/named.py +172 -90
  60. pygeodesy/namedTuples.py +33 -25
  61. pygeodesy/nvectorBase.py +8 -8
  62. pygeodesy/osgr.py +40 -48
  63. pygeodesy/points.py +18 -18
  64. pygeodesy/props.py +29 -16
  65. pygeodesy/rhumb/__init__.py +1 -1
  66. pygeodesy/rhumb/aux_.py +13 -15
  67. pygeodesy/rhumb/bases.py +12 -5
  68. pygeodesy/rhumb/ekx.py +24 -18
  69. pygeodesy/rhumb/solve.py +13 -10
  70. pygeodesy/simplify.py +16 -16
  71. pygeodesy/solveBase.py +18 -18
  72. pygeodesy/sphericalBase.py +17 -21
  73. pygeodesy/sphericalTrigonometry.py +21 -21
  74. pygeodesy/streprs.py +5 -5
  75. pygeodesy/trf.py +13 -11
  76. pygeodesy/triaxials.py +68 -64
  77. pygeodesy/units.py +35 -35
  78. pygeodesy/unitsBase.py +24 -11
  79. pygeodesy/ups.py +66 -70
  80. pygeodesy/utily.py +3 -3
  81. pygeodesy/utm.py +183 -187
  82. pygeodesy/utmups.py +38 -38
  83. pygeodesy/utmupsBase.py +104 -106
  84. pygeodesy/vector2d.py +6 -7
  85. pygeodesy/vector3d.py +16 -17
  86. pygeodesy/vector3dBase.py +4 -5
  87. pygeodesy/webmercator.py +43 -51
  88. PyGeodesy-24.5.15.dist-info/RECORD +0 -116
  89. {PyGeodesy-24.5.15.dist-info → PyGeodesy-24.6.1.dist-info}/WHEEL +0 -0
  90. {PyGeodesy-24.5.15.dist-info → PyGeodesy-24.6.1.dist-info}/top_level.txt +0 -0
pygeodesy/namedTuples.py CHANGED
@@ -11,13 +11,13 @@ of C{_NamedTuple} defined in C{pygeodesy.named}.
11
11
  from pygeodesy.basics import map1, _xinstanceof
12
12
  # from pygeodesy.constants import INT0 # from .units
13
13
  from pygeodesy.errors import _ALL_LAZY, _MODS, _xattr, _xkwds_not # _xkwds
14
- from pygeodesy.interns import NN, _1_, _2_, _a_, _A_, _area_, _angle_, _b_, \
15
- _B_, _band_, _c_, _C_, _datum_, _D_, _distance_, \
16
- _E_, _easting_, _end_, _fi_, _gamma_, _height_, \
17
- _h_, _j_, _hemipole_, _initial_, _lam_, _lat_, \
18
- _lon_, _n_, _northing_, _number_, _outside_, \
19
- _phi_, _point_, _precision_, _points_, _radius_, \
20
- _scale_, _start_, _x_, _y_, _z_, _zone_
14
+ from pygeodesy.interns import _1_, _2_, _a_, _A_, _area_, _angle_, _b_, _B_, \
15
+ _band_, _c_, _C_, _datum_, _D_, _distance_, \
16
+ _E_, _easting_, _end_, _fi_, _gamma_, _height_, \
17
+ _h_, _j_, _hemipole_, _initial_, _lam_, _lat_, \
18
+ _lon_, _n_, _northing_, _number_, _outside_, \
19
+ _phi_, _point_, _precision_, _points_, _radius_, \
20
+ _scale_, _start_, _x_, _y_, _z_, _zone_
21
21
  # from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS # from .errors
22
22
  from pygeodesy.named import _NamedTuple, _Pass
23
23
  from pygeodesy.props import deprecated_property_RO, property_RO
@@ -27,7 +27,7 @@ from pygeodesy.units import Band, Bearing, Degrees, Degrees2, Easting, \
27
27
  Radians, Radius, Scalar, Str
28
28
 
29
29
  __all__ = _ALL_LAZY.namedTuples
30
- __version__ = '23.12.07'
30
+ __version__ = '24.05.18'
31
31
 
32
32
  # __DUNDER gets mangled in class
33
33
  _closest_ = 'closest'
@@ -202,7 +202,8 @@ class LatLon2Tuple(_NamedTuple):
202
202
  '''Extend this L{LatLon2Tuple} to a L{LatLon3Tuple}.
203
203
 
204
204
  @arg height: The height to add (C{scalar}).
205
- @kwarg name: Optional name (C{str}), overriding this name.
205
+ @kwarg name: Optional C{B{name}=NN} (C{str}), overriding
206
+ this name.
206
207
 
207
208
  @return: A L{LatLon3Tuple}C{(lat, lon, height)}.
208
209
 
@@ -215,7 +216,8 @@ class LatLon2Tuple(_NamedTuple):
215
216
 
216
217
  @arg height: The height to add (C{scalar}).
217
218
  @arg datum: The datum to add (C{Datum}).
218
- @kwarg name: Optional name (C{str}), overriding this name.
219
+ @kwarg name: Optional C{B{name}=NN} (C{str}), overriding
220
+ this name.
219
221
 
220
222
  @return: A L{LatLon4Tuple}C{(lat, lon, height, datum)}.
221
223
 
@@ -237,7 +239,8 @@ class LatLon3Tuple(_NamedTuple):
237
239
  '''Extend this L{LatLon3Tuple} to a L{LatLon4Tuple}.
238
240
 
239
241
  @arg datum: The datum to add (C{Datum}).
240
- @kwarg name: Optional name (C{str}), overriding this name.
242
+ @kwarg name: Optional C{B{name}=NN} (C{str}), overriding
243
+ this name.
241
244
 
242
245
  @return: A L{LatLon4Tuple}C{(lat, lon, height, datum)}.
243
246
 
@@ -256,17 +259,17 @@ class LatLon4Tuple(LatLon3Tuple): # .cartesianBase, .css, .ecef, .lcc
256
259
 
257
260
 
258
261
  def _LL4Tuple(lat, lon, height, datum, LatLon, LatLon_kwds, inst=None,
259
- iteration=None, name=NN):
262
+ iteration=None, **name):
260
263
  '''(INTERNAL) Return a L{LatLon4Tuple} or a B{C{LatLon}} instance.
261
264
  '''
262
265
  if LatLon is None: # ignore LatLon_kwds
263
- r = LatLon4Tuple(lat, lon, height, datum, name=name)
266
+ r = LatLon4Tuple(lat, lon, height, datum, **name)
264
267
  else:
265
268
  kwds = {} if inst is None else _xkwds_not(None,
266
269
  # datum=_xattr(inst, datum=None),
267
270
  epoch=_xattr(inst, epoch=None),
268
271
  reframe=_xattr(inst, reframe=None)) # PYCHOK indent
269
- kwds.update(datum=datum, height=height, name=name)
272
+ kwds.update(datum=datum, height=height, **name)
270
273
  if LatLon_kwds:
271
274
  kwds.update(LatLon_kwds)
272
275
  r = LatLon(lat, lon, **kwds)
@@ -303,7 +306,8 @@ class LatLonPrec3Tuple(_NamedTuple): # .gars.py, .wgrs.py
303
306
 
304
307
  @arg height: The height to add (C{float} or C{None}).
305
308
  @arg radius: The radius to add (C{float} or C{None}).
306
- @kwarg name: Optional name (C{str}), overriding this name.
309
+ @kwarg name: Optional C{B{name}=NN} (C{str}), overriding
310
+ this name.
307
311
 
308
312
  @return: A L{LatLonPrec5Tuple}C{(lat, lon, precision,
309
313
  height, radius)}.
@@ -401,7 +405,8 @@ class PhiLam2Tuple(_NamedTuple): # .frechet, .hausdorff, .latlonBase, .points,
401
405
  '''Extend this L{PhiLam2Tuple} to a L{PhiLam3Tuple}.
402
406
 
403
407
  @arg height: The height to add (C{scalar}).
404
- @kwarg name: Optional name (C{str}), overriding this name.
408
+ @kwarg name: Optional C{B{name}=NN} (C{str}),
409
+ overriding this name.
405
410
 
406
411
  @return: A L{PhiLam3Tuple}C{(phi, lam, height)}.
407
412
 
@@ -440,7 +445,8 @@ class PhiLam3Tuple(_NamedTuple): # .nvector.py, extends -2Tuple
440
445
  '''Extend this L{PhiLam3Tuple} to a L{PhiLam4Tuple}.
441
446
 
442
447
  @arg datum: The datum to add (C{Datum}).
443
- @kwarg name: Optional name (C{str}), overriding this name.
448
+ @kwarg name: Optional C{B{name}=NN} (C{str}),
449
+ overriding this name.
444
450
 
445
451
  @return: A L{PhiLam4Tuple}C{(phi, lam, height, datum)}.
446
452
 
@@ -546,11 +552,11 @@ class UtmUps5Tuple(_NamedTuple): # .mgrs.py, .ups.py, .utm.py, .utmups.py
546
552
  _Names_ = (_zone_, _hemipole_, _easting_, _northing_, _band_)
547
553
  _Units_ = ( Number_, Str, Easting, Northing, Band)
548
554
 
549
- def __new__(cls, z, h, e, n, B, Error=None, name=NN):
555
+ def __new__(cls, z, h, e, n, B, Error=None, **name):
550
556
  if Error is not None:
551
557
  e = Easting( e, Error=Error)
552
558
  n = Northing(n, Error=Error)
553
- return _NamedTuple.__new__(cls, z, h, e, n, B, name=name)
559
+ return _NamedTuple.__new__(cls, z, h, e, n, B, **name)
554
560
 
555
561
 
556
562
  class UtmUps8Tuple(_NamedTuple, _Convergence): # .ups, .utm, .utmups
@@ -567,13 +573,13 @@ class UtmUps8Tuple(_NamedTuple, _Convergence): # .ups, .utm, .utmups
567
573
  _Units_ = ( Number_, Str, Easting, Northing,
568
574
  Band, _Pass, Degrees, Scalar)
569
575
 
570
- def __new__(cls, z, h, e, n, B, d, g, s, Error=None, name=NN): # PYCHOK 11 args
576
+ def __new__(cls, z, h, e, n, B, d, g, s, Error=None, **name): # PYCHOK 11 args
571
577
  if Error is not None:
572
578
  e = Easting( e, Error=Error)
573
579
  n = Northing(n, Error=Error)
574
580
  g = Degrees(gamma=g, Error=Error)
575
581
  s = Scalar(scale=s, Error=Error)
576
- return _NamedTuple.__new__(cls, z, h, e, n, B, d, g, s, name=name)
582
+ return _NamedTuple.__new__(cls, z, h, e, n, B, d, g, s, **name)
577
583
 
578
584
 
579
585
  class UtmUpsLatLon5Tuple(_NamedTuple): # .ups.py, .utm.py, .utmups.py
@@ -587,11 +593,11 @@ class UtmUpsLatLon5Tuple(_NamedTuple): # .ups.py, .utm.py, .utmups.py
587
593
  _Names_ = (_zone_, _band_, _hemipole_, _lat_, _lon_)
588
594
  _Units_ = ( Number_, Band, Str, Lat, Lon)
589
595
 
590
- def __new__(cls, z, B, h, lat, lon, Error=None, name=NN):
596
+ def __new__(cls, z, B, h, lat, lon, Error=None, **name):
591
597
  if Error is not None:
592
598
  lat = Lat(lat, Error=Error)
593
599
  lon = Lon(lon, Error=Error)
594
- return _NamedTuple.__new__(cls, z, B, h, lat, lon, name=name)
600
+ return _NamedTuple.__new__(cls, z, B, h, lat, lon, **name)
595
601
 
596
602
 
597
603
  class Vector2Tuple(_NamedTuple):
@@ -605,7 +611,8 @@ class Vector2Tuple(_NamedTuple):
605
611
  '''Extend this L{Vector2Tuple} to a L{Vector3Tuple}.
606
612
 
607
613
  @kwarg z: The Z component add (C{scalar}).
608
- @kwarg name: Optional name (C{str}), overriding this name.
614
+ @kwarg name: Optional C{B{name}=NN} (C{str}),
615
+ overriding this name.
609
616
 
610
617
  @return: A L{Vector3Tuple}C{(x, y, z)}.
611
618
 
@@ -625,7 +632,8 @@ class Vector3Tuple(_NamedTuple):
625
632
  '''Extend this L{Vector3Tuple} to a L{Vector4Tuple}.
626
633
 
627
634
  @arg h: The height to add (C{scalar}).
628
- @kwarg name: Optional name (C{str}), overriding this name.
635
+ @kwarg name: Optional C{B{name}=NN} (C{str}),
636
+ overriding this name.
629
637
 
630
638
  @return: A L{Vector4Tuple}C{(x, y, z, h)}.
631
639
 
pygeodesy/nvectorBase.py CHANGED
@@ -39,7 +39,7 @@ from pygeodesy.vector3d import Vector3d, _xyzhdn3
39
39
  from math import fabs, sqrt
40
40
 
41
41
  __all__ = _ALL_LAZY.nvectorBase
42
- __version__ = '24.05.13'
42
+ __version__ = '24.05.31'
43
43
 
44
44
 
45
45
  class NvectorBase(Vector3d): # XXX kept private
@@ -49,7 +49,7 @@ class NvectorBase(Vector3d): # XXX kept private
49
49
  _h = Height(h=0) # height (C{meter})
50
50
  _H = NN # height prefix (C{str}), '↑' in JS version
51
51
 
52
- def __init__(self, x_xyz, y=None, z=None, h=0, ll=None, datum=None, name=NN):
52
+ def __init__(self, x_xyz, y=None, z=None, h=0, ll=None, datum=None, **name):
53
53
  '''New n-vector normal to the earth's surface.
54
54
 
55
55
  @arg x_xyz: X component of vector (C{scalar}) or (3-D) vector
@@ -62,15 +62,15 @@ class NvectorBase(Vector3d): # XXX kept private
62
62
  @kwarg h: Optional height above surface (C{meter}).
63
63
  @kwarg ll: Optional, original latlon (C{LatLon}).
64
64
  @kwarg datum: Optional, I{pass-thru} datum (L{Datum}).
65
- @kwarg name: Optional name (C{str}).
65
+ @kwarg name: Optional C{B{name}=NN} (C{str}).
66
66
 
67
67
  @raise TypeError: Non-scalar B{C{x}}, B{C{y}} or B{C{z}}
68
68
  coordinate or B{C{x}} not an C{Nvector},
69
69
  L{Vector3Tuple} or L{Vector4Tuple} or
70
70
  invalid B{C{datum}}.
71
71
  '''
72
- h, d, n = _xyzhdn3(x_xyz, h, datum, ll)
73
- Vector3d.__init__(self, x_xyz, y=y, z=z, ll=ll, name=name or n)
72
+ h, d, n = _xyzhdn3(x_xyz, h, datum, ll, **name)
73
+ Vector3d.__init__(self, x_xyz, y=y, z=z, ll=ll, name=n)
74
74
  if h:
75
75
  self.h = h
76
76
  if d is not None:
@@ -385,7 +385,7 @@ SouthPole = NvectorBase(0, 0, -1, name=_SouthPole_) # South pole (C{Nvector})
385
385
  class _N_vector_(NvectorBase):
386
386
  '''(INTERNAL) Minimal, low-overhead C{n-vector}.
387
387
  '''
388
- def __init__(self, x, y, z, h=0, name=NN):
388
+ def __init__(self, x, y, z, h=0, **name):
389
389
  self._x, self._y, self._z = x, y, z
390
390
  if h:
391
391
  self._h = h
@@ -461,8 +461,8 @@ class LatLonNvectorBase(LatLonBase):
461
461
  @arg bearing1: Bearing at this point (compass C{degrees360}).
462
462
  @arg other: The other point (C{LatLon}).
463
463
  @arg bearing2: Bearing at the other point (compass C{degrees360}).
464
- @kwarg height: Optional height at the triangulated point,
465
- overriding the mean height (C{meter}).
464
+ @kwarg height: Optional height at the triangulated point, overriding
465
+ the mean height (C{meter}).
466
466
  @kwarg wrap: If C{True}, use this and the B{C{other}} point
467
467
  I{normalized} (C{bool}).
468
468
 
pygeodesy/osgr.py CHANGED
@@ -33,14 +33,14 @@ from pygeodesy.datums import Datums, _ellipsoidal_datum, _WGS84
33
33
  # from pygeodesy.dms import parseDMS2 # _MODS
34
34
  from pygeodesy.ellipsoidalBase import LatLonEllipsoidalBase as _LLEB
35
35
  from pygeodesy.errors import _parseX, _TypeError, _ValueError, \
36
- _xkwds, _xkwds_get
36
+ _xkwds, _xkwds_get, _xkwds_pop2
37
37
  from pygeodesy.fmath import Fdot, fpowers
38
38
  from pygeodesy.fsums import _Fsumf_
39
39
  from pygeodesy.interns import MISSING, NN, _A_, _COLON_, _COMMA_, \
40
40
  _COMMASPACE_, _DOT_, _ellipsoidal_, \
41
41
  _latlon_, _not_, _SPACE_
42
42
  from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS
43
- from pygeodesy.named import _NamedBase, nameof, _xnamed
43
+ from pygeodesy.named import _name2__, _NamedBase, nameof
44
44
  from pygeodesy.namedTuples import EasNor2Tuple, LatLon2Tuple, \
45
45
  LatLonDatum3Tuple
46
46
  from pygeodesy.props import Property_RO, property_RO
@@ -53,7 +53,7 @@ from pygeodesy.utily import degrees90, degrees180, sincostan3, truncate
53
53
  from math import cos, fabs, radians, sin, sqrt
54
54
 
55
55
  __all__ = _ALL_LAZY.osgr
56
- __version__ = '24.05.13'
56
+ __version__ = '24.05.31'
57
57
 
58
58
  _equivalent_ = 'equivalent'
59
59
  _OSGR_ = 'OSGR'
@@ -194,22 +194,17 @@ class Osgr(_NamedBase):
194
194
  _northing = 0 # Nothing (C{meter})
195
195
  _resolution = 0 # from L{parseOSGR} (C{meter})
196
196
 
197
- def __init__(self, easting, northing, datum=None, name=NN,
198
- resolution=0):
197
+ def __init__(self, easting, northing, datum=None, resolution=0, **name):
199
198
  '''New L{Osgr} coordinate.
200
199
 
201
- @arg easting: Easting from the OS C{National Grid}
202
- origin (C{meter}).
203
- @arg northing: Northing from the OS C{National Grid}
204
- origin (C{meter}).
200
+ @arg easting: Easting from the OS C{National Grid} origin (C{meter}).
201
+ @arg northing: Northing from the OS C{National Grid} origin (C{meter}).
205
202
  @kwarg datum: Override default datum (C{Datums.OSGB36}).
206
- @kwarg name: Optional name (C{str}).
207
- @kwarg resolution: Optional resolution (C{meter}),
208
- C{0} for default.
203
+ @kwarg resolution: Optional resolution (C{meter}), C{0} for default.
204
+ @kwarg name: Optional C{B{name}=NN} (C{str}).
209
205
 
210
- @raise OSGRError: Invalid or negative B{C{easting}} or
211
- B{C{northing}} or B{C{datum}} not an
212
- C{Datums.OSGB36} equivalent.
206
+ @raise OSGRError: Invalid or negative B{C{easting}} or B{C{northing}}
207
+ or B{C{datum}} not an C{Datums.OSGB36} equivalent.
213
208
  '''
214
209
  if datum: # PYCHOK no cover
215
210
  try:
@@ -267,17 +262,17 @@ class Osgr(_NamedBase):
267
262
  '''
268
263
  return self._northing
269
264
 
270
- def parse(self, strOSGR, name=NN):
265
+ def parse(self, strOSGR, **name):
271
266
  '''Parse an OSGR reference to a similar L{Osgr} instance.
272
267
 
273
268
  @arg strOSGR: The OSGR reference (C{str}), see function L{parseOSGR}.
274
- @kwarg name: Optional instance name (C{str}), overriding this name.
269
+ @kwarg name: Optional C{B{name}=NN} (C{str}), overriding this name.
275
270
 
276
271
  @return: The similar instance (L{Osgr})
277
272
 
278
273
  @raise OSGRError: Invalid B{C{strOSGR}}.
279
274
  '''
280
- return parseOSGR(strOSGR, Osgr=self.classof, name=name or self.name)
275
+ return parseOSGR(strOSGR, Osgr=self.classof, name=self._name__(name))
281
276
 
282
277
  @property_RO
283
278
  def resolution(self):
@@ -496,19 +491,20 @@ def _ll2datum(ll, datum, name):
496
491
  def _ll2LatLon3(ll, LatLon, datum, LatLon_kwds):
497
492
  '''(INTERNAL) Convert C{ll} to C{LatLon}
498
493
  '''
494
+ n = nameof(ll)
499
495
  if LatLon is None:
500
496
  r = _ll2datum(ll, datum, LatLonDatum3Tuple.__name__)
501
- r = LatLonDatum3Tuple(r.lat, r.lon, r.datum)
497
+ r = LatLonDatum3Tuple(r.lat, r.lon, r.datum, name=n)
502
498
  else: # must be ellipsoidal
503
499
  _xsubclassof(_LLEB, LatLon=LatLon)
504
500
  r = _ll2datum(ll, datum, LatLon.__name__)
505
- r = LatLon(r.lat, r.lon, datum=r.datum, **LatLon_kwds)
501
+ r = LatLon(r.lat, r.lon, datum=r.datum, **_xkwds(LatLon_kwds, name=n))
506
502
  if r._iteration != ll._iteration:
507
503
  r._iteration = ll._iteration
508
- return _xnamed(r, nameof(ll))
504
+ return r
509
505
 
510
506
 
511
- def parseOSGR(strOSGR, Osgr=Osgr, name=NN, **Osgr_kwds):
507
+ def parseOSGR(strOSGR, Osgr=Osgr, **name_Osgr_kwds):
512
508
  '''Parse a string representing an OS Grid Reference, consisting
513
509
  of C{"[GD] easting northing"}.
514
510
 
@@ -520,9 +516,9 @@ def parseOSGR(strOSGR, Osgr=Osgr, name=NN, **Osgr_kwds):
520
516
  @arg strOSGR: An OSGR coordinate (C{str}).
521
517
  @kwarg Osgr: Optional class to return the OSGR coordinate
522
518
  (L{Osgr}) or C{None}.
523
- @kwarg name: Optional B{C{Osgr}} name (C{str}).
524
- @kwarg Osgr_kwds: Optional, additional B{C{Osgr}} keyword
525
- arguments, ignored if C{B{Osgr} is None}.
519
+ @kwarg name_Osgr_kwds: Optional C{B{name}=NN} (C{str}) and
520
+ optional, additional B{C{Osgr}} keyword arguments,
521
+ ignored if C{B{Osgr} is None}.
526
522
 
527
523
  @return: An (B{C{Osgr}}) instance or if B{C{Osgr}} is
528
524
  C{None} an L{EasNor2Tuple}C{(easting, northing)}.
@@ -537,7 +533,7 @@ def parseOSGR(strOSGR, Osgr=Osgr, name=NN, **Osgr_kwds):
537
533
  raise ValueError
538
534
  return g
539
535
 
540
- def _OSGR(strOSGR, Osgr, name):
536
+ def _OSGR(strOSGR, Osgr, kwds):
541
537
  s = _splituple(strOSGR.strip())
542
538
  p = len(s)
543
539
  if not p:
@@ -570,20 +566,20 @@ def parseOSGR(strOSGR, Osgr=Osgr, name=NN, **Osgr_kwds):
570
566
  e += E * _100km
571
567
  n += N * _100km
572
568
 
569
+ name, kwds = _name2__(**kwds)
573
570
  if Osgr is None:
574
571
  _ = _MODS.osgr.Osgr(e, n, resolution=m) # validate
575
572
  r = EasNor2Tuple(e, n, name=name)
576
573
  else:
577
- r = Osgr(e, n, name=name,
578
- **_xkwds(Osgr_kwds, resolution=m))
574
+ r = Osgr(e, n, name=name, **_xkwds(kwds, resolution=m))
579
575
  return r
580
576
 
581
- return _parseX(_OSGR, strOSGR, Osgr, name,
577
+ return _parseX(_OSGR, strOSGR, Osgr, name_Osgr_kwds,
582
578
  strOSGR=strOSGR, Error=OSGRError)
583
579
 
584
580
 
585
- def toOsgr(latlon, lon=None, kTM=False, datum=_WGS84, Osgr=Osgr, name=NN, # MCCABE 14
586
- **prec_Osgr_kwds):
581
+ def toOsgr(latlon, lon=None, kTM=False, datum=_WGS84, Osgr=Osgr, # MCCABE 14
582
+ **prec_name_Osgr_kwds):
587
583
  '''Convert a lat-/longitude point to an OSGR coordinate.
588
584
 
589
585
  @arg latlon: Latitude (C{degrees}) or an (ellipsoidal) geodetic
@@ -597,11 +593,10 @@ def toOsgr(latlon, lon=None, kTM=False, datum=_WGS84, Osgr=Osgr, name=NN, # MCC
597
593
  L{a_f2Tuple}).
598
594
  @kwarg Osgr: Optional class to return the OSGR coordinate
599
595
  (L{Osgr}) or C{None}.
600
- @kwarg name: Optional B{C{Osgr}} name (C{str}).
601
- @kwarg prec_Osgr_kwds: Optional L{truncate} precision
602
- C{B{prec}=ndigits} and/or additional
603
- B{C{Osgr}} keyword arguments, ignored
604
- if C{B{Osgr} is None}.
596
+ @kwarg prec_name_Osgr_kwds: Optional C{B{name}=NN} (C{str}),
597
+ optional L{truncate} precision C{B{prec}=ndigits}
598
+ and additional B{C{Osgr}} keyword arguments,
599
+ ignored if C{B{Osgr} is None}.
605
600
 
606
601
  @return: An (B{C{Osgr}}) instance or if B{C{Osgr}} is C{None}
607
602
  an L{EasNor2Tuple}C{(easting, northing)}.
@@ -615,9 +610,6 @@ def toOsgr(latlon, lon=None, kTM=False, datum=_WGS84, Osgr=Osgr, name=NN, # MCC
615
610
  B{C{datum}}, B{C{Osgr}}, B{C{Osgr_kwds}}
616
611
  or conversion to C{Datums.OSGB36} failed.
617
612
  '''
618
- def _prec_kwds2(prec=MISSING, **kwds):
619
- return prec, kwds
620
-
621
613
  if lon is not None:
622
614
  try:
623
615
  lat, lon = _MODS.dms.parseDMS2(latlon, lon)
@@ -626,8 +618,6 @@ def toOsgr(latlon, lon=None, kTM=False, datum=_WGS84, Osgr=Osgr, name=NN, # MCC
626
618
  raise OSGRError(latlon=latlon, lon=lon, datum=datum, cause=x)
627
619
  elif not isinstance(latlon, _LLEB):
628
620
  raise _TypeError(latlon=latlon, txt=_not_(_ellipsoidal_))
629
- elif not name: # use latlon.name
630
- name = nameof(latlon)
631
621
 
632
622
  NG = _NG
633
623
  # convert latlon to OSGB36 first
@@ -663,22 +653,24 @@ def toOsgr(latlon, lon=None, kTM=False, datum=_WGS84, Osgr=Osgr, name=NN, # MCC
663
653
  d2 / 12 * (_Fsumf_( 5, ta2, 9 * n2) +
664
654
  d2 / 30 * _Fsumf_(61, ta4, 58 * ta2)))).fsum_(m0, NG.nor0)
665
655
 
666
- p, kwds = _prec_kwds2(**prec_Osgr_kwds)
667
- if p is not MISSING:
668
- e = truncate(e, p)
669
- n = truncate(n, p)
656
+ t, kwds = _name2__(prec_name_Osgr_kwds, _or_nameof=latlon)
657
+ if kwds:
658
+ p, kwds = _xkwds_pop2(kwds, prec=MISSING)
659
+ if p is not MISSING:
660
+ e = truncate(e, p)
661
+ n = truncate(n, p)
670
662
 
671
663
  if Osgr is None:
672
664
  _ = _MODS.osgr.Osgr(e, n) # validate
673
- r = EasNor2Tuple(e, n)
665
+ r = EasNor2Tuple(e, n, name=t)
674
666
  else:
675
- r = Osgr(e, n, **kwds) # datum=NG.datum
667
+ r = Osgr(e, n, name=t, **kwds) # datum=NG.datum
676
668
  if lon is None and isinstance(latlon, _LLEB):
677
669
  if kTM:
678
670
  r._latlonTM = latlon # XXX weakref(latlon)?
679
671
  else:
680
672
  r._latlon = latlon # XXX weakref(latlon)?
681
- return _xnamed(r, name or nameof(latlon))
673
+ return r
682
674
 
683
675
 
684
676
  if __name__ == '__main__':
pygeodesy/points.py CHANGED
@@ -38,11 +38,11 @@ from pygeodesy.errors import CrossError, crosserrors, _IndexError, \
38
38
  _xattr, _xkwds, _xkwds_item2, _xkwds_pop2
39
39
  from pygeodesy.fmath import favg, fdot, hypot, Fsum, fsum
40
40
  # from pygeodesy.fsums import Fsum, fsum # from .fmath
41
- from pygeodesy.formy import _bearingTo2, equirectangular_, _spherical_datum
41
+ from pygeodesy.formy import _bearingTo2, equirectangular4, _spherical_datum
42
42
  from pygeodesy.interns import NN, _colinear_, _COMMASPACE_, _composite_, \
43
43
  _DEQUALSPACED_, _ELLIPSIS_, _EW_, _immutable_, \
44
- _near_, _no_, _not_, _NS_, _point_, _SPACE_, \
45
- _UNDER_, _valid_ # _lat_, _lon_
44
+ _near_, _no_, _NS_, _point_, _SPACE_, _UNDER_, \
45
+ _valid_ # _lat_, _lon_
46
46
  from pygeodesy.iters import LatLon2PsxyIter, PointsIter, points2
47
47
  from pygeodesy.latlonBase import LatLonBase, _latlonheight3, \
48
48
  _ALL_DOCS, _ALL_LAZY, _MODS
@@ -62,7 +62,7 @@ from pygeodesy.utily import atan2b, degrees90, degrees180, degrees2m, \
62
62
  from math import cos, fabs, fmod as _fmod, radians, sin
63
63
 
64
64
  __all__ = _ALL_LAZY.points
65
- __version__ = '24.05.10'
65
+ __version__ = '24.05.25'
66
66
 
67
67
  _ilat_ = 'ilat'
68
68
  _ilon_ = 'ilon'
@@ -92,7 +92,7 @@ class LatLon_(LatLonBase): # XXX in heights._HeightBase.height
92
92
  # python3 -m timeit -s "from pygeodesy... import LatLonBase as LL" "LL(0, 0)" 2.14 usec
93
93
  # python3 -m timeit -s "from pygeodesy import LatLon_" "LatLon_(0, 0)" 216 nsec
94
94
 
95
- def __init__(self, latlonh, lon=None, height=0, wrap=False, name=NN, datum=None):
95
+ def __init__(self, latlonh, lon=None, height=0, wrap=False, datum=None, **name):
96
96
  '''New L{LatLon_}.
97
97
 
98
98
  @note: The lat- and longitude values are taken I{as-given,
@@ -283,7 +283,7 @@ class _Basequence(_Sequence): # immutable, on purpose
283
283
  '''
284
284
  for i in self._findall(point, start_end):
285
285
  return i
286
- raise _IndexError(self._itemname, point, txt=_not_('found'))
286
+ raise _IndexError(self._itemname, point, txt_not_='found')
287
287
 
288
288
  @property_RO
289
289
  def isNumpy2(self): # PYCHOK no cover
@@ -1156,7 +1156,7 @@ def fractional(points, fi, j=None, wrap=None, LatLon=None, Vector=None, **kwds):
1156
1156
  '''
1157
1157
  if LatLon and Vector: # PYCHOK no cover
1158
1158
  kwds = _xkwds(kwds, fi=fi, LatLon=LatLon, Vector=Vector)
1159
- raise _TypeError(txt=fractional.__name__, **kwds)
1159
+ raise _TypeError(txt__=fractional, **kwds)
1160
1160
  w = wrap if LatLon else False # intermediateTo
1161
1161
  try:
1162
1162
  if not isscalar(fi) or fi < 0:
@@ -1168,7 +1168,7 @@ def fractional(points, fi, j=None, wrap=None, LatLon=None, Vector=None, **kwds):
1168
1168
  elif Vector:
1169
1169
  p = Vector(p.x, p.y, p.z, **kwds)
1170
1170
  except (IndexError, TypeError):
1171
- raise _IndexError(fi=fi, points=points, wrap=w, txt=fractional.__name__)
1171
+ raise _IndexError(fi=fi, points=points, wrap=w, txt__=fractional)
1172
1172
  return p
1173
1173
 
1174
1174
 
@@ -1191,12 +1191,12 @@ def _fractional(points, fi, j, fin=None, wrap=None): # in .frechet.py
1191
1191
  elif _isLatLon(p): # backward compatible default
1192
1192
  p = LatLon2Tuple(favg(p.lat, q.lat, f=r),
1193
1193
  favg(p.lon, q.lon, f=r),
1194
- name=fractional.__name__)
1194
+ name__=fractional)
1195
1195
  else: # assume p and q are cartesian or vectorial
1196
1196
  z = p.z if p.z is q.z else favg(p.z, q.z, f=r)
1197
1197
  p = Vector3Tuple(favg(p.x, q.x, f=r),
1198
1198
  favg(p.y, q.y, f=r), z,
1199
- name=fractional.__name__)
1199
+ name__=fractional)
1200
1200
  return p
1201
1201
 
1202
1202
 
@@ -1473,8 +1473,8 @@ def nearestOn5(point, points, closed=False, wrap=False, adjust=True,
1473
1473
  @kwarg closed: Optionally, close the path or polygon (C{bool}).
1474
1474
  @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the
1475
1475
  B{C{points}} (C{bool}).
1476
- @kwarg adjust: See function L{pygeodesy.equirectangular_} (C{bool}).
1477
- @kwarg limit: See function L{pygeodesy.equirectangular_} (C{degrees}),
1476
+ @kwarg adjust: See function L{pygeodesy.equirectangular4} (C{bool}).
1477
+ @kwarg limit: See function L{pygeodesy.equirectangular4} (C{degrees}),
1478
1478
  default C{9 degrees} is about C{1,000 Kmeter} (for mean
1479
1479
  spherical earth radius L{R_KM}).
1480
1480
  @kwarg LatLon_and_kwds: Optional, C{B{LatLon}=None} class to use for
@@ -1490,24 +1490,24 @@ def nearestOn5(point, points, closed=False, wrap=False, adjust=True,
1490
1490
  compass C{degrees}, like function L{pygeodesy.compassAngle}.
1491
1491
 
1492
1492
  @raise LimitError: Lat- and/or longitudinal delta exceeds the B{C{limit}},
1493
- see function L{pygeodesy.equirectangular_}.
1493
+ see function L{pygeodesy.equirectangular4}.
1494
1494
 
1495
1495
  @raise PointsError: Insufficient number of B{C{points}}
1496
1496
 
1497
1497
  @raise TypeError: Some B{C{points}} are not C{LatLon}.
1498
1498
 
1499
- @note: Distances are I{approximated} by function L{pygeodesy.equirectangular_}.
1499
+ @note: Distances are I{approximated} by function L{pygeodesy.equirectangular4}.
1500
1500
  For more accuracy use one of the C{LatLon.nearestOn6} methods.
1501
1501
 
1502
1502
  @see: Function L{pygeodesy.degrees2m}.
1503
1503
  '''
1504
1504
  def _d2yx4(p2, p1, u, alw):
1505
1505
  # w = wrap if (i < (n - 1) or not closed) else False
1506
- # equirectangular_ returns a Distance4Tuple(distance
1506
+ # equirectangular4 returns a Distance4Tuple(distance
1507
1507
  # in degrees squared, delta lat, delta lon, p2.lon
1508
1508
  # unroll/wrap'd); the previous p2.lon unroll/wrap'd
1509
1509
  # is also applied to the next edge's p1.lon
1510
- return equirectangular_(p1.lat, p1.lon + u,
1510
+ return equirectangular4(p1.lat, p1.lon + u,
1511
1511
  p2.lat, p2.lon, **alw)
1512
1512
 
1513
1513
  def _h(p): # get height or default 0
@@ -1604,7 +1604,7 @@ def perimeterOf(points, closed=False, adjust=True, radius=R_M, wrap=True):
1604
1604
  @raise ValueError: Invalid B{C{radius}} or C{B{closed}=False} with
1605
1605
  C{B{points}} a composite.
1606
1606
 
1607
- @note: This perimeter is based on the L{pygeodesy.equirectangular_}
1607
+ @note: This perimeter is based on the L{pygeodesy.equirectangular4}
1608
1608
  distance approximation and is ill-suited for regions exceeding
1609
1609
  several hundred Km or Miles or with near-polar latitudes.
1610
1610
 
@@ -1618,7 +1618,7 @@ def perimeterOf(points, closed=False, adjust=True, radius=R_M, wrap=True):
1618
1618
  if w and c:
1619
1619
  w = not Ps.looped
1620
1620
  # apply previous x2's unroll/wrap'd to new x1
1621
- _, dy, dx, u = equirectangular_(p1.y, p1.x + u,
1621
+ _, dy, dx, u = equirectangular4(p1.y, p1.x + u,
1622
1622
  p2.y, p2.x,
1623
1623
  adjust=a, limit=None,
1624
1624
  wrap=w) # PYCHOK non-seq
pygeodesy/props.py CHANGED
@@ -10,9 +10,9 @@ with command line option C{-X dev} or with one of the C{-W}
10
10
  choices, see callable L{DeprecationWarnings} below.
11
11
  '''
12
12
 
13
- from pygeodesy.basics import isclass as _isclass # _MODS
13
+ from pygeodesy.basics import isclass as _isclass
14
14
  from pygeodesy.errors import _AssertionError, _AttributeError, \
15
- _xkwds, _xkwds_get
15
+ _xcallable, _xkwds, _xkwds_get
16
16
  from pygeodesy.interns import MISSING, NN, _an_, _COMMASPACE_, \
17
17
  _DEPRECATED_, _DOT_, _EQUALSPACED_, \
18
18
  _immutable_, _invalid_, _module_, _N_A_, \
@@ -25,7 +25,7 @@ from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS, \
25
25
  from functools import wraps as _wraps
26
26
 
27
27
  __all__ = _ALL_LAZY.props
28
- __version__ = '24.05.12'
28
+ __version__ = '24.05.26'
29
29
 
30
30
  _class_ = 'class'
31
31
  _dont_use_ = _DEPRECATED_ + ", don't use."
@@ -157,8 +157,7 @@ class _PropertyBase(property):
157
157
  '''
158
158
  def __init__(self, method, fget, fset, doc=NN):
159
159
 
160
- if not callable(method):
161
- self.getter(method) # PYCHOK no cover
160
+ _xcallable(getter=method, fget=fget)
162
161
 
163
162
  self.method = method
164
163
  self.name = method.__name__
@@ -288,20 +287,34 @@ class Property(Property_RO):
288
287
  @note: Setting a new property value always clears the previously I{cached}
289
288
  or I{memoized} value I{after} invoking the B{C{method}}.
290
289
  '''
291
- if not callable(method):
292
- _PropertyBase.setter(self, method) # PYCHOK no cover
290
+ def _fset(inst, val):
291
+ '''Set and I{cache}, I{memoize} the C{property} value.
292
+ '''
293
+ _ = method(inst, val)
294
+ self._update(inst) # un-cache this item
293
295
 
294
- if _FOR_DOCS: # XXX force method.__doc__ into epydoc
295
- _PropertyBase.__init__(self, self.method, self.method, method)
296
- else:
296
+ return self._setters(method, _fset)
297
297
 
298
- def _fset(inst, val):
299
- '''Set and I{cache}, I{memoize} the C{property} value.
300
- '''
301
- method(inst, val)
302
- self._update(inst) # un-cache this item
298
+ def setter_(self, method):
299
+ '''Make this C{Property} I{mutable}.
303
300
 
304
- # class Property <https://docs.Python.org/3/howto/descriptor.html>
301
+ @arg method: The callable being decorated as this C{Property}'s C{setter}
302
+ and returning the new property value to be I{cached} or
303
+ I{memoized}.
304
+ '''
305
+ def _fset(inst, val):
306
+ '''Set and I{cache}, I{memoize} the C{property} value.
307
+ '''
308
+ val = method(inst, val)
309
+ inst.__dict__[self.name] = val
310
+
311
+ return self._setters(method, _fset)
312
+
313
+ def _setters(self, method, _fset):
314
+ _xcallable(setter=method, fset=_fset)
315
+ if _FOR_DOCS: # XXX force method.__doc__ into epydoc
316
+ _PropertyBase.__init__(self, self.method, self.method, method)
317
+ else: # class Property <https://docs.Python.org/3/howto/descriptor.html>
305
318
  _PropertyBase.__init__(self, self.method, self._fget, _fset)
306
319
  return self
307
320
 
@@ -9,7 +9,7 @@ u'''Package of lazily imported C{rhumb} modules L{rhumb.aux_}, L{rhumb.ekx} and
9
9
  from pygeodesy.lazily import _ALL_LAZY, _ALL_OTHER, _lazy_import_as, _unLazy0
10
10
 
11
11
  __all__ = _ALL_LAZY.rhumb
12
- __version__ = '23.12.29'
12
+ __version__ = '24.05.24'
13
13
 
14
14
  if _unLazy0: # or _isfrozen
15
15
  from pygeodesy.rhumb.aux_ import RhumbAux, RhumbLineAux