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/geodesicw.py CHANGED
@@ -23,7 +23,7 @@ from pygeodesy.fsums import Fsum, Fmt, unstr
23
23
  from pygeodesy.internals import _dunder_nameof, _under
24
24
  from pygeodesy.interns import NN, _DOT_, _SPACE_, _to_, _too_
25
25
  from pygeodesy.karney import _atan2d, Caps, Direct9Tuple, GDict, \
26
- _kWrapped, Inverse10Tuple
26
+ Inverse10Tuple, _kWrapped, _llz2line
27
27
  from pygeodesy.latlonBase import LatLonBase as _LLB, F_D, Radius_
28
28
  from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS
29
29
  from pygeodesy.named import callername, classname, _name1__, _name2__
@@ -37,7 +37,7 @@ from contextlib import contextmanager
37
37
  # from math import fabs # from .utily
38
38
 
39
39
  __all__ = _ALL_LAZY.geodesicw
40
- __version__ = '24.06.24'
40
+ __version__ = '24.07.09'
41
41
 
42
42
  _plumb_ = 'plumb'
43
43
  _TRIPS = 65
@@ -220,7 +220,9 @@ class _gWrapped(_kWrapped):
220
220
  '''
221
221
  with _wargs(self, lat1, lon1, lat2, lon2, caps, **name) as args:
222
222
  t = _Geodesic.InverseLine(self, *args)
223
- return self._Line13(t, **name)
223
+ gl = self._Line13(t, **name)
224
+ p2 = gl.Position(gl.s13, outmask=Caps.AZIMUTH)
225
+ return _llz2line(gl, lat2=lat2, lon2=lon2, azi2=p2.azi2)
224
226
 
225
227
  def Line(self, lat1, lon1, azi1, caps=Caps._STD_LINE, **name):
226
228
  '''Set up a I{wrapped} C{GeodesicLine} to compute several points
@@ -23,7 +23,7 @@ from pygeodesy.karney import Caps, GeodesicError
23
23
  from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY
24
24
 
25
25
  __all__ = _ALL_LAZY.geodesicx + _ALL_DOCS(Caps, GeodesicError)
26
- __version__ = '24.06.19'
26
+ __version__ = '24.07.09'
27
27
 
28
28
  # **) MIT License
29
29
  #
pygeodesy/geodesicx/gx.py CHANGED
@@ -63,7 +63,7 @@ from pygeodesy.utily import atan2d as _atan2d_reverse, _unrollon, _Wrap, wrap360
63
63
  from math import atan2, copysign, cos, degrees, fabs, radians, sqrt
64
64
 
65
65
  __all__ = ()
66
- __version__ = '24.06.24'
66
+ __version__ = '24.07.09'
67
67
 
68
68
  _MAXIT1 = 20
69
69
  _MAXIT2 = 10 + _MAXIT1 + MANT_DIG # MANT_DIG == C++ digits
@@ -212,7 +212,7 @@ class GeodesicExact(_GeodesicBase):
212
212
  <https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1GeodesicExact.html>} and
213
213
  Python U{Geodesic.ArcDirectLine<https://GeographicLib.SourceForge.io/Python/doc/code.html>}.
214
214
  '''
215
- return self._GenDirectLine(lat1, lon1, azi1, True, a12, caps, **name)
215
+ return GeodesicLineExact(self, lat1, lon1, azi1, caps=caps, **name)._GenSet(self._debug, a12=a12)
216
216
 
217
217
  def Area(self, polyline=False, **name):
218
218
  '''Set up a L{GeodesicAreaExact} to compute area and
@@ -390,7 +390,7 @@ class GeodesicExact(_GeodesicBase):
390
390
  <https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1GeodesicExact.html>} and
391
391
  Python U{Geodesic.DirectLine<https://GeographicLib.SourceForge.io/Python/doc/code.html>}.
392
392
  '''
393
- return self._GenDirectLine(lat1, lon1, azi1, False, s12, caps, **name)
393
+ return GeodesicLineExact(self, lat1, lon1, azi1, caps=caps, **name)._GenSet(self._debug, s12=s12)
394
394
 
395
395
  def _dn(self, sbet, cbet): # in gxline._GeodesicLineExact.__init__
396
396
  '''(INTERNAL) Helper.
@@ -497,7 +497,7 @@ class GeodesicExact(_GeodesicBase):
497
497
  Cs = Caps
498
498
  if self._debug: # PYCHOK no cover
499
499
  outmask |= Cs._DEBUG_INVERSE & self._debug
500
- outmask &= Cs._OUT_MASK # incl. _SALPs_CALPs and _DEBUG_
500
+ outmask &= Cs._OUT_MASK # incl. _S_CALPs_ and _DEBUG_
501
501
  # compute longitude difference carefully (with _diff182):
502
502
  # result is in [-180, +180] but -180 is only for west-going
503
503
  # geodesics, +180 is for east-going and meridional geodesics
@@ -505,8 +505,10 @@ class GeodesicExact(_GeodesicBase):
505
505
  # see C{result} from geographiclib.geodesic.Inverse
506
506
  if (outmask & Cs.LONG_UNROLL): # == (lon1 + lon12) + lon12s
507
507
  r = GDict(lon1=lon1, lon2=fsumf_(lon1, lon12, lon12s))
508
- else:
508
+ elif (outmask & Cs.LONGITUDE):
509
509
  r = GDict(lon1=_norm180(lon1), lon2=_norm180(lon2))
510
+ else:
511
+ r = GDict()
510
512
  if _K_2_0: # GeographicLib 2.0
511
513
  # make longitude difference positive
512
514
  lon12, lon_ = _unsigned2(lon12)
@@ -535,7 +537,8 @@ class GeodesicExact(_GeodesicBase):
535
537
  # If really close to the equator, treat as on equator.
536
538
  lat1 = _around(_fix90(lat1))
537
539
  lat2 = _around(_fix90(lat2))
538
- r.set_(lat1=lat1, lat2=lat2)
540
+ if (outmask & Cs.LATITUDE):
541
+ r.set_(lat1=lat1, lat2=lat2)
539
542
  # Swap points so that point with higher (abs) latitude is
540
543
  # point 1. If one latitude is a NAN, then it becomes lat1.
541
544
  swap_ = fabs(lat1) < fabs(lat2) or isnan(lat2)
@@ -671,7 +674,7 @@ class GeodesicExact(_GeodesicBase):
671
674
  S12 = -S12
672
675
  r.set_(S12=unsigned0(S12))
673
676
 
674
- if (outmask & (Cs.AZIMUTH | Cs._SALPs_CALPs)):
677
+ if (outmask & (Cs.AZIMUTH | Cs._S_CALPs_)):
675
678
  if swap_:
676
679
  salp1, salp2 = salp2, salp1
677
680
  calp1, calp2 = calp2, calp1
@@ -683,7 +686,7 @@ class GeodesicExact(_GeodesicBase):
683
686
  if (outmask & Cs.AZIMUTH):
684
687
  r.set_(azi1=_atan2d(salp1, calp1),
685
688
  azi2=_atan2d_reverse(salp2, calp2, reverse=outmask & Cs.REVERSE2))
686
- if (outmask & Cs._SALPs_CALPs):
689
+ if (outmask & Cs._S_CALPs_):
687
690
  r.set_(salp1=salp1, calp1=calp1,
688
691
  salp2=salp2, calp2=calp2)
689
692
 
@@ -707,25 +710,13 @@ class GeodesicExact(_GeodesicBase):
707
710
  r = self._GDictDirect(lat1, lon1, azi1, arcmode, s12_a12, outmask)
708
711
  return r.toDirect9Tuple()
709
712
 
710
- def _GenDirectLine(self, lat1, lon1, azi1, arcmode, s12_a12, caps, **name):
711
- '''(INTERNAL) Helper for C{ArcDirectLine} and C{DirectLine}.
712
-
713
- @return: A L{GeodesicLineExact} instance.
714
- '''
715
- azi1 = _norm180(azi1)
716
- # guard against underflow in salp0. Also -0 is converted to +0.
717
- s, c = _sincos2d(_around(azi1))
718
- C = caps if arcmode else (caps | Caps.DISTANCE_IN)
719
- return _GeodesicLineExact(self, lat1, lon1, azi1, C,
720
- self._debug, s, c, **name)._GenSet(arcmode, s12_a12)
721
-
722
713
  def _GenInverse(self, lat1, lon1, lat2, lon2, outmask=Caps.STANDARD):
723
714
  '''(INTERNAL) The general I{Inverse} geodesic calculation.
724
715
 
725
716
  @return: L{Inverse10Tuple}C{(a12, s12, salp1, calp1, salp2, calp2,
726
717
  m12, M12, M21, S12)}.
727
718
  '''
728
- r = self._GDictInverse(lat1, lon1, lat2, lon2, outmask | Caps._SALPs_CALPs)
719
+ r = self._GDictInverse(lat1, lon1, lat2, lon2, outmask | Caps._S_CALPs_)
729
720
  return r.toInverse10Tuple()
730
721
 
731
722
  def _Inverse(self, ll1, ll2, wrap, **outmask):
@@ -815,11 +806,9 @@ class GeodesicExact(_GeodesicBase):
815
806
  Python U{Geodesic.InverseLine<https://GeographicLib.SourceForge.io/Python/doc/code.html>}.
816
807
  '''
817
808
  Cs = Caps
818
- r = self._GDictInverse(lat1, lon1, lat2, lon2, Cs._SALPs_CALPs) # No need for AZIMUTH
819
- C = (caps | Cs.DISTANCE) if (caps & (Cs.DISTANCE_IN & Cs._OUT_MASK)) else caps
820
- azi1 = _atan2d(r.salp1, r.calp1)
821
- return _GeodesicLineExact(self, lat1, lon1, azi1, C, # ensure a12 is distance
822
- self._debug, r.salp1, r.calp1, **name)._GenSet(True, r.a12)
809
+ r = self._GDictInverse(lat1, lon1, lat2, lon2, Cs.AZIMUTH | Cs.DISTANCE | Cs._S_CALPs_)
810
+ return GeodesicLineExact(self, lat1, lon1, None, caps=caps, _s_calp1=(r.salp1, r.calp1),
811
+ **name)._GenSet(self._debug, lat2=lat2, lon2=lon2, **r)
823
812
 
824
813
  def _InverseArea(self, _meridian, salp1, calp1, # PYCHOK 9 args
825
814
  salp2, calp2,
@@ -1130,7 +1119,7 @@ class GeodesicExact(_GeodesicBase):
1130
1119
  <https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1GeodesicExact.html>}
1131
1120
  and Python U{Geodesic.Line<https://GeographicLib.SourceForge.io/Python/doc/code.html>}.
1132
1121
  '''
1133
- return _GeodesicLineExact(self, lat1, lon1, azi1, caps, self._debug, **name)
1122
+ return GeodesicLineExact(self, lat1, lon1, azi1, caps=caps, **name)._GenSet(self._debug)
1134
1123
 
1135
1124
  @Property_RO
1136
1125
  def n(self):
@@ -1250,8 +1239,8 @@ class GeodesicExact(_GeodesicBase):
1250
1239
 
1251
1240
  @return: C{GeodesicExact} (C{str}).
1252
1241
  '''
1253
- return self._instr(props=(GeodesicExact.ellipsoid,),
1254
- C4order=self.C4order, **prec_sep_name)
1242
+ t = GeodesicExact.caps, GeodesicExact.ellipsoid
1243
+ return self._instr(props=t, C4order=self.C4order, **prec_sep_name)
1255
1244
 
1256
1245
 
1257
1246
  class GeodesicLineExact(_GeodesicLineExact):
@@ -1282,7 +1271,7 @@ class GeodesicLineExact(_GeodesicLineExact):
1282
1271
  if (caps & Caps.LINE_OFF): # copy to avoid updates
1283
1272
  geodesic = geodesic.copy(deep=False, name=_UNDER_(NN, geodesic.name))
1284
1273
  # _update_all(geodesic)
1285
- _GeodesicLineExact.__init__(self, geodesic, lat1, lon1, azi1, caps, 0, **name)
1274
+ _GeodesicLineExact.__init__(self, geodesic, lat1, lon1, azi1, caps, **name)
1286
1275
 
1287
1276
 
1288
1277
  def _Astroid(x, y):
@@ -38,8 +38,8 @@ from __future__ import division as _; del _ # PYCHOK semicolon
38
38
 
39
39
  # from pygeodesy.basics import _xinstanceof # _MODS
40
40
  from pygeodesy.constants import NAN, _EPSqrt as _TOL, _0_0, _1_0, \
41
- _180_0, _2__PI, _copysign_1_0
42
- # from pygeodesy.errors import _xError # _MODS
41
+ _180_0, _2__PI, _copysign_1_0, isfinite
42
+ from pygeodesy.errors import _xError, _xkwds_pop2
43
43
  from pygeodesy.fsums import fsumf_, fsum1f_
44
44
  from pygeodesy.geodesicx.gxbases import _cosSeries, _GeodesicBase, \
45
45
  _sincos12, _sin1cos2, \
@@ -47,7 +47,8 @@ from pygeodesy.geodesicx.gxbases import _cosSeries, _GeodesicBase, \
47
47
  # from pygeodesy.geodesicw import _Intersecant2 # _MODS
48
48
  from pygeodesy.lazily import _ALL_DOCS, _ALL_MODS as _MODS
49
49
  from pygeodesy.karney import _around, _atan2d, Caps, GDict, _fix90, \
50
- _K_2_0, _norm2, _norm180, _sincos2, _sincos2d
50
+ _K_2_0, _llz2line, _norm2, _norm180, \
51
+ _sincos2, _sincos2d
51
52
  from pygeodesy.named import Property_RO, _update_all
52
53
  # from pygeodesy.props import Property_RO, _update_all # from .named
53
54
  from pygeodesy.utily import atan2d as _atan2d_reverse, sincos2
@@ -55,7 +56,7 @@ from pygeodesy.utily import atan2d as _atan2d_reverse, sincos2
55
56
  from math import atan2, cos, degrees, fabs, floor, radians, sin
56
57
 
57
58
  __all__ = ()
58
- __version__ = '24.06.24'
59
+ __version__ = '24.07.09'
59
60
 
60
61
  _glXs = [] # instances of C{[_]GeodesicLineExact} to be updated
61
62
 
@@ -92,23 +93,18 @@ class _GeodesicLineExact(_GeodesicBase):
92
93
  # _somg1 = _comg1 = NAN
93
94
  # _ssig1 = _csig1 = NAN
94
95
 
95
- def __init__(self, gX, lat1, lon1, azi1, caps, _debug, *salp1_calp1, **name):
96
+ def __init__(self, gX, lat1, lon1, azi1, caps, **name_):
96
97
  '''(INTERNAL) New C{[_]GeodesicLineExact} instance.
97
98
  '''
98
- _xGeodesicExact(gX=gX)
99
- Cs = Caps
100
- if _debug: # PYCHOK no cover
101
- self._debug |= _debug & Cs._DEBUG_ALL
102
- # _CapsBase.debug._update(self)
103
- if salp1_calp1:
104
- salp1, calp1 = salp1_calp1
105
- else:
99
+ # _xGeodesicExact(gX=gX)
100
+ if azi1 is None: # see GeodesicExact.InverseLine
101
+ (salp1, calp1), name_ = _xkwds_pop2(name_, _s_calp1=(_0_0, _1_0))
102
+ azi1 = _atan2d(salp1, calp1)
103
+ else: # guard against salp0 underflow, convert -0 to +0
106
104
  azi1 = _norm180(azi1)
107
- # guard against salp0 underflow,
108
- # also -0 is converted to +0
109
105
  salp1, calp1 = _sincos2d(_around(azi1))
110
- if name:
111
- self.name = name
106
+ if name_:
107
+ self.name = name_
112
108
 
113
109
  self._gX = gX # GeodesicExact only
114
110
  self._lat1 = lat1 = _fix90(lat1)
@@ -117,7 +113,7 @@ class _GeodesicLineExact(_GeodesicBase):
117
113
  self._salp1 = salp1
118
114
  self._calp1 = calp1
119
115
  # allow lat, azimuth and unrolling of lon
120
- self._caps = caps | Cs._LINE
116
+ self._caps = caps | Caps._LINE
121
117
 
122
118
  sbet1, cbet1 = _sinf1cos2d(_around(lat1), gX.f1)
123
119
  self._dn1 = gX._dn(sbet1, cbet1)
@@ -142,11 +138,11 @@ class _GeodesicLineExact(_GeodesicBase):
142
138
  self._ssig1, self._csig1 = _norm2(sbet1, c) # sig1 in (-pi, pi]
143
139
  # _norm2(somg1, comg1) # no need to normalize!
144
140
  # _norm2(schi1?, cchi1) # no need to normalize!
145
- if not (caps & Cs.LINE_OFF):
141
+ if not (caps & Caps.LINE_OFF):
146
142
  _glXs.append(self)
147
143
  # no need to pre-compute other attrs based on _Caps.X. All are
148
- # Property_RO's, computed once and cached/memoized until reset
149
- # when C4order is changed or Elliptic function reset is invoked.
144
+ # Property_RO's, computed once and cached/memoized until reset when
145
+ # arc, distance, C4order is changed or Elliptic function is reset.
150
146
 
151
147
  def __del__(self): # XXX use weakref?
152
148
  if _glXs: # may be empty or None
@@ -295,22 +291,18 @@ class _GeodesicLineExact(_GeodesicBase):
295
291
  C{lon1}, C{azi1} and arc length C{a12} always included,
296
292
  except when C{a12=NAN}.
297
293
  '''
298
-
299
- r = GDict(a12=NAN, s12=NAN) # note both a12 and s12, always
300
- if not (arcmode or self._caps_DISTANCE_IN): # PYCHOK no cover
301
- return r # Uninitialized or impossible distance requested
302
-
303
294
  Cs = Caps
304
- if self._debug: # PYCHOK no cover
305
- outmask |= self._debug & Cs._DEBUG_DIRECT_LINE
306
- outmask &= self._caps & Cs._OUT_MASK
307
-
295
+ if outmask:
296
+ outmask &= self._caps & Cs._OUT_MASK
308
297
  eF = self._eF
309
298
  gX = self.geodesic # ._gX
299
+ r = GDict(a12=NAN, s12=NAN) # both a12 and s12, always
310
300
 
311
- if arcmode:
312
- # s12_a12 is spherical arc length
313
- E2 = _0_0
301
+ if not isfinite(s12_a12):
302
+ # E2 = sig12 = ssig12 = csig12 = NAN
303
+ return r._toNAN(outmask)
304
+ elif arcmode: # s12_a12 is (spherical) arc length
305
+ r.set_(a12=s12_a12)
314
306
  sig12 = radians(s12_a12)
315
307
  if _K_2_0:
316
308
  ssig12, csig12 = sincos2(sig12) # utily, no NEG0
@@ -319,31 +311,25 @@ class _GeodesicLineExact(_GeodesicBase):
319
311
  a -= floor(a / _180_0) * _180_0 # 0 <= 0 < 180
320
312
  ssig12 = _0_0 if a == 0 else sin(sig12)
321
313
  csig12 = _0_0 if a == 90 else cos(sig12)
322
- else: # s12_a12 is distance
314
+ E2 = _0_0
315
+ elif self._caps_DISTANCE_IN: # s12_a12 is distance
323
316
  t = s12_a12 / self._E0b
324
317
  s, c = _sincos2(t) # tau12
325
318
  # tau2 = tau1 + tau12
326
319
  E2 = -eF.deltaEinv(*_sincos12(-s, c, *self._stau1_ctau1))
327
320
  sig12 = fsum1f_(self._E1, -E2, t) # == t - (E2 - E1)
328
321
  ssig12, csig12 = _sincos2(sig12)
329
-
330
- salp0, calp0 = self._salp0, self._calp0
331
- ssig1, csig1 = self._ssig1, self._csig1
322
+ r.set_(a12=degrees(sig12))
323
+ else: # uninitialized or impossible distance requested
324
+ return r
332
325
 
333
326
  # sig2 = sig1 + sig12
334
- ssig2, csig2 = _sincos12(-ssig12, csig12, ssig1, csig1)
335
- dn2 = eF.fDelta(ssig2, csig2)
336
- # sin(bet2) = cos(alp0) * sin(sig2) and
337
- # cbet2 = hypot(salp0, calp0 * csig2). Alt:
338
- # cbet2 = hypot(csig2, salp0 * ssig2)
339
- sbet2, cbet2 = _sin1cos2(calp0, salp0, csig2, ssig2)
340
- if cbet2 == 0: # salp0 = 0, csig2 = 0, break degeneracy
341
- cbet2 = csig2 = _TINY
342
- # tan(alp0) = cos(sig2) * tan(alp2)
343
- salp2 = salp0
344
- calp2 = calp0 * csig2 # no need to normalize
327
+ ssig1, csig1 = self._ssig1, self._csig1
328
+ ssig2, csig2 = t = _sincos12(-ssig12, csig12, ssig1, csig1)
329
+ dn2 = eF.fDelta(*t)
345
330
 
346
- if (outmask & Cs.DISTANCE):
331
+ if (outmask & Cs.DISTANCE):
332
+ outmask ^= Cs.DISTANCE
347
333
  if arcmode: # or f_0_01
348
334
  E2 = eF.deltaE(ssig2, csig2, dn2)
349
335
  # AB1 = _E0 * (E2 - _E1)
@@ -355,10 +341,34 @@ class _GeodesicLineExact(_GeodesicBase):
355
341
  s12 = s12_a12
356
342
  r.set_(s12=s12)
357
343
 
344
+ if not outmask: # all done, see ._GenSet
345
+ return r
346
+
347
+ if self._debug: # PYCHOK no cover
348
+ outmask |= self._debug & Cs._DEBUG_DIRECT_LINE
349
+
358
350
  if (outmask & Cs._DEBUG_DIRECT_LINE): # PYCHOK no cover
359
351
  r.set_(sig12=sig12, dn2=dn2, b=gX.b, e2=gX.e2, f1=gX.f1,
360
352
  E0b=self._E0b, E1=self._E1, E2=E2, eFk2=eF.k2, eFa2=eF.alpha2)
361
353
 
354
+ # sin(bet2) = cos(alp0) * sin(sig2) and
355
+ # cbet2 = hypot(salp0, calp0 * csig2). Alt:
356
+ # cbet2 = hypot(csig2, salp0 * ssig2)
357
+ salp0, calp0 = self._salp0, self._calp0
358
+ sbet2, cbet2 = _sin1cos2(calp0, salp0, csig2, ssig2)
359
+ if cbet2 == 0: # salp0 = 0, csig2 = 0, break degeneracy
360
+ cbet2 = csig2 = _TINY
361
+ # tan(alp0) = cos(sig2) * tan(alp2)
362
+ salp2 = salp0
363
+ calp2 = calp0 * csig2 # no need to normalize
364
+
365
+ if (outmask & Cs.AZIMUTH):
366
+ r.set_(azi2=_atan2d_reverse(salp2, calp2,
367
+ reverse=outmask & Cs.REVERSE2))
368
+
369
+ if (outmask & Cs.LATITUDE):
370
+ r.set_(lat2=_atan2d(sbet2, gX.f1 * cbet2))
371
+
362
372
  if (outmask & Cs.LONGITUDE):
363
373
  schi1 = self._somg1
364
374
  cchi1 = self._cchi1
@@ -372,7 +382,7 @@ class _GeodesicLineExact(_GeodesicBase):
372
382
  tchi2 = t * schi2
373
383
  chi12 = t * fsum1f_(_a(ssig1, csig1), -_a(ssig2, csig2),
374
384
  _a(tchi2, cchi2), -_a(tchi1, cchi1), sig12)
375
- lon2 = self.lon1 + degrees(chi12 - lam12)
385
+ lon2 = self.lon1 + degrees(chi12 - lam12)
376
386
  else:
377
387
  chi12 = atan2(*_sincos12(schi1, cchi1, schi2, cchi2))
378
388
  lon2 = _norm180(self._lon1_norm180 + _norm180(degrees(chi12 - lam12)))
@@ -381,12 +391,6 @@ class _GeodesicLineExact(_GeodesicBase):
381
391
  r.set_(ssig2=ssig2, chi12=chi12, H0e2_f1=self._H0e2_f1,
382
392
  csig2=csig2, lam12=lam12, H1=self._H1)
383
393
 
384
- if (outmask & Cs.LATITUDE):
385
- r.set_(lat2=_atan2d(sbet2, gX.f1 * cbet2))
386
-
387
- if (outmask & Cs.AZIMUTH):
388
- r.set_(azi2=_atan2d_reverse(salp2, calp2, reverse=outmask & Cs.REVERSE2))
389
-
390
394
  if (outmask & Cs._REDUCEDLENGTH_GEODESICSCALE):
391
395
  dn1 = self._dn1
392
396
  J12 = self._D0k2 * fsumf_(eF.deltaD(ssig2, csig2, dn2), -self._D1, sig12)
@@ -438,10 +442,9 @@ class _GeodesicLineExact(_GeodesicBase):
438
442
  S12 += gX.c2 * atan2(salp12, calp12)
439
443
  r.set_(S12=S12)
440
444
 
441
- r.set_(a12=s12_a12 if arcmode else degrees(sig12),
445
+ r.set_(azi1=_norm180(self.azi1),
442
446
  lat1=self.lat1, # == _fix90(lat1)
443
- lon1=self.lon1 if (outmask & Cs.LONG_UNROLL) else self._lon1_norm180,
444
- azi1=_norm180(self.azi1))
447
+ lon1=self.lon1 if (outmask & Cs.LONG_UNROLL) else self._lon1_norm180)
445
448
  return r
446
449
 
447
450
  def _GenPosition(self, arcmode, s12_a12, outmask):
@@ -453,14 +456,24 @@ class _GeodesicLineExact(_GeodesicBase):
453
456
  r = self._GDictPosition(arcmode, s12_a12, outmask)
454
457
  return r.toDirect9Tuple()
455
458
 
456
- def _GenSet(self, arcmode, s13_a13):
459
+ def _GenSet(self, debug, s12=None, a12=None, **llz2):
457
460
  '''(INTERNAL) Aka C++ C{GenSetDistance}.
458
461
  '''
459
- if arcmode:
460
- self.SetArc(s13_a13)
461
- else:
462
- self.SetDistance(s13_a13)
463
- return self # for gx.GeodesicExact.InverseLine and -._GenDirectLine
462
+ Cs = Caps
463
+ if debug: # PYCHOK no cover
464
+ self._debug |= debug & Cs._DEBUG_ALL
465
+ # _CapsBase.debug._update(self)
466
+ if s12 is None:
467
+ if a12 is None: # see GeodesicExact.Line
468
+ return self
469
+ s12 = self._GDictPosition(True, a12, outmask=Cs.DISTANCE).s12 if a12 else _0_0
470
+ elif a12 is None:
471
+ a12 = self._GDictPosition(False, s12, 0).a12 if s12 else _0_0
472
+ self._s13 = s12
473
+ self._a13 = a12
474
+ self._caps |= Cs.DISTANCE | Cs.DISTANCE_IN
475
+ # _update_all(self) # new, from GeodesicExact.*Line
476
+ return _llz2line(self, **llz2)
464
477
 
465
478
  @Property_RO
466
479
  def geodesic(self):
@@ -498,7 +511,7 @@ class _GeodesicLineExact(_GeodesicBase):
498
511
  try:
499
512
  return _MODS.geodesicw._Intersecant2(self, lat0, lon0, radius, tol=tol)
500
513
  except (TypeError, ValueError) as x:
501
- raise _MODS.errors._xError(x, lat0, lon0, radius, tol=_TOL)
514
+ raise _xError(x, lat0, lon0, radius, tol=_TOL)
502
515
 
503
516
  @Property_RO
504
517
  def _H0e2_f1(self):
@@ -594,8 +607,7 @@ class _GeodesicLineExact(_GeodesicBase):
594
607
  the reference point or C{NAN}.
595
608
  '''
596
609
  if self._a13 != a13:
597
- self._a13 = a13
598
- self._s13 = self._GDictPosition(True, a13, Caps.DISTANCE).s12 # if a13 else _0_0
610
+ self._GenSet(0, a12=a13)
599
611
  _update_all(self)
600
612
  return self._s13
601
613
 
@@ -608,10 +620,9 @@ class _GeodesicLineExact(_GeodesicBase):
608
620
  and the reference point or C{NAN}.
609
621
  '''
610
622
  if self._s13 != s13:
611
- self._s13 = s13
612
- self._a13 = self._GDictPosition(False, s13, 0).a12 if s13 else _0_0
623
+ self._GenSet(0, s12=s13)
613
624
  _update_all(self)
614
- return self._a13 # NAN for GeodesicLineExact without Cap.DISTANCE_IN
625
+ return self._a13
615
626
 
616
627
  @Property_RO
617
628
  def _stau1_ctau1(self):
@@ -632,7 +643,7 @@ class _GeodesicLineExact(_GeodesicBase):
632
643
  @return: C{GeodesicLineExact} (C{str}).
633
644
  '''
634
645
  C = _GeodesicLineExact
635
- t = C.lat1, C.lon1, C.azi1, C.a13, C.s13, C.geodesic
646
+ t = C.lat1, C.lon1, C.azi1, C.a13, C.s13, C.caps, C.geodesic
636
647
  return self._instr(props=t, **prec_sep_name)
637
648
 
638
649