pygeodesy 25.8.25__py2.py3-none-any.whl → 25.9.9__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
pygeodesy/internals.py CHANGED
@@ -4,10 +4,10 @@
4
4
  u'''Mostly INTERNAL functions, except L{machine}, L{print_} and L{printf}.
5
5
  '''
6
6
  # from pygeodesy.basics import isiterablen, ubstr # _MODS
7
- # from pygeodesy.errors import _AttributeError, _error_init, _UnexpectedError, _xError2 # _MODS
8
- from pygeodesy.interns import _BAR_, _COLON_, _DASH_, _DMAIN_, _DOT_, _ELLIPSIS_, _EQUALSPACED_, \
9
- _immutable_, _NL_, NN, _pygeodesy_, _PyPy__, _python_, _QUOTE1_, \
10
- _QUOTE2_, _s_, _SPACE_, _sys, _UNDER_
7
+ # from pygeodesy.errors import _AttributeError, _error_init, _ImmutableError, _UnexpectedError, _xError2 # _MODS
8
+ from pygeodesy.interns import _BAR_, _COLON_, _DASH_, _DMAIN_, _DOT_, _ELLIPSIS_, _NL_, NN, \
9
+ _pygeodesy_, _PyPy__, _python_, _QUOTE1_, _QUOTE2_, _s_, _sys, \
10
+ _SPACE_, _UNDER_
11
11
  from pygeodesy.interns import _COMMA_, _Python_ # PYCHOK used!
12
12
  # from pygeodesy.streprs import anstr, pairs, unstr # _MODS
13
13
 
@@ -56,6 +56,27 @@ def _Property_RO(method):
56
56
  return property(_get, _set, _del)
57
57
 
58
58
 
59
+ class _Enum(object): # in .elliptic, .utily
60
+ '''(INTERNAL) Enum-like, immutable items.
61
+ '''
62
+ # _ImmutableError = None
63
+
64
+ def __init__(self, **enums):
65
+ self.__dict__.update(enums)
66
+ # for item in enums.items():
67
+ # setattr(self, *item) # object.__setattr__
68
+
69
+ def __str__(self):
70
+ _unstr = _MODS.streprs.unstr
71
+ return _unstr(_Enum, **self.__dict__)
72
+
73
+ # def __delattr__(self, attr): # PYCHOK no cover
74
+ # raise _ImmutableError(self, attr) # _del_
75
+
76
+ # def __setattr__(self, attr, value): # PYCHOK no cover
77
+ # raise _ImmutableError(self, attr, value)
78
+
79
+
59
80
  class _MODS_Base(object):
60
81
  '''(INTERNAL) Base-class for C{lazily._ALL_MODS}.
61
82
  '''
@@ -63,10 +84,7 @@ class _MODS_Base(object):
63
84
  self.__dict__.pop(attr, None)
64
85
 
65
86
  def __setattr__(self, attr, value): # PYCHOK no cover
66
- e = _MODS.errors
67
- n = _DOT_(self.name, attr)
68
- t = _EQUALSPACED_(n, repr(value))
69
- raise e._AttributeError(_immutable_, txt=t)
87
+ raise _ImmutableError(self, attr, value)
70
88
 
71
89
  @_Property_RO
72
90
  def basics(self):
@@ -302,6 +320,12 @@ def _headof(name):
302
320
  return name if i < 0 else name[:i]
303
321
 
304
322
 
323
+ def _ImmutableError(*inst_attr_value):
324
+ '''(INTERNAL) Format an C{_ImmutableError}.
325
+ '''
326
+ return _MODS.errors._ImmutableError(*inst_attr_value)
327
+
328
+
305
329
  # def _is(a, b): # PYCHOK no cover
306
330
  # '''(INTERNAL) C{a is b}? in C{PyPy}
307
331
  # '''
@@ -473,10 +497,10 @@ def printf(fmt, *args, **nl_nt_prec_prefix__end_file_flush_sep__kwds):
473
497
  else:
474
498
  t = fmt
475
499
  except Exception as x:
476
- _E, s = _MODS.errors._xError2(x)
477
- unstr = _MODS.streprs.unstr
478
- t = unstr(printf, fmt, *args, **nl_nt_prec_prefix__end_file_flush_sep__kwds)
479
- raise _E(s, txt=t, cause=x)
500
+ _Error, s = _MODS.errors._xError2(x)
501
+ _unstr = _MODS.strepr.unstr
502
+ t = _unstr(printf, fmt, *args, **nl_nt_prec_prefix__end_file_flush_sep__kwds)
503
+ raise _Error(s, txt=t, cause=x)
480
504
  try:
