pygeodesy 24.7.24__py2.py3-none-any.whl → 24.8.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.24.dist-info → PyGeodesy-24.8.24.dist-info}/METADATA +20 -19
- {PyGeodesy-24.7.24.dist-info → PyGeodesy-24.8.24.dist-info}/RECORD +57 -57
- {PyGeodesy-24.7.24.dist-info → PyGeodesy-24.8.24.dist-info}/WHEEL +1 -1
- pygeodesy/__init__.py +26 -27
- pygeodesy/auxilats/auxAngle.py +2 -2
- pygeodesy/auxilats/auxDST.py +3 -3
- pygeodesy/azimuthal.py +4 -4
- pygeodesy/basics.py +3 -3
- pygeodesy/cartesianBase.py +6 -6
- pygeodesy/constants.py +11 -11
- pygeodesy/css.py +5 -5
- pygeodesy/ellipsoidalBase.py +18 -15
- pygeodesy/ellipsoidalExact.py +2 -2
- pygeodesy/ellipsoidalGeodSolve.py +2 -2
- pygeodesy/ellipsoidalKarney.py +2 -2
- pygeodesy/ellipsoidalNvector.py +2 -2
- pygeodesy/ellipsoidalVincenty.py +7 -6
- pygeodesy/ellipsoids.py +3 -3
- pygeodesy/epsg.py +3 -3
- pygeodesy/fmath.py +2 -1
- pygeodesy/formy.py +2 -2
- pygeodesy/fsums.py +4 -4
- pygeodesy/gars.py +66 -58
- pygeodesy/geodesici.py +4 -10
- pygeodesy/geodesicx/gx.py +3 -3
- pygeodesy/geodesicx/gxarea.py +3 -3
- pygeodesy/geodsolve.py +3 -3
- pygeodesy/geohash.py +491 -267
- pygeodesy/geoids.py +298 -316
- pygeodesy/heights.py +176 -194
- pygeodesy/internals.py +39 -6
- pygeodesy/interns.py +2 -3
- pygeodesy/karney.py +2 -2
- pygeodesy/latlonBase.py +14 -8
- pygeodesy/lazily.py +22 -21
- pygeodesy/ltp.py +6 -7
- pygeodesy/ltpTuples.py +12 -6
- pygeodesy/named.py +5 -4
- pygeodesy/namedTuples.py +14 -1
- pygeodesy/osgr.py +7 -7
- pygeodesy/points.py +2 -2
- pygeodesy/resections.py +7 -7
- pygeodesy/rhumb/solve.py +3 -3
- pygeodesy/simplify.py +10 -10
- pygeodesy/sphericalBase.py +3 -3
- pygeodesy/sphericalTrigonometry.py +2 -2
- pygeodesy/streprs.py +3 -3
- pygeodesy/triaxials.py +210 -204
- pygeodesy/units.py +36 -19
- pygeodesy/unitsBase.py +4 -4
- pygeodesy/utmupsBase.py +3 -3
- pygeodesy/vector2d.py +158 -51
- pygeodesy/vector3d.py +13 -52
- pygeodesy/vector3dBase.py +81 -63
- pygeodesy/webmercator.py +3 -3
- pygeodesy/wgrs.py +109 -101
- {PyGeodesy-24.7.24.dist-info → PyGeodesy-24.8.24.dist-info}/top_level.txt +0 -0
pygeodesy/wgrs.py
CHANGED
|
@@ -1,25 +1,26 @@
|
|
|
1
1
|
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
|
|
4
|
-
u'''World Geographic Reference System (WGRS) en-/decoding.
|
|
4
|
+
u'''World Geographic Reference System (WGRS) en-/decoding, aka GEOREF.
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
Class L{Georef} and several functions to encode, decode and inspect WGRS
|
|
7
|
+
(or GEOREF) references.
|
|
8
8
|
|
|
9
9
|
Transcoded from I{Charles Karney}'s C++ class U{Georef
|
|
10
10
|
<https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1Georef.html>},
|
|
11
|
-
but with modified C{precision} and extended with C{height} and C{radius}.
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
but with modified C{precision} and extended with C{height} and C{radius}.
|
|
12
|
+
|
|
13
|
+
@see: U{World Geographic Reference System
|
|
14
|
+
<https://WikiPedia.org/wiki/World_Geographic_Reference_System>}.
|
|
14
15
|
'''
|
|
15
16
|
# from pygeodesy.basics import isstr # from .named
|
|
16
17
|
from pygeodesy.constants import INT0, _float, _off90, _0_001, \
|
|
17
18
|
_0_5, _1_0, _2_0, _60_0, _1000_0
|
|
18
|
-
from pygeodesy.dms import parse3llh
|
|
19
|
+
from pygeodesy.dms import parse3llh
|
|
19
20
|
from pygeodesy.errors import _ValueError, _xattr, _xStrError
|
|
20
21
|
from pygeodesy.interns import NN, _0to9_, _AtoZnoIO_, _COMMA_, \
|
|
21
|
-
_height_, _radius_, _SPACE_
|
|
22
|
-
from pygeodesy.lazily import
|
|
22
|
+
_height_, _INV_, _radius_, _SPACE_
|
|
23
|
+
from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY
|
|
23
24
|
from pygeodesy.named import _name2__, nameof, isstr, Property_RO
|
|
24
25
|
from pygeodesy.namedTuples import LatLon2Tuple, LatLonPrec3Tuple
|
|
25
26
|
# from pygeodesy.props import Property_RO # from .named
|
|
@@ -31,21 +32,18 @@ from pygeodesy.utily import ft2m, m2ft, m2NM
|
|
|
31
32
|
from math import floor
|
|
32
33
|
|
|
33
34
|
__all__ = _ALL_LAZY.wgrs
|
|
34
|
-
__version__ = '24.
|
|
35
|
+
__version__ = '24.08.15'
|
|
35
36
|
|
|
36
37
|
_Base = 10
|
|
37
38
|
_BaseLen = 4
|
|
38
39
|
_DegChar = _AtoZnoIO_.tillQ
|
|
39
40
|
_Digits = _0to9_
|
|
40
|
-
_Height_ = Height.__name__
|
|
41
|
-
_INV_ = 'INV' # INValid
|
|
42
41
|
_LatOrig = -90
|
|
43
42
|
_LatTile = _AtoZnoIO_.tillM
|
|
44
43
|
_LonOrig = -180
|
|
45
44
|
_LonTile = _AtoZnoIO_
|
|
46
45
|
_60B = 60000000000 # == 60_000_000_000 == 60e9
|
|
47
46
|
_MaxPrec = 11
|
|
48
|
-
_Radius_ = Radius.__name__
|
|
49
47
|
_Tile = 15 # tile size in degrees
|
|
50
48
|
|
|
51
49
|
_MaxLen = _BaseLen + 2 * _MaxPrec
|
|
@@ -68,31 +66,30 @@ def _divmod3(x, _Orig_60B):
|
|
|
68
66
|
return xt, xd, x
|
|
69
67
|
|
|
70
68
|
|
|
71
|
-
def
|
|
72
|
-
'''(INTERNAL) Convert lat, lon
|
|
69
|
+
def _2fll(lat, lon):
|
|
70
|
+
'''(INTERNAL) Convert lat, lon.
|
|
73
71
|
'''
|
|
74
72
|
# lat, lon = parseDMS2(lat, lon)
|
|
75
73
|
return (Lat(lat, Error=WGRSError),
|
|
76
|
-
Lon(lon, Error=WGRSError)
|
|
74
|
+
Lon(lon, Error=WGRSError))
|
|
77
75
|
|
|
78
76
|
|
|
79
|
-
def
|
|
77
|
+
def _2geostr2(georef):
|
|
80
78
|
'''(INTERNAL) Check a georef string.
|
|
81
79
|
'''
|
|
82
80
|
try:
|
|
83
|
-
n,
|
|
81
|
+
n, g = len(georef), georef.upper()
|
|
84
82
|
p, o = divmod(n, 2)
|
|
85
83
|
if o or n < _MinLen or n > _MaxLen \
|
|
86
|
-
or
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
return geostr, _Precision(p - 1)
|
|
84
|
+
or g.startswith(_INV_) or not g.isalnum():
|
|
85
|
+
raise ValueError()
|
|
86
|
+
return g, _2Precision(p - 1)
|
|
90
87
|
|
|
91
88
|
except (AttributeError, TypeError, ValueError) as x:
|
|
92
89
|
raise WGRSError(Georef.__name__, georef, cause=x)
|
|
93
90
|
|
|
94
91
|
|
|
95
|
-
def
|
|
92
|
+
def _2Precision(precision):
|
|
96
93
|
'''(INTERNAL) Return a L{Precision_} instance.
|
|
97
94
|
'''
|
|
98
95
|
return Precision_(precision, Error=WGRSError, low=0, high=_MaxPrec)
|
|
@@ -108,48 +105,51 @@ class Georef(Str):
|
|
|
108
105
|
'''Georef class, a named C{str}.
|
|
109
106
|
'''
|
|
110
107
|
# no str.__init__ in Python 3
|
|
111
|
-
def __new__(cls,
|
|
108
|
+
def __new__(cls, lat_gll, lon=None, height=None, precision=3, name=NN):
|
|
112
109
|
'''New L{Georef} from an other L{Georef} instance or georef
|
|
113
110
|
C{str} or from a C{LatLon} instance or lat-/longitude C{str}.
|
|
114
111
|
|
|
115
|
-
@arg
|
|
116
|
-
|
|
117
|
-
@kwarg
|
|
118
|
-
|
|
119
|
-
|
|
112
|
+
@arg lat_gll: Latitude (C{degrees90}), a georef (L{Georef},
|
|
113
|
+
C{str}) or a location (C{LatLon}, C{LatLon*Tuple}).
|
|
114
|
+
@kwarg lon: Logitude (C{degrees180)}, required if B{C{lat_gll}}
|
|
115
|
+
is C{degrees90}, ignored otherwise.
|
|
116
|
+
@kwarg height: Optional height in C{meter}, used if B{C{lat_gll}}
|
|
117
|
+
is a location.
|
|
118
|
+
@kwarg precision: The desired georef resolution and length (C{int}
|
|
119
|
+
0..11), see L{encode<pygeodesy.wgrs.encode>}.
|
|
120
120
|
@kwarg name: Optional name (C{str}).
|
|
121
121
|
|
|
122
122
|
@return: New L{Georef}.
|
|
123
123
|
|
|
124
|
-
@raise RangeError: Invalid B{C{
|
|
124
|
+
@raise RangeError: Invalid B{C{lat_gll}} or B{C{lon}}.
|
|
125
125
|
|
|
126
|
-
@raise TypeError: Invalid B{C{
|
|
126
|
+
@raise TypeError: Invalid B{C{lat_gll}} or B{C{lon}}.
|
|
127
127
|
|
|
128
|
-
@raise WGRSError: INValid
|
|
128
|
+
@raise WGRSError: INValid B{C{lat_gll}}.
|
|
129
129
|
'''
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
ll =
|
|
151
|
-
|
|
152
|
-
self = Str.__new__(cls, g, name=name or nameof(
|
|
130
|
+
if lon is None:
|
|
131
|
+
if isinstance(lat_gll, Georef):
|
|
132
|
+
g, ll, p = str(lat_gll), lat_gll.latlon, lat_gll.precision
|
|
133
|
+
elif isstr(lat_gll):
|
|
134
|
+
if _COMMA_ in lat_gll or _SPACE_ in lat_gll:
|
|
135
|
+
lat, lon, h = parse3llh(lat_gll, height=height)
|
|
136
|
+
g, ll, p = _encode3(lat, lon, precision, h=h)
|
|
137
|
+
else:
|
|
138
|
+
g, ll = lat_gll.upper(), None
|
|
139
|
+
try:
|
|
140
|
+
_, p = _2geostr2(g) # validate
|
|
141
|
+
except WGRSError: # R00H00?
|
|
142
|
+
p = None # = decode5(g).precision?
|
|
143
|
+
else: # assume LatLon
|
|
144
|
+
try:
|
|
145
|
+
g, ll, p = _encode3(lat_gll.lat, lat_gll.lon, precision,
|
|
146
|
+
h=_xattr(lat_gll, height=height))
|
|
147
|
+
except AttributeError:
|
|
148
|
+
raise _xStrError(Georef, gll=lat_gll) # Error=WGRSError
|
|
149
|
+
else:
|
|
150
|
+
g, ll, p = _encode3(lat_gll, lon, precision, h=height)
|
|
151
|
+
|
|
152
|
+
self = Str.__new__(cls, g, name=name or nameof(lat_gll))
|
|
153
153
|
self._latlon = ll
|
|
154
154
|
self._precision = p
|
|
155
155
|
return self
|
|
@@ -232,8 +232,8 @@ def decode3(georef, center=True):
|
|
|
232
232
|
'''Decode a C{georef} to lat-, longitude and precision.
|
|
233
233
|
|
|
234
234
|
@arg georef: To be decoded (L{Georef} or C{str}).
|
|
235
|
-
@kwarg center: If C{True} the center, otherwise
|
|
236
|
-
lower-left corner (C{bool}).
|
|
235
|
+
@kwarg center: If C{True}, use the georef's center, otherwise
|
|
236
|
+
the south-west, lower-left corner (C{bool}).
|
|
237
237
|
|
|
238
238
|
@return: A L{LatLonPrec3Tuple}C{(lat, lon, precision)}.
|
|
239
239
|
|
|
@@ -255,7 +255,7 @@ def decode3(georef, center=True):
|
|
|
255
255
|
raise _Error(i)
|
|
256
256
|
return k
|
|
257
257
|
|
|
258
|
-
g, precision =
|
|
258
|
+
g, precision = _2geostr2(georef)
|
|
259
259
|
lon = _index(_LonTile, g, 0) + _LonOrig_Tile
|
|
260
260
|
lat = _index(_LatTile, g, 1) + _LatOrig_Tile
|
|
261
261
|
|
|
@@ -285,33 +285,32 @@ def decode5(georef, center=True):
|
|
|
285
285
|
'''Decode a C{georef} to lat-, longitude, precision, height and radius.
|
|
286
286
|
|
|
287
287
|
@arg georef: To be decoded (L{Georef} or C{str}).
|
|
288
|
-
@kwarg center: If C{True} the center, otherwise the
|
|
289
|
-
lower-left corner (C{bool}).
|
|
288
|
+
@kwarg center: If C{True}, use the georef's center, otherwise the
|
|
289
|
+
south-west, lower-left corner (C{bool}).
|
|
290
290
|
|
|
291
|
-
@return: A L{LatLonPrec5Tuple}C{(lat, lon,
|
|
292
|
-
|
|
293
|
-
C{radius} are C{None} if missing.
|
|
291
|
+
@return: A L{LatLonPrec5Tuple}C{(lat, lon, precision, height, radius)}
|
|
292
|
+
where C{height} and/or C{radius} are C{None} if missing.
|
|
294
293
|
|
|
295
|
-
@raise WGRSError: Invalid B{C{georef}}
|
|
296
|
-
or odd length B{C{georef}}.
|
|
294
|
+
@raise WGRSError: Invalid B{C{georef}}.
|
|
297
295
|
'''
|
|
298
|
-
def _h2m(kft,
|
|
299
|
-
return Height(ft2m(kft * _1000_0), name=
|
|
296
|
+
def _h2m(kft, g_n):
|
|
297
|
+
return Height(ft2m(kft * _1000_0), name=g_n, Error=WGRSError)
|
|
300
298
|
|
|
301
|
-
def _r2m(NM,
|
|
302
|
-
return Radius(NM / m2NM(1), name=
|
|
299
|
+
def _r2m(NM, g_n):
|
|
300
|
+
return Radius(NM / m2NM(1), name=g_n, Error=WGRSError)
|
|
303
301
|
|
|
304
|
-
def _split2(g,
|
|
305
|
-
|
|
302
|
+
def _split2(g, Unit, _2m):
|
|
303
|
+
n = Unit.__name__
|
|
304
|
+
i = max(g.find(n[0]), g.rfind(n[0]))
|
|
306
305
|
if i > _BaseLen:
|
|
307
|
-
return g[:i], _2m(int(g[i+1:]), _SPACE_(georef,
|
|
306
|
+
return g[:i], _2m(int(g[i+1:]), _SPACE_(georef, n))
|
|
308
307
|
else:
|
|
309
308
|
return g, None
|
|
310
309
|
|
|
311
310
|
g = Str(georef, Error=WGRSError)
|
|
312
311
|
|
|
313
|
-
g, h = _split2(g,
|
|
314
|
-
g, r = _split2(g,
|
|
312
|
+
g, h = _split2(g, Height, _h2m) # H is last
|
|
313
|
+
g, r = _split2(g, Radius, _r2m) # R before H
|
|
315
314
|
|
|
316
315
|
return decode3(g, center=center).to5Tuple(h, r)
|
|
317
316
|
|
|
@@ -334,41 +333,49 @@ def encode(lat, lon, precision=3, height=None, radius=None): # MCCABE 14
|
|
|
334
333
|
|
|
335
334
|
@raise WGRSError: Invalid B{C{precision}}, B{C{height}} or B{C{radius}}.
|
|
336
335
|
|
|
337
|
-
@note: The B{C{precision}} value differs from U{Georef<https://
|
|
336
|
+
@note: The B{C{precision}} value differs from I{Karney}'s U{Georef<https://
|
|
338
337
|
GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1Georef.html>}.
|
|
339
|
-
The C{georef} length is M{2 * (precision + 1)} and the
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
M{10**(2 - precision)}.
|
|
338
|
+
The C{georef} length is M{2 * (precision + 1)} and the C{georef}
|
|
339
|
+
resolution is I{15°} for B{C{precision}} 0:, I{1°} for 1, I{1′} for 2,
|
|
340
|
+
I{0.1′} for 3, I{0.01′} for 4, ... up to I{10**(2 - precision)′}.
|
|
343
341
|
'''
|
|
344
342
|
def _option(name, m, m2_, K):
|
|
345
343
|
f = Scalar_(m, name=name, Error=WGRSError)
|
|
346
344
|
return NN(name[0].upper(), int(m2_(f * K) + _0_5))
|
|
347
345
|
|
|
348
|
-
|
|
346
|
+
g, _, _ = _encode3(lat, lon, precision)
|
|
347
|
+
if radius is not None: # R before H
|
|
348
|
+
g += _option(_radius_, radius, m2NM, _1_0)
|
|
349
|
+
if height is not None: # H is last
|
|
350
|
+
g += _option(_height_, height, m2ft, _0_001)
|
|
351
|
+
return g
|
|
352
|
+
|
|
349
353
|
|
|
350
|
-
|
|
351
|
-
|
|
354
|
+
def _encode3(lat, lon, precision, h=None):
|
|
355
|
+
'''Return 3-tuple C{(georef, (lat, lon), p)}.
|
|
356
|
+
'''
|
|
357
|
+
p = _2Precision(precision)
|
|
352
358
|
|
|
353
|
-
|
|
354
|
-
yt, yd, y = _divmod3(lat, _LatOrig_60B)
|
|
359
|
+
lat, lon = _2fll(lat, lon)
|
|
355
360
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
p -= 1
|
|
360
|
-
if p > 0:
|
|
361
|
-
d = pow(_Base, _MaxPrec - p)
|
|
362
|
-
x = _0wd(p, x // d)
|
|
363
|
-
y = _0wd(p, y // d)
|
|
364
|
-
g += x, y
|
|
361
|
+
if h is None:
|
|
362
|
+
xt, xd, x = _divmod3( lon, _LonOrig_60B)
|
|
363
|
+
yt, yd, y = _divmod3(_off90(lat), _LatOrig_60B)
|
|
365
364
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
365
|
+
g = _LonTile[xt], _LatTile[yt]
|
|
366
|
+
if p > 0:
|
|
367
|
+
g += _DegChar[xd], _DegChar[yd]
|
|
368
|
+
p -= 1
|
|
369
|
+
if p > 0:
|
|
370
|
+
d = pow(_Base, _MaxPrec - p)
|
|
371
|
+
x = _0wd(p, x // d)
|
|
372
|
+
y = _0wd(p, y // d)
|
|
373
|
+
g += x, y
|
|
374
|
+
g = NN.join(g)
|
|
375
|
+
else:
|
|
376
|
+
g = encode(lat, lon, precision=p, height=h)
|
|
370
377
|
|
|
371
|
-
return
|
|
378
|
+
return g, (lat, lon), p # XXX Georef(''.join(g))
|
|
372
379
|
|
|
373
380
|
|
|
374
381
|
def precision(res):
|
|
@@ -403,7 +410,8 @@ def resolution(prec):
|
|
|
403
410
|
'''
|
|
404
411
|
p = Int(prec=prec, Error=WGRSError)
|
|
405
412
|
if p > 1:
|
|
406
|
-
|
|
413
|
+
p = min(p, _MaxPrec) - 1
|
|
414
|
+
r = _1_0 / (pow(_Base, p) * _60_0)
|
|
407
415
|
elif p < 1:
|
|
408
416
|
r = _float_Tile
|
|
409
417
|
else:
|
|
@@ -411,8 +419,8 @@ def resolution(prec):
|
|
|
411
419
|
return r
|
|
412
420
|
|
|
413
421
|
|
|
414
|
-
__all__ +=
|
|
415
|
-
|
|
422
|
+
__all__ += _ALL_DOCS(decode3, decode5, # functions
|
|
423
|
+
encode, precision, resolution)
|
|
416
424
|
|
|
417
425
|
# **) MIT License
|
|
418
426
|
#
|
|
File without changes
|