pygeodesy 24.6.24__py2.py3-none-any.whl → 24.7.24__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/karney.py CHANGED
@@ -4,14 +4,12 @@
4
4
  u'''Wrapper around several C{geomath.Math} functions from I{Karney}'s Python package U{geographiclib
5
5
  <https://PyPI.org/project/geographiclib>}, provided that package is installed.
6
6
 
7
- The I{wrapped} class methods return a L{GDict} instance offering access to the C{dict} items
8
- either by C{key} or by C{attribute} name.
9
- All methods of the I{wrapped} L{Geodesic<geodesicw.Geodesic>} and L{GeodesicLine<geodesicw.GeodesicLine>}
7
+ Methods of the I{wrapped} L{Geodesic<geodesicw.Geodesic>} and L{GeodesicLine<geodesicw.GeodesicLine>}
10
8
  classes return a L{GDict} instance offering access to the C{dict} items either by C{key} or by
11
9
  C{attribute} name.
12
10
 
13
- With env variable C{PYGEODESY_GEOGRAPHICLIB} left undefined or set to C{"2"}, modules L{geodesicx},
14
- L{geodesicw} and this module will use U{GeographicLib 2.0<https://GeographicLib.SourceForge.io/C++/doc/>}
11
+ With env variable C{PYGEODESY_GEOGRAPHICLIB} left undefined or set to C{"2"}, modules L{geodesicw},
12
+ L{geodesicx} and this module will use U{GeographicLib 2.0+<https://GeographicLib.SourceForge.io/C++/doc/>}
15
13
  and newer transcoding, otherwise C{1.52} or older.
16
14
 
17
15
  Karney-based functionality
@@ -60,8 +58,11 @@ Karney-based functionality
60
58
  - L{GnomonicExact}, L{GnomonicGeodSolve}, L{GnomonicKarney} -- U{Gnomonic
61
59
  <https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1Gnomonic.html>}
62
60
 
61
+ - L{Intersector} -- U{Intersect
62
+ <https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1Intersect.html>} from I{GeographicLib 2.3+}
63
+
63
64
  - L{JacobiConformal} -- U{JacobiConformal
64
- <https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1JacobiConformal.html#details>}
65
+ <https://geographiclib.sourceforge.io/C++/doc/classGeographicLib_1_1experimental_1_1JacobiConformal.html>}
65
66
 
66
67
  - L{KTransverseMercator} - U{TransverseMercator
67
68
  <https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1TransverseMercator.html>}
@@ -94,13 +95,14 @@ are I{transcoded} from C++ classes in I{Karney}'s U{GeographicLib<https://Geogra
94
95
 
95
96
  2. These C{pygeodesy} modules and classes
96
97
 
97
- - L{ellipsoidalGeodSolve}, L{ellipsoidalKarney}, L{geodsolve}, L{karney}, L{rhumb.solve}
98
+ - L{ellipsoidalGeodSolve}, L{ellipsoidalKarney}, L{geodesici}, L{geodsolve}, L{karney}, L{rhumb.solve}
98
99
  - L{EquidistantKarney}, L{FrechetKarney}, L{GeodesicSolve}, L{GeodesicLineSolve}, L{GnomonicGeodSolve},
99
- L{GnomonicKarney}, L{HeightIDWkarney}
100
+ L{GnomonicKarney}, L{HeightIDWkarney}, L{Intersectool}
100
101
 
101
- are or use I{wrappers} around I{Karney}'s Python U{geographiclib<https://PyPI.org/project/geographiclib>}
102
- C{geodesic}, C++ utility U{GeodSolve<https://GeographicLib.SourceForge.io/C++/doc/GeodSolve.1.html>} or
103
- C++ utility U{RhumbSolve<https://GeographicLib.SourceForge.io/C++/doc/RhumbSolve.1.html>}.
102
+ are or use I{wrappers} around I{Karney}'s Python U{geographiclib<https://PyPI.org/project/geographiclib>} or
103
+ C++ utility U{GeodSolve<https://GeographicLib.SourceForge.io/C++/doc/GeodSolve.1.html>},
104
+ U{IntersectTool<https://GeographicLib.SourceForge.io/C++/doc/IntersectTool.1.html>} or
105
+ U{RhumbSolve<https://GeographicLib.SourceForge.io/C++/doc/RhumbSolve.1.html>}.
104
106
 
105
107
  3. All C{pygeodesy} functions and methods to compute I{ellipsoidal} intersections, nearest points and trilaterations
106
108
 
@@ -139,20 +141,20 @@ in C{pygeodesy} are based on I{Karney}'s post U{Area of a spherical polygon
139
141
  # make sure int/int division yields float quotient, see .basics
140
142
  from __future__ import division as _; del _ # PYCHOK semicolon
141
143
 
142
- from pygeodesy.basics import _copysign, int1s, isint, itemsorted, neg, unsigned0, \
143
- _xgeographiclib, _zip, _version_info
144
+ from pygeodesy.basics import _copysign, isint, neg, unsigned0, _xgeographiclib, \
145
+ _zip, _version_info
144
146
  from pygeodesy.constants import NAN, _isfinite as _math_isfinite, _0_0, \
145
147
  _1_16th, _1_0, _2_0, _180_0, _N_180_0, _360_0
146
148
  from pygeodesy.errors import GeodesicError, _ValueError, _xkwds, _xkwds_get1
147
149
  from pygeodesy.fmath import cbrt, fremainder, norm2
148
150
  # 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!
151
+ from pygeodesy.interns import NN, _2_, _a12_, _area_, _azi1_, _azi2_, _azi12_, \
152
+ _composite_, _lat1_, _lat2_, _lon1_, _lon2_, \
153
+ _m12_, _M12_, _M21_, _number_, _s12_, _S12_, \
154
+ _UNDER_, _X_, _BAR_ # PYCHOK used!
153
155
  from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS, _getenv
154
156
  from pygeodesy.named import ADict, _NamedBase, _NamedTuple, notImplemented, _Pass
155
- from pygeodesy.props import deprecated_method, Property_RO
157
+ from pygeodesy.props import deprecated_method, Property_RO, property_ROnce
156
158
  from pygeodesy.units import Bearing as _Azi, Degrees as _Deg, Lat, Lon, \
157
159
  Meter as _M, Meter2 as _M2, Number_
158
160
  from pygeodesy.utily import atan2d, sincos2d, tand, _unrollon, fabs
@@ -160,7 +162,7 @@ from pygeodesy.utily import atan2d, sincos2d, tand, _unrollon, fabs
160
162
  # from math import fabs # from .utily
161
163
 
162
164
  __all__ = _ALL_LAZY.karney
163
- __version__ = '24.06.27'
165
+ __version__ = '24.07.16'
164
166
 
165
167
  _K_2_0 = _getenv('PYGEODESY_GEOGRAPHICLIB', _2_) == _2_
166
168
  _perimeter_ = 'perimeter'
@@ -207,39 +209,39 @@ class Area3Tuple(_NamedTuple): # in .geodesicx.gxarea
207
209
  _Units_ = ( Number_, _M, _M2)
208
210
 
209
211
 
210
- class Caps(object): # PYCHOK
212
+ class Caps(object):
211
213
  '''(INTERNAL) Overriden by C{Caps} below.
