pygeodesy 24.6.24__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.
pygeodesy/rhumb/solve.py CHANGED
@@ -17,21 +17,21 @@ from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS, _getenv,
17
17
  _PYGEODESY_RHUMBSOLVE_
18
18
  from pygeodesy.namedTuples import Destination3Tuple, Distance3Tuple
19
19
  from pygeodesy.props import deprecated_method, Property, Property_RO
20
- from pygeodesy.solveBase import _SolveBase, _SolveLineBase
20
+ from pygeodesy.solveBase import _SolveGDictBase, _SolveGDictLineBase
21
21
  from pygeodesy.utily import _unrollon, _Wrap, wrap360
22
22
 
23
23
  __all__ = _ALL_LAZY.rhumb_solve
24
- __version__ = '24.06.04'
24
+ __version__ = '24.06.28'
25
25
 
26
26
 
27
- class _RhumbSolveBase(_SolveBase):
27
+ class _RhumbSolveBase(_SolveGDictBase):
28
28
  '''(INTERNAL) Base class for L{RhumbSolve} and L{RhumbLineSolve}.
29
29
  '''
30
30
  _Error = RhumbError
31
31
  _Names_Direct = _lat2_, _lon2_, _S12_
32
32
  _Names_Inverse = _azi12_, _s12_, _S12_
33
- _Solve_name = 'RhumbSolve'
34
- _Solve_path = _getenv(_PYGEODESY_RHUMBSOLVE_, _PYGEODESY_RHUMBSOLVE_)
33
+ _Xable_name = 'RhumbSolve'
34
+ _Xable_path = _getenv(_PYGEODESY_RHUMBSOLVE_, _PYGEODESY_RHUMBSOLVE_)
35
35
 
36
36
  @Property_RO
37
37
  def _cmdBasic(self):
@@ -46,7 +46,7 @@ class _RhumbSolveBase(_SolveBase):
46
46
  '''Get the U{RhumbSolve<https://GeographicLib.SourceForge.io/C++/doc/RhumbSolve.1.html>}
47
47
  executable (C{filename}).
48
48
  '''
49
- return self._Solve_path
49
+ return self._Xable_path
50
50
 
51
51
  @RhumbSolve.setter # PYCHOK setter!
52
52
  def RhumbSolve(self, path):
@@ -56,7 +56,7 @@ class _RhumbSolveBase(_SolveBase):
56
56
  @raise RhumbError: Invalid B{C{path}}, B{C{path}} doesn't exist or isn't
57
57
  the C{RhumbSolve} executable.
58
58
  '''
59
- self._setSolve(path)
59
+ self._setXable(path)
60
60
 
61
61
  @Property_RO
62
62
  def _s_option(self): # == not -E for GeodSolve
@@ -65,11 +65,11 @@ class _RhumbSolveBase(_SolveBase):
65
65
  def toStr(self, **prec_sep): # PYCHOK signature
66
66
  '''Return this C{RhumbSolve} as string.
67
67
 
68
- @kwarg prec_sep: Keyword argumens C{B{prec}=6} and C{B{sep}=', '}
68
+ @kwarg prec_sep: Keyword argumens C{B{prec}=6} and C{B{sep}=", "}
69
69
  for the C{float} C{prec}ision, number of decimal digits
70
70
  (0..9) and the C{sep}arator string to join. Trailing
71
- zero decimals are stripped for B{C{prec}} values of
72
- 1 and above, but kept for negative B{C{prec}} values.
71
+ zero decimals are stripped for B{C{prec}} values of 1
72
+ and above, but kept for negative B{C{prec}} values.
73
73
 
74
74
  @return: RhumbSolve items (C{str}).
75
75
  '''
@@ -173,8 +173,7 @@ class RhumbSolve(_RhumbSolveBase):
173
173
  return r
174
174
 
175
175
  def _GDictInverse(self, lat1, lon1, lat2, lon2, *unused, **floats): # PYCHOK signature
176
- '''(INTERNAL) Get C{_GenInverse}-like result as an 8-item C{GDict}, but
177
- I{without} C{_SALPs_CALPs_}.
176
+ '''(INTERNAL) Get C{_GenInverse}-like result as an 8-item C{GDict}, but I{without} C{_S_CALPs_}.
178
177
  '''
179
178
  i = _RhumbSolveBase._GDictInverse(self, lat1, lon1, lat2, lon2, **floats)
180
179
  a = _over(float(i.s12), self._mpd) # for .Inverse1
@@ -231,7 +230,7 @@ class RhumbSolve(_RhumbSolveBase):
231
230
  Line = DirectLine
232
231
 
233
232
 
234
- class RhumbLineSolve(_RhumbSolveBase, _SolveLineBase):
233
+ class RhumbLineSolve(_RhumbSolveBase, _SolveGDictLineBase):
235
234
  '''Wrapper to invoke I{Karney}'s U{RhumbSolve<https://GeographicLib.SourceForge.io/C++/doc/RhumbSolve.1.html>}
236
235
  like a class, similar to L{pygeodesy.RhumbLine} and L{pygeodesy.RhumbLineAux}.
237
236
 
@@ -267,7 +266,7 @@ class RhumbLineSolve(_RhumbSolveBase, _SolveLineBase):
267
266
  _xinstanceof(RhumbSolve, rhumb=rhumb)
268
267
  if (caps & Caps.LINE_OFF): # copy to avoid updates
269
268
  rhumb = rhumb.copy(deep=False, name=NN(_UNDER_, rhumb.name))
270
- _SolveLineBase.__init__(self, rhumb, lat1, lon1, caps, azi12=azi12, **name)
269
+ _SolveGDictLineBase.__init__(self, rhumb, lat1, lon1, caps, azi12=azi12, **name)
271
270
  try:
272
271
  self.RhumbSolve = rhumb.RhumbSolve # rhumb or copy of rhumb
273
272
  except RhumbError:
@@ -283,7 +282,7 @@ class RhumbLineSolve(_RhumbSolveBase, _SolveLineBase):
283
282
  # azi12, a12, s12, S12}.
284
283
  # '''