481
505
  n = f.write(NN(b, t, e))
482
506
  except UnicodeEncodeError: # XXX only Windows
@@ -686,7 +710,7 @@ def _versions(sep=_SPACE_):
686
710
 
687
711
 
688
712
  __all__ = tuple(map(typename, (machine, print_, printf, typename)))
689
- __version__ = '25.08.18'
713
+ __version__ = '25.09.05'
690
714
 
691
715
  if __name__ == _DMAIN_:
692
716
 
pygeodesy/karney.py CHANGED
@@ -157,8 +157,7 @@ from pygeodesy.interns import NN, _a12_, _area_, _azi1_, _azi2_, _azi12_, \
157
157
  _SPACE_, _UNDER_, _X_, _1_, _2_, _BAR_ # PYCHOK used!
158
158
  from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS, _FOR_DOCS
159
159
  from pygeodesy.named import ADict, _NamedBase, _NamedTuple, notImplemented, _Pass
160
- from pygeodesy.props import deprecated_method, Property_RO, property_RO, \
161
- property_ROnce
160
+ from pygeodesy.props import deprecated_method, property_RO, property_ROnce
162
161
  from pygeodesy.units import Azimuth as _Azi, Degrees as _Deg, Lat, Lon, \
163
162
  Meter as _M, Meter2 as _M2, Number_
164
163
  from pygeodesy.utily import atan2d, sincos2d, tand, _unrollon, fabs
@@ -166,7 +165,7 @@ from pygeodesy.utily import atan2d, sincos2d, tand, _unrollon, fabs
166
165
  # from math import fabs # from .utily
167
166
 
168
167
  __all__ = _ALL_LAZY.karney
169
- __version__ = '25.05.28'
168
+ __version__ = '25.08.31'
170
169
 
171
170
  _2_4_ = '2.4'
172
171
  _K_2_0 = _getenv(_PYGEODESY_ENV(typename(_xgeographiclib)[2:]), _2_)
@@ -270,16 +269,16 @@ class Caps(object):
270
269
  REDUCEDLENGTH = 1 << 12 | _CAP_1 | _CAP_2 # compute reduced length C{m12}
271
270
  GEODESICSCALE = 1 << 13 | _CAP_1 | _CAP_2 # compute geodesic scales C{M12} and C{M21}
272
271
  AREA = 1 << 14 | _CAP_4 # compute area C{S12}
272
+ ALL = 0x7F80 | _CAP_ALL # without LONG_UNROLL, LINE_OFF, NONFINITONAN, REVERSE2 and _DEBUG_*
273
273
 
274
274
  STANDARD = AZIMUTH | DISTANCE | LATITUDE | LONGITUDE
275
275
  STANDARD_LINE = STANDARD | DISTANCE_IN # for goedesici/-w
276
276
 
277
277
  LINE_CAPS = STANDARD_LINE | REDUCEDLENGTH | GEODESICSCALE # .geodesici only
278
278
  LONG_UNROLL = 1 << 15 # unroll C{lon2} in .Direct and .Position
279
- NONFINITONAN = 1 << 16 # see method GDict._toNAN
280
- LINE_OFF = 1 << 17 # Line without updates from parent geodesic or rhumb
279
+ LINE_OFF = 1 << 16 # Line without updates from parent geodesic or rhumb
280
+ NONFINITONAN = 1 << 17 # see method GDict._toNAN
281
281
  REVERSE2 = 1 << 18 # reverse C{azi2}
282
- ALL = 0x7F80 | _CAP_ALL # without LONG_UNROLL, LINE_OFF, REVERSE2 and _DEBUG_*
283
282
 
284
283
  AZIMUTH_DISTANCE = AZIMUTH | DISTANCE
285
284
  AZIMUTH_DISTANCE_AREA = AZIMUTH | DISTANCE | AREA
@@ -300,7 +299,7 @@ class Caps(object):
300
299
  _INVERSE3 = AZIMUTH | DISTANCE # for goedesicw only
301
300
 
302
301
  _OUT_ALL = ALL # see geographiclib.geodesiccapabilities.py
303
- _OUT_MASK = ALL | LONG_UNROLL | REVERSE2 | _DEBUG_ALL
302
+ _OUT_MASK = ALL | LONG_UNROLL | NONFINITONAN | REVERSE2 | _DEBUG_ALL
304
303
 