212
214
  '''
213
- EMPTY = 0 # formerly aka NONE
214
- _CAP_1 = 1 << 0 # for goedesicw only
215
- _CAP_1p = 1 << 1 # for goedesicw only
216
- _CAP_2 = 1 << 2
217
- _CAP_3 = 1 << 3 # for goedesicw only
218
- # _CAP_4 = 1 << 4
219
- # _CAP_ALL = 0x1F
220
- # _CAP_MASK = _CAP_ALL
221
- LATITUDE = 1 << 7 # compute latitude C{lat2}
222
- LONGITUDE = 1 << 8 # compute longitude C{lon2} _CAP_3
223
- AZIMUTH = 1 << 9 # azimuths C{azi1} and C{azi2}
224
- DISTANCE = 1 << 10 # compute distance C{s12} _CAP_1
225
- DISTANCE_IN = 1 << 11 # allow distance C{s12} in Direct _CAP_1 | _CAP_1p
226
- REDUCEDLENGTH = 1 << 12 # compute reduced length C{m12} _CAP_1 | _CAP_2
227
- GEODESICSCALE = 1 << 13 # compute geodesic scales C{M12} and C{M21} _CAP_1 | _CAP_2
228
- AREA = 1 << 14 # compute area C{S12} _CAP_4
229
-
230
- STANDARD = AZIMUTH | DISTANCE | DISTANCE_IN | LATITUDE | LONGITUDE
231
- ALL = 0x7F80 # without LONG_UNROLL, LINE_OFF, REVERSE2 and _DEBUG_*
232
-
233
- _DIRECT3 = AZIMUTH | LATITUDE | LONGITUDE | _CAP_3 # for goedesicw only
234
- _INVERSE3 = AZIMUTH | DISTANCE | _CAP_1 # for goedesicw only
235
- _STD = STANDARD | _CAP_3 | _CAP_1 # for goedesicw only
236
- _STD_LINE = _STD | _CAP_2 | _CAP_1p # for goedesici and -w
237
-
238
- LINE_CAPS = _STD_LINE | REDUCEDLENGTH | GEODESICSCALE # .geodesici only
239
-
240
- LINE_OFF = 1 << 15 # Line without updates from parent geodesic or rhumb
241
- LONG_UNROLL = 1 << 16 # unroll C{lon2} in .Direct and .Position
242
- REVERSE2 = 1 << 17 # reverse C{azi2}
215
+ EMPTY = 0 # formerly aka NONE
216
+ _CAP_1 = 1 << 0 # for goedesici/-w
217
+ _CAP_1p = 1 << 1 # for goedesici/-w
218
+ _CAP_2 = 1 << 2
219
+ _CAP_3 = 1 << 3 # for goedesici/-w
220
+ _CAP_4 = 1 << 4 # for goedesicw
221
+ _CAP_ALL = 0x1F
222
+ # _CAP_MASK = _CAP_ALL
223
+ LATITUDE = 1 << 7 # compute latitude C{lat2}
224
+ LONGITUDE = 1 << 8 | _CAP_3 # compute longitude C{lon2}
225
+ AZIMUTH = 1 << 9 # azimuths C{azi1} and C{azi2}
226
+ DISTANCE = 1 << 10 | _CAP_1 # compute distance C{s12}
227
+ DISTANCE_IN = 1 << 11 | _CAP_1 | _CAP_1p # allow distance C{s12} in Direct
228
+ REDUCEDLENGTH = 1 << 12 | _CAP_1 | _CAP_2 # compute reduced length C{m12}
229
+ GEODESICSCALE = 1 << 13 | _CAP_1 | _CAP_2 # compute geodesic scales C{M12} and C{M21}
230
+ AREA = 1 << 14 | _CAP_4 # compute area C{S12}
231
+
232
+ STANDARD = AZIMUTH | DISTANCE | LATITUDE | LONGITUDE
233
+
234
+ _DIRECT3 = AZIMUTH | LATITUDE | LONGITUDE # for goedesicw only
235
+ _INVERSE3 = AZIMUTH | DISTANCE # for goedesicw only
236
+ _STD = STANDARD # for goedesicw only
237
+ _STD_LINE = _STD | DISTANCE_IN # for goedesici/-w
238
+
239
+ LINE_CAPS = _STD_LINE | REDUCEDLENGTH | GEODESICSCALE # .geodesici only
240
+ LONG_UNROLL = 1 << 15 # unroll C{lon2} in .Direct and .Position
241
+ # = 1 << 16 # unused
242
+ LINE_OFF = 1 << 17 # Line without updates from parent geodesic or rhumb
243
+ REVERSE2 = 1 << 18 # reverse C{azi2}
244
+ ALL = 0x7F80 | _CAP_ALL # without LONG_UNROLL, LINE_OFF, REVERSE2 and _DEBUG_*
243
245
 
244
246
  LATITUDE_LONGITUDE = LATITUDE | LONGITUDE
245
247
  LATITUDE_LONGITUDE_AREA = LATITUDE | LONGITUDE | AREA
@@ -247,35 +249,38 @@ class Caps(object): # PYCHOK
247
249
  AZIMUTH_DISTANCE = AZIMUTH | DISTANCE
248
250
  AZIMUTH_DISTANCE_AREA = AZIMUTH | DISTANCE | AREA
249
251
 
250
- _ANGLE_ONLY = 1 << 18 # angular distance C{a12} only
251
- _SALPs_CALPs = 1 << 19 # (INTERNAL) GeodesicExact._GenInverse
252
+ _SALP_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 | _SALP_CALPs_
259
260
 
260
- _OUT_ALL = ALL
261
+ _OUT_ALL = ALL # see geographiclib.geodesiccapabilities.py
261
262
  _OUT_MASK = ALL | LONG_UNROLL | REVERSE2 | _DEBUG_ALL
262
263
 
263
264
  _AZIMUTH_LATITUDE_LONGITUDE = AZIMUTH | LATITUDE | LONGITUDE
265
+ _AZIMUTH_LATITUDE_LONG_UNROLL = AZIMUTH | LATITUDE | LONG_UNROLL
264
266
  _DEBUG_DIRECT_LINE = _DEBUG_DIRECT | _DEBUG_LINE
265
267
  # _DISTANCE_IN_OUT = DISTANCE_IN & _OUT_MASK # == DISTANCE_IN in .gx, .gxline
266
- _LINE = AZIMUTH | LATITUDE | LONG_UNROLL
267
268
  _REDUCEDLENGTH_GEODESICSCALE = REDUCEDLENGTH | GEODESICSCALE
268
269
  # _REDUCEDLENGTH_GEODESICSCALE_DISTANCE = REDUCEDLENGTH | GEODESICSCALE | DISTANCE
269
270
 
270
- def toStr(self, Csk, sep=_BAR_):
271
- '''Return a C{Caps} or C{outmask} as C{str} or tuple of C{str}s.
271
+ def items(self):
272
+ '''Yield all I{public} C{Caps} as 2-tuple C{(NAME, mask)}.
273
+ '''
274
+ for n, C in Caps.__class__.__dict__.items():
275
+ if isint(C) and not n.startswith(_UNDER_) \
276
+ and n.replace(_UNDER_, NN).isupper():
277
+ yield n, C
278
+
279
+ def toStr(self, Cask, sep=_BAR_):
280
+ '''Return C{Caps} or an C{outmask} as C{str} or tuple of C{str}s.
272
281
  '''
