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/geodsolve.py CHANGED
@@ -10,48 +10,31 @@ of the C{GeodSolve} executable.
10
10
  '''
11
11
 
12
12
  from pygeodesy.basics import _xinstanceof
13
- # from pygeodesy.constants import NAN, _0_0 # from .karney
13
+ # from pygeodesy.constants import NAN, _0_0 # from .karney
14
14
  # from pygeodesy.geodesicx import GeodesicAreaExact # _MODS
15
- from pygeodesy.interns import NN, _a12_, _azi1_, _azi2_, \
16
- _lat1_, _lat2_, _lon1_, _lon2_, _m12_, \
17
- _M12_, _M21_, _s12_, _S12_, _UNDER_
18
- from pygeodesy.interns import _UNUSED_, _not_ # PYCHOK used!
19
- from pygeodesy.karney import _Azi, Caps, _Deg, GeodesicError, _GTuple, \
20
- _Pass, _Lat, _Lon, _M, _M2, _sincos2d, \
21
- _0_0, NAN
15
+ from pygeodesy.interns import NN, _UNDER_
16
+ from pygeodesy.karney import Caps, GeodesicError, GeodSolve12Tuple, \
17
+ _llz2line, _sincos2d, _0_0, NAN
22
18
  from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS, \
23
19
  _getenv, _PYGEODESY_GEODSOLVE_
24
20
  from pygeodesy.named import _name1__
25
21
  from pygeodesy.namedTuples import Destination3Tuple, Distance3Tuple
26
22
  from pygeodesy.props import Property, Property_RO, property_RO
27
- from pygeodesy.solveBase import _SolveBase, _SolveLineBase
23
+ from pygeodesy.solveBase import _SolveGDictBase, _SolveGDictLineBase
28
24
  from pygeodesy.utily import _unrollon, _Wrap, wrap360
29
25
 
30
26
  __all__ = _ALL_LAZY.geodsolve
31
- __version__ = '24.06.26'
27
+ __version__ = '24.07.09'
32
28
 
33
29
 
34
- class GeodSolve12Tuple(_GTuple):
35
- '''12-Tuple C{(lat1, lon1, azi1, lat2, lon2, azi2, s12, a12, m12, M12, M21, S12)} with
36
- angles C{lat1}, C{lon1}, C{azi1}, C{lat2}, C{lon2} and C{azi2} and arc C{a12} all in
37
- C{degrees}, initial C{azi1} and final C{azi2} forward azimuths, distance C{s12} and
38
- reduced length C{m12} in C{meter}, area C{S12} in C{meter} I{squared} and geodesic
39
- scale factors C{M12} and C{M21}, both C{scalar}, see U{GeodSolve
40
- <https://GeographicLib.SourceForge.io/C++/doc/GeodSolve.1.html>}.
41
- '''
42
- # from GeodSolve --help option -f ... lat1 lon1 azi1 lat2 lon2 azi2 s12 a12 m12 M12 M21 S12
43
- _Names_ = (_lat1_, _lon1_, _azi1_, _lat2_, _lon2_, _azi2_, _s12_, _a12_, _m12_, _M12_, _M21_, _S12_)
44
- _Units_ = (_Lat, _Lon, _Azi, _Lat, _Lon, _Azi, _M, _Deg, _Pass, _Pass, _Pass, _M2)
45
-
46
-
47
- class _GeodesicSolveBase(_SolveBase):
30
+ class _GeodesicSolveBase(_SolveGDictBase):
48
31
  '''(INTERNAL) Base class for L{GeodesicSolve} and L{GeodesicLineSolve}.
49
32
  '''
50
33
  _Error = GeodesicError
51
34
  _Names_Direct = \
52
35
  _Names_Inverse = GeodSolve12Tuple._Names_
53
- _Solve_name = 'GeodSolve'
54
- _Solve_path = _getenv(_PYGEODESY_GEODSOLVE_, _PYGEODESY_GEODSOLVE_)
36
+ _Xable_name = 'GeodSolve'
37
+ _Xable_path = _getenv(_PYGEODESY_GEODSOLVE_, _PYGEODESY_GEODSOLVE_)
55
38
 
56
39
  @Property_RO
57
40
  def _b_option(self):
@@ -67,16 +50,12 @@ class _GeodesicSolveBase(_SolveBase):
67
50
  self._p_option +
68
51
  self._u_option)
69
52
 
70
- @Property_RO
71
- def _E_option(self):
72
- return ('-E',) if self.Exact else ()
73
-
74
53
  @Property
75
54
  def GeodSolve(self):
76
55
  '''Get the U{GeodSolve<https://GeographicLib.SourceForge.io/C++/doc/GeodSolve.1.html>}
77
56
  executable (C{filename}).
78
57
  '''
79
- return self._Solve_path
58
+ return self._Xable_path
80
59
 
81
60
  @GeodSolve.setter # PYCHOK setter!
82
61
  def GeodSolve(self, path):
@@ -86,20 +65,20 @@ class _GeodesicSolveBase(_SolveBase):
86
65
  @raise GeodesicError: Invalid B{C{path}}, B{C{path}} doesn't exist or
87
66
  isn't the C{GeodSolve} executable.
88
67
  '''
89
- self._setSolve(path)
68
+ self._setXable(path)
90
69
 
91
70
  def toStr(self, **prec_sep): # PYCHOK signature
92
71
  '''Return this C{GeodesicSolve} as string.
93
72
 
94
- @kwarg prec_sep: Keyword argumens C{B{prec}=6} and C{B{sep}=', '}
95
- for the C{float} C{prec}ision, number of decimal digits
96
- (0..9) and the C{sep}arator string to join. Trailing
97
- zero decimals are stripped for B{C{prec}} values of
98
- 1 and above, but kept for negative B{C{prec}} values.
73
+ @kwarg prec_sep: Keyword argumens C{B{prec}=6} and C{B{sep}=", "}
74
+ for the C{float} C{prec}ision, number of decimal digits
75
+ (0..9) and the C{sep}arator string to join. Trailing
76
+ zero decimals are stripped for B{C{prec}} values of 1
77
+ and above, but kept for negative B{C{prec}} values.
99
78
 
100
79
  @return: GeodesicSolve items (C{str}).
101
80
  '''
102
- return _SolveBase._toStr(self, GeodSolve=self.GeodSolve, **prec_sep)
81
+ return _SolveGDictBase._toStr(self, GeodSolve=self.GeodSolve, **prec_sep)
103
82
 
104
83
  @Property_RO
105
84
  def _u_option(self):
@@ -119,11 +98,11 @@ class GeodesicSolve(_GeodesicSolveBase):
119
98
  '''
120
99
 
121
100
  def Area(self, polyline=False, **name):
122
- '''Set up a L{GeodesicAreaExact} to compute area and
123
- perimeter of a polygon.
101
+ '''Set up a L{GeodesicAreaExact} to compute area and perimeter
102
+ of a polygon.
124
103
 
125
- @kwarg polyline: If C{True} perimeter only, otherwise
126
- area and perimeter (C{bool}).
104
+ @kwarg polyline: If C{True} perimeter only, otherwise area
105
+ and perimeter (C{bool}).
127
106
  @kwarg name: Optional C{B{name}=NN} (C{str}).
128
107
 
129
108
  @return: A L{GeodesicAreaExact} instance.
@@ -139,8 +118,8 @@ class GeodesicSolve(_GeodesicSolveBase):
139
118
  Polygon = Area # for C{geographiclib} compatibility
140
119
 
141
120
  def Direct3(self, lat1, lon1, azi1, s12): # PYCHOK outmask
142
- '''Return the destination lat, lon and reverse azimuth
143
- (final bearing) in C{degrees}.
121
+ '''Return the destination lat, lon and reverse azimuth (final bearing)
122
+ in C{degrees}.
144
123
 
145
124
  @return: L{Destination3Tuple}C{(lat, lon, final)}.
146
125
  '''
@@ -228,10 +207,10 @@ class GeodesicSolve(_GeodesicSolveBase):
228
207
  gl = GeodesicLineSolve(self, lat1, lon1, r.azi1, **_name1__(caps_name, _or_nameof=self))
229
208
  gl._a13 = r.a12 # gl.SetArc(r.a12)
230
209
  gl._s13 = r.s12 # gl.SetDistance(r.s12)
231
- return gl
210
+ return _llz2line(gl, lat2=lat2, lon2=lon2, azi2=r.azi2)
232
211
 
233
212
 
234
- class GeodesicLineSolve(_GeodesicSolveBase, _SolveLineBase):
213
+ class GeodesicLineSolve(_GeodesicSolveBase, _SolveGDictLineBase):
235
214
  '''Wrapper to invoke I{Karney}'s U{GeodSolve<https://GeographicLib.SourceForge.io/C++/doc/GeodSolve.1.html>}
236
215
  as an C{Exact} version of I{Karney}'s Python class U{GeodesicLine<https://GeographicLib.SourceForge.io/C++/doc/
237
216
  python/code.html#geographiclib.geodesicline.GeodesicLine>}.
@@ -269,7 +248,7 @@ class GeodesicLineSolve(_GeodesicSolveBase, _SolveLineBase):
269
248
  _xinstanceof(GeodesicSolve, geodesic=geodesic)
270
249
  if (caps & Caps.LINE_OFF): # copy to avoid updates
271
250
  geodesic = geodesic.copy(deep=False, name=_UNDER_(NN, geodesic.name)) # NOT _under!
272
- _SolveLineBase.__init__(self, geodesic, lat1, lon1, caps, azi1=azi1, **name)
251
+ _SolveGDictLineBase.__init__(self, geodesic, lat1, lon1, caps, azi1=azi1, **name)
273
252
  try:
274
253
  self.GeodSolve = geodesic.GeodSolve # geodesic or copy of geodesic
275
254
  except GeodesicError:
@@ -299,7 +278,7 @@ class GeodesicLineSolve(_GeodesicSolveBase, _SolveLineBase):
299
278
  @return: A C{GDict} with 12 items C{lat1, lon1, azi1, lat2, lon2,
300
279
  azi2, m12, a12, s12, M12, M21, S12}.
301
280
  '''
302
- return self._GDictInvoke(self._cmdArc, True, self._Names_Direct, a12)._unCaps(outmask)
281
+ return self._GDictInvoke(self._cmdArc, self._Names_Direct, a12)._unCaps(outmask)
303
282
 
304
283
  @Property_RO
305
284
  def azi1(self):
@@ -350,7 +329,7 @@ class GeodesicLineSolve(_GeodesicSolveBase, _SolveLineBase):
350
329
  @return: A C{GDict} with 12 items C{lat1, lon1, azi1, lat2, lon2,
351
330
  azi2, m12, a12, s12, M12, M21, S12}, possibly C{a12=NAN}.
352
331
  '''
353
- return self._GDictInvoke(self._cmdDistance, True, self._Names_Direct, s12)._unCaps(outmask)
332
+ return self._GDictInvoke(self._cmdDistance, self._Names_Direct, s12)._unCaps(outmask)
354
333
 
355
334
  @Property_RO
356
335
  def s13(self):
@@ -392,16 +371,16 @@ class GeodesicLineSolve(_GeodesicSolveBase, _SolveLineBase):
392
371
  def toStr(self, **prec_sep): # PYCHOK signature
393
372
  '''Return this C{GeodesicLineSolve} as string.
394
373
 
395
- @kwarg prec_sep: Keyword argumens C{B{prec}=6} and C{B{sep}=', '}
396
- for the C{float} C{prec}ision, number of decimal digits
397
- (0..9) and the C{sep}arator string to join. Trailing
398
- zero decimals are stripped for B{C{prec}} values of
399
- 1 and above, but kept for negative B{C{prec}} values.
374
+ @kwarg prec_sep: Keyword argumens C{B{prec}=6} and C{B{sep}=", "}
375
+ for the C{float} C{prec}ision, number of decimal digits
376
+ (0..9) and the C{sep}arator string to join. Trailing
377
+ zero decimals are stripped for B{C{prec}} values of 1
378
+ and above, but kept for negative B{C{prec}} values.
400
379
 
401
380
  @return: GeodesicLineSolve items (C{str}).
402
381
  '''
403
- return _SolveLineBase._toStr(self, azi1=self.azi1, geodesic=self._solve,
404
- GeodSolve=self.GeodSolve, **prec_sep)
382
+ return _SolveGDictLineBase._toStr(self, azi1=self.azi1, geodesic=self._solve,
383
+ GeodSolve=self.GeodSolve, **prec_sep)
405
384
 
406
385
 
407
386
  __all__ += _ALL_DOCS(_GeodesicSolveBase)
@@ -415,7 +394,7 @@ if __name__ == '__main__':
415
394
  gS.verbose = '--verbose' in argv # or '-v' in argv
416
395
 
417
396
  if gS.GeodSolve in (_PYGEODESY_GEODSOLVE_, None): # not set
418
- gS.GeodSolve = '/opt/local/bin/GeodSolve' # '/opt/local/Cellar/geographiclib/1.51/bin/GeodSolve' # HomeBrew
397
+ gS.GeodSolve = '/opt/local/bin/GeodSolve' # '/opt/local/Cellar/geographiclib/2.3/bin/GeodSolve' # HomeBrew
419
398
  printf('version: %s', gS.version)
420
399
 
421
400
  r = gS.Direct(40.6, -73.8, 51, 5.5e6)
pygeodesy/internals.py CHANGED
@@ -4,9 +4,9 @@ u'''Mostly INTERNAL functions, except L{machine}, L{print_} and L{printf}.
4
4
  '''
5
5
  # from pygeodesy.basics import isiterablen # _MODS
6
6
  # from pygeodesy.errors import _AttributeError, _error_init, _UnexpectedError, _xError2 # _MODS
7
- from pygeodesy.interns import NN, _COLON_, _DOT_, _ELLIPSIS_, _EQUALSPACED_, \
8
- _immutable_, _NL_, _pygeodesy_, _PyPy__, _python_, \
9
- _QUOTE1_, _QUOTE2_, _s_, _SPACE_, _sys, _UNDER_, _utf_8_
7
+ from pygeodesy.interns import NN, _BAR_, _COLON_, _DASH_, _DOT_, _ELLIPSIS_, _EQUALSPACED_, \
8
+ _immutable_, _NL_, _pygeodesy_, _PyPy__, _python_, _QUOTE1_, \
9
+ _QUOTE2_, _s_, _SPACE_, _sys, _UNDER_, _utf_8_
10
10
  from pygeodesy.interns import _COMMA_, _Python_ # PYCHOK used!
11
11
  # from pygeodesy.streprs import anstr, pairs, unstr # _MODS
12
12
 
@@ -360,10 +360,10 @@ def _passargs(*args):
360
360
  return args
361
361
 
362
362
 
363
- def _plural(noun, n):
363
+ def _plural(noun, n, nn=NN):
364
364
  '''(INTERNAL) Return C{noun}['s'] or C{NN}.
365
365
  '''
366
- return NN(noun, _s_) if n > 1 else (noun if n else NN)
366
+ return NN(noun, _s_) if n > 1 else (noun if n else nn)
367
367
 
368
368
 
369
369
  def print_(*args, **nl_nt_prec_prefix__end_file_flush_sep__kwds): # PYCHOK no cover
@@ -504,17 +504,44 @@ def _under(name): # PYCHOK in .datums, .auxilats, .ups, .utm, .utmupsBase, ...
504
504
  return name if name.startswith(_UNDER_) else NN(_UNDER_, name)
505
505
 
506
506
 
507
- def _usage(file_py, *args): # in .etm
507
+ def _usage(file_py, *args, **opts_help): # in .etm, .geodesici
508
508
  '''(INTERNAL) Build "usage: python -m ..." cmd line for module B{C{file_py}}.
509
509
  '''
510
- m = _os_path.dirname(file_py).replace(_os.getcwd(), _ELLIPSIS_) \
511
- .replace(_os.sep, _DOT_).strip()
512
- b, x = _os_path.splitext(_os_path.basename(file_py))
510
+ if opts_help:
511
+
512
+ def _help(alts=(), help=NN, **unused):
513
+ if alts and help:
514
+ h = NN(help, _SPACE_).lstrip(_DASH_)
515
+ for a in alts:
516
+ if a.startswith(h):
517
+ return NN(_DASH_, a),
518
+
519
+ def _opts(opts=NN, alts=(), **unused):
520
+ # opts='T--v-C-R meter-c|i|n|o'
521
+ d, fmt = NN, _MODS.streprs.Fmt.SQUARE
522
+ for o in (opts + _BAR_(*alts)).split(_DASH_):
523
+ if o:
524
+ yield fmt(NN(d, _DASH_, o.replace(_BAR_, ' | -')))
525
+ d = NN
526
+ else:
527
+ d = _DASH_
528
+
529
+ args = _help(**opts_help) or (tuple(_opts(**opts_help)) + args)
530
+
531
+ u = _COLON_(_dunder_nameof(_usage)[1:], NN)
532
+ return _SPACE_(u, *_usage_argv(file_py, *args))
533
+
534
+
535
+ def _usage_argv(argv0, *args):
536
+ '''(INTERNAL) Return 3-tuple C{(python, '-m', module, *args)}.
537
+ '''
538
+ m = _os_path.dirname(argv0).replace(_os.getcwd(), _ELLIPSIS_) \
539
+ .replace(_os.sep, _DOT_).strip()
540
+ b, x = _os_path.splitext(_os_path.basename(argv0))
513
541
  if x == '.py' and not _dunder_ismain(b):
514
542
  m = _DOT_(m or _pygeodesy_, b)
515
- p = NN(_python_, _sys.version_info[0])
516
- u = _COLON_(_dunder_nameof(_usage)[1:], NN)
517
- return _SPACE_(u, p, '-m', _enquote(m), *args)
543
+ p = NN(_python_, _sys.version_info[0])
544
+ return (p, '-m', _enquote(m)) + args
518
545
 
519
546
 
520
547
  def _version2(version, n=2):
@@ -550,7 +577,7 @@ def _version_ints(vs):
550
577
 
551
578
 
552
579
  __all__ = tuple(map(_dunder_nameof, (machine, print_, printf)))
553
- __version__ = '24.06.05'
580
+ __version__ = '24.07.04'
554
581
 
555
582
  if _dunder_ismain(__name__): # PYCHOK no cover
556
583
 
pygeodesy/karney.py CHANGED
@@ -143,13 +143,14 @@ from pygeodesy.basics import _copysign, int1s, isint, itemsorted, neg, unsigned0
143
143
  _xgeographiclib, _zip, _version_info
144
144
  from pygeodesy.constants import NAN, _isfinite as _math_isfinite, _0_0, \
145
145
  _1_16th, _1_0, _2_0, _180_0, _N_180_0, _360_0
146
- from pygeodesy.errors import GeodesicError, _ValueError, _xkwds, _xkwds_get1
146
+ from pygeodesy.errors import GeodesicError, _ValueError, _xkwds, _xkwds_get1, \
147
+ _xkwds_kwds, _xkwds_not
147
148
  from pygeodesy.fmath import cbrt, fremainder, norm2
148
149
  # from pygeodesy.internals import _version_info # from .basics
149
- from pygeodesy.interns import _2_, _a12_, _area_, _azi2_, _azi12_, _composite_, \
150
- _lat1_, _lat2_, _lon1_, _lon2_, _m12_, _M12_, \
151
- _M21_, _number_, _s12_, _S12_, _UNDER_, \
152
- _BAR_, NN # PYCHOK used!
150
+ from pygeodesy.interns import NN, _2_, _a12_, _area_, _azi1_, _azi2_, _azi12_, \
151
+ _composite_, _lat1_, _lat2_, _lon1_, _lon2_, \
152
+ _m12_, _M12_, _M21_, _number_, _s12_, _S12_, \
153
+ _UNDER_, _X_, _BAR_ # PYCHOK used!
153
154
  from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS, _getenv
154
155
  from pygeodesy.named import ADict, _NamedBase, _NamedTuple, notImplemented, _Pass
155
156
  from pygeodesy.props import deprecated_method, Property_RO
@@ -160,7 +161,7 @@ from pygeodesy.utily import atan2d, sincos2d, tand, _unrollon, fabs
160
161
  # from math import fabs # from .utily
161
162
 
162
163
  __all__ = _ALL_LAZY.karney
163
- __version__ = '24.06.27'
164
+ __version__ = '24.07.09'
164
165
 
165
166
  _K_2_0 = _getenv('PYGEODESY_GEOGRAPHICLIB', _2_) == _2_
166
167
  _perimeter_ = 'perimeter'
@@ -211,10 +212,10 @@ class Caps(object): # PYCHOK
211
212
  '''(INTERNAL) Overriden by C{Caps} below.
212
213
  '''
213
214
  EMPTY = 0 # formerly aka NONE
214
- _CAP_1 = 1 << 0 # for goedesicw only
215
- _CAP_1p = 1 << 1 # for goedesicw only
215
+ _CAP_1 = 1 << 0 # for goedesici/-w
216
+ _CAP_1p = 1 << 1 # for goedesici/-w
216
217
  _CAP_2 = 1 << 2
217
- _CAP_3 = 1 << 3 # for goedesicw only
218
+ _CAP_3 = 1 << 3 # for goedesici/-w
218
219
  # _CAP_4 = 1 << 4
219
220
  # _CAP_ALL = 0x1F
220
221
  # _CAP_MASK = _CAP_ALL
@@ -233,7 +234,7 @@ class Caps(object): # PYCHOK
233
234
  _DIRECT3 = AZIMUTH | LATITUDE | LONGITUDE | _CAP_3 # for goedesicw only
234
235
  _INVERSE3 = AZIMUTH | DISTANCE | _CAP_1 # for goedesicw only
235
236
  _STD = STANDARD | _CAP_3 | _CAP_1 # for goedesicw only
236
- _STD_LINE = _STD | _CAP_2 | _CAP_1p # for goedesici and -w
237
+ _STD_LINE = _STD | _CAP_2 | _CAP_1p # for goedesici/-w
237
238
 
238
239
  LINE_CAPS = _STD_LINE | REDUCEDLENGTH | GEODESICSCALE # .geodesici only
239
240
 
@@ -248,14 +249,14 @@ class Caps(object): # PYCHOK
248
249
  AZIMUTH_DISTANCE_AREA = AZIMUTH | DISTANCE | AREA
249
250
 
250
251
  _ANGLE_ONLY = 1 << 18 # angular distance C{a12} only
251
- _SALPs_CALPs = 1 << 19 # (INTERNAL) GeodesicExact._GenInverse
252
+ _S_CALPs_ = 1 << 19 # (INTERNAL) GeodesicExact._GenInverse
252
253
 
253
254
  _DEBUG_AREA = 1 << 20 # (INTERNAL) include Line details
254
255
  _DEBUG_DIRECT = 1 << 21 # (INTERNAL) include Direct details
255
256
  _DEBUG_INVERSE = 1 << 22 # (INTERNAL) include Inverse details
256
257
  _DEBUG_LINE = 1 << 23 # (INTERNAL) include Line details
257
258
  _DEBUG_ALL = _DEBUG_AREA | _DEBUG_DIRECT | _DEBUG_INVERSE | \
258
- _DEBUG_LINE | _ANGLE_ONLY | _SALPs_CALPs
259
+ _DEBUG_LINE | _ANGLE_ONLY | _S_CALPs_
259
260
 
260
261
  _OUT_ALL = ALL
261
262
  _OUT_MASK = ALL | LONG_UNROLL | REVERSE2 | _DEBUG_ALL
@@ -273,7 +274,7 @@ class Caps(object): # PYCHOK
273
274
  s = []
274
275
  for c, C in itemsorted(self.__class__.__dict__):
275
276
  if isint(C) and (Csk & C) and int1s(C) == 1 \
276
- and (C in (Caps.REVERSE2, Caps._SALPs_CALPs)
277
+ and (C in (Caps.REVERSE2, Caps._S_CALPs_)
277
278
  or c.replace(_UNDER_, NN).isupper()):
278
279
  s.append(c)
279
280
  return sep.join(s) if sep else tuple(s)
@@ -310,9 +311,14 @@ and C{ALL} - all of the above.
310
311
 
311
312
  C{STANDARD} = C{AZIMUTH | DISTANCE | DISTANCE_IN | LATITUDE | LONGITUDE}'''
312
313
 
313
- _KEY2Caps = dict(m12=Caps.REDUCEDLENGTH, # see GDict._unCaps
314
- M12=Caps.GEODESICSCALE,
315
- M21=Caps.GEODESICSCALE, S12=Caps.AREA)
314
+ _KEY2Caps = dict(azi2=Caps.AZIMUTH, # see GDict._unCaps
315
+ lat2=Caps.LATITUDE,
316
+ lon2=Caps.LONGITUDE,
317
+ m12 =Caps.REDUCEDLENGTH,
318
+ M12 =Caps.GEODESICSCALE,
319
+ M21 =Caps.GEODESICSCALE,
320
+ s12 =Caps.DISTANCE,
321
+ S12 =Caps.AREA)
316
322
 
317
323
 
318
324
  class _CapsBase(_NamedBase): # in .auxilats, .geodesicx.gxbases
@@ -426,6 +432,12 @@ class GDict(ADict): # XXX _NamedDict
426
432
  '''
427
433
  return self._toTuple(Inverse10Tuple, dflt)
428
434
 
435
+ def _toNAN(self, outmask): # .GeodesicLineExact._GenPosition
436
+ '''(INTERNAL) Convert this C{GDict} to all C{NAN}s.
437
+ '''
438
+ d = dict((n, NAN) for n in GeodSolve12Tuple._Names_)
439
+ return self.set_(**d)._unCaps(outmask)
440
+
429
441
  @deprecated_method
430
442
  def toRhumb7Tuple(self, dflt=NAN): # PYCHOK no cover
431
443
  '''DEPRECATED on 23.12.07, use method C{toRhumb8Tuple}.
@@ -461,6 +473,18 @@ class GDict(ADict): # XXX _NamedDict
461
473
  t = tuple(_g(self, n, dflt) for n in nTuple._Names_)
462
474
  return nTuple(t, iteration=self._iteration)
463
475
 
476
+ def _2X(self, gl, _2X=_X_): # .Intesectool, .Intersector
477
+ '''(INTERNAL) Rename attr tail from C{-2} to C{-X} or C{-M}.
478
+ '''
479
+ X = GDict(self)
480
+ for n in (_lat2_, _lon2_, _azi2_, _s12_, _a12_):
481
+ if n in X: # X._X = X._2
482
+ X[n[:-1] + _2X] = X.pop(n)
483
+ v = getattr(gl, n, X)
484
+ if v is not X: # X._2 = gl._2
485
+ X[n] = v
486
+ return X
487
+
464
488
  def _unCaps(self, outmask): # in .geodsolve
465
489
  '''(INTERNAL) Remove superfluous items.
466
490
  '''
@@ -470,6 +494,19 @@ class GDict(ADict): # XXX _NamedDict
470
494
  return self
471
495
 
472
496
 
497
+ class GeodSolve12Tuple(_GTuple):
498
+ '''12-Tuple C{(lat1, lon1, azi1, lat2, lon2, azi2, s12, a12, m12, M12, M21, S12)} with
499
+ angles C{lat1}, C{lon1}, C{azi1}, C{lat2}, C{lon2} and C{azi2} and arc C{a12} all in
500
+ C{degrees}, initial C{azi1} and final C{azi2} forward azimuths, distance C{s12} and
501
+ reduced length C{m12} in C{meter}, area C{S12} in C{meter} I{squared} and geodesic
502
+ scale factors C{M12} and C{M21}, both C{scalar}, see U{GeodSolve
503
+ <https://GeographicLib.SourceForge.io/C++/doc/GeodSolve.1.html>}.
504
+ '''
505
+ # from GeodSolve --help option -f ... lat1 lon1 azi1 lat2 lon2 azi2 s12 a12 m12 M12 M21 S12
506
+ _Names_ = (_lat1_, _lon1_, _azi1_, _lat2_, _lon2_, _azi2_, _s12_, _a12_, _m12_, _M12_, _M21_, _S12_)
507
+ _Units_ = (_Lat, _Lon, _Azi, _Lat, _Lon, _Azi, _M, _Deg, _Pass, _Pass, _Pass, _M2)
508
+
509
+
473
510
  class Inverse10Tuple(_GTuple):
474
511
  '''10-Tuple C{(a12, s12, salp1, calp1, salp2, calp2, m12, M12, M21, S12)} with arc length
475
512
  C{a12} in C{degrees}, distance C{s12} and reduced length C{m12} in C{meter}, area
@@ -687,6 +724,16 @@ def _isfinite(x): # mimick geomath.Math.isfinite
687
724
  return _math_isfinite(x) # and fabs(x) <= _MAX
688
725
 
689
726
 
727
+ def _llz2line(line, **llz2):
728
+ '''(INTERNAL) Set C{line.lat2, .lon2, .azi2} from C{llz2}.
729
+ '''
730
+ if llz2:
731
+ llz2 = _xkwds_not(None, **_xkwds_kwds(llz2, lat2=None, lon2=None, azi2=None))
732
+ if llz2:
733
+ line.__dict__.update(llz2)
734
+ return line
735
+
736
+
690
737
  def _norm2(x, y): # mimick geomath.Math.norm
691
738
  '''Normalize C{B{x}} and C{B{y}}.
692
739
 
pygeodesy/lazily.py CHANGED
@@ -48,26 +48,27 @@ except ImportError as x: # Python 2.6-
48
48
  from os import getenv as _getenv
49
49
  # import sys as _sys # from .interns
50
50
 
51
- __as__ = ' as '
52
- _dunder_all_ = '__all__' # in .__main__
53
- _enabled_ = 'enabled'
54
- _FOR_DOCS = _getenv('PYGEODESY_FOR_DOCS', NN) # for epydoc ...
55
- _i0 = () # PYCHOK empty tuple
56
- _init__all__ = _FOR_DOCS or _getenv('PYGEODESY_INIT__ALL__', _dunder_all_) == _dunder_all_ # PYCHOK exported
57
- _lazily_ = 'lazily'
58
- _lazily_imported_ = _SPACE_(_HASH_, _lazily_, 'imported')
59
- _PYGEODESY_GEOCONVERT_ = 'PYGEODESY_GEOCONVERT' # PYCHOK .mgrs, test.bases
60
- _PYGEODESY_GEODSOLVE_ = 'PYGEODESY_GEODSOLVE' # PYCHOK .geodsolve, test.bases
61
- _PYGEODESY_LAZY_IMPORT_ = 'PYGEODESY_LAZY_IMPORT'
62
- _PYGEODESY_RHUMBSOLVE_ = 'PYGEODESY_RHUMBSOLVE' # PYCHOK .rhumb.solve, test.bases
63
- _PYTHON_X_DEV = getattr(_sys, '_xoptions', {}).get('dev', # Python 3.2+
51
+ __as__ = ' as '
52
+ _dunder_all_ = '__all__' # in .__main__
53
+ _enabled_ = 'enabled'
54
+ _FOR_DOCS = _getenv('PYGEODESY_FOR_DOCS', NN) # for epydoc ...
55
+ _i0 = () # PYCHOK empty tuple
56
+ _init__all__ = _FOR_DOCS or _getenv('PYGEODESY_INIT__ALL__', _dunder_all_) == _dunder_all_ # PYCHOK exported
57
+ _lazily_ = 'lazily'
58
+ _lazily_imported_ = _SPACE_(_HASH_, _lazily_, 'imported')
59
+ _PYGEODESY_GEOCONVERT_ = 'PYGEODESY_GEOCONVERT' # PYCHOK .mgrs, test.bases
60
+ _PYGEODESY_GEODSOLVE_ = 'PYGEODESY_GEODSOLVE' # PYCHOK .geodsolve, test.bases
61
+ _PYGEODESY_INTERSECTTOOL_ = 'PYGEODESY_INTERSECTTOOL' # PYCHOK .intersectool, test.bases
62
+ _PYGEODESY_LAZY_IMPORT_ = 'PYGEODESY_LAZY_IMPORT'
63
+ _PYGEODESY_RHUMBSOLVE_ = 'PYGEODESY_RHUMBSOLVE' # PYCHOK .rhumb.solve, test.bases
64
+ _PYTHON_X_DEV = getattr(_sys, '_xoptions', {}).get('dev', # Python 3.2+
64
65
  _getenv('PYTHONDEVMODE', NN)) # PYCHOK exported
65
- _sys_version_info2 = _sys.version_info[:2] # in .basics, .fmath, ...
66
- _unlazy = _unLazy0 = _isfrozen or _sys_version_info2 < (3, 7) # PYCHOK mod.__getattr__ 3.7+
67
- _WARNINGS_X_DEV = _getenv('PYGEODESY_WARNINGS', NN) and (
68
- _PYTHON_X_DEV or bool(_sys.warnoptions)) # PYCHOK .props
66
+ _sys_version_info2 = _sys.version_info[:2] # in .basics, .fmath, ...
67
+ _unlazy = _unLazy0 = _isfrozen or _sys_version_info2 < (3, 7) # PYCHOK mod.__getattr__ 3.7+
68
+ _WARNINGS_X_DEV = _getenv('PYGEODESY_WARNINGS', NN) and (
69
+ _PYTHON_X_DEV or bool(_sys.warnoptions)) # PYCHOK .props
69
70
  # @module_property[_RO?] <https://GitHub.com/jtushman/proxy_tools/>
70
- isLazy = None # see @var isLazy in .__init__
71
+ isLazy = None # see @var isLazy in .__init__
71
72
 
72
73
 
73
74
  class LazyAttributeError(AttributeError):
@@ -283,7 +284,8 @@ _ALL_LAZY = _NamedEnum_RO(_name='_ALL_LAZY',
283
284
  fsums=_i('Fsum', 'DivMod2Tuple', 'Fsum2Tuple', 'ResidualError',
284
285
  'fsum', 'fsum_', 'fsumf_', 'fsum1', 'fsum1_', 'fsum1f_'),
285
286
  gars=_i('Garef', 'GARSError'),
286
- geodesici=_i('Intersector', 'Intersector5Tuple', 'XDist'),
287
+ geodesici=_i('Intersectool', 'Intersectool5Tuple', 'Middle5Tuple',
288
+ 'Intersector', 'Intersector5Tuple', 'XDict'),
287
289
  geodesicw=_i('Geodesic', 'GeodesicLine', 'Geodesic_WGS84'),
288
290
  geodesicx=_i('gx', 'gxarea', 'gxbases', 'gxline', # modules
289
291
  'GeodesicAreaExact', 'GeodesicExact', 'GeodesicLineExact', 'PolygonArea'),
@@ -409,7 +411,7 @@ _ALL_DEPRECATED = _NamedEnum_RO(_name='_ALL_DEPRECATED',
409
411
  'HeightIDW', 'HeightIDW2', 'HeightIDW3', 'Helmert7Tuple',
410
412
  'Lam_', 'LatLonExact4Tuple', 'NearestOn4Tuple', 'Ned3Tuple',
411
413
  'Phi_', 'RefFrameError', 'Rhumb7Tuple', 'RhumbOrder2Tuple',
412
- 'Transform7Tuple', 'TriAngle4Tuple', 'UtmUps4Tuple'),
414
+ 'Transform7Tuple', 'TriAngle4Tuple', 'UtmUps4Tuple', 'XDist'),
413
415
  deprecated_consterns=_i('EPS1_2', 'MANTIS', 'OK'),
414
416
  deprecated_datum=_i('Curvature2Tuple', 'Datum', 'Ellipsoid', 'Transform', # assert
415
417
  'Datums', 'Ellipsoids', 'Transforms',
@@ -519,7 +521,7 @@ class _ALL_MODS(_internals._MODS_Base):
519
521
  _internals._MODS = _ALL_MODS = _ALL_MODS() # PYCHOK singleton
520
522
 
521
523
  __all__ = _ALL_LAZY.lazily
522
- __version__ = '24.06.19'
524
+ __version__ = '24.07.09'
523
525
 
524
526
 
525
527
  def _ALL_OTHER(*objs):
pygeodesy/ltpTuples.py CHANGED
@@ -36,7 +36,7 @@ from pygeodesy.vector3d import Vector3d
36
36
  # from math import cos, radians # from .utily
37
37
 
38
38
  __all__ = _ALL_LAZY.ltpTuples
39
- __version__ = '24.06.15'
39
+ __version__ = '24.06.28'
40
40
 
41
41
  _aer_ = 'aer'
42
42
  _alt_ = 'alt'
@@ -349,7 +349,7 @@ class Aer(_AbcBase):
349
349
  number of (decimal) digits, unstripped
350
350
  (C{int}), C{B{fmt}='[]'} the enclosing
351
351
  backets format (C{str}) and separator
352
- C{B{sep}=', '} to join (C{str}).
352
+ C{B{sep}=", "} to join (C{str}).
353
353
 
354
354
  @return: This AER as "[degrees360, degrees90, meter]" (C{str}).
355
355
  '''
@@ -572,7 +572,7 @@ class Ned(_AbcBase):
572
572
  number of (decimal) digits, unstripped
573
573
  (C{int}), C{B{fmt}='[]'} the enclosing
574
574
  backets format (C{str}) and separator
575
- C{B{sep}=', '} to join (C{str}).
575
+ C{B{sep}=", "} to join (C{str}).
576
576
 
577
577
  @return: This NED as "[meter, meter, meter]" (C{str}).
578
578
  '''
@@ -659,7 +659,7 @@ class _Vector3d(Vector3d):
659
659
  number of (decimal) digits, unstripped
660
660
  (C{int}), C{B{fmt}='[]'} the enclosing
661
661
  backets format (C{str}) and separator
662
- C{B{sep}=', '} to join (C{str}).
662
+ C{B{sep}=", "} to join (C{str}).
663
663
 
664
664
  @return: This XYZ as "[meter, meter, meter]" (C{str}).
665
665
  '''