305
304
  _AZIMUTH_LATITUDE_LONGITUDE = AZIMUTH | LATITUDE | LONGITUDE
306
305
  _AZIMUTH_LATITUDE_LONG_UNROLL = AZIMUTH | LATITUDE | LONG_UNROLL
@@ -366,7 +365,7 @@ class _CapsBase(_NamedBase): # in .auxilats, .geodesicx.gxbases
366
365
  _caps = 0 # None
367
366
  _debug = 0 # or Caps._DEBUG_...
368
367
 
369
- @Property_RO
368
+ @property_RO
370
369
  def caps(self):
371
370
  '''Get the capabilities (bit-or'ed C{Caps}).
372
371
  '''
@@ -455,13 +454,16 @@ class GDict(ADict): # XXX _NamedDict
455
454
  '''
456
455
  return self._toTuple(Inverse10Tuple, dflt)
457
456
 
458
- def _toNAN(self, outmask): # .GeodesicExact._GDistInverse, .GeodesicLineExact._GenPosition
457
+ def _toNAN(self, outmask, **specs): # .GeodesicExact._GDistInverse, .GeodesicLineExact._GenPosition
459
458
  '''(INTERNAL) Convert this C{GDict} to all C{NAN}s.
460
459
  '''
461
460
  if (outmask & Caps.NONFINITONAN):
462
- d = dict((k, NAN) for k, C in _key2Caps.items()
463
- if (outmask & C) == C)
464
- self.set_(**d)
461
+ def _t2(k):
462
+ return k, specs.get(k, NAN)
463
+
464
+ d = dict(_t2(k) for k, C in _key2Caps.items()
465
+ if (outmask & C) == C)
466
+ self.set_(**d) # self.update(d)
465
467
  return self
466
468
 
467
469
  @deprecated_method
@@ -721,12 +723,11 @@ def _around(x): # in .utily.sincos2d
721
723
  try:
722
724
  return _wrapped.Math.AngRound(x)
723
725
  except AttributeError:
724
- if x:
725
- y = _1_16th - fabs(x)
726
- if y > 0: # fabs(x) < _1_16th
727
- x = _copysign(_1_16th - y, x)
728
- else:
729
- x = _0_0 # -0 to 0
726
+ b, a = _1_16th, fabs(x)
727
+ if a < b:
728
+ a -= b
729
+ a += b
730
+ x = _copysign(a, x)
730
731
  return x
731
732
 
732
733
 
pygeodesy/ktm.py CHANGED
@@ -66,7 +66,7 @@ from cmath import polar as _polar
66
66
  from math import asinh, cos, cosh, degrees, fabs, sin, sinh, sqrt, tanh
67
67
 
68
68
  __all__ = _ALL_LAZY.ktm
69
- __version__ = '25.08.18'
69
+ __version__ = '25.08.31'
70
70
 
71
71
 
72
72
  class KTMError(_ValueError):
pygeodesy/lazily.py CHANGED
@@ -29,15 +29,15 @@ and line number.
29
29
 
30
30
  from pygeodesy import internals as _internals, interns as _interns, \
31
31
  _isfrozen # DON'T _lazy_import2
32
- # from pygeodesy.errors import _error_init, _xkwds_item2 # _ALL_MODS
32
+ # from pygeodesy.errors import _error_init, _ImmutableError, _xkwds_item2 # _ALL_MODS
33
33
  from pygeodesy.internals import _caller3, _envPYGEODESY, _headof, printf, _tailof, \
34
34
  typename, _versions # _getenv, _PYGEODESY_ENV, \
35
35
  # _MODS_Base, _MODS.sys_version_info2
36
36
  from pygeodesy.interns import _attribute_, _by_, _COLONSPACE_, _COMMASPACE_, _DALL_, \
37
37
  _DMAIN_, _doesn_t_exist_, _DOT_, _EQUALSPACED_, _from_, \
38
- _HASH_, _immutable_, _line_, _module_, NN, _no_, _not_, \
39
- _pygeodesy_, _pygeodesy_abspath_, _SPACE_, _SUB_PACKAGES, \
40
- _or_, _UNDER_, _version_, _sys, _intern # function, _1_
38
+ _HASH_, _line_, _module_, NN, _no_, _not_, _pygeodesy_, \
39
+ _pygeodesy_abspath_, _SPACE_, _SUB_PACKAGES, _or_, \
40
+ _UNDER_, _version_, _sys, _intern # function, _1_
41
41
  try:
42
42
  from importlib import import_module
43
43
  except ImportError as x: # Python 2.6-
@@ -125,8 +125,9 @@ class _NamedEnum_RO(dict):
125
125
  raise LazyAttributeError(t, txt=_doesn_t_exist_)
126
126
 
127
127
  def __setattr__(self, attr, value): # PYCHOK no cover
128
- t = _EQUALSPACED_(self._DOT_(attr), repr(value))
129
- raise LazyAttributeError(_immutable_, txt=t)
128
+ e = _ALL_MODS.errors
129
+ raise e._ImmutableError(self, attr, value,
130
+ Error=LazyAttributeError)
130
131
 
131
132
  def enums(self):
132
133
  # Yield all C{(mod_, tuple)} pairs
@@ -200,10 +201,10 @@ _ALL_LAZY = _NamedEnum_RO(_name='_ALL_LAZY',
200
201
  'EasNorAziRk4Tuple', 'EasNorAziRkEqu6Tuple', 'LatLonAziRk4Tuple'),
201
202
  constants=_a('DIG', 'EPS', 'EPS0', 'EPS02', 'EPS1', 'EPS2', 'EPS4', 'EPS_2',
202
203
  'INF', 'INT0', 'MANT_DIG', 'MAX', 'MAX_EXP', 'MIN', 'MIN_EXP', 'NAN', 'NEG0', 'NINF',
203
- 'PI', 'PI2', 'PI_2', 'PI3', 'PI_3', 'PI3_2', 'PI4', 'PI_4',
204
+ 'PI', 'PI2', 'PI_2', 'PI3', 'PI_3', 'PI3_2', 'PI4', 'PI_4', 'PI_6',
204
205
  'R_FM', 'R_GM', 'R_KM', 'R_M', 'R_MA', 'R_MB', 'R_NM', 'R_QM', 'R_SM', 'R_VM',
205
206
  'float_', 'float0_', 'isclose', 'isfinite', 'isinf', 'isint0',
206
- 'isnan', 'isnear0', 'isnear1', 'isnear90', 'isneg0', 'isninf', 'isnon0',
207
+ 'isnan', 'isnear0', 'isnear1', 'isnear90', 'isneg', 'isneg0', 'isninf', 'isnon0',
207
208
  'remainder'),
208
209
  datums=_a('Datum', 'Datums', 'Transform', 'Transforms'),
209
210
  # deprecated=_a(), # module only
@@ -357,11 +358,11 @@ _ALL_LAZY = _NamedEnum_RO(_name='_ALL_LAZY',
357
358
  'Radius_', 'Scalar', 'Scalar_', 'Zone'),
358
359
  unitsBase=_a('Float', 'Int', 'Radius', 'Str'),
359
360
  ups=_a('Ups', 'UPSError', 'parseUPS5', 'toUps8', 'upsZoneBand5'),
360
- utily=_a('acos1', 'acre2ha', 'acre2m2', 'asin1', 'atan1', 'atan1d', 'atan2', 'atan2b', 'atan2d',
361
+ utily=_a('acos1', 'acre2ha', 'acre2m2', 'agdf', 'asin1', 'atan1', 'atan1d', 'atan2', 'atan2b', 'atan2d',
361
362
  'chain2m', 'circle4', 'cot', 'cot_', 'cotd', 'cotd_',
362
363
  'degrees', 'degrees90', 'degrees180', 'degrees360', 'degrees2grades', 'degrees2m',
363
364
  'fathom2m', 'ft2m', 'furlong2m', # 'degrees2grades as degrees2gons',
364
- 'grades', 'grades400', 'grades2degrees', 'grades2radians',
365
+ 'gdf', 'grades', 'grades400', 'grades2degrees', 'grades2radians',
365
366
  # 'grades as gons', 'grades400 as gons400', 'grades2degrees as gons2degrees', 'grades2radians as gons2radians',
366
367
  'ha2acre', 'ha2m2', 'hav', 'km2m',
367
368
  'm2acre', 'm2chain', 'm2degrees', 'm2fathom', 'm2ft', 'm2furlong',
@@ -510,7 +511,7 @@ class _ALL_MODS(_internals._MODS_Base):
510
511
  _internals._MODS = _ALL_MODS = _ALL_MODS() # PYCHOK singleton
511
512
 
512
513
  __all__ = _ALL_LAZY.lazily
513
- __version__ = '25.08.22'
514
+ __version__ = '25.09.09'
514
515
 
515
516
 
516
517
  def _ALL_OTHER(*objs):
pygeodesy/lcc.py CHANGED
@@ -24,10 +24,10 @@ and John P. Snyder U{'Map Projections - A Working Manual'<https://Pubs.USGS.gov/
24
24
  # make sure int/int division yields float quotient, see .basics
25
25
  from __future__ import division as _; del _ # noqa: E702 ;
26
26
 
27
- from pygeodesy.basics import copysign0, _isin, _xinstanceof, _xsubclassof, \
28
- typename
29
- from pygeodesy.constants import EPS, EPS02, PI_2, _float as _F, _0_0, _0_5, \
30
- _1_0, _2_0, _90_0
27
+ from pygeodesy.basics import copysign0, _isin, typename, \
28
+ _xinstanceof, _xsubclassof
29
+ from pygeodesy.constants import EPS, EPS02, PI_2, _float as _F, \
30
+ _0_0, _0_5, _1_0, _2_0, _90_0
31
31
  from pygeodesy.ellipsoidalBase import LatLonEllipsoidalBase as _LLEB
32
32
  from pygeodesy.datums import Datums, _ellipsoidal_datum
33
33
  from pygeodesy.errors import _IsnotError, _ValueError
@@ -50,7 +50,7 @@ from pygeodesy.utily import atan1, degrees90, degrees180, sincos2, tanPI_2_2
50
50
  from math import atan, fabs, log, radians, sin, sqrt
51
51
 
52
52
  __all__ = _ALL_LAZY.lcc
53
- __version__ = '25.05.26'
53
+ __version__ = '25.08.31'
54
54
 
55
55
  _E0_ = 'E0'
56
56
  _N0_ = 'N0'
pygeodesy/named.py CHANGED
@@ -16,17 +16,17 @@ standard Python C{namedtuple}s.
16
16
  from pygeodesy.basics import isbool, isidentifier, iskeyword, isstr, itemsorted, \
17
17
  len2, _xcopy, _xdup, _xinstanceof, _xsubclassof, _zip
18
18
  # from pygeodesy.ecef import EcefKarney # _MODS
19
- from pygeodesy.errors import _AssertionError, _AttributeError, _incompatible, \
20
- _IndexError, _KeyError, LenError, _NameError, \
21
- _NotImplementedError, _TypeError, _TypesError, \
22
- _UnexpectedError, UnitError, _ValueError, \
19
+ from pygeodesy.errors import _AssertionError, _AttributeError, _ImmutableError, \
20
+ _incompatible, _IndexError, _KeyError, LenError, \
21
+ _NameError, _NotImplementedError, _TypeError, \
22
+ _TypesError, _UnexpectedError, UnitError, _ValueError, \
23
23
  _xattr, _xkwds, _xkwds_item2, _xkwds_pop2
24
24
  from pygeodesy.internals import _caller3, _envPYGEODESY, _isPyPy, _sizeof, \
25
25
  typename, _under
26
26
  from pygeodesy.interns import MISSING, NN, _AT_, _COLON_, _COLONSPACE_, _COMMA_, \
27
27
  _COMMASPACE_, _DNAME_, _doesn_t_exist_, _DOT_, _DUNDER_, \
28
- _EQUAL_, _exists_, _immutable_, _name_, _NL_, _NN_, \
29
- _no_, _other_, _s_, _SPACE_, _std_, _UNDER_, _vs_
28
+ _EQUAL_, _exists_, _name_, _NL_, _NN_, _no_, _other_, \
29
+ _s_, _SPACE_, _std_, _UNDER_, _vs_
30
30
  from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS
31
31
  from pygeodesy.props import _allPropertiesOf_n, deprecated_method, _hasProperty, \
32
32
  _update_all, property_doc_, Property_RO, property_RO, \
@@ -35,11 +35,10 @@ from pygeodesy.streprs import attrs, Fmt, lrstrip, pairs, reprs, unstr
35
35
  # from pygeodesy.units import _toUnit # _MODS
36
36
 
37
37
  __all__ = _ALL_LAZY.named
38
- __version__ = '25.04.28'
38
+ __version__ = '25.09.04'
39
39
 
40
40
  _COMMANL_ = _COMMA_ + _NL_
41
41
  _COMMASPACEDOT_ = _COMMASPACE_ + _DOT_
42
- _del_ = 'del'
43
42
  _item_ = 'item'
44
43
  _MRO_ = 'MRO'
45
44
  # __DUNDER gets mangled in class
@@ -111,7 +110,7 @@ class ADict(dict):
111
110
  self._iteration = iteration
112
111
  if items:
113
112
  dict.update(self, items)
114
- return self # in RhumbLineBase.Intersecant2, _PseudoRhumbLine.Position
113
+ return self # in RhumbLineBase.Intersecant2, _PseudoRhumbLine.Position, ...
115
114
 
116
115
  def _toL(self):
117
116
  '''(INTERNAL) Get items as list.