273
- s = []
274
- for c, C in itemsorted(self.__class__.__dict__):
275
- if isint(C) and (Csk & C) and int1s(C) == 1 \
276
- and (C in (Caps.REVERSE2, Caps._SALPs_CALPs)
277
- or c.replace(_UNDER_, NN).isupper()):
278
- s.append(c)
282
+ s = (n for n, C in sorted(Caps.items())
283
+ if C and (Cask & C) == C) # and int1s(C) <= 3
279
284
  return sep.join(s) if sep else tuple(s)
280
285
 
281
286
  Caps = Caps() # PYCHOK singleton
@@ -286,7 +291,7 @@ C{AREA} - compute area C{S12},
286
291
 
287
292
  C{AZIMUTH} - include azimuths C{azi1} and C{azi2},
288
293
 
289
- C{DISTANCE} - compute distance C{s12},
294
+ C{DISTANCE} - compute distance C{s12} and angular distance C{a12},
290
295
 
291
296
  C{DISTANCE_IN} - allow distance C{s12} in C{.Direct},
292
297
 
@@ -310,13 +315,19 @@ and C{ALL} - all of the above.
310
315
 
311
316
  C{STANDARD} = C{AZIMUTH | DISTANCE | DISTANCE_IN | LATITUDE | LONGITUDE}'''
312
317
 
313
- _KEY2Caps = dict(m12=Caps.REDUCEDLENGTH, # see GDict._unCaps
314
- M12=Caps.GEODESICSCALE,
315
- M21=Caps.GEODESICSCALE, S12=Caps.AREA)
318
+ _key2Caps = dict(a12 =Caps.DISTANCE, # in GDict._unCaps
319
+ azi2=Caps.AZIMUTH,
320
+ lat2=Caps.LATITUDE,
321
+ lon2=Caps.LONGITUDE,
322
+ m12 =Caps.REDUCEDLENGTH,
323
+ M12 =Caps.GEODESICSCALE,
324
+ M21 =Caps.GEODESICSCALE,
325
+ s12 =Caps.DISTANCE,
326
+ S12 =Caps.AREA)
316
327
 
317
328
 
318
329
  class _CapsBase(_NamedBase): # in .auxilats, .geodesicx.gxbases
319
- '''(INTERNAL) Base class for C{[_]Geodesic*Exact}.
330
+ '''(INTERNAL) Base class for C{Geodesic*}, C{Geodesic*Exact}, C{Intersectool} and C{Rhumb*Base}.
320
331
  '''
