pygeodesy 24.7.7__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-24.7.7.dist-info → PyGeodesy-24.7.24.dist-info}/METADATA +25 -23
- {PyGeodesy-24.7.7.dist-info → PyGeodesy-24.7.24.dist-info}/RECORD +29 -29
- pygeodesy/__init__.py +47 -47
- pygeodesy/auxilats/auxAngle.py +5 -5
- pygeodesy/auxilats/auxDST.py +9 -10
- pygeodesy/auxilats/auxily.py +2 -2
- pygeodesy/cartesianBase.py +5 -6
- pygeodesy/ecef.py +7 -9
- pygeodesy/ellipsoids.py +12 -12
- pygeodesy/fsums.py +12 -6
- pygeodesy/geodesici.py +232 -131
- pygeodesy/geodesicw.py +70 -45
- pygeodesy/geodesicx/gx.py +8 -8
- pygeodesy/geodesicx/gxline.py +5 -5
- pygeodesy/geodsolve.py +12 -3
- pygeodesy/geoids.py +8 -10
- pygeodesy/karney.py +84 -78
- pygeodesy/ktm.py +2 -5
- pygeodesy/latlonBase.py +4 -5
- pygeodesy/lazily.py +5 -4
- pygeodesy/ltp.py +6 -6
- pygeodesy/named.py +3 -3
- pygeodesy/nvectorBase.py +4 -5
- pygeodesy/props.py +75 -17
- pygeodesy/rhumb/solve.py +2 -2
- pygeodesy/solveBase.py +26 -12
- pygeodesy/triaxials.py +4 -5
- {PyGeodesy-24.7.7.dist-info → PyGeodesy-24.7.24.dist-info}/WHEEL +0 -0
- {PyGeodesy-24.7.7.dist-info → PyGeodesy-24.7.24.dist-info}/top_level.txt +0 -0
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
|
-
|
|
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{
|
|
14
|
-
L{
|
|
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://
|
|
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
|
|
103
|
-
|
|
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,12 +141,11 @@ 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,
|
|
143
|
-
|
|
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
|
-
from pygeodesy.errors import GeodesicError, _ValueError, _xkwds, _xkwds_get1
|
|
147
|
-
_xkwds_kwds, _xkwds_not
|
|
148
|
+
from pygeodesy.errors import GeodesicError, _ValueError, _xkwds, _xkwds_get1
|
|
148
149
|
from pygeodesy.fmath import cbrt, fremainder, norm2
|
|
149
150
|
# from pygeodesy.internals import _version_info # from .basics
|
|
150
151
|
from pygeodesy.interns import NN, _2_, _a12_, _area_, _azi1_, _azi2_, _azi12_, \
|
|
@@ -153,7 +154,7 @@ from pygeodesy.interns import NN, _2_, _a12_, _area_, _azi1_, _azi2_, _azi12_, \
|
|
|
153
154
|
_UNDER_, _X_, _BAR_ # PYCHOK used!
|
|
154
155
|
from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS, _getenv
|
|
155
156
|
from pygeodesy.named import ADict, _NamedBase, _NamedTuple, notImplemented, _Pass
|
|
156
|
-
from pygeodesy.props import deprecated_method, Property_RO
|
|
157
|
+
from pygeodesy.props import deprecated_method, Property_RO, property_ROnce
|
|
157
158
|
from pygeodesy.units import Bearing as _Azi, Degrees as _Deg, Lat, Lon, \
|
|
158
159
|
Meter as _M, Meter2 as _M2, Number_
|
|
159
160
|
from pygeodesy.utily import atan2d, sincos2d, tand, _unrollon, fabs
|
|
@@ -161,7 +162,7 @@ from pygeodesy.utily import atan2d, sincos2d, tand, _unrollon, fabs
|
|
|
161
162
|
# from math import fabs # from .utily
|
|
162
163
|
|
|
163
164
|
__all__ = _ALL_LAZY.karney
|
|
164
|
-
__version__ = '24.07.
|
|
165
|
+
__version__ = '24.07.16'
|
|
165
166
|
|
|
166
167
|
_K_2_0 = _getenv('PYGEODESY_GEOGRAPHICLIB', _2_) == _2_
|
|
167
168
|
_perimeter_ = 'perimeter'
|
|
@@ -208,39 +209,39 @@ class Area3Tuple(_NamedTuple): # in .geodesicx.gxarea
|
|
|
208
209
|
_Units_ = ( Number_, _M, _M2)
|
|
209
210
|
|
|
210
211
|
|
|
211
|
-
class Caps(object):
|
|
212
|
+
class Caps(object):
|
|
212
213
|
'''(INTERNAL) Overriden by C{Caps} below.
|
|
213
214
|
'''
|
|
214
|
-
EMPTY
|
|
215
|
-
_CAP_1
|
|
216
|
-
_CAP_1p
|
|
217
|
-
_CAP_2
|
|
218
|
-
_CAP_3
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
# _CAP_MASK
|
|
222
|
-
LATITUDE
|
|
223
|
-
LONGITUDE
|
|
224
|
-
AZIMUTH
|
|
225
|
-
DISTANCE
|
|
226
|
-
DISTANCE_IN
|
|
227
|
-
REDUCEDLENGTH
|
|
228
|
-
GEODESICSCALE
|
|
229
|
-
AREA
|
|
230
|
-
|
|
231
|
-
STANDARD
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
LINE_OFF
|
|
242
|
-
|
|
243
|
-
|
|
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_*
|
|
244
245
|
|
|
245
246
|
LATITUDE_LONGITUDE = LATITUDE | LONGITUDE
|
|
246
247
|
LATITUDE_LONGITUDE_AREA = LATITUDE | LONGITUDE | AREA
|
|
@@ -248,35 +249,38 @@ class Caps(object): # PYCHOK
|
|
|
248
249
|
AZIMUTH_DISTANCE = AZIMUTH | DISTANCE
|
|
249
250
|
AZIMUTH_DISTANCE_AREA = AZIMUTH | DISTANCE | AREA
|
|
250
251
|
|
|
251
|
-
|
|
252
|
-
_S_CALPs_ = 1 << 19 # (INTERNAL) GeodesicExact._GenInverse
|
|
252
|
+
_SALP_CALPs_ = 1 << 19 # (INTERNAL) GeodesicExact._GenInverse
|
|
253
253
|
|
|
254
254
|
_DEBUG_AREA = 1 << 20 # (INTERNAL) include Line details
|
|
255
255
|
_DEBUG_DIRECT = 1 << 21 # (INTERNAL) include Direct details
|
|
256
256
|
_DEBUG_INVERSE = 1 << 22 # (INTERNAL) include Inverse details
|
|
257
257
|
_DEBUG_LINE = 1 << 23 # (INTERNAL) include Line details
|
|
258
258
|
_DEBUG_ALL = _DEBUG_AREA | _DEBUG_DIRECT | _DEBUG_INVERSE | \
|
|
259
|
-
_DEBUG_LINE |
|
|
259
|
+
_DEBUG_LINE | _SALP_CALPs_
|
|
260
260
|
|
|
261
|
-
_OUT_ALL = ALL
|
|
261
|
+
_OUT_ALL = ALL # see geographiclib.geodesiccapabilities.py
|
|
262
262
|
_OUT_MASK = ALL | LONG_UNROLL | REVERSE2 | _DEBUG_ALL
|
|
263
263
|
|
|
264
264
|
_AZIMUTH_LATITUDE_LONGITUDE = AZIMUTH | LATITUDE | LONGITUDE
|
|
265
|
+
_AZIMUTH_LATITUDE_LONG_UNROLL = AZIMUTH | LATITUDE | LONG_UNROLL
|
|
265
266
|
_DEBUG_DIRECT_LINE = _DEBUG_DIRECT | _DEBUG_LINE
|
|
266
267
|
# _DISTANCE_IN_OUT = DISTANCE_IN & _OUT_MASK # == DISTANCE_IN in .gx, .gxline
|
|
267
|
-
_LINE = AZIMUTH | LATITUDE | LONG_UNROLL
|
|
268
268
|
_REDUCEDLENGTH_GEODESICSCALE = REDUCEDLENGTH | GEODESICSCALE
|
|
269
269
|
# _REDUCEDLENGTH_GEODESICSCALE_DISTANCE = REDUCEDLENGTH | GEODESICSCALE | DISTANCE
|
|
270
270
|
|
|
271
|
-
def
|
|
272
|
-
'''
|
|
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.
|
|
273
281
|
'''
|
|
274
|
-
s =
|
|
275
|
-
|
|
276
|
-
if isint(C) and (Csk & C) and int1s(C) == 1 \
|
|
277
|
-
and (C in (Caps.REVERSE2, Caps._S_CALPs_)
|
|
278
|
-
or c.replace(_UNDER_, NN).isupper()):
|
|
279
|
-
s.append(c)
|
|
282
|
+
s = (n for n, C in sorted(Caps.items())
|
|
283
|
+
if C and (Cask & C) == C) # and int1s(C) <= 3
|
|
280
284
|
return sep.join(s) if sep else tuple(s)
|
|
281
285
|
|
|
282
286
|
Caps = Caps() # PYCHOK singleton
|
|
@@ -287,7 +291,7 @@ C{AREA} - compute area C{S12},
|
|
|
287
291
|
|
|
288
292
|
C{AZIMUTH} - include azimuths C{azi1} and C{azi2},
|
|
289
293
|
|
|
290
|
-
C{DISTANCE} - compute distance C{s12},
|
|
294
|
+
C{DISTANCE} - compute distance C{s12} and angular distance C{a12},
|
|
291
295
|
|
|
292
296
|
C{DISTANCE_IN} - allow distance C{s12} in C{.Direct},
|
|
293
297
|
|
|
@@ -311,7 +315,8 @@ and C{ALL} - all of the above.
|
|
|
311
315
|
|
|
312
316
|
C{STANDARD} = C{AZIMUTH | DISTANCE | DISTANCE_IN | LATITUDE | LONGITUDE}'''
|
|
313
317
|
|
|
314
|
-
|
|
318
|
+
_key2Caps = dict(a12 =Caps.DISTANCE, # in GDict._unCaps
|
|
319
|
+
azi2=Caps.AZIMUTH,
|
|
315
320
|
lat2=Caps.LATITUDE,
|
|
316
321
|
lon2=Caps.LONGITUDE,
|
|
317
322
|
m12 =Caps.REDUCEDLENGTH,
|
|
@@ -322,7 +327,7 @@ _KEY2Caps = dict(azi2=Caps.AZIMUTH, # see GDict._unCaps
|
|
|
322
327
|
|
|
323
328
|
|
|
324
329
|
class _CapsBase(_NamedBase): # in .auxilats, .geodesicx.gxbases
|
|
325
|
-
'''(INTERNAL) Base class for C{
|
|
330
|
+
'''(INTERNAL) Base class for C{Geodesic*}, C{Geodesic*Exact}, C{Intersectool} and C{Rhumb*Base}.
|
|
326
331
|
'''
|
|
327
332
|
ALL = Caps.ALL
|
|
328
333
|
AREA = Caps.AREA
|
|
@@ -473,8 +478,8 @@ class GDict(ADict): # XXX _NamedDict
|
|
|
473
478
|
t = tuple(_g(self, n, dflt) for n in nTuple._Names_)
|
|
474
479
|
return nTuple(t, iteration=self._iteration)
|
|
475
480
|
|
|
476
|
-
def _2X(self, gl, _2X=_X_): # .
|
|
477
|
-
'''(INTERNAL) Rename
|
|
481
|
+
def _2X(self, gl, _2X=_X_): # .Intersectool, .Intersector
|
|
482
|
+
'''(INTERNAL) Rename C{-2} attr to C{-X} or C{-M}.
|
|
478
483
|
'''
|
|
479
484
|
X = GDict(self)
|
|
480
485
|
for n in (_lat2_, _lon2_, _azi2_, _s12_, _a12_):
|
|
@@ -488,8 +493,8 @@ class GDict(ADict): # XXX _NamedDict
|
|
|
488
493
|
def _unCaps(self, outmask): # in .geodsolve
|
|
489
494
|
'''(INTERNAL) Remove superfluous items.
|
|
490
495
|
'''
|
|
491
|
-
for k,
|
|
492
|
-
if k in self and
|
|
496
|
+
for k, C in _key2Caps.items():
|
|
497
|
+
if k in self and (outmask & C) != C:
|
|
493
498
|
self.pop(k) # delattr(self, k)
|
|
494
499
|
return self
|
|
495
500
|
|
|
@@ -531,13 +536,13 @@ class _kWrapped(object): # in .geodesicw
|
|
|
531
536
|
<https://PyPI.org/project/geographiclib>} classes.
|
|
532
537
|
'''
|
|
533
538
|
|
|
534
|
-
@
|
|
539
|
+
@property_ROnce
|
|
535
540
|
def geographiclib(self):
|
|
536
541
|
'''Lazily import C{geographiclib}, provided the U{geographiclib
|
|
537
542
|
<https://PyPI.org/project/geographiclib>} package is installed,
|
|
538
543
|
otherwise raise a C{LazyImportError}.
|
|
539
544
|
'''
|
|
540
|
-
g = _xgeographiclib(self.__class__, 1, 49)
|
|
545
|
+
g = _xgeographiclib(self.__class__.__module__, 1, 49)
|
|
541
546
|
from geographiclib.geodesic import Geodesic
|
|
542
547
|
g.Geodesic = Geodesic
|
|
543
548
|
from geographiclib.geodesicline import GeodesicLine
|
|
@@ -546,7 +551,7 @@ class _kWrapped(object): # in .geodesicw
|
|
|
546
551
|
g.Math = Math
|
|
547
552
|
return g
|
|
548
553
|
|
|
549
|
-
@
|
|
554
|
+
@property_ROnce
|
|
550
555
|
def Math(self):
|
|
551
556
|
'''Wrap the C{geomath.Math} class, provided the U{geographiclib
|
|
552
557
|
<https://PyPI.org/project/geographiclib>} package is installed,
|
|
@@ -599,7 +604,7 @@ class Rhumb8Tuple(_GTuple):
|
|
|
599
604
|
|
|
600
605
|
@kwarg dflt: Default value for missing items (C{any}).
|
|
601
606
|
@kwarg a12_m12_M12_M21_salp1_calp1_salp2_calp2: Optional keyword
|
|
602
|
-
|
|
607
|
+
arguments to specify or override L{Inverse10Tuple} items.
|
|
603
608
|
|
|
604
609
|
@return: L{Inverse10Tuple}C{(a12, s12, salp1, calp1, salp2, calp2,
|
|
605
610
|
m12, M12, M21, S12)}.
|
|
@@ -724,14 +729,15 @@ def _isfinite(x): # mimick geomath.Math.isfinite
|
|
|
724
729
|
return _math_isfinite(x) # and fabs(x) <= _MAX
|
|
725
730
|
|
|
726
731
|
|
|
727
|
-
def
|
|
728
|
-
'''(INTERNAL) Set C{
|
|
732
|
+
def _llz2gl(gl, **llz2): # see .geodesici._llz2G
|
|
733
|
+
'''(INTERNAL) Set C{gl.lat2, .lon2, .azi2} from C{llz2}.
|
|
729
734
|
'''
|
|
730
735
|
if llz2:
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
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
|
|
735
741
|
|
|
736
742
|
|
|
737
743
|
def _norm2(x, y): # mimick geomath.Math.norm
|
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.
|
|
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.
|
|
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
|
-
@
|
|
478
|
+
@property_ROnce
|
|
479
479
|
def Ecef(self):
|
|
480
480
|
'''Get the ECEF I{class} (L{EcefKarney}), I{once}.
|
|
481
481
|
'''
|
|
482
|
-
|
|
483
|
-
return E
|
|
482
|
+
return _MODS.ecef.EcefKarney
|
|
484
483
|
|
|
485
484
|
@Property_RO
|
|
486
485
|
def _Ecef_forward(self):
|
pygeodesy/lazily.py
CHANGED
|
@@ -284,8 +284,8 @@ _ALL_LAZY = _NamedEnum_RO(_name='_ALL_LAZY',
|
|
|
284
284
|
fsums=_i('Fsum', 'DivMod2Tuple', 'Fsum2Tuple', 'ResidualError',
|
|
285
285
|
'fsum', 'fsum_', 'fsumf_', 'fsum1', 'fsum1_', 'fsum1f_'),
|
|
286
286
|
gars=_i('Garef', 'GARSError'),
|
|
287
|
-
geodesici=_i('Intersectool', 'Intersectool5Tuple', '
|
|
288
|
-
'Intersector', 'Intersector5Tuple', 'XDict'),
|
|
287
|
+
geodesici=_i('Intersectool', 'Intersectool5Tuple', 'Intersect7Tuple',
|
|
288
|
+
'Intersector', 'Intersector5Tuple', 'Middle5Tuple', 'XDict'),
|
|
289
289
|
geodesicw=_i('Geodesic', 'GeodesicLine', 'Geodesic_WGS84'),
|
|
290
290
|
geodesicx=_i('gx', 'gxarea', 'gxbases', 'gxline', # modules
|
|
291
291
|
'GeodesicAreaExact', 'GeodesicExact', 'GeodesicLineExact', 'PolygonArea'),
|
|
@@ -343,7 +343,8 @@ _ALL_LAZY = _NamedEnum_RO(_name='_ALL_LAZY',
|
|
|
343
343
|
'areaOf', 'boundsOf', 'centroidOf', 'fractional',
|
|
344
344
|
'isclockwise', 'isconvex', 'isconvex_', 'isenclosedBy', 'ispolar',
|
|
345
345
|
'luneOf', 'nearestOn5', 'perimeterOf', 'quadOf'),
|
|
346
|
-
props=_i('Property', 'Property_RO', '
|
|
346
|
+
props=_i('Property', 'Property_RO', 'property_doc_',
|
|
347
|
+
'property_RO', 'property_ROnce', 'property_ROver',
|
|
347
348
|
'deprecated_class', 'deprecated_function', 'deprecated_method',
|
|
348
349
|
'deprecated_Property_RO', 'deprecated_property_RO', 'DeprecationWarnings'),
|
|
349
350
|
resections=_i('Collins5Tuple', 'ResectionError', 'Survey3Tuple', 'Tienstra7Tuple',
|
|
@@ -521,7 +522,7 @@ class _ALL_MODS(_internals._MODS_Base):
|
|
|
521
522
|
_internals._MODS = _ALL_MODS = _ALL_MODS() # PYCHOK singleton
|
|
522
523
|
|
|
523
524
|
__all__ = _ALL_LAZY.lazily
|
|
524
|
-
__version__ = '24.07.
|
|
525
|
+
__version__ = '24.07.18'
|
|
525
526
|
|
|
526
527
|
|
|
527
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_,
|
|
37
|
-
|
|
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.
|
|
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
|
-
@
|
|
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
|
-
|
|
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/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.
|
|
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 =
|
|
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.
|
|
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
|
-
@
|
|
81
|
+
@property_ROnce
|
|
82
82
|
def Ecef(self):
|
|
83
83
|
'''Get the ECEF I{class} (L{EcefKarney}), I{once}.
|
|
84
84
|
'''
|
|
85
|
-
|
|
86
|
-
return E
|
|
85
|
+
return _MODS.ecef.EcefKarney
|
|
87
86
|
|
|
88
87
|
@property_RO
|
|
89
88
|
def ellipsoidalNvector(self):
|
pygeodesy/props.py
CHANGED
|
@@ -25,7 +25,7 @@ from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS, \
|
|
|
25
25
|
from functools import wraps as _wraps
|
|
26
26
|
|
|
27
27
|
__all__ = _ALL_LAZY.props
|
|
28
|
-
__version__ = '24.
|
|
28
|
+
__version__ = '24.07.23'
|
|
29
29
|
|
|
30
30
|
_class_ = 'class'
|
|
31
31
|
_dont_use_ = _DEPRECATED_ + ", don't use."
|
|
@@ -48,11 +48,12 @@ def _allPropertiesOf(Clas_or_inst, *Bases, **excls):
|
|
|
48
48
|
except AttributeError:
|
|
49
49
|
raise
|
|
50
50
|
S = () # not an inst
|
|
51
|
-
B
|
|
52
|
-
|
|
51
|
+
B = Bases or _PropertyBase
|
|
52
|
+
P = _property_RO___
|
|
53
53
|
for C in S:
|
|
54
54
|
for n, p in C.__dict__.items():
|
|
55
|
-
if
|
|
55
|
+
if isinstance(p, B) and p.name == n and not (
|
|
56
|
+
isinstance(p, P) or n in excls):
|
|
56
57
|
yield p
|
|
57
58
|
|
|
58
59
|
|
|
@@ -251,9 +252,9 @@ class Property_RO(_PropertyBase):
|
|
|
251
252
|
<https://Docs.Python.org/3/library/functools.html#functools.cache>}
|
|
252
253
|
to I{cache} or I{memoize} the property value.
|
|
253
254
|
|
|
254
|
-
@see: Luciano Ramalho, "Fluent Python", O'Reilly,
|
|
255
|
-
|
|
256
|
-
<https://docs.Python.org/3/howto/descriptor.html>}.
|
|
255
|
+
@see: Luciano Ramalho, "Fluent Python", O'Reilly, 2016 p. 636
|
|
256
|
+
Example 19-24 or 2022 p. 870 Example 22-28 and U{class
|
|
257
|
+
Property<https://docs.Python.org/3/howto/descriptor.html>}.
|
|
257
258
|
'''
|
|
258
259
|
_fget = method if _FOR_DOCS else self._fget # XXX force method.__doc__ to epydoc
|
|
259
260
|
_PropertyBase.__init__(self, method, _fget, self._fset_error)
|
|
@@ -355,6 +356,61 @@ class property_RO(_PropertyBase):
|
|
|
355
356
|
inst.__dict__.pop(uname)
|
|
356
357
|
|
|
357
358
|
|
|
359
|
+
class _property_RO___(_PropertyBase):
|
|
360
|
+
# No __doc__ on purpose
|
|
361
|
+
|
|
362
|
+
def __init__(self, method, doc=NN): # PYCHOK expected
|
|
363
|
+
'''New C{property_ROnce} or C{property_ROver}, holding a singleton value as
|
|
364
|
+
class attribute for all instances of that class and overwriting C{self},
|
|
365
|
+
the C{property_ROver} instance in the 1st invokation.
|
|
366
|
+
|
|
367
|
+
@see: L{property_RO} for further details.
|
|
368
|
+
'''
|
|
369
|
+
_PropertyBase.__init__(self, method, self._fget, self._fset_error, doc=doc)
|
|
370
|
+
|
|
371
|
+
def _fdel(self, unused): # PYCHOK no cover
|
|
372
|
+
'''Silently ignored, always.
|
|
373
|
+
'''
|
|
374
|
+
pass
|
|
375
|
+
|
|
376
|
+
def _update(self, *unused): # PYCHOK signature
|
|
377
|
+
'''(INTERNAL) No-op, ignore updates.
|
|
378
|
+
'''
|
|
379
|
+
pass
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
class property_ROnce(_property_RO___):
|
|
383
|
+
# No __doc__ on purpose
|
|
384
|
+
|
|
385
|
+
def _fget(self, inst):
|
|
386
|
+
'''Get the C{property} value, only I{once} and memoize/cache it.
|
|
387
|
+
'''
|
|
388
|
+
try:
|
|
389
|
+
v = self._val
|
|
390
|
+
except AttributeError:
|
|
391
|
+
v = self._val = self.method(inst)
|
|
392
|
+
return v
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
class property_ROver(_property_RO___):
|
|
396
|
+
# No __doc__ on purpose
|
|
397
|
+
|
|
398
|
+
def _fget(self, inst):
|
|
399
|
+
'''Get the C{property} value I{once} and overwrite C{self}, this C{property} instance.
|
|
400
|
+
'''
|
|
401
|
+
v = self.method(inst)
|
|
402
|
+
n = self.name
|
|
403
|
+
C = inst.__class__
|
|
404
|
+
for c in C.__mro__: # [:-1]
|
|
405
|
+
if getattr(c, n, None) is self:
|
|
406
|
+
setattr(c, n, v) # overwrite property_ROver
|
|
407
|
+
break
|
|
408
|
+
else:
|
|
409
|
+
n = _DOT_(C.__name__, n)
|
|
410
|
+
raise _AssertionError(_EQUALSPACED_(n, v))
|
|
411
|
+
return v
|
|
412
|
+
|
|
413
|
+
|
|
358
414
|
class _NamedProperty(property):
|
|
359
415
|
'''Class C{property} with retrievable name.
|
|
360
416
|
'''
|
|
@@ -372,16 +428,18 @@ def property_doc_(doc):
|
|
|
372
428
|
|
|
373
429
|
@example:
|
|
374
430
|
|
|
375
|
-
>>>
|
|
376
|
-
>>>
|
|
377
|
-
>>>
|
|
431
|
+
>>>class Clas(object):
|
|
432
|
+
>>>
|
|
433
|
+
>>> @property_doc_("documentation text.")
|
|
434
|
+
>>> def name(self):
|
|
435
|
+
>>> ...
|
|
378
436
|
>>>
|
|
379
|
-
>>>
|
|
380
|
-
>>>
|
|
381
|
-
>>>
|
|
437
|
+
>>> @name.setter
|
|
438
|
+
>>> def name(self, value):
|
|
439
|
+
>>> ...
|
|
382
440
|
'''
|
|
383
|
-
# See Luciano Ramalho, "Fluent Python", O'Reilly,
|
|
384
|
-
#
|
|
441
|
+
# See Luciano Ramalho, "Fluent Python", O'Reilly, 2016 p. 212+
|
|
442
|
+
# Example 7-23 or 2022 p. 331+ Example 9-22 and <https://
|
|
385
443
|
# Python-3-Patterns-Idioms-Test.ReadTheDocs.io/en/latest/PythonDecorators.html>
|
|
386
444
|
|
|
387
445
|
def _documented_property(method):
|
|
@@ -396,8 +454,8 @@ def property_doc_(doc):
|
|
|
396
454
|
def _deprecated(call, kind, qual_d):
|
|
397
455
|
'''(INTERNAL) Decorator for DEPRECATED functions, methods, etc.
|
|
398
456
|
|
|
399
|
-
@see: Brett Slatkin, "Effective Python", page 105, 2nd
|
|
400
|
-
Addison-Wesley
|
|
457
|
+
@see: Brett Slatkin, "Effective Python", 2019 page 105, 2nd
|
|
458
|
+
ed, Addison-Wesley.
|
|
401
459
|
'''
|
|
402
460
|
doc = _docof(call)
|
|
403
461
|
|
pygeodesy/rhumb/solve.py
CHANGED
|
@@ -21,7 +21,7 @@ from pygeodesy.solveBase import _SolveGDictBase, _SolveGDictLineBase
|
|
|
21
21
|
from pygeodesy.utily import _unrollon, _Wrap, wrap360
|
|
22
22
|
|
|
23
23
|
__all__ = _ALL_LAZY.rhumb_solve
|
|
24
|
-
__version__ = '24.
|
|
24
|
+
__version__ = '24.07.11'
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
class _RhumbSolveBase(_SolveGDictBase):
|
|
@@ -173,7 +173,7 @@ class RhumbSolve(_RhumbSolveBase):
|
|
|
173
173
|
return r
|
|
174
174
|
|
|
175
175
|
def _GDictInverse(self, lat1, lon1, lat2, lon2, *unused, **floats): # PYCHOK signature
|
|
176
|
-
'''(INTERNAL) Get C{_GenInverse}-like result as an 8-item C{GDict}, but I{without} C{
|
|
176
|
+
'''(INTERNAL) Get C{_GenInverse}-like result as an 8-item C{GDict}, but I{without} C{_SALP_CALPs_}.
|
|
177
177
|
'''
|
|
178
178
|
i = _RhumbSolveBase._GDictInverse(self, lat1, lon1, lat2, lon2, **floats)
|
|
179
179
|
a = _over(float(i.s12), self._mpd) # for .Inverse1
|