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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. {PyGeodesy-24.6.9.dist-info → PyGeodesy-24.7.7.dist-info}/METADATA +2 -2
  2. PyGeodesy-24.7.7.dist-info/RECORD +117 -0
  3. pygeodesy/__init__.py +39 -32
  4. pygeodesy/__main__.py +6 -1
  5. pygeodesy/albers.py +2 -2
  6. pygeodesy/auxilats/__init__.py +1 -1
  7. pygeodesy/auxilats/auxAngle.py +40 -39
  8. pygeodesy/auxilats/auxDLat.py +3 -2
  9. pygeodesy/auxilats/auxLat.py +16 -18
  10. pygeodesy/auxilats/auxily.py +1 -1
  11. pygeodesy/azimuthal.py +10 -10
  12. pygeodesy/basics.py +16 -4
  13. pygeodesy/booleans.py +4 -4
  14. pygeodesy/cartesianBase.py +11 -14
  15. pygeodesy/css.py +14 -18
  16. pygeodesy/datums.py +6 -6
  17. pygeodesy/deprecated/__init__.py +1 -1
  18. pygeodesy/deprecated/classes.py +25 -4
  19. pygeodesy/deprecated/datum.py +3 -3
  20. pygeodesy/deprecated/functions.py +6 -8
  21. pygeodesy/dms.py +23 -27
  22. pygeodesy/ecef.py +4 -4
  23. pygeodesy/elevations.py +4 -4
  24. pygeodesy/ellipsoidalBase.py +23 -28
  25. pygeodesy/ellipsoidalBaseDI.py +19 -23
  26. pygeodesy/ellipsoidalExact.py +3 -3
  27. pygeodesy/ellipsoidalGeodSolve.py +15 -23
  28. pygeodesy/ellipsoidalKarney.py +37 -60
  29. pygeodesy/ellipsoidalNvector.py +38 -44
  30. pygeodesy/ellipsoidalVincenty.py +11 -14
  31. pygeodesy/ellipsoids.py +107 -101
  32. pygeodesy/errors.py +109 -48
  33. pygeodesy/etm.py +32 -44
  34. pygeodesy/formy.py +55 -58
  35. pygeodesy/frechet.py +18 -20
  36. pygeodesy/fsums.py +3 -3
  37. pygeodesy/gars.py +3 -4
  38. pygeodesy/geodesici.py +1696 -0
  39. pygeodesy/geodesicw.py +15 -15
  40. pygeodesy/geodesicx/__init__.py +4 -4
  41. pygeodesy/geodesicx/gx.py +34 -55
  42. pygeodesy/geodesicx/gxbases.py +20 -8
  43. pygeodesy/geodesicx/gxline.py +93 -88
  44. pygeodesy/geodsolve.py +108 -59
  45. pygeodesy/geohash.py +26 -34
  46. pygeodesy/geoids.py +28 -37
  47. pygeodesy/hausdorff.py +17 -18
  48. pygeodesy/heights.py +2 -2
  49. pygeodesy/internals.py +46 -13
  50. pygeodesy/interns.py +2 -2
  51. pygeodesy/karney.py +78 -15
  52. pygeodesy/ktm.py +13 -16
  53. pygeodesy/latlonBase.py +17 -19
  54. pygeodesy/lazily.py +28 -25
  55. pygeodesy/lcc.py +28 -31
  56. pygeodesy/ltp.py +7 -8
  57. pygeodesy/ltpTuples.py +71 -73
  58. pygeodesy/mgrs.py +8 -9
  59. pygeodesy/named.py +19 -10
  60. pygeodesy/nvectorBase.py +9 -10
  61. pygeodesy/osgr.py +9 -9
  62. pygeodesy/points.py +6 -6
  63. pygeodesy/rhumb/__init__.py +1 -1
  64. pygeodesy/rhumb/aux_.py +5 -5
  65. pygeodesy/rhumb/bases.py +30 -31
  66. pygeodesy/rhumb/ekx.py +3 -4
  67. pygeodesy/rhumb/solve.py +21 -22
  68. pygeodesy/solveBase.py +177 -123
  69. pygeodesy/sphericalBase.py +10 -11
  70. pygeodesy/sphericalNvector.py +13 -13
  71. pygeodesy/sphericalTrigonometry.py +86 -97
  72. pygeodesy/streprs.py +4 -34
  73. pygeodesy/triaxials.py +48 -43
  74. pygeodesy/units.py +208 -275
  75. pygeodesy/unitsBase.py +115 -107
  76. pygeodesy/ups.py +26 -31
  77. pygeodesy/utily.py +8 -8
  78. pygeodesy/utm.py +35 -40
  79. pygeodesy/utmups.py +43 -46
  80. pygeodesy/utmupsBase.py +8 -9
  81. pygeodesy/vector3d.py +26 -27
  82. pygeodesy/vector3dBase.py +6 -7
  83. pygeodesy/webmercator.py +19 -21
  84. pygeodesy/wgrs.py +18 -20
  85. PyGeodesy-24.6.9.dist-info/RECORD +0 -116
  86. {PyGeodesy-24.6.9.dist-info → PyGeodesy-24.7.7.dist-info}/WHEEL +0 -0
  87. {PyGeodesy-24.6.9.dist-info → PyGeodesy-24.7.7.dist-info}/top_level.txt +0 -0