321
332
  ALL = Caps.ALL
322
333
  AREA = Caps.AREA
@@ -426,6 +437,12 @@ class GDict(ADict): # XXX _NamedDict
426
437
  '''
427
438
  return self._toTuple(Inverse10Tuple, dflt)
428
439
 
440
+ def _toNAN(self, outmask): # .GeodesicLineExact._GenPosition
441
+ '''(INTERNAL) Convert this C{GDict} to all C{NAN}s.
442
+ '''
443
+ d = dict((n, NAN) for n in GeodSolve12Tuple._Names_)
444
+ return self.set_(**d)._unCaps(outmask)
445
+
429
446
  @deprecated_method
430
447
  def toRhumb7Tuple(self, dflt=NAN): # PYCHOK no cover
431
448
  '''DEPRECATED on 23.12.07, use method C{toRhumb8Tuple}.
@@ -461,15 +478,40 @@ class GDict(ADict): # XXX _NamedDict
461
478
  t = tuple(_g(self, n, dflt) for n in nTuple._Names_)
462
479
  return nTuple(t, iteration=self._iteration)
463
480
 
481
+ def _2X(self, gl, _2X=_X_): # .Intersectool, .Intersector
482
+ '''(INTERNAL) Rename C{-2} attr to C{-X} or C{-M}.
483
+ '''
484
+ X = GDict(self)
485
+ for n in (_lat2_, _lon2_, _azi2_, _s12_, _a12_):
486
+ if n in X: # X._X = X._2
487
+ X[n[:-1] + _2X] = X.pop(n)
488
+ v = getattr(gl, n, X)
489
+ if v is not X: # X._2 = gl._2
490
+ X[n] = v
491
+ return X
492
+
464
493
  def _unCaps(self, outmask): # in .geodsolve