@@ -977,8 +976,7 @@ class _NamedTuple(tuple, _Named):
977
976
  @note: Items can not be deleted.
978
977
  '''
979
978
  if name in self._Names_:
980
- t = _SPACE_(_del_, self._DOT_(name))
981
- raise _TypeError(t, txt=_immutable_)
979
+ raise _ImmutableError(self, name) # _del_
982
980
  elif name in (_name_, _name):
983
981
  _Named.__setattr__(self, name, NN) # XXX _Named.name.fset(self, NN)
984
982
  else:
@@ -1011,8 +1009,7 @@ class _NamedTuple(tuple, _Named):
1011
1009
  '''Set attribute or item B{C{name}} to B{C{value}}.
1012
1010
  '''
1013
1011
  if name in self._Names_:
1014
- t = Fmt.EQUALSPACED(self._DOT_(name), repr(value))
1015
- raise _TypeError(t, txt=_immutable_)
1012
+ raise _ImmutableError(self, name, value)
1016
1013
  elif name in (_name_, _name):
1017
1014
  _Named.__setattr__(self, name, value) # XXX _Named.name.fset(self, value)
1018
1015
  else: # e.g. _iteration
@@ -9,7 +9,7 @@ u'''Package of lazily imported C{rhumb} modules L{rhumb.aux_}, L{rhumb.ekx} and
9
9
  from pygeodesy.lazily import _ALL_LAZY, _ALL_OTHER, _lazy_import_as, _unLazy0