285
284
  # s = a12 * self._mpd
286
- # a = self._GDictInvoke(self._cmdArc, True, self._Names_Direct, s)
285
+ # a = self._GDictInvoke(self._cmdArc, self._Names_Direct, s)
287
286
  # r = GDict(a12=a12, s12=s, **self._lla1)
288
287
  # r.updated(a)
289
288
  # return r
@@ -318,7 +317,7 @@ class RhumbLineSolve(_RhumbSolveBase, _SolveLineBase):
318
317
  @return: A L{GDict} with 7 items C{lat1, lon1, lat2, lon2,
319
318
  azi12, s12, S12}.
320
319
  '''
321
- d = self._GDictInvoke(self._cmdDistance, True, self._Names_Direct, s12)
320
+ d = self._GDictInvoke(self._cmdDistance, self._Names_Direct, s12)
322
321
  r = GDict(s12=s12, **self._lla1) # a12=_over(s12, self._mpd)
323
322
  r.update(d)
324
323
  return r
@@ -326,16 +325,16 @@ class RhumbLineSolve(_RhumbSolveBase, _SolveLineBase):
326
325
  def toStr(self, **prec_sep): # PYCHOK signature
327
326
  '''Return this C{RhumbLineSolve} as string.
328
327
 
329
- @kwarg prec_sep: Keyword argumens C{B{prec}=6} and C{B{sep}=', '}
328
+ @kwarg prec_sep: Keyword argumens C{B{prec}=6} and C{B{sep}=", "}
330
329
  for the C{float} C{prec}ision, number of decimal digits
331
330
  (0..9) and the C{sep}arator string to join. Trailing
332
- zero decimals are stripped for B{C{prec}} values of
333
- 1 and above, but kept for negative B{C{prec}} values.
331
+ zero decimals are stripped for B{C{prec}} values of 1
332
+ and above, but kept for negative B{C{prec}} values.
334
333
 
335
334
  @return: RhumbLineSolve items (C{str}).
336
335
  '''
337
- return _SolveLineBase._toStr(self, azi12=self.azi12, rhumb=self._solve,
338
- RhumbSolve=self.RhumbSolve, **prec_sep)
336
+ return _SolveGDictLineBase._toStr(self, azi12=self.azi12, rhumb=self._solve,
337
+ RhumbSolve=self.RhumbSolve, **prec_sep)
339
338
 
340
339
 
341
340
  class RhumbSolve7Tuple(Rhumb8Tuple):
@@ -396,7 +395,7 @@ if __name__ == '__main__':
396
395
  rS.verbose = '--verbose' in argv # or '-v' in argv
397
396
 
398
397
  if rS.RhumbSolve in (_PYGEODESY_RHUMBSOLVE_, None): # not set
399
- rS.RhumbSolve = '/opt/local/bin/RhumbSolve' # '/opt/local/Cellar/geographiclib/2.2/bin/RhumbSolve' # HomeBrew
398
+ rS.RhumbSolve = '/opt/local/bin/RhumbSolve' # '/opt/local/Cellar/geographiclib/2.3/bin/RhumbSolve' # HomeBrew
400
399
  printf('version: %s', rS.version)
401
400
 
402
401
  if len(argv) > 6: # 60 0 30 0 45 1e6
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
  #
pygeodesy/units.py CHANGED
@@ -27,7 +27,7 @@ from pygeodesy.unitsBase import Float, Int, _NamedUnit, Radius, Str, Fmt, fstr
27
27
  from math import degrees, radians
28
28
 
29
29
  __all__ = _ALL_LAZY.units
30
- __version__ = '24.06.15'
30
+ __version__ = '24.06.29'
31
31
 
32
32
 
33
33
  class Float_(Float):
@@ -781,10 +781,10 @@ class Zone(Int):
781
781
  return Int_.__new__(cls, arg=arg, name=name, **Error_name_arg)
782
782
 
783
783
 
784
- _Scalars = Float, Float_, Scalar, Scalar_
785
- _Degrees = (Bearing, Bearing_, Degrees, Degrees_) + _Scalars
786
- _Meters = (Distance, Distance_, Meter, Meter_) + _Scalars
787
- _Radians = (Radians, Radians_) + _Scalars # PYCHOK unused
784
+ _ScalarU = Float, Float_, Scalar, Scalar_
785
+ _Degrees = (Bearing, Bearing_, Degrees, Degrees_) + _ScalarU
786
+ _Meters = (Distance, Distance_, Meter, Meter_) + _ScalarU
787
+ _Radians = (Radians, Radians_) + _ScalarU # PYCHOK unused
788
788
  _Radii = _Meters + (Radius, Radius_)
789
789
 
790
790