465
494
  '''(INTERNAL) Remove superfluous items.
466
495
  '''
467
- for k, m in _KEY2Caps.items():
468
- if k in self and not (outmask & m):
496
+ for k, C in _key2Caps.items():
497
+ if k in self and (outmask & C) != C:
469
498
  self.pop(k) # delattr(self, k)
470
499
  return self
471
500
 
472
501
 
502
+ class GeodSolve12Tuple(_GTuple):
503
+ '''12-Tuple C{(lat1, lon1, azi1, lat2, lon2, azi2, s12, a12, m12, M12, M21, S12)} with
504
+ angles C{lat1}, C{lon1}, C{azi1}, C{lat2}, C{lon2} and C{azi2} and arc C{a12} all in
505
+ C{degrees}, initial C{azi1} and final C{azi2} forward azimuths, distance C{s12} and
506
+ reduced length C{m12} in C{meter}, area C{S12} in C{meter} I{squared} and geodesic
507
+ scale factors C{M12} and C{M21}, both C{scalar}, see U{GeodSolve
508
+ <https://GeographicLib.SourceForge.io/C++/doc/GeodSolve.1.html>}.
509
+ '''
510
+ # from GeodSolve --help option -f ... lat1 lon1 azi1 lat2 lon2 azi2 s12 a12 m12 M12 M21 S12
511
+ _Names_ = (_lat1_, _lon1_, _azi1_, _lat2_, _lon2_, _azi2_, _s12_, _a12_, _m12_, _M12_, _M21_, _S12_)
512
+ _Units_ = (_Lat, _Lon, _Azi, _Lat, _Lon, _Azi, _M, _Deg, _Pass, _Pass, _Pass, _M2)
513
+
514
+
473
515
  class Inverse10Tuple(_GTuple):
474
516
  '''10-Tuple C{(a12, s12, salp1, calp1, salp2, calp2, m12, M12, M21, S12)} with arc length
475
517
  C{a12} in C{degrees}, distance C{s12} and reduced length C{m12} in C{meter}, area
@@ -494,13 +536,13 @@ class _kWrapped(object): # in .geodesicw
494
536
  <https://PyPI.org/project/geographiclib>} classes.
495
537
  '''
496
538
 
497
- @Property_RO
539
+ @property_ROnce
498
540
  def geographiclib(self):
499
541
  '''Lazily import C{geographiclib}, provided the U{geographiclib
500
542
  <https://PyPI.org/project/geographiclib>} package is installed,
501
543
  otherwise raise a C{LazyImportError}.
502
544
  '''
503
- g = _xgeographiclib(self.__class__, 1, 49)
545
+ g = _xgeographiclib(self.__class__.__module__, 1, 49)
504
546
  from geographiclib.geodesic import Geodesic
505
547
  g.Geodesic = Geodesic
506
548
  from geographiclib.geodesicline import GeodesicLine
@@ -509,7 +551,7 @@ class _kWrapped(object): # in .geodesicw
509
551
  g.Math = Math
510
552
  return g
511
553
 
512
- @Property_RO
554
+ @property_ROnce
513
555
  def Math(self):