10
10
 
11
11
  __all__ = _ALL_LAZY.rhumb
12
- __version__ = '25.04.14'
12
+ __version__ = '25.08.28'
13
13
 
14
14
  if _unLazy0: # or _isfrozen
15
15
  from pygeodesy.rhumb.aux_ import RhumbAux, RhumbLineAux
pygeodesy/rhumb/aux_.py CHANGED
@@ -48,7 +48,7 @@ from pygeodesy.rhumb.bases import RhumbBase, RhumbLineBase, \
48
48
  from math import ceil as _ceil, fabs, radians
49
49
 
50
50
  __all__ = _ALL_LAZY.rhumb_aux_
51
- __version__ = '25.05.12'
51
+ __version__ = '25.08.31'
52
52
 
53
53
  # DIGITS = (sizeof(real) * 8) bits
54
54
  # = (ctypes.sizeof(ctypes.c_double(1.0)) * 8) bits
pygeodesy/rhumb/bases.py CHANGED
@@ -732,8 +732,7 @@ class RhumbLineBase(_CapsBase):
732
732
  azi02=other.azi12, a02=t.a12, s02=t.s12,
733
733
  at=other.azi12 - self.azi12, iteration=i)
734
734
  except Exception as x:
735
- raise IntersectionError(self, other, tol=tol,
736
- eps=eps, cause=x)
735
+ raise IntersectionError(self, other, tol=tol, cause=x, **eps)
737
736
  return P
