pygeodesy 24.7.24__py2.py3-none-any.whl → 24.8.4__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.4.dist-info}/METADATA +6 -6
- {PyGeodesy-24.7.24.dist-info → PyGeodesy-24.8.4.dist-info}/RECORD +26 -26
- pygeodesy/__init__.py +4 -5
- pygeodesy/auxilats/auxAngle.py +2 -2
- pygeodesy/auxilats/auxDST.py +2 -2
- pygeodesy/azimuthal.py +4 -4
- pygeodesy/cartesianBase.py +2 -2
- pygeodesy/css.py +5 -5
- pygeodesy/ellipsoids.py +3 -3
- pygeodesy/formy.py +2 -2
- pygeodesy/gars.py +59 -52
- pygeodesy/geodesici.py +4 -10
- pygeodesy/geohash.py +484 -267
- pygeodesy/geoids.py +6 -2
- pygeodesy/heights.py +30 -40
- pygeodesy/internals.py +19 -6
- pygeodesy/karney.py +2 -2
- pygeodesy/latlonBase.py +2 -2
- pygeodesy/lazily.py +17 -16
- pygeodesy/ltp.py +2 -2
- pygeodesy/ltpTuples.py +6 -6
- pygeodesy/triaxials.py +4 -4
- pygeodesy/units.py +34 -17
- pygeodesy/wgrs.py +93 -83
- {PyGeodesy-24.7.24.dist-info → PyGeodesy-24.8.4.dist-info}/WHEEL +0 -0
- {PyGeodesy-24.7.24.dist-info → PyGeodesy-24.8.4.dist-info}/top_level.txt +0 -0
pygeodesy/wgrs.py
CHANGED
|
@@ -1,21 +1,22 @@
|
|
|
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
|
|
7
|
+
WGRS (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
22
|
_height_, _radius_, _SPACE_
|
|
@@ -31,13 +32,12 @@ 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.02'
|
|
35
36
|
|
|
36
37
|
_Base = 10
|
|
37
38
|
_BaseLen = 4
|
|
38
39
|
_DegChar = _AtoZnoIO_.tillQ
|
|
39
40
|
_Digits = _0to9_
|
|
40
|
-
_Height_ = Height.__name__
|
|
41
41
|
_INV_ = 'INV' # INValid
|
|
42
42
|
_LatOrig = -90
|
|
43
43
|
_LatTile = _AtoZnoIO_.tillM
|
|
@@ -45,7 +45,6 @@ _LonOrig = -180
|
|
|
45
45
|
_LonTile = _AtoZnoIO_
|
|
46
46
|
_60B = 60000000000 # == 60_000_000_000 == 60e9
|
|
47
47
|
_MaxPrec = 11
|
|
48
|
-
_Radius_ = Radius.__name__
|
|
49
48
|
_Tile = 15 # tile size in degrees
|
|
50
49
|
|
|
51
50
|
_MaxLen = _BaseLen + 2 * _MaxPrec
|
|
@@ -68,15 +67,15 @@ def _divmod3(x, _Orig_60B):
|
|
|
68
67
|
return xt, xd, x
|
|
69
68
|
|
|
70
69
|
|
|
71
|
-
def
|
|
72
|
-
'''(INTERNAL) Convert lat, lon
|
|
70
|
+
def _2fll(lat, lon):
|
|
71
|
+
'''(INTERNAL) Convert lat, lon.
|
|
73
72
|
'''
|
|
74
73
|
# lat, lon = parseDMS2(lat, lon)
|
|
75
74
|
return (Lat(lat, Error=WGRSError),
|
|
76
|
-
Lon(lon, Error=WGRSError)
|
|
75
|
+
Lon(lon, Error=WGRSError))
|
|
77
76
|
|
|
78
77
|
|
|
79
|
-
def
|
|
78
|
+
def _2geostr2(georef):
|
|
80
79
|
'''(INTERNAL) Check a georef string.
|
|
81
80
|
'''
|
|
82
81
|
try:
|
|
@@ -85,14 +84,14 @@ def _geostr2(georef):
|
|
|
85
84
|
if o or n < _MinLen or n > _MaxLen \
|
|
86
85
|
or geostr[:3] == _INV_ \
|
|
87
86
|
or not geostr.isalnum():
|
|
88
|
-
raise ValueError
|
|
89
|
-
return geostr,
|
|
87
|
+
raise ValueError()
|
|
88
|
+
return geostr, _2Precision(p - 1)
|
|
90
89
|
|
|
91
90
|
except (AttributeError, TypeError, ValueError) as x:
|
|
92
91
|
raise WGRSError(Georef.__name__, georef, cause=x)
|
|
93
92
|
|
|
94
93
|
|
|
95
|
-
def
|
|
94
|
+
def _2Precision(precision):
|
|
96
95
|
'''(INTERNAL) Return a L{Precision_} instance.
|
|
97
96
|
'''
|
|
98
97
|
return Precision_(precision, Error=WGRSError, low=0, high=_MaxPrec)
|
|
@@ -108,48 +107,51 @@ class Georef(Str):
|
|
|
108
107
|
'''Georef class, a named C{str}.
|
|
109
108
|
'''
|
|
110
109
|
# no str.__init__ in Python 3
|
|
111
|
-
def __new__(cls,
|
|
110
|
+
def __new__(cls, lat_gll, lon=None, height=None, precision=3, name=NN):
|
|
112
111
|
'''New L{Georef} from an other L{Georef} instance or georef
|
|
113
112
|
C{str} or from a C{LatLon} instance or lat-/longitude C{str}.
|
|
114
113
|
|
|
115
|
-
@arg
|
|
116
|
-
|
|
117
|
-
@kwarg
|
|
118
|
-
|
|
119
|
-
|
|
114
|
+
@arg lat_gll: Latitude (C{degrees90}), a georef (L{Georef},
|
|
115
|
+
C{str}) or a location (C{LatLon}, C{LatLon*Tuple}).
|
|
116
|
+
@kwarg lon: Logitude (C{degrees180)}, required if B{C{lat_gll}}
|
|
117
|
+
is C{degrees90}, ignored otherwise.
|
|
118
|
+
@kwarg height: Optional height in C{meter}, used if B{C{lat_gll}}
|
|
119
|
+
is a location.
|
|
120
|
+
@kwarg precision: The desired georef resolution and length (C{int}
|
|
121
|
+
0..11), see L{encode<pygeodesy.wgrs.encode>}.
|
|
120
122
|
@kwarg name: Optional name (C{str}).
|
|
121
123
|
|
|
122
124
|
@return: New L{Georef}.
|
|
123
125
|
|
|
124
|
-
@raise RangeError: Invalid B{C{
|
|
126
|
+
@raise RangeError: Invalid B{C{lat_gll}} or B{C{lon}}.
|
|
125
127
|
|
|
126
|
-
@raise TypeError: Invalid B{C{
|
|
128
|
+
@raise TypeError: Invalid B{C{lat_gll}} or B{C{lon}}.
|
|
127
129
|
|
|
128
|
-
@raise WGRSError: INValid
|
|
130
|
+
@raise WGRSError: INValid B{C{lat_gll}}.
|
|
129
131
|
'''
|
|
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(
|
|
132
|
+
if lon is None:
|
|
133
|
+
if isinstance(lat_gll, Georef):
|
|
134
|
+
g, ll, p = str(lat_gll), lat_gll.latlon, lat_gll.precision
|
|
135
|
+
elif isstr(lat_gll):
|
|
136
|
+
if _COMMA_ in lat_gll or _SPACE_ in lat_gll:
|
|
137
|
+
lat, lon, h = parse3llh(lat_gll, height=height)
|
|
138
|
+
g, ll, p = _encode3(lat, lon, precision, h=h)
|
|
139
|
+
else:
|
|
140
|
+
g, ll = lat_gll.upper(), None
|
|
141
|
+
try:
|
|
142
|
+
_, p = _2geostr2(g) # validate
|
|
143
|
+
except WGRSError: # R00H00?
|
|
144
|
+
p = None # = decode5(g).precision?
|
|
145
|
+
else: # assume LatLon
|
|
146
|
+
try:
|
|
147
|
+
g, ll, p = _encode3(lat_gll.lat, lat_gll.lon, precision,
|
|
148
|
+
h=_xattr(lat_gll, height=height))
|
|
149
|
+
except AttributeError:
|
|
150
|
+
raise _xStrError(Georef, gll=lat_gll) # Error=WGRSError
|
|
151
|
+
else:
|
|
152
|
+
g, ll, p = _encode3(lat_gll, lon, precision, h=height)
|
|
153
|
+
|
|
154
|
+
self = Str.__new__(cls, g, name=name or nameof(lat_gll))
|
|
153
155
|
self._latlon = ll
|
|
154
156
|
self._precision = p
|
|
155
157
|
return self
|
|
@@ -255,7 +257,7 @@ def decode3(georef, center=True):
|
|
|
255
257
|
raise _Error(i)
|
|
256
258
|
return k
|
|
257
259
|
|
|
258
|
-
g, precision =
|
|
260
|
+
g, precision = _2geostr2(georef)
|
|
259
261
|
lon = _index(_LonTile, g, 0) + _LonOrig_Tile
|
|
260
262
|
lat = _index(_LatTile, g, 1) + _LatOrig_Tile
|
|
261
263
|
|
|
@@ -288,30 +290,29 @@ def decode5(georef, center=True):
|
|
|
288
290
|
@kwarg center: If C{True} the center, otherwise the south-west,
|
|
289
291
|
lower-left corner (C{bool}).
|
|
290
292
|
|
|
291
|
-
@return: A L{LatLonPrec5Tuple}C{(lat, lon,
|
|
292
|
-
|
|
293
|
-
C{radius} are C{None} if missing.
|
|
293
|
+
@return: A L{LatLonPrec5Tuple}C{(lat, lon, precision, height, radius)}
|
|
294
|
+
where C{height} and/or C{radius} are C{None} if missing.
|
|
294
295
|
|
|
295
|
-
@raise WGRSError: Invalid B{C{georef}}
|
|
296
|
-
or odd length B{C{georef}}.
|
|
296
|
+
@raise WGRSError: Invalid B{C{georef}}.
|
|
297
297
|
'''
|
|
298
|
-
def _h2m(kft,
|
|
299
|
-
return Height(ft2m(kft * _1000_0), name=
|
|
298
|
+
def _h2m(kft, g_n):
|
|
299
|
+
return Height(ft2m(kft * _1000_0), name=g_n, Error=WGRSError)
|
|
300
300
|
|
|
301
|
-
def _r2m(NM,
|
|
302
|
-
return Radius(NM / m2NM(1), name=
|
|
301
|
+
def _r2m(NM, g_n):
|
|
302
|
+
return Radius(NM / m2NM(1), name=g_n, Error=WGRSError)
|
|
303
303
|
|
|
304
|
-
def _split2(g,
|
|
305
|
-
|
|
304
|
+
def _split2(g, Unit, _2m):
|
|
305
|
+
n = Unit.__name__
|
|
306
|
+
i = max(g.find(n[0]), g.rfind(n[0]))
|
|
306
307
|
if i > _BaseLen:
|
|
307
|
-
return g[:i], _2m(int(g[i+1:]), _SPACE_(georef,
|
|
308
|
+
return g[:i], _2m(int(g[i+1:]), _SPACE_(georef, n))
|
|
308
309
|
else:
|
|
309
310
|
return g, None
|
|
310
311
|
|
|
311
312
|
g = Str(georef, Error=WGRSError)
|
|
312
313
|
|
|
313
|
-
g, h = _split2(g,
|
|
314
|
-
g, r = _split2(g,
|
|
314
|
+
g, h = _split2(g, Height, _h2m) # H is last
|
|
315
|
+
g, r = _split2(g, Radius, _r2m) # R before H
|
|
315
316
|
|
|
316
317
|
return decode3(g, center=center).to5Tuple(h, r)
|
|
317
318
|
|
|
@@ -345,30 +346,39 @@ def encode(lat, lon, precision=3, height=None, radius=None): # MCCABE 14
|
|
|
345
346
|
f = Scalar_(m, name=name, Error=WGRSError)
|
|
346
347
|
return NN(name[0].upper(), int(m2_(f * K) + _0_5))
|
|
347
348
|
|
|
348
|
-
|
|
349
|
+
g, _, _ = _encode3(lat, lon, precision)
|
|
350
|
+
if radius is not None: # R before H
|
|
351
|
+
g += _option(_radius_, radius, m2NM, _1_0)
|
|
352
|
+
if height is not None: # H is last
|
|
353
|
+
g += _option(_height_, height, m2ft, _0_001)
|
|
354
|
+
return g
|
|
355
|
+
|
|
349
356
|
|
|
350
|
-
|
|
351
|
-
|
|
357
|
+
def _encode3(lat, lon, precision, h=None):
|
|
358
|
+
'''Return 3-tuple C{(georef, (lat, lon), p)}.
|
|
359
|
+
'''
|
|
360
|
+
p = _2Precision(precision)
|
|
352
361
|
|
|
353
|
-
|
|
354
|
-
yt, yd, y = _divmod3(lat, _LatOrig_60B)
|
|
362
|
+
lat, lon = _2fll(lat, lon)
|
|
355
363
|
|
|
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
|
|
364
|
+
if h is None:
|
|
365
|
+
xt, xd, x = _divmod3( lon, _LonOrig_60B)
|
|
366
|
+
yt, yd, y = _divmod3(_off90(lat), _LatOrig_60B)
|
|
365
367
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
368
|
+
g = _LonTile[xt], _LatTile[yt]
|
|
369
|
+
if p > 0:
|
|
370
|
+
g += _DegChar[xd], _DegChar[yd]
|
|
371
|
+
p -= 1
|
|
372
|
+
if p > 0:
|
|
373
|
+
d = pow(_Base, _MaxPrec - p)
|
|
374
|
+
x = _0wd(p, x // d)
|
|
375
|
+
y = _0wd(p, y // d)
|
|
376
|
+
g += x, y
|
|
377
|
+
g = NN.join(g)
|
|
378
|
+
else:
|
|
379
|
+
g = encode(lat, lon, precision=p, height=h)
|
|
370
380
|
|
|
371
|
-
return
|
|
381
|
+
return g, (lat, lon), p # XXX Georef(''.join(g))
|
|
372
382
|
|
|
373
383
|
|
|
374
384
|
def precision(res):
|
|
File without changes
|
|
File without changes
|