pygeodesy 24.5.24__py2.py3-none-any.whl → 24.6.9__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. {PyGeodesy-24.5.24.dist-info → PyGeodesy-24.6.9.dist-info}/METADATA +6 -5
  2. PyGeodesy-24.6.9.dist-info/RECORD +116 -0
  3. pygeodesy/__init__.py +4 -4
  4. pygeodesy/auxilats/__init__.py +1 -1
  5. pygeodesy/auxilats/__main__.py +2 -2
  6. pygeodesy/auxilats/auxAngle.py +4 -4
  7. pygeodesy/basics.py +39 -5
  8. pygeodesy/booleans.py +54 -67
  9. pygeodesy/cartesianBase.py +138 -147
  10. pygeodesy/constants.py +3 -3
  11. pygeodesy/deprecated/functions.py +9 -3
  12. pygeodesy/ecef.py +67 -72
  13. pygeodesy/ellipsoidalBase.py +18 -56
  14. pygeodesy/ellipsoidalGeodSolve.py +2 -2
  15. pygeodesy/ellipsoidalKarney.py +3 -3
  16. pygeodesy/ellipsoidalNvector.py +7 -7
  17. pygeodesy/ellipsoids.py +6 -5
  18. pygeodesy/errors.py +20 -10
  19. pygeodesy/etm.py +16 -21
  20. pygeodesy/fmath.py +9 -20
  21. pygeodesy/formy.py +60 -74
  22. pygeodesy/frechet.py +13 -14
  23. pygeodesy/fsums.py +60 -26
  24. pygeodesy/geodesicx/__init__.py +1 -1
  25. pygeodesy/geodesicx/__main__.py +2 -2
  26. pygeodesy/geodesicx/gx.py +3 -5
  27. pygeodesy/geodsolve.py +24 -26
  28. pygeodesy/geohash.py +27 -40
  29. pygeodesy/geoids.py +1 -1
  30. pygeodesy/hausdorff.py +17 -18
  31. pygeodesy/heights.py +17 -30
  32. pygeodesy/internals.py +15 -14
  33. pygeodesy/interns.py +3 -9
  34. pygeodesy/iters.py +2 -2
  35. pygeodesy/karney.py +8 -7
  36. pygeodesy/latlonBase.py +189 -176
  37. pygeodesy/lazily.py +92 -56
  38. pygeodesy/lcc.py +2 -2
  39. pygeodesy/ltp.py +93 -55
  40. pygeodesy/ltpTuples.py +304 -240
  41. pygeodesy/mgrs.py +51 -24
  42. pygeodesy/named.py +159 -136
  43. pygeodesy/namedTuples.py +43 -14
  44. pygeodesy/nvectorBase.py +20 -23
  45. pygeodesy/osgr.py +40 -48
  46. pygeodesy/points.py +11 -11
  47. pygeodesy/props.py +29 -16
  48. pygeodesy/rhumb/aux_.py +13 -15
  49. pygeodesy/rhumb/bases.py +12 -5
  50. pygeodesy/rhumb/ekx.py +24 -18
  51. pygeodesy/rhumb/solve.py +20 -70
  52. pygeodesy/simplify.py +16 -16
  53. pygeodesy/solveBase.py +35 -32
  54. pygeodesy/sphericalBase.py +33 -31
  55. pygeodesy/sphericalTrigonometry.py +17 -17
  56. pygeodesy/streprs.py +6 -4
  57. pygeodesy/trf.py +11 -9
  58. pygeodesy/triaxials.py +71 -50
  59. pygeodesy/units.py +40 -65
  60. pygeodesy/unitsBase.py +2 -2
  61. pygeodesy/ups.py +66 -70
  62. pygeodesy/utily.py +7 -6
  63. pygeodesy/utm.py +152 -156
  64. pygeodesy/utmups.py +38 -38
  65. pygeodesy/utmupsBase.py +102 -106
  66. pygeodesy/vector3d.py +34 -36
  67. pygeodesy/vector3dBase.py +12 -9
  68. pygeodesy/webmercator.py +43 -51
  69. PyGeodesy-24.5.24.dist-info/RECORD +0 -116
  70. {PyGeodesy-24.5.24.dist-info → PyGeodesy-24.6.9.dist-info}/WHEEL +0 -0
  71. {PyGeodesy-24.5.24.dist-info → PyGeodesy-24.6.9.dist-info}/top_level.txt +0 -0
pygeodesy/latlonBase.py CHANGED
@@ -10,7 +10,7 @@ u'''(INTERNAL) Base class L{LatLonBase} for all elliposiodal, spherical and N-ve
10
10
  U{RhumbLine<https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1RhumbLine.html>} classes.
11
11
  '''
12
12
 
13
- from pygeodesy.basics import isstr, map1, _xinstanceof
13
+ from pygeodesy.basics import isstr, map1, _xinstanceof, _passarg
14
14
  from pygeodesy.constants import EPS, EPS0, EPS1, EPS4, INT0, R_M, \
15
15
  _EPSqrt as _TOL, _0_0, _0_5, _1_0, \
16
16
  _360_0, _umod_360
@@ -28,14 +28,15 @@ from pygeodesy.errors import _AttributeError, IntersectionError, \
28
28
  # flatPolar, _hartzell, haversine, isantipode, \
29
29
  # _isequalTo, isnormal, normal, philam2n_xyz, \
30
30
  # thomas_, vincentys # as _formy
31
+ # from pygeodesy.internals import _passarg # from .basics
31
32
  from pygeodesy.interns import NN, _COMMASPACE_, _concentric_, _height_, \
32
33
  _intersection_, _LatLon_, _m_, _negative_, \
33
34
  _no_, _overlap_, _too_, _point_ # PYCHOK used!
34
- # from pygeodesy.iters import PointsIter, points2 # from .vector3d, _MODS
35
+ # from pygeodesy.iters import PointsIter, points2 # _MODS
35
36
  # from pygeodesy.karney import Caps # _MODS
36
37
  from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS
37
38
  # from pygeodesy.ltp import Ltp, _xLtp # _MODS
38
- from pygeodesy.named import _NamedBase, Fmt
39
+ from pygeodesy.named import _name2__, _NamedBase, Fmt
39
40
  from pygeodesy.namedTuples import Bounds2Tuple, LatLon2Tuple, PhiLam2Tuple, \
40
41
  Trilaterate5Tuple
41
42
  # from pygeodesy.nvectorBase import _N_vector_ # _MODS
@@ -45,15 +46,17 @@ from pygeodesy.props import deprecated_method, Property, Property_RO, \
45
46
  from pygeodesy.units import _isDegrees, _isRadius, Distance_, Lat, Lon, \
46
47
  Height, Radius, Radius_, Scalar, Scalar_
47
48
  from pygeodesy.utily import _unrollon, _unrollon3, _Wrap
48
- from pygeodesy.vector2d import _circin6, Circin6Tuple, _circum3, circum4_, \
49
- Circum3Tuple, _radii11ABC
50
- from pygeodesy.vector3d import nearestOn6, Vector3d, PointsIter
49
+ # from pygeodesy.vector2d import _circin6, Circin6Tuple, _circum3, circum4_, \
50
+ # Circum3Tuple, _radii11ABC # _MODS
51
+ # from pygeodesy.vector3d import nearestOn6, Vector3d # _MODS
51
52
 
52
53
  from contextlib import contextmanager
53
54
  from math import asin, cos, degrees, fabs, radians
54
55
 
55
56
  __all__ = _ALL_LAZY.latlonBase
56
- __version__ = '24.05.18'
57
+ __version__ = '24.06.07'
58
+
59
+ _formy = _MODS.into(formy=__name__)
57
60
 
58
61
 
59
62
  class LatLonBase(_NamedBase):
@@ -66,7 +69,7 @@ class LatLonBase(_NamedBase):
66
69
  _lat = 0 # latitude (C{degrees})
67
70
  _lon = 0 # longitude (C{degrees})
68
71
 
69
- def __init__(self, latlonh, lon=None, height=0, wrap=False, datum=None, **name):
72
+ def __init__(self, latlonh, lon=None, height=0, datum=None, **wrap_name):
70
73
  '''New C{LatLon}.
71
74
 
72
75
  @arg latlonh: Latitude (C{degrees} or DMS C{str} with N or S suffix) or
@@ -75,11 +78,11 @@ class LatLonBase(_NamedBase):
75
78
  C(None), indicating B{C{latlonh}} is a C{LatLon}.
76
79
  @kwarg height: Optional height above (or below) the earth surface
77
80
  (C{meter}, conventionally).
78
- @kwarg wrap: If C{True}, wrap or I{normalize} B{C{lat}} and B{C{lon}}
79
- (C{bool}).
80
81
  @kwarg datum: Optional datum (L{Datum}, L{Ellipsoid}, L{Ellipsoid2},
81
82
  L{a_f2Tuple} or I{scalar} radius) or C{None}.
82
- @kwarg name: Optional C{B{name}=NN} (C{str}).
83
+ @kwarg wrap_name: Optional C{B{name}=NN} (C{str}) and optional keyword
84
+ argument C{B{wrap}=False}, if C{True}, wrap or I{normalize}
85
+ B{C{lat}} and B{C{lon}} (C{bool}).
83
86
 
84
87
  @return: New instance (C{LatLon}).
85
88
 
@@ -90,12 +93,13 @@ class LatLonBase(_NamedBase):
90
93
 
91
94
  @raise UnitError: Invalid B{C{lat}}, B{C{lon}} or B{C{height}}.
92
95
  '''
93
- if name:
94
- self.name = name
96
+ w, n = self._wrap_name2(**wrap_name)
97
+ if n:
98
+ self.name = n
95
99
 
96
100
  if lon is None:
97
- lat, lon, height = _latlonheight3(latlonh, height, wrap)
98
- elif wrap:
101
+ lat, lon, height = _latlonheight3(latlonh, height, w)
102
+ elif w:
99
103
  lat, lon = _Wrap.latlonDMS2(latlonh, lon)
100
104
  else:
101
105
  lat = latlonh
@@ -125,8 +129,8 @@ class LatLonBase(_NamedBase):
125
129
 
126
130
  @return: The antipodal point (C{LatLon}).
127
131
  '''
128
- a = self._formy.antipode(*self.latlon)
129
- h = self._heigHt(height)
132
+ a = _formy.antipode(*self.latlon)
133
+ h = self._heigHt(height)
130
134
  return self.classof(*a, height=h)
131
135
 
132
136
  @deprecated_method
@@ -134,7 +138,7 @@ class LatLonBase(_NamedBase):
134
138
  '''DEPRECATED, use method C{boundsOf}.'''
135
139
  return self.boundsOf(wide, tall, radius=radius)
136
140
 
137
- def boundsOf(self, wide, tall, radius=R_M, height=None):
141
+ def boundsOf(self, wide, tall, radius=R_M, height=None, **name):
138
142
  '''Return the SW and NE lat-/longitude of a great circle
139
143
  bounding box centered at this location.
140
144
 
@@ -146,6 +150,7 @@ class LatLonBase(_NamedBase):
146
150
  B{C{wide}} and B{C{tall}} are in C{degrees}.
147
151
  @kwarg height: Height for C{latlonSW} and C{latlonNE} (C{meter}),
148
152
  overriding the point's height.
153
+ @kwarg name: Optional C{B{name}=NN} (C{str}).
149
154
 
150
155
  @return: A L{Bounds2Tuple}C{(latlonSW, latlonNE)}, the
151
156
  lower-left and upper-right corner (C{LatLon}).
@@ -165,15 +170,15 @@ class LatLonBase(_NamedBase):
165
170
  h = self._heigHt(height)
166
171
  sw = self.classof(y - t, x - w, height=h)
167
172
  ne = self.classof(y + t, x + w, height=h)
168
- return Bounds2Tuple(sw, ne, name=self.name)
173
+ return Bounds2Tuple(sw, ne, name=self._name__(name))
169
174
 
170
175
  def chordTo(self, other, height=None, wrap=False):
171
176
  '''Compute the length of the chord through the earth between
172
177
  this and an other point.
173
178
 
174
179
  @arg other: The other point (C{LatLon}).
175
- @kwarg height: Overriding height for both points (C{meter})
176
- or C{None} for each point's height.
180
+ @kwarg height: Overriding height for both points (C{meter}),
181
+ or if C{None}, use each point's height.
177
182
  @kwarg wrap: If C{True}, wrap or I{normalize} the B{C{other}}
178
183
  point (C{bool}).
179
184
 
@@ -181,24 +186,25 @@ class LatLonBase(_NamedBase):
181
186
 
182
187
  @raise TypeError: The B{C{other}} point is not C{LatLon}.
183
188
  '''
184
- def _v3d(ll):
185
- t = ll.toEcef(height=height) # .toVector(Vector=Vector3d)
186
- return Vector3d(t.x, t.y, t.z)
189
+ def _v3d(ll, V3d=_MODS.vector3d.Vector3d):
190
+ t = ll.toEcef(height=height) # .toVector(Vector=V3d)
191
+ return V3d(t.x, t.y, t.z)
187
192
 
188
193
  p = self.others(other)
189
194
  if wrap:
190
195
  p = _Wrap.point(p)
191
196
  return _v3d(self).minus(_v3d(p)).length
192
197
 
193
- def circin6(self, point2, point3, eps=EPS4, wrap=False):
198
+ def circin6(self, point2, point3, eps=EPS4, **wrap_name):
194
199
  '''Return the radius and center of the I{inscribed} aka I{In-}circle
195
200
  of the (planar) triangle formed by this and two other points.
196
201
 
197
202
  @arg point2: Second point (C{LatLon}).
198
203
  @arg point3: Third point (C{LatLon}).
199
204
  @kwarg eps: Tolerance for function L{pygeodesy.trilaterate3d2}.
200
- @kwarg wrap: If C{True}, wrap or I{normalize} B{C{point2}} and
201
- B{C{point3}} (C{bool}).
205
+ @kwarg wrap_name: Optional C{B{name}=NN} (C{str}) and optional keyword
206
+ argument C{B{wrap}=False}, if C{True}, wrap or I{normalize}
207
+ the B{C{points}} (C{bool}).
202
208
 
203
209
  @return: L{Circin6Tuple}C{(radius, center, deltas, cA, cB, cC)}. The
204
210
  C{center} and contact points C{cA}, C{cB} and C{cC}, each an
@@ -225,12 +231,17 @@ class LatLonBase(_NamedBase):
225
231
  <https://MathWorld.Wolfram.com/Incircle.html>} and U{Contact Triangle
226
232
  <https://MathWorld.Wolfram.com/ContactTriangle.html>}.
227
233
  '''
228
- with _toCartesian3(self, point2, point3, wrap) as cs:
229
- r, c, d, cA, cB, cC = _circin6(*cs, eps=eps, useZ=True, dLL3=True,
230
- datum=self.datum) # PYCHOK unpack
231
- return Circin6Tuple(r, c.toLatLon(), d, cA.toLatLon(), cB.toLatLon(), cC.toLatLon())
234
+ w, n = self._wrap_name2(**wrap_name)
232
235
 
233
- def circum3(self, point2, point3, circum=True, eps=EPS4, wrap=False):
236
+ with _toCartesian3(self, point2, point3, w) as cs:
237
+ m = _MODS.vector2d
238
+ r, c, d, A, B, C = m._circin6(*cs, eps=eps, useZ=True, dLL3=True,
239
+ datum=self.datum) # PYCHOK unpack
240
+ return m.Circin6Tuple(r, c.toLatLon(), d, A.toLatLon(),
241
+ B.toLatLon(),
242
+ C.toLatLon(), name=n)
243
+
244
+ def circum3(self, point2, point3, circum=True, eps=EPS4, **wrap_name):
234
245
  '''Return the radius and center of the smallest circle I{through} or I{containing}
235
246
  this and two other points.
236
247
 
@@ -239,8 +250,9 @@ class LatLonBase(_NamedBase):
239
250
  @kwarg circum: If C{True} return the C{circumradius} and C{circumcenter},
240
251
  always, ignoring the I{Meeus}' Type I case (C{bool}).
241
252
  @kwarg eps: Tolerance for function L{pygeodesy.trilaterate3d2}.
242
- @kwarg wrap: If C{True}, wrap or I{normalize} B{C{point2}} and
243
- B{C{point3}} (C{bool}).
253
+ @kwarg wrap_name: Optional C{B{name}=NN} (C{str}) and optional keyword
254
+ argument C{B{wrap}=False}, if C{True}, wrap or I{normalize}
255
+ the B{C{points}} (C{bool}).
244
256
 
245
257
  @return: A L{Circum3Tuple}C{(radius, center, deltas)}. The C{center}, an
246
258
  instance of this (sub-)class, is co-planar with this and the two
@@ -268,20 +280,24 @@ class LatLonBase(_NamedBase):
268
280
 
269
281
  @see: Function L{pygeodesy.circum3} and methods L{circin6} and L{circum4_}.
270
282
  '''
271
- with _toCartesian3(self, point2, point3, wrap, circum=circum) as cs:
272
- r, c, d = _circum3(*cs, circum=circum, eps=eps, useZ=True, dLL3=True, # XXX -3d2
273
- clas=cs[0].classof, datum=self.datum) # PYCHOK unpack
274
- return Circum3Tuple(r, c.toLatLon(), d)
283
+ w, n = self._wrap_name2(**wrap_name)
284
+
285
+ with _toCartesian3(self, point2, point3, w, circum=circum) as cs:
286
+ m = _MODS.vector2d
287
+ r, c, d = m._circum3(*cs, circum=circum, eps=eps, useZ=True, dLL3=True, # XXX -3d2
288
+ clas=cs[0].classof, datum=self.datum) # PYCHOK unpack
289
+ return m.Circum3Tuple(r, c.toLatLon(), d, name=n)
275
290
 
276
- def circum4_(self, *points, **wrap):
291
+ def circum4_(self, *points, **wrap_name):
277
292
  '''Best-fit a sphere through this and two or more other points.
278
293
 
279
294
  @arg points: The other points (each a C{LatLon}).
280
- @kwarg wrap: If C{True}, wrap or I{normalize} the B{C{points}}
281
- (C{bool}), default C{False}.
295
+ @kwarg wrap_name: Optional C{B{name}=NN} (C{str}) and optional keyword argument
296
+ C{B{wrap}=False}, if C{True}, wrap or I{normalize} the B{C{points}}
297
+ (C{bool}).
282
298
 
283
- @return: L{Circum4Tuple}C{(radius, center, rank, residuals)} with C{center}
284
- an instance of this (sub-)class.
299
+ @return: L{Circum4Tuple}C{(radius, center, rank, residuals)} with C{center} an
300
+ instance of this (sub-)class.
285
301
 
286
302
  @raise ImportError: Package C{numpy} not found, not installed or older than
287
303
  version 1.10.
@@ -294,16 +310,18 @@ class LatLonBase(_NamedBase):
294
310
 
295
311
  @see: Function L{pygeodesy.circum4_} and L{circum3}.
296
312
  '''
297
- def _cs(ps, C, wrap=False):
298
- _wp = _Wrap.point if wrap else (lambda p: p)
313
+ w, n = self._wrap_name2(**wrap_name)
314
+
315
+ def _cs(ps, C, w):
316
+ _wp = _Wrap.point if w else _passarg
299
317
  for i, p in enumerate(ps):
300
318
  yield C(i=i, points=_wp(p))
301
319
 
302
- C = self._toCartesianEcef
303
- c = C(point=self)
304
- t = circum4_(c, Vector=c.classof, *_cs(points, C, **wrap))
305
- c = t.center.toLatLon(LatLon=self.classof)
306
- return t.dup(center=c)
320
+ C = self._toCartesianEcef
321
+ c = C(point=self)
322
+ t = _MODS.vector2d.circum4_(c, Vector=c.classof, *_cs(points, C, w))
323
+ c = t.center.toLatLon(LatLon=self.classof)
324
+ return t.dup(center=c, name=n)
307
325
 
308
326
  @property
309
327
  def clipid(self):
@@ -344,19 +362,19 @@ class LatLonBase(_NamedBase):
344
362
  <https://www.EdWilliams.org/avform.htm#flat>}.
345
363
  '''
346
364
  p = self.others(other)
347
- return self._formy.compassAngle(self.lat, self.lon, p.lat, p.lon, **adjust_wrap)
365
+ return _formy.compassAngle(self.lat, self.lon, p.lat, p.lon, **adjust_wrap)
348
366
 
349
- def cosineAndoyerLambertTo(self, other, wrap=False):
367
+ def cosineAndoyerLambertTo(self, other, **wrap):
350
368
  '''Compute the distance between this and an other point using the U{Andoyer-Lambert correction<https://
351
369
  navlib.net/wp-content/uploads/2013/10/admiralty-manual-of-navigation-vol-1-1964-english501c.pdf>}
352
370
  of the U{Law of Cosines<https://www.Movable-Type.co.UK/scripts/latlong.html#cosine-law>} formula.
353
371
 
354
372
  @arg other: The other point (C{LatLon}).
355
- @kwarg wrap: If C{True}, wrap or I{normalize} and unroll
356
- the B{C{other}} point (C{bool}).
373
+ @kwarg wrap: Optional keyword argument C{B{wrap}=False}, if C{True}, wrap
374
+ or I{normalize} and unroll the B{C{other}} point (C{bool}).
357
375
 
358
- @return: Distance (C{meter}, same units as the axes of this
359
- point's datum ellipsoid).
376
+ @return: Distance (C{meter}, same units as the axes of this point's datum
377
+ ellipsoid).
360
378
 
361
379
  @raise TypeError: The B{C{other}} point is not C{LatLon}.
362
380
 
@@ -366,9 +384,9 @@ class LatLonBase(_NamedBase):
366
384
  L{flatLocalTo}/L{hubenyTo}, L{flatPolarTo}, L{haversineTo},
367
385
  L{thomasTo} and L{vincentysTo}.
368
386
  '''
369
- return self._distanceTo_(self._formy.cosineAndoyerLambert_, other, wrap=wrap)
387
+ return self._distanceTo_(_formy.cosineAndoyerLambert_, other, **wrap)
370
388
 
371
- def cosineForsytheAndoyerLambertTo(self, other, wrap=False):
389
+ def cosineForsytheAndoyerLambertTo(self, other, **wrap):
372
390
  '''Compute the distance between this and an other point using
373
391
  the U{Forsythe-Andoyer-Lambert correction
374
392
  <https://www2.UNB.Ca/gge/Pubs/TR77.pdf>} of the U{Law of Cosines
@@ -376,11 +394,11 @@ class LatLonBase(_NamedBase):
376
394
  formula.
377
395
 
378
396
  @arg other: The other point (C{LatLon}).
379
- @kwarg wrap: If C{True}, wrap or I{normalize} and unroll
380
- the B{C{other}} point (C{bool}).
397
+ @kwarg wrap: Optional keyword argument C{B{wrap}=False}, if C{True}, wrap
398
+ or I{normalize} and unroll the B{C{other}} point (C{bool}).
381
399
 
382
- @return: Distance (C{meter}, same units as the axes of
383
- this point's datum ellipsoid).
400
+ @return: Distance (C{meter}, same units as the axes of this point's datum
401
+ ellipsoid).
384
402
 
385
403
  @raise TypeError: The B{C{other}} point is not C{LatLon}.
386
404
 
@@ -389,20 +407,19 @@ class LatLonBase(_NamedBase):
389
407
  L{equirectangularTo}, L{euclideanTo}, L{flatLocalTo}/L{hubenyTo},
390
408
  L{flatPolarTo}, L{haversineTo}, L{thomasTo} and L{vincentysTo}.
391
409
  '''
392
- return self._distanceTo_(self._formy.cosineForsytheAndoyerLambert_, other, wrap=wrap)
410
+ return self._distanceTo_(_formy.cosineForsytheAndoyerLambert_, other, **wrap)
393
411
 
394
- def cosineLawTo(self, other, radius=None, wrap=False):
412
+ def cosineLawTo(self, other, radius=None, **wrap):
395
413
  '''Compute the distance between this and an other point using the
396
414
  U{spherical Law of Cosines
397
415
  <https://www.Movable-Type.co.UK/scripts/latlong.html#cosine-law>}
398
416
  formula.
399
417
 
400
418
  @arg other: The other point (C{LatLon}).
401
- @kwarg radius: Mean earth radius (C{meter}) or C{None}
402
- for the mean radius of this point's datum
403
- ellipsoid.
404
- @kwarg wrap: If C{True}, wrap or I{normalize} and unroll
405
- the B{C{other}} point (C{bool}).
419
+ @kwarg radius: Mean earth radius (C{meter}) or C{None} for the mean radius
420
+ of this point's datum ellipsoid.
421
+ @kwarg wrap: Optional keyword argument C{B{wrap}=False}, if C{True}, wrap
422
+ or I{normalize} and unroll the B{C{other}} point (C{bool}).
406
423
 
407
424
  @return: Distance (C{meter}, same units as B{C{radius}}).
408
425
 
@@ -413,7 +430,7 @@ class LatLonBase(_NamedBase):
413
430
  L{euclideanTo}, L{flatLocalTo}/L{hubenyTo}, L{flatPolarTo},
414
431
  L{haversineTo}, L{thomasTo} and L{vincentysTo}.
415
432
  '''
416
- return self._distanceTo(self._formy.cosineLaw, other, radius, wrap=wrap)
433
+ return self._distanceTo(_formy.cosineLaw, other, radius, **wrap)
417
434
 
418
435
  @property_RO
419
436
  def datum(self): # PYCHOK no cover
@@ -517,7 +534,7 @@ class LatLonBase(_NamedBase):
517
534
  C{euclideanTo}, L{flatLocalTo}/L{hubenyTo}, L{flatPolarTo},
518
535
  L{haversineTo}, L{thomasTo} and L{vincentysTo}.
519
536
  '''
520
- return self._distanceTo(self._formy.equirectangular, other, **radius_adjust_limit_wrap)
537
+ return self._distanceTo(_formy.equirectangular, other, **radius_adjust_limit_wrap)
521
538
 
522
539
  def euclideanTo(self, other, **radius_adjust_wrap):
523
540
  '''Approximate the C{Euclidian} distance between this and
@@ -539,20 +556,19 @@ class LatLonBase(_NamedBase):
539
556
  L{equirectangularTo}, L{flatLocalTo}/L{hubenyTo}, L{flatPolarTo},
540
557
  L{haversineTo}, L{thomasTo} and L{vincentysTo}.
541
558
  '''
542
- return self._distanceTo(self._formy.euclidean, other, **radius_adjust_wrap)
559
+ return self._distanceTo(_formy.euclidean, other, **radius_adjust_wrap)
543
560
 
544
- def flatLocalTo(self, other, radius=None, wrap=False):
561
+ def flatLocalTo(self, other, radius=None, **wrap):
545
562
  '''Compute the distance between this and an other point using the
546
563
  U{ellipsoidal Earth to plane projection
547
564
  <https://WikiPedia.org/wiki/Geographical_distance#Ellipsoidal_Earth_projected_to_a_plane>}
548
565
  aka U{Hubeny<https://www.OVG.AT/de/vgi/files/pdf/3781/>} formula.
549
566
 
550
567
  @arg other: The other point (C{LatLon}).
551
- @kwarg radius: Mean earth radius (C{meter}) or C{None} for
552
- the I{equatorial radius} of this point's
553
- datum ellipsoid.
554
- @kwarg wrap: If C{True}, wrap or I{normalize} and unroll
555
- the B{C{other}} point (C{bool}).
568
+ @kwarg radius: Mean earth radius (C{meter}) or C{None} for the I{equatorial
569
+ radius} of this point's datum ellipsoid.
570
+ @kwarg wrap: Optional keyword argument C{B{wrap}=False}, if C{True}, wrap
571
+ or I{normalize} and unroll the B{C{other}} point (C{bool}).
556
572
 
557
573
  @return: Distance (C{meter}, same units as B{C{radius}}).
558
574
 
@@ -566,8 +582,8 @@ class LatLonBase(_NamedBase):
566
582
  L{flatPolarTo}, L{haversineTo}, L{thomasTo} and L{vincentysTo} and
567
583
  U{local, flat Earth approximation<https://www.edwilliams.org/avform.htm#flat>}.
568
584
  '''
569
- return self._distanceTo_(self._formy.flatLocal_, other, wrap=wrap, radius=
570
- radius if radius in (None, R_M, _1_0, 1) else Radius(radius)) # PYCHOK kwargs
585
+ r = radius if radius in (None, R_M, _1_0, 1) else Radius(radius)
586
+ return self._distanceTo_(_formy.flatLocal_, other, radius=r, **wrap) # PYCHOK kwargs
571
587
 
572
588
  hubenyTo = flatLocalTo # for Karl Hubeny
573
589
 
@@ -591,14 +607,7 @@ class LatLonBase(_NamedBase):
591
607
  L{equirectangularTo}, L{euclideanTo}, L{flatLocalTo}/L{hubenyTo},
592
608
  L{haversineTo}, L{thomasTo} and L{vincentysTo}.
593
609
  '''
594
- return self._distanceTo(self._formy.flatPolar, other, **radius_wrap)
595
-
596
- @property_RO
597
- def _formy(self):
598
- '''(INTERNAL) Get module C{formy}, I{once}.
599
- '''
600
- LatLonBase._formy = f = _MODS.formy # overwrite property_RO
601
- return f
610
+ return self._distanceTo(_formy.flatPolar, other, **radius_wrap)
602
611
 
603
612
  def hartzell(self, los=False, earth=None):
604
613
  '''Compute the intersection of a Line-Of-Sight from this (geodetic) Point-Of-View
@@ -622,7 +631,7 @@ class LatLonBase(_NamedBase):
622
631
 
623
632
  @see: Function L{hartzell<pygeodesy.formy.hartzell>} for further details.
624
633
  '''
625
- return self._formy._hartzell(self, los, earth, LatLon=self.classof)
634
+ return _formy._hartzell(self, los, earth, LatLon=self.classof)
626
635
 
627
636
  def haversineTo(self, other, **radius_wrap):
628
637
  '''Compute the distance between this and an other point using the
@@ -644,7 +653,7 @@ class LatLonBase(_NamedBase):
644
653
  L{equirectangularTo}, L{euclideanTo}, L{flatLocalTo}/L{hubenyTo},
645
654
  L{flatPolarTo}, L{thomasTo} and L{vincentysTo}.
646
655
  '''
647
- return self._distanceTo(self._formy.haversine, other, **radius_wrap)
656
+ return self._distanceTo(_formy.haversine, other, **radius_wrap)
648
657
 
649
658
  def _havg(self, other, f=_0_5, h=None):
650
659
  '''(INTERNAL) Weighted, average height.
@@ -779,13 +788,13 @@ class LatLonBase(_NamedBase):
779
788
  tolerance, C{False} otherwise.
780
789
  '''
781
790
  p = self.others(other)
782
- return self._formy.isantipode(*(self.latlon + p.latlon), eps=eps)
791
+ return _formy.isantipode(*(self.latlon + p.latlon), eps=eps)
783
792
 
784
793
  @Property_RO
785
794
  def isEllipsoidal(self):
786
795
  '''Check whether this point is ellipsoidal (C{bool} or C{None} if unknown).
787
796
  '''
788
- return self.datum.isEllipsoidal if self._datum else None
797
+ return _xattr(self.datum, isEllipsoidal=None)
789
798
 
790
799
  def isequalTo(self, other, eps=None):
791
800
  '''Compare this point with an other point, I{ignoring} height.
@@ -804,7 +813,7 @@ class LatLonBase(_NamedBase):
804
813
 
805
814
  @see: Method L{isequalTo3}.
806
815
  '''
807
- return self._formy._isequalTo(self, self.others(other), eps=eps)
816
+ return _formy._isequalTo(self, self.others(other), eps=eps)
808
817
 
809
818
  def isequalTo3(self, other, eps=None):
810
819
  '''Compare this point with an other point, I{including} height.
@@ -822,7 +831,7 @@ class LatLonBase(_NamedBase):
822
831
  @see: Method L{isequalTo}.
823
832
  '''
824
833
  return self.height == self.others(other).height and \
825
- self._formy._isequalTo(self, other, eps=eps)
834
+ _formy._isequalTo(self, other, eps=eps)
826
835
 
827
836
  @Property_RO
828
837
  def isnormal(self):
@@ -832,13 +841,13 @@ class LatLonBase(_NamedBase):
832
841
  @see: Methods L{normal}, L{toNormal} and functions L{isnormal
833
842
  <pygeodesy.isnormal>} and L{normal<pygeodesy.normal>}.
834
843
  '''
835
- return self._formy.isnormal(self.lat, self.lon, eps=0)
844
+ return _formy.isnormal(self.lat, self.lon, eps=0)
836
845
 
837
846
  @Property_RO
838
847
  def isSpherical(self):
839
848
  '''Check whether this point is spherical (C{bool} or C{None} if unknown).
840
849
  '''
841
- return self.datum.isSpherical if self._datum else None
850
+ return _xattr(self.datum, isSpherical=None)
842
851
 
843
852
  @Property_RO
844
853
  def lam(self):
@@ -953,18 +962,11 @@ class LatLonBase(_NamedBase):
953
962
  _update_all(self)
954
963
  self._lon = lon
955
964
 
956
- @property_RO
957
- def _ltp(self):
958
- '''(INTERNAL) Get the C{.ltp} module, I{once}.
959
- '''
960
- LatLonBase._ltp = m = _MODS.ltp # overwrite property_RO
961
- return m
962
-
963
965
  @Property_RO
964
966
  def _Ltp(self):
965
967
  '''(INTERNAL) Cache for L{toLtp}.
966
968
  '''
967
- return self._ltp.Ltp(self, ecef=self.Ecef(self.datum), name=self.name)
969
+ return _MODS.ltp.Ltp(self, ecef=self.Ecef(self.datum), name=self.name)
968
970
 
969
971
  def nearestOn6(self, points, closed=False, height=None, wrap=False):
970
972
  '''Locate the point on a path or polygon closest to this point.
@@ -1007,8 +1009,8 @@ class LatLonBase(_NamedBase):
1007
1009
  C = self._toCartesianEcef # to verify datum and Ecef
1008
1010
  Ps = self.PointsIter(points, wrap=wrap)
1009
1011
 
1010
- c = C(height=height, this=self) # this Cartesian
1011
- t = nearestOn6(c, _cs(Ps, height, wrap, C), closed=closed)
1012
+ c = C(height=height, this=self) # this Cartesian
1013
+ t = _MODS.vector3d.nearestOn6(c, _cs(Ps, height, wrap, C), closed=closed)
1012
1014
  c, s, e = t.closest, t.start, t.end
1013
1015
 
1014
1016
  kwds = _xkwds_not(None, LatLon=self.classof, # this LatLon
@@ -1034,21 +1036,21 @@ class LatLonBase(_NamedBase):
1034
1036
  '''
1035
1037
  n = self.isnormal
1036
1038
  if not n:
1037
- self.latlon = self._formy.normal(*self.latlon)
1039
+ self.latlon = _formy.normal(*self.latlon)
1038
1040
  return n
1039
1041
 
1040
1042
  @property_RO
1041
1043
  def _N_vector(self):
1042
1044
  '''(INTERNAL) Get the C{Nvector} (C{nvectorBase._N_vector_})
1043
1045
  '''
1044
- x, y, z = self._n_xyz3
1045
- return _MODS.nvectorBase._N_vector_(x, y, z, h=self.height, name=self.name)
1046
+ _N = _MODS.nvectorBase._N_vector_
1047
+ return _N(*self._n_xyz3, h=self.height, name=self.name)
1046
1048
 
1047
1049
  @Property_RO
1048
1050
  def _n_xyz3(self):
1049
1051
  '''(INTERNAL) Get the n-vector components as L{Vector3Tuple}.
1050
1052
  '''
1051
- return self._formy.philam2n_xyz(self.phi, self.lam, name=self.name)
1053
+ return _formy.philam2n_xyz(self.phi, self.lam, name=self.name)
1052
1054
 
1053
1055
  @Property_RO
1054
1056
  def phi(self):
@@ -1083,9 +1085,9 @@ class LatLonBase(_NamedBase):
1083
1085
  return self.philam.to3Tuple(self.height)
1084
1086
 
1085
1087
  @deprecated_method
1086
- def points(self, points, closed=True): # PYCHOK no cover
1088
+ def points(self, points, **closed): # PYCHOK no cover
1087
1089
  '''DEPRECATED, use method L{points2}.'''
1088
- return self.points2(points, closed=closed)
1090
+ return self.points2(points, **closed)
1089
1091
 
1090
1092
  def points2(self, points, closed=True):
1091
1093
  '''Check a path or polygon represented by points.
@@ -1109,7 +1111,7 @@ class LatLonBase(_NamedBase):
1109
1111
 
1110
1112
  @arg points: The path or polygon points (C{LatLon}[])
1111
1113
  @kwarg loop: Number of loop-back points (non-negative C{int}).
1112
- @kwarg dedup: Skip duplicate points (C{bool}).
1114
+ @kwarg dedup: If C{True}, skip duplicate points (C{bool}).
1113
1115
  @kwarg wrap: If C{True}, wrap or I{normalize} the
1114
1116
  enum-/iterated B{C{points}} (C{bool}).
1115
1117
 
@@ -1117,7 +1119,8 @@ class LatLonBase(_NamedBase):
1117
1119
 
1118
1120
  @raise PointsError: Insufficient number of B{C{points}}.
1119
1121
  '''
1120
- return PointsIter(points, base=self, loop=loop, dedup=dedup, wrap=wrap)
1122
+ return _MODS.iters.PointsIter(points, base=self, loop=loop,
1123
+ dedup=dedup, wrap=wrap)
1121
1124
 
1122
1125
  def radii11(self, point2, point3, wrap=False):
1123
1126
  '''Return the radii of the C{Circum-}, C{In-}, I{Soddy} and C{Tangent}
@@ -1140,7 +1143,7 @@ class LatLonBase(_NamedBase):
1140
1143
  Circles<https://MathWorld.Wolfram.com/TangentCircles.html>}.
1141
1144
  '''
1142
1145
  with _toCartesian3(self, point2, point3, wrap) as cs:
1143
- return _radii11ABC(*cs, useZ=True)[0]
1146
+ return _MODS.vector2d._radii11ABC(*cs, useZ=True)[0]
1144
1147
 
1145
1148
  def _rhumb3(self, exact, radius): # != .sphericalBase._rhumbs3
1146
1149
  '''(INTERNAL) Get the C{rhumb} for this point's datum or for
@@ -1157,14 +1160,14 @@ class LatLonBase(_NamedBase):
1157
1160
  except AttributeError as x:
1158
1161
  raise _AttributeError(datum=D, radius=radius, cause=x)
1159
1162
  t = r, D, _MODS.karney.Caps
1160
- while d:
1161
- d.popitem()
1163
+ if len(d) > 2:
1164
+ d.clear() # d[:] = {}
1162
1165
  d[(exact, radius)] = t # cache 3-tuple
1163
1166
  return t
1164
1167
 
1165
1168
  @Property_RO
1166
- def _rhumb3dict(self): # in rhumbIntersecant2 below
1167
- return {} # single-item cache
1169
+ def _rhumb3dict(self): # in ._update
1170
+ return {} # 3-item cache
1168
1171
 
1169
1172
  def rhumbAzimuthTo(self, other, exact=False, radius=None, wrap=False, b360=False):
1170
1173
  '''Return the azimuth (bearing) of a rhumb line (loxodrome) between this
@@ -1178,9 +1181,10 @@ class LatLonBase(_NamedBase):
1178
1181
  this point's datum.
1179
1182
  @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the B{C{other}}
1180
1183
  point (C{bool}).
1181
- @kwarg b360: If C{True}, return the azimuth in the bearing range.
1184
+ @kwarg b360: If C{True}, return the azimuth as bearing in compass
1185
+ degrees (C{bool}).
1182
1186
 
1183
- @return: Rhumb azimuth (compass C{degrees180} or C{degrees360}).
1187
+ @return: Rhumb azimuth (C{degrees180} or compass C{degrees360}).
1184
1188
 
1185
1189
  @raise TypeError: The B{C{other}} point is incompatible or B{C{radius}}
1186
1190
  is invalid.
@@ -1189,19 +1193,21 @@ class LatLonBase(_NamedBase):
1189
1193
  z = r._Inverse(self, other, wrap, outmask=Cs.AZIMUTH).azi12
1190
1194
  return _umod_360(z + _360_0) if b360 else z
1191
1195
 
1192
- def rhumbDestination(self, distance, azimuth, exact=False, radius=None, height=None):
1196
+ def rhumbDestination(self, distance, azimuth, radius=None, height=None,
1197
+ exact=False, **name):
1193
1198
  '''Return the destination point having travelled the given distance from
1194
1199
  this point along a rhumb line (loxodrome) of the given azimuth.
1195
1200
 
1196
1201
  @arg distance: Distance travelled (C{meter}, same units as this point's
1197
1202
  datum (ellipsoid) axes or B{C{radius}}, may be negative.
1198
1203
  @arg azimuth: Azimuth (bearing) of the rhumb line (compass C{degrees}).
1199
- @kwarg exact: Exact C{Rhumb...} to use (C{bool} or C{Rhumb...}), see
1200
- method L{Ellipsoid.rhumb_}.
1201
1204
  @kwarg radius: Optional earth radius (C{meter}) or earth model (L{Datum},
1202
1205
  L{Ellipsoid}, L{Ellipsoid2} or L{a_f2Tuple}), overriding
1203
1206
  this point's datum.
1204
1207
  @kwarg height: Optional height, overriding the default height (C{meter}).
1208
+ @kwarg exact: Exact C{Rhumb...} to use (C{bool} or C{Rhumb...}), see
1209
+ method L{Ellipsoid.rhumb_}.
1210
+ @kwarg name: Optional C{B{name}=NN} (C{str}).
1205
1211
 
1206
1212
  @return: The destination point (ellipsoidal C{LatLon}).
1207
1213
 
@@ -1213,7 +1219,7 @@ class LatLonBase(_NamedBase):
1213
1219
  r, D, _ = self._rhumb3(exact, radius)
1214
1220
  d = r._Direct(self, azimuth, distance)
1215
1221
  h = self._heigHt(height)
1216
- return self.classof(d.lat2, d.lon2, datum=D, height=h)
1222
+ return self.classof(d.lat2, d.lon2, datum=D, height=h, **name)
1217
1223
 
1218
1224
  def rhumbDistanceTo(self, other, exact=False, radius=None, wrap=False):
1219
1225
  '''Return the distance from this to an other point along a rhumb line
@@ -1283,7 +1289,6 @@ class LatLonBase(_NamedBase):
1283
1289
 
1284
1290
  return self._intersecend2(p, other, w, height, rl.rhumb, P, Q,
1285
1291
  self.rhumbIntersecant2)
1286
-
1287
1292
  except (TypeError, ValueError) as x:
1288
1293
  raise _xError(x, center=self, circle=circle, point=point, other=other,
1289
1294
  **exact_radius_wrap_eps_tol)
@@ -1318,7 +1323,7 @@ class LatLonBase(_NamedBase):
1318
1323
  return rl
1319
1324
 
1320
1325
  def rhumbMidpointTo(self, other, exact=False, radius=None,
1321
- height=None, fraction=_0_5, wrap=False):
1326
+ height=None, fraction=_0_5, **wrap_name):
1322
1327
  '''Return the (loxodromic) midpoint on the rhumb line between this and
1323
1328
  an other point.
1324
1329
 
@@ -1332,8 +1337,9 @@ class LatLonBase(_NamedBase):
1332
1337
  @kwarg fraction: Midpoint location from this point (C{scalar}), 0 for this,
1333
1338
  1 for the B{C{other}}, 0.5 for halfway between this and
1334
1339
  the B{C{other}} point, may be negative or greater than 1.
1335
- @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the B{C{other}}
1336
- point (C{bool}).
1340
+ @kwarg wrap_name: Optional C{B{name}=NN} (C{str}) and optional keyword
1341
+ argument C{B{wrap}=False}, if C{True}, wrap or I{normalize}
1342
+ and unroll the B{C{other}} point (C{bool}).
1337
1343
 
1338
1344
  @return: The midpoint at the given B{C{fraction}} along the rhumb line
1339
1345
  (this C{LatLon}).
@@ -1343,12 +1349,13 @@ class LatLonBase(_NamedBase):
1343
1349
 
1344
1350
  @raise ValueError: Invalid B{C{height}} or B{C{fraction}}.
1345
1351
  '''
1352
+ w, n = self._wrap_name2(**wrap_name)
1346
1353
  r, D, _ = self._rhumb3(exact, radius)
1347
1354
  f = Scalar(fraction=fraction)
1348
- d = r._Inverse(self, self.others(other), wrap) # C.AZIMUTH_DISTANCE
1355
+ d = r._Inverse(self, self.others(other), w) # C.AZIMUTH_DISTANCE
1349
1356
  d = r._Direct( self, d.azi12, d.s12 * f)
1350
1357
  h = self._havg(other, f=f, h=height)
1351
- return self.classof(d.lat2, d.lon2, datum=D, height=h)
1358
+ return self.classof(d.lat2, d.lon2, datum=D, height=h, name=n)
1352
1359
 
1353
1360
  @property_RO
1354
1361
  def sphericalLatLon(self):
@@ -1356,17 +1363,16 @@ class LatLonBase(_NamedBase):
1356
1363
  '''
1357
1364
  return False
1358
1365
 
1359
- def thomasTo(self, other, wrap=False):
1360
- '''Compute the distance between this and an other point using
1361
- U{Thomas'<https://apps.DTIC.mil/dtic/tr/fulltext/u2/703541.pdf>}
1362
- formula.
1366
+ def thomasTo(self, other, **wrap):
1367
+ '''Compute the distance between this and an other point using U{Thomas'
1368
+ <https://apps.DTIC.mil/dtic/tr/fulltext/u2/703541.pdf>} formula.
1363
1369
 
1364
1370
  @arg other: The other point (C{LatLon}).
1365
- @kwarg wrap: If C{True}, wrap or I{normalize} and unroll
1366
- the B{C{other}} point (C{bool}).
1371
+ @kwarg wrap: Optional keyword argument C{B{wrap}=False}, if C{True}, wrap
1372
+ or I{normalize} and unroll the B{C{other}} point (C{bool}).
1367
1373
 
1368
- @return: Distance (C{meter}, same units as the axes of
1369
- this point's datum ellipsoid).
1374
+ @return: Distance (C{meter}, same units as the axes of this point's datum
1375
+ ellipsoid).
1370
1376
 
1371
1377
  @raise TypeError: The B{C{other}} point is not C{LatLon}.
1372
1378
 
@@ -1375,7 +1381,7 @@ class LatLonBase(_NamedBase):
1375
1381
  L{equirectangularTo}, L{euclideanTo}, L{flatLocalTo}/L{hubenyTo},
1376
1382
  L{flatPolarTo}, L{haversineTo} and L{vincentysTo}.
1377
1383
  '''
1378
- return self._distanceTo_(self._formy.thomas_, other, wrap=wrap)
1384
+ return self._distanceTo_(_formy.thomas_, other, **wrap)
1379
1385
 
1380
1386
  @deprecated_method
1381
1387
  def to2ab(self): # PYCHOK no cover
@@ -1404,7 +1410,7 @@ class LatLonBase(_NamedBase):
1404
1410
  '''
1405
1411
  r = self._ecef9 if height is None else self.toEcef(height=height)
1406
1412
  if Cartesian is not None: # class or .classof
1407
- r = Cartesian(r, **_xkwds(Cartesian_kwds, name=self.name))
1413
+ r = Cartesian(r, **self._name1__(Cartesian_kwds))
1408
1414
  _xdatum(r.datum, self.datum)
1409
1415
  return r
1410
1416
 
@@ -1452,30 +1458,28 @@ class LatLonBase(_NamedBase):
1452
1458
  def toLocal(self, Xyz=None, ltp=None, **Xyz_kwds):
1453
1459
  '''Convert this I{geodetic} point to I{local} C{X}, C{Y} and C{Z}.
1454
1460
 
1455
- @kwarg Xyz: Optional class to return C{X}, C{Y} and C{Z}
1456
- (L{XyzLocal}, L{Enu}, L{Ned}) or C{None}.
1457
- @kwarg ltp: The I{local tangent plane} (LTP) to use,
1458
- overriding this point's LTP (L{Ltp}).
1459
- @kwarg Xyz_kwds: Optional, additional B{C{Xyz}} keyword
1460
- arguments, ignored if C{B{Xyz} is None}.
1461
+ @kwarg Xyz: Optional class to return C{X}, C{Y} and C{Z} (L{XyzLocal},
1462
+ L{Enu}, L{Ned}) or C{None}.
1463
+ @kwarg ltp: The I{local tangent plane} (LTP) to use, overriding this
1464
+ point's LTP (L{Ltp}).
1465
+ @kwarg Xyz_kwds: Optional, additional B{C{Xyz}} keyword arguments,
1466
+ ignored if C{B{Xyz} is None}.
1461
1467
 
1462
- @return: An B{C{Xyz}} instance or if C{B{Xyz} is None},
1463
- a L{Local9Tuple}C{(x, y, z, lat, lon, height,
1464
- ltp, ecef, M)} with C{M=None}, always.
1468
+ @return: An B{C{Xyz}} instance or a L{Local9Tuple}C{(x, y, z, lat, lon,
1469
+ height, ltp, ecef, M)} if C{B{Xyz} is None} (with C{M=None}).
1465
1470
 
1466
1471
  @raise TypeError: Invalid B{C{ltp}}.
1467
1472
  '''
1468
- p = self._ltp._xLtp(ltp, self._Ltp)
1469
- return p._ecef2local(self._ecef9, Xyz, Xyz_kwds)
1473
+ return _MODS.ltp._toLocal(self, ltp, Xyz, Xyz_kwds) # self._ecef9
1470
1474
 
1471
- def toLtp(self, Ecef=None):
1475
+ def toLtp(self, Ecef=None, **name):
1472
1476
  '''Return the I{local tangent plane} (LTP) for this point.
1473
1477
 
1474
1478
  @kwarg Ecef: Optional ECEF I{class} (L{EcefKarney}, ...
1475
1479
  L{EcefYou}), overriding this point's C{Ecef}.
1480
+ @kwarg name: Optional C{B{name}=NN} (C{str}).
1476
1481
  '''
1477
- return self._Ltp if Ecef in (None, self.Ecef) else self._ltp.Ltp(
1478
- self, ecef=Ecef(self.datum), name=self.name)
1482
+ return _MODS.ltp._toLtp(self, Ecef, self, name) # self._Ltp
1479
1483
 
1480
1484
  def toNormal(self, deep=False, **name):
1481
1485
  '''Get this point I{normalized} to C{abs(lat) <= 90}
@@ -1497,30 +1501,34 @@ class LatLonBase(_NamedBase):
1497
1501
  ll.rename(name)
1498
1502
  return ll
1499
1503
 
1500
- def toNvector(self, h=None, Nvector=None, **Nvector_kwds):
1504
+ def toNvector(self, h=None, Nvector=None, **name_Nvector_kwds):
1501
1505
  '''Convert this point to C{n-vector} (normal to the earth's surface)
1502
1506
  components, I{including height}.
1503
1507
 
1504
1508
  @kwarg h: Optional height, overriding this point's height (C{meter}).
1505
1509
  @kwarg Nvector: Optional class to return the C{n-vector} components
1506
1510
  (C{Nvector}) or C{None}.
1507
- @kwarg Nvector_kwds: Optional, additional B{C{Nvector}} keyword
1508
- arguments, ignored if C{B{Nvector} is None}.
1511
+ @kwarg name_Nvector_kwds: Optional C{B{name}=NN} (C{str}) and optional,
1512
+ additional B{C{Nvector}} keyword arguments, ignored if
1513
+ C{B{Nvector} is None}.
1509
1514
 
1510
1515
  @return: An B{C{Nvector}} or a L{Vector4Tuple}C{(x, y, z, h)} if
1511
1516
  B{C{Nvector}} is C{None}.
1512
1517
 
1513
- @raise TypeError: Invalid B{C{h}}, B{C{Nvector}} or B{C{Nvector_kwds}}
1514
- item.
1518
+ @raise TypeError: Invalid B{C{h}}, B{C{Nvector}} or
1519
+ B{C{name_Nvector_kwds}} item.
1515
1520
 
1516
1521
  @see: Methods C{toCartesian}, C{toVector} and C{toVector3d}.
1517
1522
  '''
1518
1523
  h = self._heigHt(h)
1519
1524
  if Nvector is None:
1520
1525
  r = self._n_xyz3.to4Tuple(h)
1526
+ n, _ = _name2__(name_Nvector_kwds, _or_nameof=self)
1527
+ if n:
1528
+ r.rename(n)
1521
1529
  else:
1522
1530
  x, y, z = self._n_xyz3
1523
- r = Nvector(x, y, z, h=h, ll=self, **_xkwds(Nvector_kwds, name=self.name))
1531
+ r = Nvector(x, y, z, h=h, ll=self, **self._name1__(name_Nvector_kwds))
1524
1532
  return r
1525
1533
 
1526
1534
  def toStr(self, form=F_DMS, joined=_COMMASPACE_, m=_m_, **prec_sep_s_D_M_S): # PYCHOK expected
@@ -1561,29 +1569,29 @@ class LatLonBase(_NamedBase):
1561
1569
  @kwarg Vector_kwds: Optional, additional B{C{Vector}} keyword
1562
1570
  arguments, ignored if C{B{Vector} is None}.
1563
1571
 
1564
- @return: A B{C{Vector}} or a L{Vector3Tuple}C{(x, y, z)}
1565
- if B{C{Vector}} is C{None}.
1572
+ @return: A named B{C{Vector}} or if B{C{Vector}} is C{None} a
1573
+ named L{Vector3Tuple}C{(x, y, z)}.
1566
1574
 
1567
1575
  @raise TypeError: Invalid B{C{Vector}} or B{C{Vector_kwds}} item.
1568
1576
 
1569
1577
  @see: Methods C{toCartesian}, C{toNvector} and C{toVector3d}.
1570
1578
  '''
1571
- return self._ecef9.toVector(Vector=Vector, **Vector_kwds)
1579
+ return self._ecef9.toVector(Vector=Vector, **self._name1__(Vector_kwds))
1572
1580
 
1573
1581
  def toVector3d(self, norm=True, **Vector3d_kwds):
1574
- '''Convert this point to a L{Vector3d} with the I{geocentric} C{(x,
1575
- y, z)} (ECEF) I{unit} coordinates, I{ignoring height}.
1582
+ '''Convert this point to a L{Vector3d} with the I{geocentric} C{(x, y,
1583
+ z)} (ECEF) coordinates, I{ignoring height}.
1576
1584
 
1577
- @kwarg norm: Normalize the 3-D vector (C{bool}).
1585
+ @kwarg norm: If C{False}, don't normalize the coordinates (C{bool}).
1578
1586
  @kwarg Vector3d_kwds: Optional L{Vector3d} keyword arguments.
1579
1587
 
1580
- @return: Unit vector (L{Vector3d}).
1588
+ @return: Named, unit vector or vector (L{Vector3d}).
1581
1589
 
1582
1590
  @raise TypeError: Invalid B{C{Vector3d_kwds}} item.
1583
1591
 
1584
1592
  @see: Methods C{toCartesian}, C{toNvector} and C{toVector}.
1585
1593
  '''
1586
- r = self.toVector(Vector=Vector3d, **Vector3d_kwds)
1594
+ r = self.toVector(Vector=_MODS.vector3d.Vector3d, **Vector3d_kwds)
1587
1595
  if norm:
1588
1596
  r = r.unit(ll=self)
1589
1597
  return r
@@ -1597,8 +1605,7 @@ class LatLonBase(_NamedBase):
1597
1605
 
1598
1606
  @see: Function L{pygeodesy.toWm}.
1599
1607
  '''
1600
- return self._wm if not toWm_kwds else _MODS.webmercator.toWm(
1601
- self, **_xkwds(toWm_kwds, name=self.name))
1608
+ return _MODS.webmercator.toWm(self, **self._name1__(toWm_kwds))
1602
1609
 
1603
1610
  @deprecated_method
1604
1611
  def to3xyz(self): # PYCHOK no cover
@@ -1606,6 +1613,13 @@ class LatLonBase(_NamedBase):
1606
1613
  L{toVector3d} or perhaps (geocentric) L{toEcef}.'''
1607
1614
  return self.xyz # self.toVector()
1608
1615
 
1616
+ # def _update(self, updated, *attrs, **setters):
1617
+ # '''(INTERNAL) See C{_NamedBase._update}.
1618
+ # '''
1619
+ # if updated:
1620
+ # self._rhumb3dict.clear()
1621
+ # return _NamedBase._update(self, updated, *attrs, **setters)
1622
+
1609
1623
  def vincentysTo(self, other, **radius_wrap):
1610
1624
  '''Compute the distance between this and an other point using
1611
1625
  U{Vincenty's<https://WikiPedia.org/wiki/Great-circle_distance>}
@@ -1626,13 +1640,12 @@ class LatLonBase(_NamedBase):
1626
1640
  L{equirectangularTo}, L{euclideanTo}, L{flatLocalTo}/L{hubenyTo},
1627
1641
  L{flatPolarTo}, L{haversineTo} and L{thomasTo}.
1628
1642
  '''
1629
- return self._distanceTo(self._formy.vincentys, other, **_xkwds(radius_wrap, radius=None))
1643
+ return self._distanceTo(_formy.vincentys, other, **_xkwds(radius_wrap, radius=None))
1630
1644
 
1631
- @Property_RO
1632
- def _wm(self):
1633
- '''(INTERNAL) Get this point as webmercator (L{Wm}).
1645
+ def _wrap_name2(self, wrap=False, **name):
1646
+ '''(INTERNAL) Return the C{wrap} and C{name} value.
1634
1647
  '''
1635
- return _MODS.webmercator.toWm(self)
1648
+ return wrap, (self._name__(name) if name else NN)
1636
1649
 
1637
1650
  @property_RO
1638
1651
  def xyz(self):