738
737
 
739
738
  def Inverse(self, lat2, lon2, wrap=False, **outmask):
@@ -870,19 +869,19 @@ class RhumbLineBase(_CapsBase):
870
869
  P = self.Intersection(rl, tol=tol, eps=eps)
871
870
 
872
871
  else: # C{rhumb-intercept}
873
- E = self.ellipsoid
874
- _gI = E.geodesic_(exact=exact).Inverse
875
- gm = Cs.STANDARD | Cs._REDUCEDLENGTH_GEODESICSCALE # ^ Cs.DISTANCE_IN
872
+ E = self.ellipsoid
873
+ _gI = E.geodesic_(exact=exact).Inverse
874
+ gm = Cs.STANDARD | Cs._REDUCEDLENGTH_GEODESICSCALE # ^ Cs.DISTANCE_IN
875
+ _d2 = _diff182
876
876
  if est is None: # get an estimate from the "perpendicular" geodesic
877
877
  r = _gI(self.lat1, self.lon1, lat0, lon0, outmask=Cs.AZIMUTH_DISTANCE)
878
- d, _ = _diff182(r.azi2, self.azi12, K_2_0=True)
878
+ d, _ = _d2(r.azi2, self.azi12, K_2_0=True)
879
879
  _, s12 = sincos2d(d)