514
556
  '''Wrap the C{geomath.Math} class, provided the U{geographiclib
515
557
  <https://PyPI.org/project/geographiclib>} package is installed,
@@ -562,7 +604,7 @@ class Rhumb8Tuple(_GTuple):
562
604
 
563
605
  @kwarg dflt: Default value for missing items (C{any}).
564
606
  @kwarg a12_m12_M12_M21_salp1_calp1_salp2_calp2: Optional keyword
565
- arguments to specify or override L{Inverse10Tuple} items.
607
+ arguments to specify or override L{Inverse10Tuple} items.
566
608
 
567
609
  @return: L{Inverse10Tuple}C{(a12, s12, salp1, calp1, salp2, calp2,
568
610
  m12, M12, M21, S12)}.
@@ -687,6 +729,17 @@ def _isfinite(x): # mimick geomath.Math.isfinite
687
729
  return _math_isfinite(x) # and fabs(x) <= _MAX
688
730
 
689
731
 
732
+ def _llz2gl(gl, **llz2): # see .geodesici._llz2G
733
+ '''(INTERNAL) Set C{gl.lat2, .lon2, .azi2} from C{llz2}.
734
+ '''
735
+ if llz2:
736
+ for n in (_lat2_, _lon2_, _azi2_): # _lat1_, _lon1_, _azi1_
737
+ v = llz2.get(n, None)
738
+ if v is not None:
739
+ setattr(gl, n, v)
740
+ return gl
741
+
742
+
690
743
  def _norm2(x, y): # mimick geomath.Math.norm
691
744
  '''Normalize C{B{x}} and C{B{y}}.
692
745
 
pygeodesy/ktm.py CHANGED
@@ -67,7 +67,7 @@ from cmath import polar
67
67
  from math import atan2, asinh, cos, cosh, degrees, fabs, sin, sinh, sqrt, tanh
68
68
 
69
69
  __all__ = _ALL_LAZY.ktm
70
- __version__ = '24.06.11'
70
+ __version__ = '24.07.16'
71
71
 
72
72
 
73
73
  class KTMError(_ValueError):
@@ -433,10 +433,7 @@ def _cma(a, b0, b1, Cn):
433
433
  @see: CPython function U{_Py_c_prod<https://GitHub.com/python/
434
434
  cpython/blob/main/Objects/complexobject.c>}.
435
435
 
436
- @note: Python function C{cmath.fsum} is no longer available,
437
- but stil mentioned in Note 4 of the comments before
438
- CPython function U{math_fsum<https://GitHub.com/python/
439
- cpython/blob/main/Modules/mathmodule.c>}
436
+ @note: Python function C{cmath.fsum} is no longer available.
440
437
  '''
441
438
  r = fsum1f_(a.real * b0.real, -a.imag * b0.imag, -b1.real, Cn)
442
439
  j = fsum1f_(a.real * b0.imag, a.imag * b0.real, -b1.imag)
pygeodesy/latlonBase.py CHANGED
@@ -41,7 +41,7 @@ from pygeodesy.namedTuples import Bounds2Tuple, LatLon2Tuple, PhiLam2Tuple, \
41
41
  Trilaterate5Tuple
42
42
  # from pygeodesy.nvectorBase import _N_vector_ # _MODS
43
43
  from pygeodesy.props import deprecated_method, Property, Property_RO, \
44
- property_RO, _update_all
44
+ property_RO, property_ROnce, _update_all
45
45
  # from pygeodesy.streprs import Fmt, hstr # from .named, _MODS
46
46
  from pygeodesy.units import _isDegrees, _isRadius, Distance_, Lat, Lon, \
47
47
  Height, Radius, Radius_, Scalar, Scalar_
@@ -54,7 +54,7 @@ from contextlib import contextmanager
54
54
  from math import asin, cos, degrees, fabs, radians
55
55
 
56
56
  __all__ = _ALL_LAZY.latlonBase
57
- __version__ = '24.06.11'
57
+ __version__ = '24.07.12'
58
58
 
59
59
  _formy = _MODS.into(formy=__name__)
60
60
 
@@ -475,12 +475,11 @@ class LatLonBase(_NamedBase):
475
475
  r = func_(phi2, self.phi, lam21, datum=D)
476
476
  return r * (D.ellipsoid.a if radius is None else radius)
477
477
 
478
- @property_RO
478
+ @property_ROnce
479
479
  def Ecef(self):
480
480
  '''Get the ECEF I{class} (L{EcefKarney}), I{once}.
481
481
  '''
482
- LatLonBase.Ecef = E = _MODS.ecef.EcefKarney # overwrite property_RO
483
- return E
482
+ return _MODS.ecef.EcefKarney
484
483
 
485
484
  @Property_RO
486
485
  def _Ecef_forward(self):
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', 'Intersect7Tuple',
288
+ 'Intersector', 'Intersector5Tuple', 'Middle5Tuple', 'XDict'),
287
289
  geodesicw=_i('Geodesic', 'GeodesicLine', 'Geodesic_WGS84'),
288
290
  geodesicx=_i('gx', 'gxarea', 'gxbases', 'gxline', # modules
289
291
  'GeodesicAreaExact', 'GeodesicExact', 'GeodesicLineExact', 'PolygonArea'),
@@ -341,7 +343,8 @@ _ALL_LAZY = _NamedEnum_RO(_name='_ALL_LAZY',
341
343
  'areaOf', 'boundsOf', 'centroidOf', 'fractional',
342
344
  'isclockwise', 'isconvex', 'isconvex_', 'isenclosedBy', 'ispolar',
343
345
  'luneOf', 'nearestOn5', 'perimeterOf', 'quadOf'),
344
- props=_i('Property', 'Property_RO', 'property_RO', 'property_doc_',
346
+ props=_i('Property', 'Property_RO', 'property_doc_',
347
+ 'property_RO', 'property_ROnce', 'property_ROver',
345
348
  'deprecated_class', 'deprecated_function', 'deprecated_method',
346
349
  'deprecated_Property_RO', 'deprecated_property_RO', 'DeprecationWarnings'),
347
350
  resections=_i('Collins5Tuple', 'ResectionError', 'Survey3Tuple', 'Tienstra7Tuple',
@@ -409,7 +412,7 @@ _ALL_DEPRECATED = _NamedEnum_RO(_name='_ALL_DEPRECATED',
409
412
  'HeightIDW', 'HeightIDW2', 'HeightIDW3', 'Helmert7Tuple',
410
413
  'Lam_', 'LatLonExact4Tuple', 'NearestOn4Tuple', 'Ned3Tuple',
411
414
  'Phi_', 'RefFrameError', 'Rhumb7Tuple', 'RhumbOrder2Tuple',
412
- 'Transform7Tuple', 'TriAngle4Tuple', 'UtmUps4Tuple'),
415
+ 'Transform7Tuple', 'TriAngle4Tuple', 'UtmUps4Tuple', 'XDist'),
413
416
  deprecated_consterns=_i('EPS1_2', 'MANTIS', 'OK'),
414
417
  deprecated_datum=_i('Curvature2Tuple', 'Datum', 'Ellipsoid', 'Transform', # assert
415
418
  'Datums', 'Ellipsoids', 'Transforms',
@@ -519,7 +522,7 @@ class _ALL_MODS(_internals._MODS_Base):
519
522
  _internals._MODS = _ALL_MODS = _ALL_MODS() # PYCHOK singleton
520
523
 
521
524
  __all__ = _ALL_LAZY.lazily
522
- __version__ = '24.06.19'
525
+ __version__ = '24.07.18'
523
526
 
524
527
 
525
528
  def _ALL_OTHER(*objs):
pygeodesy/ltp.py CHANGED
@@ -33,8 +33,8 @@ from pygeodesy.ltpTuples import Attitude4Tuple, ChLVEN2Tuple, ChLV9Tuple, \
33
33
  ChLVyx2Tuple, _XyzLocals4, _XyzLocals5, Xyz4Tuple
34
34
  from pygeodesy.named import _name__, _name2__, _NamedBase, notOverloaded
35
35
  from pygeodesy.namedTuples import LatLon3Tuple, LatLon4Tuple, Vector3Tuple
36
- from pygeodesy.props import Property, Property_RO, property_doc_, property_RO, \
37
- _update_all
36
+ from pygeodesy.props import Property, Property_RO, property_doc_, \
37
+ property_ROver, _update_all
38
38
  from pygeodesy.streprs import Fmt, strs, unstr
39
39
  from pygeodesy.units import Bearing, Degrees, _isHeight, Meter
40
40
  from pygeodesy.utily import cotd, _loneg, sincos2d, sincos2d_, tand, tand_, \
@@ -44,7 +44,7 @@ from pygeodesy.vector3d import _ALL_LAZY, Vector3d
44
44
  # from math import fabs, floor as _floor # from .fmath, .fsums
45
45
 
46
46
  __all__ = _ALL_LAZY.ltp
47
- __version__ = '24.06.11'
47
+ __version__ = '24.07.12'
48
48
 
49
49
  _height0_ = _height_ + _0_
50
50
  _narrow_ = 'narrow'
@@ -722,15 +722,15 @@ class _ChLV(object):
722
722
  t = Y_X_h_lat_lon_h + (self, self._t0, None) # PYCHOK _t0
723
723
  return ChLV9Tuple(t, name=name)
724
724
 
725
- @property_RO
725
+ @property_ROver
726
726
  def _enh_n_h(self):
727
727
  '''(INTERNAL) Get C{ChLV*.reverse} args[1:4] names, I{once}.
728
728
  '''
729
- _ChLV._enh_n_h = t = _args_kwds_names(_ChLV.reverse)[1:4] # overwrite property_RO
729
+ t = _args_kwds_names(_ChLV.reverse)[1:4]
730
730
  # assert _args_kwds_names( ChLV.reverse)[1:4] == t
731
731
  # assert _args_kwds_names(ChLVa.reverse)[1:4] == t
732
732
  # assert _args_kwds_names(ChLVe.reverse)[1:4] == t
733
- return t
733
+ return t # overwrite propertyROver
734
734
 
735
735
  def forward(self, latlonh, lon=None, height=0, M=None, **name): # PYCHOK no cover
736
736
  '''Convert WGS84 geodetic to I{Swiss} projection coordinates. I{Must be overloaded}.
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
  '''
pygeodesy/named.py CHANGED
@@ -34,7 +34,7 @@ from pygeodesy.streprs import attrs, Fmt, lrstrip, pairs, reprs, unstr
34
34
  # from pygeodesy.units import _toUnit # _MODS
35
35
 
36
36
  __all__ = _ALL_LAZY.named
37
- __version__ = '24.06.24'
37
+ __version__ = '24.07.12'
38
38
 
39
39
  _COMMANL_ = _COMMA_ + _NL_
40
40
  _COMMASPACEDOT_ = _COMMASPACE_ + _DOT_
@@ -1231,9 +1231,9 @@ def modulename(clas, prefixed=None): # in .basics._xversion
1231
1231
  @return: The B{C{class}}'s C{[module.]class} name (C{str}).
1232
1232
  '''
1233
1233
  try:
1234
- n = clas.__name__
1234
+ n = clas.__name__
1235
1235
  except AttributeError:
1236
- n = _dunder_name_
1236
+ n = clas if isstr(clas) else _dunder_name_
1237
1237
  if prefixed or (classnaming() if prefixed is None else False):
1238
1238
  try:
1239
1239
  m = clas.__module__.rsplit(_DOT_, 1)
pygeodesy/nvectorBase.py CHANGED
@@ -29,7 +29,7 @@ from pygeodesy.named import _xother3, _under
29
29
  from pygeodesy.namedTuples import Trilaterate5Tuple, Vector3Tuple, \
30
30
  Vector4Tuple, map1
31
31
  from pygeodesy.props import deprecated_method, Property_RO, property_doc_, \
32
- property_RO, _update_all
32
+ property_RO, property_ROnce, _update_all
33
33
  from pygeodesy.streprs import Fmt, hstr, unstr
34
34
  from pygeodesy.units import Bearing, Height, Radius_, Scalar
35
35
  from pygeodesy.utily import sincos2d, _unrollon, _unrollon3
@@ -38,7 +38,7 @@ from pygeodesy.vector3d import Vector3d, _xyzhdlln4
38
38
  from math import fabs, sqrt
39
39
 
40
40
  __all__ = _ALL_LAZY.nvectorBase
41
- __version__ = '24.06.12'
41
+ __version__ = '24.07.12'
42
42
 
43
43
 
44
44
  class NvectorBase(Vector3d): # XXX kept private
@@ -78,12 +78,11 @@ class NvectorBase(Vector3d): # XXX kept private
78
78
  '''
79
79
  return self._datum
80
80
 
81
- @property_RO
81
+ @property_ROnce
82
82
  def Ecef(self):
83
83
  '''Get the ECEF I{class} (L{EcefKarney}), I{once}.
84
84
  '''
85
- NvectorBase.Ecef = E = _MODS.ecef.EcefKarney # overwrite property_RO
86
- return E
85
+ return _MODS.ecef.EcefKarney
87
86
 
88
87
  @property_RO
89
88
  def ellipsoidalNvector(self):