pygeodesy/solveBase.py CHANGED
@@ -4,11 +4,12 @@
4
4
  u'''(INTERNAL) Private base classes for L{pygeodesy.geodsolve} and L{pygeodesy.rhumb.solve}.
5
5
  '''
6
6
 
7
- from pygeodesy.basics import map2, ub2str, _zip
7
+ from pygeodesy.basics import clips, map2, ub2str, _zip
8
8
  from pygeodesy.constants import DIG
9
9
  from pygeodesy.datums import _earth_datum, _WGS84, _EWGS84
10
10
  # from pygeodesy.ellipsoids import _EWGS84 # from .datums
11
- from pygeodesy.errors import _AssertionError, _xkwds_get1, _xkwds_item2
11
+ from pygeodesy.errors import _AssertionError, _xkwds_get, _xkwds_get1, \
12
+ _xkwds_item2
12
13
  from pygeodesy.internals import _enquote, printf
13
14
  from pygeodesy.interns import NN, _0_, _BACKSLASH_, _COMMASPACE_, \
14
15
  _EQUAL_, _Error_, _SPACE_, _UNUSED_
@@ -23,7 +24,7 @@ from pygeodesy.utily import unroll180, wrap360 # PYCHOK shared
23
24
  from subprocess import PIPE as _PIPE, Popen as _Popen, STDOUT as _STDOUT
24
25
 
25
26
  __all__ = _ALL_LAZY.solveBase
26
- __version__ = '24.06.05'
27
+ __version__ = '24.07.08'
27
28
 
28
29
  _ERROR_ = 'ERROR'
29
30
  _Popen_kwds = dict(creationflags=0,
@@ -43,36 +44,95 @@ def _cmd_stdin_(cmd, stdin): # PYCHOK no cover
43
44
  return _SPACE_.join(cmd)
44
45
 
45
46
 
47
+ # def _float_int(r):
48
+ # '''(INTERNAL) Convert result into C{float} or C{int}.
49
+ # '''
50
+ # f = float(r)
51
+ # i = int(f)
52
+ # return i if float(i) == f else f # PYCHOK inconsistent
53
+
54
+
46
55
  def _popen2(cmd, stdin=None): # in .mgrs, test.bases, .testMgrs
47
56
  '''(INTERNAL) Invoke C{B{cmd} tuple} and return C{exitcode}
48
- and all output to C{stdout/-err}.
57
+ and all output from C{stdout/-err}.
49
58
  '''
50
59
  p = _Popen(cmd, **_Popen_kwds) # PYCHOK kwArgs
51
- r = p.communicate(stdin)[0]
60
+ r = p.communicate(stdin)[0] # stdout + NL + stderr
52
61
  return p.returncode, ub2str(r).strip()
53
62
 
54
63
 
55
64
  class _SolveCapsBase(_CapsBase):
56
65
  '''(NTERNAL) Base class for C{_SolveBase} and C{_LineSolveBase}.
57
66
  '''
58
- _Error = None
59
- _Exact = True
60
- _invokation = 0
61
- _Names_Direct = \
62
- _Names_Inverse = ()
63
- _prec = Precision_(prec=DIG)
64
- _reverse2 = False
65
- _Solve_name = NN # executable basename
66
- _Solve_path = NN # executable path
67
- _status = None
68
- _unroll = False
69
- _verbose = False
67
+ _datum = _WGS84
68
+ _Error = None
69
+ _Exact = True
70
+ _invokation = 0
71
+ _linelimit = 0
72
+ _prec = Precision_(prec=DIG)
73
+ _prec2stdin = DIG
74
+ _Xable_name = NN # executable basename
75
+ _Xable_path = NN # executable path
76
+ _status = None
77
+ _verbose = False
78
+
79
+ @Property_RO
80
+ def a(self):
81
+ '''Get the I{equatorial} radius, semi-axis (C{meter}).
82
+ '''
83
+ return self.ellipsoid.a
70
84
 
71
85
  @property_RO
72
86
  def _cmdBasic(self): # PYCHOK no cover
73
87
  '''(INTERNAL) I{Must be overloaded}.'''
74
88
  notOverloaded(self, underOK=True)
75
89
 
90
+ @property_RO
91
+ def datum(self):
92
+ '''Get the datum (C{Datum}).
93
+ '''
94
+ return self._datum
95
+
96
+ def _Dict(self, Dict, n, v, floats=True, **unused):
97
+ if self.verbose: # PYCHOK no cover
98
+ self._print(_COMMASPACE_.join(map(Fmt.EQUAL, n, map(fstrzs, v))))
99
+ if floats:
100
+ v = map(float, v) # _float_int, see Intersectool._XDistInvoke
101
+ return Dict(_zip(n, v)) # strict=True
102
+
103
+ def _DictInvoke2(self, cmd, Names, Dict, args, **floats_R):
104
+ '''(INTERNAL) Invoke C{Solve}, return results as C{Dict}.
105
+ '''
106
+ N = len(Names)
107
+ if N < 1:
108
+ raise _AssertionError(cmd=cmd, Names=Names)
109
+ i = fstr(args, prec=self._prec2stdin, fmt=Fmt.F, sep=_SPACE_) if args else None # NOT Fmt.G!
110
+ t = self._invoke(cmd, stdin=i, **floats_R).lstrip().split() # 12-/++ tuple
111
+ if _xkwds_get(floats_R, _R=None): # == '-R' in cmd
112
+ return self._Dicts(Dict, Names, t, **floats_R), True
113
+ elif len(t) > N: # PYCHOK no cover
114
+ # unzip instrumented name=value pairs to names and values
115
+ n, v = _zip(*(p.split(_EQUAL_) for p in t[:-N])) # strict=True
116
+ v += tuple(t[-N:])
117
+ n += Names
118
+ else:
119
+ n, v = Names, t
120
+ r = self._Dict(Dict, n, t, **floats_R)
121
+ return self._iter2tion(r, **r), None
122
+
123
+ def _Dicts(self, Dict, Names, t, **floats_R):
124
+ i, N = 0, len(Names)
125
+ for x in range(0, len(t), N):
126
+ if t[x] == 'nan':
127
+ break
128
+ X = self._Dict(Dict, Names, t[x:x + N], **floats_R)
129
+ yield X.set_(iteration=i)
130
+ i += 1
131
+
132
+ @Property_RO
133
+ def _E_option(self):
134
+ return ('-E',) if self.Exact else ()
135
+
76
136
  @property
77
137
  def Exact(self):
78
138
  '''Get the Solve's C{exact} setting (C{bool}).
@@ -89,27 +149,28 @@ class _SolveCapsBase(_CapsBase):
89
149
  _update_all(self)
90
150
  self._Exact = Exact
91
151
 
92
- def _GDictInvoke(self, cmd, floats, Names, *args):
93
- '''(INTERNAL) Invoke C{Solve}, return results as C{GDict}.
152
+ @Property_RO
153
+ def ellipsoid(self):
154
+ '''Get the ellipsoid (C{Ellipsoid}).
94
155
  '''
95
- N = len(Names)
96
- if N < 1:
97
- raise _AssertionError(cmd=cmd, Names=Names)
98
- i = fstr(args, prec=DIG, fmt=Fmt.F, sep=_SPACE_) if args else None # not Fmt.G!
99
- t = self._invoke(cmd, stdin=i).lstrip().split() # 12-/+ tuple
100
- if len(t) > N: # PYCHOK no cover
101
- # unzip instrumented name=value pairs to names and values
102
- n, v = _zip(*(p.split(_EQUAL_) for p in t[:-N])) # strict=True
103
- v += tuple(t[-N:])
104
- n += Names
105
- else:
106
- n, v = Names, t
107
- if self.verbose: # PYCHOK no cover
108
- self._print(_COMMASPACE_.join(map(Fmt.EQUAL, n, map(fstrzs, v))))
109
- if floats:
110
- v = map(float, v)
111
- r = GDict(_zip(n, v)) # strict=True
112
- return self._iter2tion(r, **r)
156
+ return self.datum.ellipsoid
157
+
158
+ @Property_RO
159
+ def _e_option(self):
160
+ E = self.ellipsoid
161
+ if E is _EWGS84:
162
+ return () # default
163
+ a, f = strs(E.a_f, fmt=Fmt.F, prec=DIG + 3) # not .G!
164
+ return ('-e', a, f)
165
+
166
+ @Property_RO
167
+ def flattening(self):
168
+ '''Get the C{ellipsoid}'s I{flattening} (C{scalar}), M{(a - b) / a},
169
+ C{0} for spherical, negative for prolate.
170
+ '''
171
+ return self.ellipsoid.f
172
+
173
+ f = flattening
113
174
 
114
175
  @property_RO
115
176
  def invokation(self):
@@ -134,7 +195,7 @@ class _SolveCapsBase(_CapsBase):
134
195
 
135
196
  @note: The C{Solve} return code is in property L{status}.
136
197
  '''
137
- c = (self._Solve_path,) + map2(str, options) # map2(_enquote, options)
198
+ c = (self._Xable_path,) + map2(str, options) # map2(_enquote, options)
138
199
  i = _xkwds_get1(stdin, stdin=None)
139
200
  r = self._invoke(c, stdin=i)
140
201
  s = self.status
@@ -145,7 +206,7 @@ class _SolveCapsBase(_CapsBase):
145
206
  self._print(r)
146
207
  return r
147
208
 
148
- def _invoke(self, cmd, stdin=None):
209
+ def _invoke(self, cmd, stdin=None, **unused): # _R=None
149
210
  '''(INTERNAL) Invoke the C{Solve} executable, with the
150
211
  given B{C{cmd}} line and optional input to B{C{stdin}}.
151
212
  '''
@@ -161,8 +222,24 @@ class _SolveCapsBase(_CapsBase):
161
222
  except (IOError, OSError, TypeError, ValueError) as x:
162
223
  raise self._Error(cmd=t or _cmd_stdin_(cmd, stdin), cause=x)
163
224
  self._status = s
225
+ if self.verbose: # and _R is None: # PYCHOK no cover
226
+ self._print(repr(r))
164
227
  return r
165
228
 
229
+ def linelimit(self, *limit):
230
+ '''Set and get the print line length limit.
231
+
232
+ @arg limit: New line limit (C{int}) or C{0}
233
+ or C{None} for unlimited.
234
+
235
+ @return: Teh previous limit (C{int}).
236
+ '''
237
+ n = self._linelimit
238
+ if limit:
239
+ m = int(limit[0] or 0)
240
+ self._linelimit = max(80, m) if m > 0 else (n if m < 0 else 0)
241
+ return n
242
+
166
243
  @Property_RO
167
244
  def _mpd(self): # meter per degree
168
245
  return self.ellipsoid._Lpd
@@ -194,42 +271,29 @@ class _SolveCapsBase(_CapsBase):
194
271
  def _print(self, line): # PYCHOK no cover
195
272
  '''(INTERNAL) Print a status line.
196
273
  '''
274
+ if self._linelimit:
275
+ line = clips(line, limit=self._linelimit, length=True)
197
276
  if self.status is not None:
198
277
  line = _SPACE_(line, Fmt.PAREN(self.status))
199
- printf('%s %d: %s', self.named2, self.invokation, line)
200
-
201
- @Property
202
- def reverse2(self):
203
- '''Get the C{azi2} direction (C{bool}).
204
- '''
205
- return self._reverse2
278
+ printf('%s@%d: %s', self.named2, self.invokation, line)
206
279
 
207
- @reverse2.setter # PYCHOK setter!
208
- def reverse2(self, reverse2):
209
- '''Set the direction for C{azi2} (C{bool}), if C{True} reverse C{azi2}.
210
- '''
211
- reverse2 = bool(reverse2)
212
- if self._reverse2 != reverse2:
213
- _update_all(self)
214
- self._reverse2 = reverse2
215
-
216
- def _setSolve(self, path, **Solve_path):
280
+ def _setXable(self, path, **Xable_path):
217
281
  '''(INTERNAL) Set the executable C{path}.
218
282
  '''
219
- hold = self._Solve_path
283
+ hold = self._Xable_path
220
284
  if hold != path:
221
285
  _update_all(self)
222
- self._Solve_path = path
286
+ self._Xable_path = path
223
287
  try:
224
288
  _ = self.version # test path and ...
225
289
  if self.status: # ... return code
226
- S_p = Solve_path or {self._Solve_name: _enquote(path)}
290
+ S_p = Xable_path or {self._Xable_name: _enquote(path)}
227
291
  raise self._Error(status=self.status, txt_not_=_0_, **S_p)
228
292
  hold = path
229
293
  finally: # restore in case of error
230
- if self._Solve_path != hold:
294
+ if self._Xable_path != hold:
231
295
  _update_all(self)
232
- self._Solve_path = hold
296
+ self._Xable_path = hold
233
297
 
234
298
  @property_RO
235
299
  def status(self):
@@ -238,21 +302,6 @@ class _SolveCapsBase(_CapsBase):
238
302
  '''
239
303
  return self._status
240
304
 
241
- @Property
242
- def unroll(self):
243
- '''Get the C{lon2} unroll'ing (C{bool}).
244
- '''
245
- return self._unroll
246
-
247
- @unroll.setter # PYCHOK setter!
248
- def unroll(self, unroll):
249
- '''Set unroll'ing for C{lon2} (C{bool}), if C{True} unroll C{lon2}, otherwise don't.
250
- '''
251
- unroll = bool(unroll)
252
- if self._unroll != unroll:
253
- _update_all(self)
254
- self._unroll = unroll
255
-
256
305
  @property
257
306
  def verbose(self):
258
307
  '''Get the C{verbose} option (C{bool}).
@@ -274,9 +323,47 @@ class _SolveCapsBase(_CapsBase):
274
323
 
275
324
 
276
325
  class _SolveBase(_SolveCapsBase):
326
+ '''(INTERNAL) Base class for C{_SolveBase} and C{_SolveLineBase}.
327
+ '''
328
+ _Names_Direct = \
329
+ _Names_Inverse = ()
330
+ _reverse2 = False
331
+ _unroll = False
332
+
333
+ @Property
334
+ def reverse2(self):
335
+ '''Get the C{azi2} direction (C{bool}).
336
+ '''
337
+ return self._reverse2
338
+
339
+ @reverse2.setter # PYCHOK setter!
340
+ def reverse2(self, reverse2):
341
+ '''Set the direction for C{azi2} (C{bool}), if C{True} reverse C{azi2}.
342
+ '''
343
+ reverse2 = bool(reverse2)
344
+ if self._reverse2 != reverse2:
345
+ _update_all(self)
346
+ self._reverse2 = reverse2
347
+
348
+ @Property
349
+ def unroll(self):
350
+ '''Get the C{lon2} unroll'ing (C{bool}).
351
+ '''
352
+ return self._unroll
353
+
354
+ @unroll.setter # PYCHOK setter!
355
+ def unroll(self, unroll):
356
+ '''Set unroll'ing for C{lon2} (C{bool}), if C{True} unroll C{lon2}, otherwise don't.
357
+ '''
358
+ unroll = bool(unroll)
359
+ if self._unroll != unroll:
360
+ _update_all(self)
361
+ self._unroll = unroll
362
+
363
+
364
+ class _SolveGDictBase(_SolveBase):
277
365
  '''(NTERNAL) Base class for C{_GeodesicSolveBase} and C{_RhumbSolveBase}.
278
366
  '''
279
- _datum = _WGS84
280
367
 
281
368
  def __init__(self, a_ellipsoid=_EWGS84, f=None, path=NN, **name):
282
369
  '''New C{Solve} instance.
@@ -296,13 +383,7 @@ class _SolveBase(_SolveCapsBase):
296
383
  if name:
297
384
  self.name = name
298
385
  if path:
299
- self._setSolve(path)
300
-
301
- @Property_RO
302
- def a(self):
303
- '''Get the I{equatorial} radius, semi-axis (C{meter}).
304
- '''
305
- return self.ellipsoid.a
386
+ self._setXable(path)
306
387
 
307
388
  @Property_RO
308
389
  def _cmdDirect(self):
@@ -316,56 +397,29 @@ class _SolveBase(_SolveCapsBase):
316
397
  '''
317
398
  return self._cmdBasic + ('-i',)
318
399
 
319
- @property_RO
320
- def datum(self):
321
- '''Get the datum (C{Datum}).
322
- '''
323
- return self._datum
324
-
325
400
  def Direct(self, lat1, lon1, azi1, s12, outmask=_UNUSED_): # PYCHOK unused
326
401
  '''Return the C{Direct} result.
327
402
  '''
328
403
  return self._GDictDirect(lat1, lon1, azi1, False, s12)
329
404
 
330
- @Property_RO
331
- def ellipsoid(self):
332
- '''Get the ellipsoid (C{Ellipsoid}).
333
- '''
334
- return self.datum.ellipsoid
335
-
336
- @Property_RO
337
- def _e_option(self):
338
- E = self.ellipsoid
339
- if E is _EWGS84:
340
- return () # default
341
- a, f = strs(E.a_f, fmt=Fmt.F, prec=DIG + 3) # not .G!
342
- return ('-e', a, f)
343
-
344
- @Property_RO
345
- def flattening(self):
346
- '''Get the C{ellipsoid}'s I{flattening} (C{scalar}), M{(a - b) / a},
347
- C{0} for spherical, negative for prolate.
348
- '''
349
- return self.ellipsoid.f
350
-
351
- f = flattening
352
-
353
405
  def _GDictDirect(self, lat, lon, azi, arcmode, s12_a12, outmask=_UNUSED_, **floats): # PYCHOK for .geodesicx.gxarea
354
406
  '''(INTERNAL) Get C{_GenDirect}-like result as C{GDict}.
355
407
  '''
356
408
  if arcmode:
357
409
  raise self._Error(arcmode=arcmode, txt=str(NotImplemented))
358
- floats = _xkwds_get1(floats, floats=True)
359
- return self._GDictInvoke(self._cmdDirect, floats, self._Names_Direct,
360
- lat, lon, azi, s12_a12)
410
+ return self._GDictInvoke(self._cmdDirect, self._Names_Direct,
411
+ lat, lon, azi, s12_a12, **floats)
361
412
 
362
413
  def _GDictInverse(self, lat1, lon1, lat2, lon2, outmask=_UNUSED_, **floats): # PYCHOK for .geodesicx.gxarea
363
- '''(INTERNAL) Get C{_GenInverse}-like result as C{GDict}, but
364
- I{without} C{_SALPs_CALPs_}.
414
+ '''(INTERNAL) Get C{_GenInverse}-like result as C{GDict}, but I{without} C{_S_CALPs_}.
415
+ '''
416
+ return self._GDictInvoke(self._cmdInverse, self._Names_Inverse,
417
+ lat1, lon1, lat2, lon2, **floats)
418
+
419
+ def _GDictInvoke(self, cmd, Names, *args, **floats):
420
+ '''(INTERNAL) Invoke C{Solve}, return results as C{Dict}.
365
421
  '''
366
- floats = _xkwds_get1(floats, floats=True)
367
- return self._GDictInvoke(self._cmdInverse, floats, self._Names_Inverse,
368
- lat1, lon1, lat2, lon2)
422
+ return self._DictInvoke2(cmd, Names, GDict, args, **floats)[0] # _R
369
423
 
370
424
  def Inverse(self, lat1, lon1, lat2, lon2, outmask=_UNUSED_): # PYCHOK unused
371
425
  '''Return the C{Inverse} result.
@@ -390,7 +444,7 @@ class _SolveBase(_SolveCapsBase):
390
444
  return sep.join(pairs(d, prec=prec))
391
445
 
392
446
 
393
- class _SolveLineBase(_SolveCapsBase):
447
+ class _SolveGDictLineBase(_SolveGDictBase):
394
448
  '''(NTERNAL) Base class for C{GeodesicLineSolve} and C{RhumbLineSolve}.
395
449
  '''
396
450
  # _caps = 0
@@ -451,7 +505,7 @@ class _SolveLineBase(_SolveCapsBase):
451
505
  return sep.join(pairs(d, prec=prec))
452
506
 
453
507
 
454
- __all__ += _ALL_DOCS(_SolveBase, _SolveLineBase, _SolveCapsBase)
508
+ __all__ += _ALL_DOCS(_SolveBase, _SolveCapsBase, _SolveGDictBase, _SolveGDictLineBase)
455
509
 
456
510
  # **) MIT License
457
511
  #
@@ -19,7 +19,7 @@ from pygeodesy.constants import EPS, EPS0, PI, PI2, PI_2, R_M, \
19
19
  _over, isnear0, isnon0
20
20
  from pygeodesy.datums import Datums, _earth_ellipsoid, _spherical_datum
21
21
  from pygeodesy.errors import IntersectionError, _ValueError, \
22
- _xattr, _xError
22
+ _xattr, _xattrs, _xError
23
23
  from pygeodesy.fmath import favg, fdot, hypot, sqrt_a
24
24
  from pygeodesy.interns import _COMMA_, _concentric_, _datum_, _distant_, \
25
25
  _exceed_PI_radians_, _name_, _near_, \
@@ -27,10 +27,10 @@ from pygeodesy.interns import _COMMA_, _concentric_, _datum_, _distant_, \
27
27
  from pygeodesy.latlonBase import LatLonBase, _trilaterate5 # PYCHOK passed
28
28
  from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS
29
29
  # from pygeodesy.namedTuples import Bearing2Tuple # from .cartesianBase
30
- from pygeodesy.nvectorBase import NvectorBase, Fmt, _xattrs
30
+ from pygeodesy.nvectorBase import NvectorBase, Fmt
31
31
  from pygeodesy.props import deprecated_method, property_doc_, property_RO, \
32
32
  _update_all
33
- # from pygeodesy.streprs import Fmt, _xattrs # from .nvectorBase
33
+ # from pygeodesy.streprs import Fmt # from .nvectorBase
34
34
  from pygeodesy.units import Bearing, Bearing_, _isRadius, Radians_, Radius, \
35
35
  Radius_, Scalar_, _100km
36
36
  from pygeodesy.utily import acos1, asin1, atan2b, atan2d, degrees90, \
@@ -40,7 +40,7 @@ from pygeodesy.utily import acos1, asin1, atan2b, atan2d, degrees90, \
40
40
  from math import cos, fabs, log, sin, sqrt
41
41
 
42
42
  __all__ = _ALL_LAZY.sphericalBase
43
- __version__ = '24.06.06'
43
+ __version__ = '24.06.12'
44
44
 
45
45
 
46
46
  class CartesianSphericalBase(CartesianBase):
@@ -443,8 +443,8 @@ class LatLonSphericalBase(LatLonBase):
443
443
  @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the
444
444
  B{C{other}} point (C{bool}).
445
445
 
446
- @return: Distance (C{meter}, the same units as B{C{radius}}
447
- or C{radians} if B{C{radius}} is C{None}).
446
+ @return: Distance (C{meter}, the same units as B{C{radius}} or
447
+ C{radians} if C{B{radius} is None}).
448
448
 
449
449
  @raise TypeError: The B{C{other}} point is incompatible.
450
450
 
@@ -576,12 +576,11 @@ class LatLonSphericalBase(LatLonBase):
576
576
  '''Convert this point to C{Nvector} components, I{including
577
577
  height}.
578
578
 
579
- @kwarg Nvector_kwds: Optional, additional B{C{Nvector}}
580
- keyword arguments, ignored if
581
- C{B{Nvector} is None}.
579
+ @kwarg Nvector_kwds: Optional, additional B{C{Nvector}} keyword
580
+ arguments, ignored if C{B{Nvector} is None}.
582
581
 
583
- @return: An B{C{Nvector}} or a L{Vector4Tuple}C{(x, y, z, h)}
584
- if B{C{Nvector}} is C{None}.
582
+ @return: An B{C{Nvector}} or a L{Vector4Tuple}C{(x, y, z, h)} if
583
+ B{C{Nvector} is None}.
585
584
 
586
585
  @raise TypeError: Invalid B{C{Nvector}} or B{C{Nvector_kwds}}.
587
586
  '''
@@ -61,7 +61,7 @@ from pygeodesy.utily import atan2, degrees360, fabs, sincos2, sincos2_, \
61
61
  # from math import atan2, fabs # from utily
62
62
 
63
63
  __all__ = _ALL_LAZY.sphericalNvector
64
- __version__ = '24.04.07'
64
+ __version__ = '24.06.11'
65
65
 
66
66
  _lines_ = 'lines'
67
67
 
@@ -226,7 +226,7 @@ class LatLon(LatLonNvectorBase, LatLonSphericalBase):
226
226
 
227
227
  @return: Distance between this and the B{C{other}} point
228
228
  (C{meter}, same units as B{C{radius}} or C{radians}
229
- if B{C{radius}} is C{None}).
229
+ if C{B{radius} is None}).
230
230
 
231
231
  @raise TypeError: Invalid B{C{other}} point.
232
232
  '''
@@ -303,14 +303,14 @@ class LatLon(LatLonNvectorBase, LatLonSphericalBase):
303
303
  to an other point.
304
304
 
305
305
  @arg other: The other point (L{LatLon}).
306
- @kwarg wrap: If C{True}, wrap or I{normalize} and unroll
307
- the B{C{other}} point (C{bool}).
306
+ @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the
307
+ B{C{other}} point (C{bool}).
308
308
 
309
309
  @return: Initial bearing (compass C{degrees360}).
310
310
 
311
311
  @raise Crosserror: This point coincides with the B{C{other}}
312
- point or the C{NorthPole}, provided
313
- L{pygeodesy.crosserrors} is C{True}.
312
+ point or the C{NorthPole} and L{crosserrors
313
+ <pygeodesy.crosserrors>} is C{True}.
314
314
 
315
315
  @raise TypeError: The B{C{other}} point is not L{LatLon}.
316
316
  '''
@@ -660,8 +660,8 @@ class LatLon(LatLonNvectorBase, LatLonSphericalBase):
660
660
  the C{closest} point (L{LatLon}), the C{distance}
661
661
  between this and the C{closest} point in C{meter},
662
662
  same units as B{C{radius}} or in C{radians} if
663
- B{C{radius}} is C{None} and the C{angle} from this
664
- to the C{closest} point in compass C{degrees360}.
663
+ C{B{radius} is None} and the C{angle} from this to
664
+ the C{closest} point in compass C{degrees360}.
665
665
 
666
666
  @raise TypeError: Some B{C{points}} are not C{LatLon}.
667
667
 
@@ -707,7 +707,7 @@ class LatLon(LatLonNvectorBase, LatLonSphericalBase):
707
707
  Specify C{B{Nvector}=...} to override this C{Nvector}
708
708
  class or use C{B{Nvector}=None}.
709
709
 
710
- @return: An C{Nvector} or if B{C{Nvector}} is C{None}, a L{Vector4Tuple}C{(x, y, z, h)}.
710
+ @return: An C{Nvector} or if C{B{Nvector} is None}, a L{Vector4Tuple}C{(x, y, z, h)}.
711
711
 
712
712
  @raise TypeError: Invalid C{Nvector} or other B{C{Nvector_and_kwds}} item.
713
713
  '''
@@ -810,8 +810,8 @@ def areaOf(points, radius=R_M, wrap=False):
810
810
  @kwarg wrap: If C{True}, wrap or I{normalize} and unroll the
811
811
  B{C{points}} (C{bool}).
812
812
 
813
- @return: Polygon area (C{meter} I{squared} , same units as
814
- B{C{radius}}, or C{radians} if B{C{radius}} is C{None}).
813
+ @return: Polygon area (C{meter} I{squared}, same units as
814
+ B{C{radius}}, or C{radians} if C{B{radius} is None}).
815
815
 
816
816
  @raise PointsError: Insufficient number of B{C{points}}.
817
817
 
@@ -1085,7 +1085,7 @@ def nearestOn3(point, points, closed=False, radius=R_M, height=None, wrap=False)
1085
1085
  C{distance} and the C{angle} between the C{closest}
1086
1086
  and the given B{C{point}}. The C{distance} is in
1087
1087
  C{meter}, same units as B{C{radius}} or in C{radians}
1088
- if B{C{radius}} is C{None}, the C{angle} is in compass
1088
+ if C{B{radius} is None}, the C{angle} is in compass
1089
1089
  C{degrees360}.
1090
1090
 
1091
1091
  @raise PointsError: Insufficient number of B{C{points}}.
@@ -1109,7 +1109,7 @@ def perimeterOf(points, closed=False, radius=R_M, wrap=False):
1109
1109
  B{C{points}} (C{bool}).
1110
1110
 
1111
1111
  @return: Polygon perimeter (C{meter}, same units as B{C{radius}}
1112
- or C{radians} if B{C{radius}} is C{None}).
1112
+ or C{radians} if C{B{radius} is None}).
1113
1113
 
1114
1114
  @raise PointsError: Insufficient number of B{C{points}}.
1115
1115