880
880
  s12 *= r.s12 # signed
881
881
  else:
882
882
  s12 = Meter(est=est)
883
883
  try:
884
884
  _abs = fabs
885
- _d2 = _diff182
886
885
  _ErT = E.rocPrimeVertical # aka rocTransverse
887
886
  _ovr = _over
888
887
  _S12 = Fsum(s12).fsum2f_
@@ -894,7 +893,7 @@ class RhumbLineBase(_CapsBase):
894
893
  s, c, s2, c2 = _scd(d, r.lat2)
895
894
  c2 *= _ErT(r.lat2)
896
895
  s *= _ovr(s2 * self._salp, c2) - _ovr(s * r.M21, r.m12)
897
- s12, t = _S12(c / s) # XXX _ovr?
896
+ s12, t = _S12(c / s) if s else (s12, s) # XXX _ovr?
898
897
  if _abs(t) < tol: # or _abs(c) < EPS
899
898
  break
900
899
  P.set_(azi0=r.azi1, a02=r.a12, s02=r.s12, # azi2=r.azi2,
pygeodesy/rhumb/ekx.py CHANGED
@@ -22,9 +22,9 @@ License. For more information, see the U{GeographicLib<https://GeographicLib.So
22
22
  # make sure int/int division yields float quotient
23
23
  from __future__ import division as _; del _ # noqa: E702 ;
24
24
 
25
- from pygeodesy.basics import copysign0, neg
26
- from pygeodesy.constants import PI_2, _0_0s, _0_0, _0_5, _1_0, \
27
- _2_0, _4_0, _720_0, _over, _1_over
25
+ # from pygeodesy.basics import copysign0, neg # _MODS
26
+ from pygeodesy.constants import PI_2, _over, _1_over, _0_0s, \
27
+ _0_0, _0_5, _1_0, _2_0, _4_0, _720_0
28
28
  # from pygeodesy.datums import _WGS84 # from .rhumb.bases
29
29
  # from pygeodesy.deprecated import RhumbOrder2Tuple # _MODS
30
30
  from pygeodesy.errors import RhumbError, _xkwds_pop2, _Xorder
@@ -42,7 +42,7 @@ from pygeodesy.utily import atan1, sincos2_
42
42
  from math import asinh, atan, cos, cosh, radians, sin, sinh, sqrt, tan # as _tan
43
43
 
44
44
  __all__ = _ALL_LAZY.rhumb_ekx
45
- __version__ = '25.05.12'
45
+ __version__ = '25.08.31'
46
46
 
47
47
 
48
48
  class Rhumb(RhumbBase):
@@ -159,9 +159,9 @@ class Rhumb(RhumbBase):
159
159
  if (outmask & Cs.DISTANCE):
160
160
  a = s = hypot(lon12, psi12)
161
161
  if a:
162
- a *= self._DIsometric2Rectifyingd(psi2, psi1)
163
- s = self._mpd * a # == E._Lpd
164
- a = copysign0(a, s)
162
+ a *= self._DIsometric2Rectifyingd(psi2, psi1)
163
+ s = self._mpd * a # == E._Lpd
164
+ a = _MODS.basics.copysign0(a, s)
165
165
  r.set_(a12=a, s12=s)
166
166
 
167
167
  if ((outmask | self._debug) & Cs._DEBUG_INVERSE): # PYCHOK no cover
@@ -306,7 +306,7 @@ class RhumbLine(RhumbLineBase):
306
306
 
307
307
  @Property_RO
308
308
  def _psi1(self):
309
- '''(INTERNAL) Get the I{isometric auxiliary} latitude C{psi} (C{degrees}).
309
+ '''(INTERNAL) Get the I{isometric auxiliary} latitude (C{degrees}).
310
310
  '''
311
311
  return self.ellipsoid.auxIsometric(self.lat1)
312
312
 
@@ -465,7 +465,7 @@ def _sincosSeries(sinp, x, y, C, n):
465
465
  # SC = sinp ? sin : cos
466
466
  # CS = sinp ? cos : sin
467
467
  # ...
468
- d, _neg = (x - y), neg
468
+ d, _neg = (x - y), _MODS.basics.neg
469
469
  sp, cp, sd, cd = sincos2_(x + y, d)
470
470
  sd = (sd / d) if d else _1_0
471
471
  s = _neg(sp * sd) # negative
pygeodesy/solveBase.py CHANGED
@@ -23,7 +23,7 @@ from pygeodesy.units import Precision_
23
23
  from pygeodesy.utily import unroll180
24
24
 
25
25
  __all__ = _ALL_LAZY.solveBase
26
- __version__ = '25.05.12'
26
+ __version__ = '25.09.02'
27
27
 
28
28
  _ERROR_ = 'ERROR'
29
29
 
@@ -63,10 +63,16 @@ class _SolveCapsBase(_CapsBase):
63
63
 
64
64
  @Property_RO
65
65
  def a(self):
66
- '''Get the I{equatorial} radius, semi-axis (C{meter}).
66
+ '''Get the ellipsoid's I{equatorial} radius, semi-axis (C{meter}).
67
67
  '''
68
68
  return self.ellipsoid.a
69
69
 
70
+ @Property_RO
71
+ def b(self):
72
+ '''Get the ellipsoid's I{polar} radius, semi-axis (C{meter}).
73
+ '''
74
+ return self.ellipsoid.b
75
+
70
76
  @property_RO
71
77
  def _cmdBasic(self): # PYCHOK no covers '''(INTERNAL) I{Must be overloaded}.'''
72
78
  notOverloaded(self, underOK=True)
@@ -381,6 +387,11 @@ class _SolveGDictBase(_SolveBase):
381
387
  if path:
382
388
  self._setXable(path)
383
389
 
390
+ def ArcDirect(self, lat1, lon1, azi1, a12, outmask=_UNUSED_): # PYCHOK unused
391
+ '''Return the C{Direct} result at C{a12} degrees.
392
+ '''
393
+ return self._GDictDirect(lat1, lon1, azi1, True, a12)
394
+
384
395
  @Property_RO
385
396
  def _cmdDirect(self):
386
397
  '''(INTERNAL) Get the C{Solve} I{Direct} cmd (C{tuple}).
@@ -394,7 +405,7 @@ class _SolveGDictBase(_SolveBase):
394
405
  return self._cmdBasic + ('-i',)
395
406
 
396
407
  def Direct(self, lat1, lon1, azi1, s12, outmask=_UNUSED_): # PYCHOK unused
397
- '''Return the C{Direct} result.
408
+ '''Return the C{Direct} result at distance C{s12}.
398
409
  '''
399
410
  return self._GDictDirect(lat1, lon1, azi1, False, s12)
400
411
 
@@ -17,9 +17,9 @@ U{Latitude/Longitude<https://www.Movable-Type.co.UK/scripts/latlong.html>}.
17
17
  from __future__ import division as _; del _ # noqa: E702 ;
18
18
 
19
19
  from pygeodesy.basics import copysign0, _isin, map1, signOf, typename
20
- from pygeodesy.constants import EPS, EPS1, EPS4, PI, PI2, PI_2, PI_4, R_M, \
21
- isnear0, isnear1, isnon0, _0_0, _0_5, \
22
- _1_0, _2_0, _90_0
20
+ from pygeodesy.constants import EPS, EPS1, EPS4, PI, PI2, PI_2, PI_4, \
21
+ R_M, _0_0, _0_5, _1_0, _2_0, _90_0, \
22
+ isnear0, isnear1, isnon0
23
23
  from pygeodesy.datums import _ellipsoidal_datum, _mean_radius
24
24
  from pygeodesy.errors import _AssertionError, CrossError, crosserrors, \
25
25
  _TypeError, _ValueError, IntersectionError, \
@@ -57,7 +57,7 @@ from pygeodesy.vector3d import sumOf, Vector3d
57
57
  from math import asin, cos, degrees, fabs, radians, sin
58
58
 
59
59
  __all__ = _ALL_LAZY.sphericalTrigonometry
60
- __version__ = '25.08.18'
60
+ __version__ = '25.08.31'
61
61
 
62
62
  _PI_EPS4 = PI - EPS4
63
63
  if _PI_EPS4 >= PI: