pygeodesy 24.6.9__py2.py3-none-any.whl → 24.6.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.6.9.dist-info → PyGeodesy-24.6.24.dist-info}/METADATA +2 -2
- PyGeodesy-24.6.24.dist-info/RECORD +117 -0
- pygeodesy/__init__.py +33 -32
- pygeodesy/albers.py +2 -2
- pygeodesy/auxilats/__init__.py +1 -1
- pygeodesy/auxilats/auxAngle.py +40 -39
- pygeodesy/auxilats/auxDLat.py +3 -2
- pygeodesy/auxilats/auxLat.py +16 -18
- pygeodesy/auxilats/auxily.py +1 -1
- pygeodesy/azimuthal.py +10 -10
- pygeodesy/basics.py +9 -1
- pygeodesy/booleans.py +4 -4
- pygeodesy/cartesianBase.py +11 -14
- pygeodesy/css.py +14 -18
- pygeodesy/datums.py +6 -6
- pygeodesy/deprecated/__init__.py +1 -1
- pygeodesy/deprecated/classes.py +16 -2
- pygeodesy/deprecated/datum.py +3 -3
- pygeodesy/deprecated/functions.py +6 -8
- pygeodesy/dms.py +23 -27
- pygeodesy/ecef.py +4 -4
- pygeodesy/elevations.py +4 -4
- pygeodesy/ellipsoidalBase.py +23 -28
- pygeodesy/ellipsoidalBaseDI.py +19 -23
- pygeodesy/ellipsoidalExact.py +3 -3
- pygeodesy/ellipsoidalGeodSolve.py +15 -23
- pygeodesy/ellipsoidalKarney.py +37 -60
- pygeodesy/ellipsoidalNvector.py +38 -44
- pygeodesy/ellipsoidalVincenty.py +11 -14
- pygeodesy/ellipsoids.py +107 -101
- pygeodesy/errors.py +100 -48
- pygeodesy/etm.py +32 -44
- pygeodesy/formy.py +55 -58
- pygeodesy/frechet.py +18 -20
- pygeodesy/fsums.py +3 -3
- pygeodesy/gars.py +3 -4
- pygeodesy/geodesici.py +909 -0
- pygeodesy/geodesicw.py +11 -13
- pygeodesy/geodesicx/__init__.py +4 -4
- pygeodesy/geodesicx/gx.py +18 -28
- pygeodesy/geodesicx/gxbases.py +20 -8
- pygeodesy/geodesicx/gxline.py +16 -22
- pygeodesy/geodsolve.py +80 -10
- pygeodesy/geohash.py +26 -34
- pygeodesy/geoids.py +28 -37
- pygeodesy/hausdorff.py +17 -18
- pygeodesy/heights.py +2 -2
- pygeodesy/internals.py +6 -0
- pygeodesy/interns.py +2 -2
- pygeodesy/karney.py +20 -4
- pygeodesy/ktm.py +13 -16
- pygeodesy/latlonBase.py +17 -19
- pygeodesy/lazily.py +7 -6
- pygeodesy/lcc.py +28 -31
- pygeodesy/ltp.py +7 -8
- pygeodesy/ltpTuples.py +68 -70
- pygeodesy/mgrs.py +8 -9
- pygeodesy/named.py +19 -10
- pygeodesy/nvectorBase.py +9 -10
- pygeodesy/osgr.py +9 -9
- pygeodesy/points.py +6 -6
- pygeodesy/rhumb/__init__.py +1 -1
- pygeodesy/rhumb/aux_.py +5 -5
- pygeodesy/rhumb/bases.py +30 -31
- pygeodesy/rhumb/ekx.py +3 -4
- pygeodesy/sphericalBase.py +10 -11
- pygeodesy/sphericalNvector.py +13 -13
- pygeodesy/sphericalTrigonometry.py +86 -97
- pygeodesy/streprs.py +4 -34
- pygeodesy/triaxials.py +48 -43
- pygeodesy/units.py +204 -271
- pygeodesy/unitsBase.py +115 -107
- pygeodesy/ups.py +26 -31
- pygeodesy/utily.py +8 -8
- pygeodesy/utm.py +35 -40
- pygeodesy/utmups.py +43 -46
- pygeodesy/utmupsBase.py +8 -9
- pygeodesy/vector3d.py +26 -27
- pygeodesy/vector3dBase.py +6 -7
- pygeodesy/webmercator.py +19 -21
- pygeodesy/wgrs.py +18 -20
- PyGeodesy-24.6.9.dist-info/RECORD +0 -116
- {PyGeodesy-24.6.9.dist-info → PyGeodesy-24.6.24.dist-info}/WHEEL +0 -0
- {PyGeodesy-24.6.9.dist-info → PyGeodesy-24.6.24.dist-info}/top_level.txt +0 -0
pygeodesy/geodesicw.py
CHANGED
|
@@ -37,7 +37,7 @@ from contextlib import contextmanager
|
|
|
37
37
|
# from math import fabs # from .utily
|
|
38
38
|
|
|
39
39
|
__all__ = _ALL_LAZY.geodesicw
|
|
40
|
-
__version__ = '24.
|
|
40
|
+
__version__ = '24.06.24'
|
|
41
41
|
|
|
42
42
|
_plumb_ = 'plumb'
|
|
43
43
|
_TRIPS = 65
|
|
@@ -71,8 +71,8 @@ class _gWrapped(_kWrapped):
|
|
|
71
71
|
|
|
72
72
|
@arg a_ellipsoid: The equatorial radius I{a} (C{meter}, conventionally),
|
|
73
73
|
an ellipsoid (L{Ellipsoid}) or a datum (L{Datum}).
|
|
74
|
-
@arg f: The ellipsoid's flattening (C{scalar}),
|
|
75
|
-
is
|
|
74
|
+
@arg f: The ellipsoid's flattening (C{scalar}), required if B{C{a_ellipsoid})
|
|
75
|
+
is C{meter}, ignored otherwise.
|
|
76
76
|
@kwarg name: Optional C{B{name}=NN} (C{str}).
|
|
77
77
|
'''
|
|
78
78
|
_earth_datum(self, a_ellipsoid, f=f, **name) # raiser=NN
|
|
@@ -429,17 +429,16 @@ class _gWrapped(_kWrapped):
|
|
|
429
429
|
_wrapped = _gWrapped() # PYCHOK singleton, .ellipsoids, .test/base.py
|
|
430
430
|
|
|
431
431
|
|
|
432
|
-
def Geodesic(a_ellipsoid, f=None, **name):
|
|
432
|
+
def Geodesic(a_ellipsoid=_EWGS84, f=None, **name):
|
|
433
433
|
'''Return a I{wrapped} C{geodesic.Geodesic} instance from I{Karney}'s
|
|
434
434
|
Python U{geographiclib<https://PyPI.org/project/geographiclib>},
|
|
435
435
|
provide the latter is installed, otherwise an C{ImportError}.
|
|
436
436
|
|
|
437
437
|
@arg a_ellipsoid: An ellipsoid (L{Ellipsoid}) or datum (L{Datum})
|
|
438
438
|
or the equatorial radius I{a} of the ellipsoid (C{meter}).
|
|
439
|
-
@arg f: The flattening of the ellipsoid (C{scalar}),
|
|
440
|
-
B{C{a_ellipsoid}}) is
|
|
441
|
-
@kwarg name: Optional
|
|
442
|
-
like B{C{f}}.
|
|
439
|
+
@arg f: The flattening of the ellipsoid (C{scalar}), required if
|
|
440
|
+
B{C{a_ellipsoid}}) is C{meter}, ignored otherwise.
|
|
441
|
+
@kwarg name: Optional C{B{name}=NN} (C{str}), ignored like B{C{f}}.
|
|
443
442
|
'''
|
|
444
443
|
return _wrapped.Geodesic(a_ellipsoid, f=f, **name)
|
|
445
444
|
|
|
@@ -453,11 +452,10 @@ def GeodesicLine(geodesic, lat1, lon1, azi1, caps=Caps._STD_LINE):
|
|
|
453
452
|
@arg lat1: Latitude of the first points (C{degrees}).
|
|
454
453
|
@arg lon1: Longitude of the first points (C{degrees}).
|
|
455
454
|
@arg azi1: Azimuth at the first points (compass C{degrees360}).
|
|
456
|
-
@kwarg caps: Optional, bit-or'ed combination of L{Caps} values
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
and C{GeodesicLine.ArcPosition}.
|
|
455
|
+
@kwarg caps: Optional, bit-or'ed combination of L{Caps} values specifying
|
|
456
|
+
the capabilities the C{GeodesicLine} instance should possess,
|
|
457
|
+
i.e., which quantities can be returned by methods
|
|
458
|
+
C{GeodesicLine.Position} and C{GeodesicLine.ArcPosition}.
|
|
461
459
|
'''
|
|
462
460
|
return _wrapped.GeodesicLine(geodesic, lat1, lon1, azi1, caps=caps)
|
|
463
461
|
|
pygeodesy/geodesicx/__init__.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
|
|
4
4
|
u'''A pure Python version of I{Karney}'s C++ classes U{GeodesicExact
|
|
5
|
-
<https://GeographicLib.SourceForge.io/C++/classGeographicLib_1_1GeodesicExact.html>}
|
|
5
|
+
<https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1GeodesicExact.html>}
|
|
6
6
|
and U{GeodesicLineExact
|
|
7
7
|
<https://geographiclib.sourceforge.io/C++/doc/classGeographicLib_1_1GeodesicLine.html>}.
|
|
8
8
|
|
|
@@ -13,8 +13,8 @@ and the background information at U{Geodesics on an ellipsoid of revolution
|
|
|
13
13
|
|
|
14
14
|
Also, compare C{GeodesicExact} and C{GeodesicLineExact} to I{standard} classes C{Geodesic}
|
|
15
15
|
respectively C{GeodesicLine} from I{Karney}'s Python implementation U{geographiclib
|
|
16
|
-
<https://GeographicLib.SourceForge.io/C++/doc/other.html#python>}, see
|
|
17
|
-
L{pygeodesy.karney}.
|
|
16
|
+
<https://GeographicLib.SourceForge.io/C++/doc/other.html#python>}, see modules
|
|
17
|
+
L{pygeodesy.geodesicw} and L{pygeodesy.karney}.
|
|
18
18
|
'''
|
|
19
19
|
|
|
20
20
|
from pygeodesy.geodesicx.gx import GeodesicExact, GeodesicLineExact # PYCHOK exported
|
|
@@ -23,7 +23,7 @@ from pygeodesy.karney import Caps, GeodesicError
|
|
|
23
23
|
from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY
|
|
24
24
|
|
|
25
25
|
__all__ = _ALL_LAZY.geodesicx + _ALL_DOCS(Caps, GeodesicError)
|
|
26
|
-
__version__ = '24.
|
|
26
|
+
__version__ = '24.06.19'
|
|
27
27
|
|
|
28
28
|
# **) MIT License
|
|
29
29
|
#
|
pygeodesy/geodesicx/gx.py
CHANGED
|
@@ -44,25 +44,26 @@ from pygeodesy.constants import EPS, EPS0, EPS02, MANT_DIG, NAN, PI, _EPSqrt, \
|
|
|
44
44
|
from pygeodesy.datums import _earth_datum, _WGS84, _EWGS84
|
|
45
45
|
# from pygeodesy.ellipsoids import _EWGS84 # from .datums
|
|
46
46
|
from pygeodesy.errors import GeodesicError, _xkwds_pop2
|
|
47
|
-
from pygeodesy.fmath import hypot as _hypot
|
|
47
|
+
from pygeodesy.fmath import hypot as _hypot, Fmt
|
|
48
48
|
from pygeodesy.fsums import fsumf_, fsum1f_
|
|
49
49
|
from pygeodesy.geodesicx.gxbases import _cosSeries, _GeodesicBase, \
|
|
50
|
-
_sincos12, _sin1cos2,
|
|
51
|
-
|
|
52
|
-
from pygeodesy.
|
|
50
|
+
_sincos12, _sin1cos2, _sinf1cos2d, \
|
|
51
|
+
_TINY, _xnC4
|
|
52
|
+
from pygeodesy.geodesicx.gxline import _GeodesicLineExact, _update_glXs
|
|
53
|
+
from pygeodesy.interns import NN, _DOT_, _UNDER_
|
|
53
54
|
from pygeodesy.karney import GDict, _around, _atan2d, Caps, _cbrt, _diff182, \
|
|
54
55
|
_fix90, _K_2_0, _norm2, _norm180, _polynomial, \
|
|
55
56
|
_signBit, _sincos2, _sincos2d, _sincos2de, _unsigned2
|
|
56
57
|
from pygeodesy.lazily import _ALL_DOCS, _ALL_MODS as _MODS
|
|
57
58
|
from pygeodesy.namedTuples import Destination3Tuple, Distance3Tuple
|
|
58
59
|
from pygeodesy.props import deprecated_Property, Property, Property_RO, property_RO
|
|
59
|
-
from pygeodesy.streprs import Fmt
|
|
60
|
+
# from pygeodesy.streprs import Fmt # from .fmath
|
|
60
61
|
from pygeodesy.utily import atan2d as _atan2d_reverse, _unrollon, _Wrap, wrap360
|
|
61
62
|
|
|
62
63
|
from math import atan2, copysign, cos, degrees, fabs, radians, sqrt
|
|
63
64
|
|
|
64
65
|
__all__ = ()
|
|
65
|
-
__version__ = '24.
|
|
66
|
+
__version__ = '24.06.24'
|
|
66
67
|
|
|
67
68
|
_MAXIT1 = 20
|
|
68
69
|
_MAXIT2 = 10 + _MAXIT1 + MANT_DIG # MANT_DIG == C++ digits
|
|
@@ -553,10 +554,10 @@ class GeodesicExact(_GeodesicBase):
|
|
|
553
554
|
# to check, e.g., on verifying quadrants in atan2. In addition,
|
|
554
555
|
# this enforces some symmetries in the results returned.
|
|
555
556
|
|
|
556
|
-
# Initialize for the meridian. No longitude calculation is
|
|
557
|
-
#
|
|
558
|
-
sbet1, cbet1 =
|
|
559
|
-
sbet2, cbet2 =
|
|
557
|
+
# Initialize for the meridian. No longitude calculation is done in
|
|
558
|
+
# this case to let the parameter default to 0.
|
|
559
|
+
sbet1, cbet1 = _sinf1cos2d(lat1, self.f1)
|
|
560
|
+
sbet2, cbet2 = _sinf1cos2d(lat2, self.f1)
|
|
560
561
|
# If cbet1 < -sbet1, then cbet2 - cbet1 is a sensitive measure
|
|
561
562
|
# of the |bet1| - |bet2|. Alternatively (cbet1 >= -sbet1),
|
|
562
563
|
# abs(sbet2) + sbet1 is a better measure. This logic is used
|
|
@@ -1241,27 +1242,16 @@ class GeodesicExact(_GeodesicBase):
|
|
|
1241
1242
|
|
|
1242
1243
|
Polygon = Area # for C{geographiclib} compatibility
|
|
1243
1244
|
|
|
1244
|
-
def
|
|
1245
|
-
'''(INTERNAL) Helper, also for C{_G_GeodesicLineExact}.
|
|
1246
|
-
'''
|
|
1247
|
-
sbet, cbet = _sincos2d(lat)
|
|
1248
|
-
# ensure cbet1 = +epsilon at poles; doing the fix on beta means
|
|
1249
|
-
# that sig12 will be <= 2*tiny for two points at the same pole
|
|
1250
|
-
sbet, cbet = _norm2(sbet * self.f1, cbet)
|
|
1251
|
-
return sbet, (cbet if fabs(cbet) > _TINY else _TINY)
|
|
1252
|
-
|
|
1253
|
-
def toStr(self, prec=6, sep=_COMMASPACE_, **unused): # PYCHOK signature
|
|
1245
|
+
def toStr(self, **prec_sep_name): # PYCHOK signature
|
|
1254
1246
|
'''Return this C{GeodesicExact} as string.
|
|
1255
1247
|
|
|
1256
|
-
@
|
|
1257
|
-
|
|
1258
|
-
of 1 and above, but kept for negative B{C{prec}} values.
|
|
1259
|
-
@kwarg sep: Separator to join (C{str}).
|
|
1248
|
+
@see: L{Ellipsoid.toStr<pygeodesy.ellipsoids.Ellipsoid.toStr>}
|
|
1249
|
+
for further details.
|
|
1260
1250
|
|
|
1261
|
-
@return:
|
|
1251
|
+
@return: C{GeodesicExact} (C{str}).
|
|
1262
1252
|
'''
|
|
1263
|
-
|
|
1264
|
-
|
|
1253
|
+
return self._instr(props=(GeodesicExact.ellipsoid,),
|
|
1254
|
+
C4order=self.C4order, **prec_sep_name)
|
|
1265
1255
|
|
|
1266
1256
|
|
|
1267
1257
|
class GeodesicLineExact(_GeodesicLineExact):
|
|
@@ -1290,7 +1280,7 @@ class GeodesicLineExact(_GeodesicLineExact):
|
|
|
1290
1280
|
'''
|
|
1291
1281
|
_xinstanceof(GeodesicExact, geodesic=geodesic)
|
|
1292
1282
|
if (caps & Caps.LINE_OFF): # copy to avoid updates
|
|
1293
|
-
geodesic = geodesic.copy(deep=False, name=_UNDER_(NN, geodesic.name))
|
|
1283
|
+
geodesic = geodesic.copy(deep=False, name=_UNDER_(NN, geodesic.name))
|
|
1294
1284
|
# _update_all(geodesic)
|
|
1295
1285
|
_GeodesicLineExact.__init__(self, geodesic, lat1, lon1, azi1, caps, 0, **name)
|
|
1296
1286
|
|
pygeodesy/geodesicx/gxbases.py
CHANGED
|
@@ -9,19 +9,21 @@ U{GeographicLib<https://GeographicLib.SourceForge.io>} documentation.
|
|
|
9
9
|
'''
|
|
10
10
|
|
|
11
11
|
from pygeodesy.basics import isodd, _MODS
|
|
12
|
-
from pygeodesy.constants import _0_0, _100_0
|
|
12
|
+
from pygeodesy.constants import _EPSmin as _TINY, _0_0, _100_0
|
|
13
13
|
from pygeodesy.errors import _or, _xkwds_item2
|
|
14
14
|
from pygeodesy.fmath import hypot as _hypot
|
|
15
|
-
from pygeodesy.karney import _CapsBase, GeodesicError, _2cos2x,
|
|
15
|
+
from pygeodesy.karney import _CapsBase, GeodesicError, _2cos2x, \
|
|
16
|
+
_norm2, _sincos2d, _sum2_
|
|
16
17
|
# from pygeodesy.lazily import _MODS, printf # .basics, _MODS
|
|
17
18
|
|
|
18
|
-
from math import ldexp as _ldexp
|
|
19
|
+
from math import fabs, ldexp as _ldexp
|
|
19
20
|
|
|
20
21
|
__all__ = ()
|
|
21
|
-
__version__ = '24.
|
|
22
|
+
__version__ = '24.06.16'
|
|
22
23
|
|
|
23
24
|
# valid C{nC4}s and C{C4order}s, see _xnC4 below
|
|
24
25
|
_nC4s = {24: 2900, 27: 4032, 30: 5425}
|
|
26
|
+
# assert (_TINY * EPS) > 0 and (_TINY + EPS) == EPS # underflow guard
|
|
25
27
|
|
|
26
28
|
|
|
27
29
|
class _GeodesicBase(_CapsBase): # in .geodsolve
|
|
@@ -71,15 +73,15 @@ def _cosSeries(c4s, sx, cx): # PYCHOK shared .geodesicx.gx and -.gxline
|
|
|
71
73
|
y0 = t0 = y1 = t1 = _0_0
|
|
72
74
|
c4 = list(c4s)
|
|
73
75
|
_c4 = c4.pop
|
|
74
|
-
_s2 = _sum2_
|
|
75
76
|
if isodd(len(c4)):
|
|
76
77
|
y0 = _c4()
|
|
78
|
+
_s2 = _sum2_
|
|
77
79
|
while c4:
|
|
78
80
|
# y1 = ar * y0 - y1 + c4.pop()
|
|
79
81
|
# y0 = ar * y1 - y0 + c4.pop()
|
|
80
82
|
y1, t1 = _s2(ar * y0, ar * t0, -y1, -t1, _c4())
|
|
81
83
|
y0, t0 = _s2(ar * y1, ar * t1, -y0, -t0, _c4())
|
|
82
|
-
# s =
|
|
84
|
+
# s = (y0 - y1) * cx
|
|
83
85
|
s, _ = _s2(cx * y0, _0_0, cx * t0, -cx * y1, -cx * t1)
|
|
84
86
|
return s
|
|
85
87
|
|
|
@@ -93,7 +95,7 @@ def _f2(hi, lo): # in .geodesicx._C4_24, _27 and _30
|
|
|
93
95
|
return _ldexp(_f(hi), 52) + _f(lo)
|
|
94
96
|
|
|
95
97
|
|
|
96
|
-
def _sincos12(sin1, cos1, sin2, cos2, sineg0=False):
|
|
98
|
+
def _sincos12(sin1, cos1, sin2, cos2, sineg0=False):
|
|
97
99
|
'''(INTERNAL) Compute the sine and cosine of angle
|
|
98
100
|
M{ang12 = atan2(sin2, cos2) - atan2(sin1, cos1)}.
|
|
99
101
|
|
|
@@ -111,7 +113,7 @@ def _sincos12(sin1, cos1, sin2, cos2, sineg0=False): # PYCHOK shared
|
|
|
111
113
|
return s, c
|
|
112
114
|
|
|
113
115
|
|
|
114
|
-
def _sin1cos2(sin1, cos1, sin2, cos2):
|
|
116
|
+
def _sin1cos2(sin1, cos1, sin2, cos2):
|
|
115
117
|
'''(INTERNAL) Compute the C{sin1 * cos2} sine and its cosine.
|
|
116
118
|
|
|
117
119
|
@return: 2-Tuple C{(sin1 * cos2, hypot(sin1 * sin2, cos1)}.
|
|
@@ -121,6 +123,16 @@ def _sin1cos2(sin1, cos1, sin2, cos2): # PYCHOK shared
|
|
|
121
123
|
return s, c # _norm2(s, c)
|
|
122
124
|
|
|
123
125
|
|
|
126
|
+
def _sinf1cos2d(lat, f1):
|
|
127
|
+
'''(INTERNAL) See C{GeodesicExact} and C{_GeodesicLineExact}.
|
|
128
|
+
'''
|
|
129
|
+
sbet, cbet = _sincos2d(lat)
|
|
130
|
+
# ensure cbet1 = +epsilon at poles; doing the fix on beta means
|
|
131
|
+
# that sig12 will be <= 2*tiny for two points at the same pole
|
|
132
|
+
sbet, cbet = _norm2(sbet * f1, cbet)
|
|
133
|
+
return sbet, (cbet if fabs(cbet) > _TINY else _TINY)
|
|
134
|
+
|
|
135
|
+
|
|
124
136
|
def _xnC4(**name_nC4):
|
|
125
137
|
'''(INTERNAL) Validate C{C4order}.
|
|
126
138
|
'''
|
pygeodesy/geodesicx/gxline.py
CHANGED
|
@@ -37,30 +37,27 @@ from __future__ import division as _; del _ # PYCHOK semicolon
|
|
|
37
37
|
# - s and c prefixes mean sin and cos
|
|
38
38
|
|
|
39
39
|
# from pygeodesy.basics import _xinstanceof # _MODS
|
|
40
|
-
from pygeodesy.constants import NAN,
|
|
41
|
-
|
|
42
|
-
from pygeodesy.errors import _xError
|
|
40
|
+
from pygeodesy.constants import NAN, _EPSqrt as _TOL, _0_0, _1_0, \
|
|
41
|
+
_180_0, _2__PI, _copysign_1_0
|
|
42
|
+
# from pygeodesy.errors import _xError # _MODS
|
|
43
43
|
from pygeodesy.fsums import fsumf_, fsum1f_
|
|
44
44
|
from pygeodesy.geodesicx.gxbases import _cosSeries, _GeodesicBase, \
|
|
45
|
-
_sincos12, _sin1cos2
|
|
45
|
+
_sincos12, _sin1cos2, \
|
|
46
|
+
_sinf1cos2d, _TINY
|
|
46
47
|
# from pygeodesy.geodesicw import _Intersecant2 # _MODS
|
|
47
|
-
# from pygeodesy.interns import _COMMASPACE_ # from .errors
|
|
48
48
|
from pygeodesy.lazily import _ALL_DOCS, _ALL_MODS as _MODS
|
|
49
49
|
from pygeodesy.karney import _around, _atan2d, Caps, GDict, _fix90, \
|
|
50
50
|
_K_2_0, _norm2, _norm180, _sincos2, _sincos2d
|
|
51
|
-
from pygeodesy.
|
|
52
|
-
# from pygeodesy.
|
|
51
|
+
from pygeodesy.named import Property_RO, _update_all
|
|
52
|
+
# from pygeodesy.props import Property_RO, _update_all # from .named
|
|
53
53
|
from pygeodesy.utily import atan2d as _atan2d_reverse, sincos2
|
|
54
54
|
|
|
55
55
|
from math import atan2, cos, degrees, fabs, floor, radians, sin
|
|
56
56
|
|
|
57
57
|
__all__ = ()
|
|
58
|
-
__version__ = '24.
|
|
58
|
+
__version__ = '24.06.24'
|
|
59
59
|
|
|
60
60
|
_glXs = [] # instances of C{[_]GeodesicLineExact} to be updated
|
|
61
|
-
# underflow guard, we require _TINY * EPS > 0, _TINY + EPS == EPS
|
|
62
|
-
_TINY = _EPSmin
|
|
63
|
-
# assert (_TINY * EPS) > 0 and (_TINY + EPS) == EPS
|
|
64
61
|
|
|
65
62
|
|
|
66
63
|
def _update_glXs(gX): # see GeodesicExact.C4order and -._ef_reset_k2
|
|
@@ -122,7 +119,7 @@ class _GeodesicLineExact(_GeodesicBase):
|
|
|
122
119
|
# allow lat, azimuth and unrolling of lon
|
|
123
120
|
self._caps = caps | Cs._LINE
|
|
124
121
|
|
|
125
|
-
sbet1, cbet1 =
|
|
122
|
+
sbet1, cbet1 = _sinf1cos2d(_around(lat1), gX.f1)
|
|
126
123
|
self._dn1 = gX._dn(sbet1, cbet1)
|
|
127
124
|
# Evaluate alp0 from sin(alp1) * cos(bet1) = sin(alp0), with alp0
|
|
128
125
|
# in [0, pi/2 - |bet1|]. Alt: calp0 = hypot(sbet1, calp1 * cbet1),
|
|
@@ -501,7 +498,7 @@ class _GeodesicLineExact(_GeodesicBase):
|
|
|
501
498
|
try:
|
|
502
499
|
return _MODS.geodesicw._Intersecant2(self, lat0, lon0, radius, tol=tol)
|
|
503
500
|
except (TypeError, ValueError) as x:
|
|
504
|
-
raise _xError(x, lat0, lon0, radius, tol=_TOL)
|
|
501
|
+
raise _MODS.errors._xError(x, lat0, lon0, radius, tol=_TOL)
|
|
505
502
|
|
|
506
503
|
@Property_RO
|
|
507
504
|
def _H0e2_f1(self):
|
|
@@ -626,20 +623,17 @@ class _GeodesicLineExact(_GeodesicBase):
|
|
|
626
623
|
# unnecessary because Einv inverts E
|
|
627
624
|
# return -self._eF.deltaEinv(stau1, ctau1)
|
|
628
625
|
|
|
629
|
-
def toStr(self,
|
|
626
|
+
def toStr(self, **prec_sep_name): # PYCHOK signature
|
|
630
627
|
'''Return this C{GeodesicLineExact} as string.
|
|
631
628
|
|
|
632
|
-
@
|
|
633
|
-
|
|
634
|
-
of 1 and above, but kept for negative B{C{prec}} values.
|
|
635
|
-
@kwarg sep: Separator to join (C{str}).
|
|
629
|
+
@see: L{Ellipsoid.toStr<pygeodesy.ellipsoids.Ellipsoid.toStr>}
|
|
630
|
+
for further details.
|
|
636
631
|
|
|
637
632
|
@return: C{GeodesicLineExact} (C{str}).
|
|
638
633
|
'''
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
return sep.join(_MODS.streprs.pairs(d, prec=prec))
|
|
634
|
+
C = _GeodesicLineExact
|
|
635
|
+
t = C.lat1, C.lon1, C.azi1, C.a13, C.s13, C.geodesic
|
|
636
|
+
return self._instr(props=t, **prec_sep_name)
|
|
643
637
|
|
|
644
638
|
|
|
645
639
|
__all__ += _ALL_DOCS(_GeodesicLineExact)
|
pygeodesy/geodsolve.py
CHANGED
|
@@ -10,30 +10,32 @@ of the C{GeodSolve} executable.
|
|
|
10
10
|
'''
|
|
11
11
|
|
|
12
12
|
from pygeodesy.basics import _xinstanceof
|
|
13
|
+
# from pygeodesy.constants import NAN, _0_0 # from .karney
|
|
13
14
|
# from pygeodesy.geodesicx import GeodesicAreaExact # _MODS
|
|
14
15
|
from pygeodesy.interns import NN, _a12_, _azi1_, _azi2_, \
|
|
15
16
|
_lat1_, _lat2_, _lon1_, _lon2_, _m12_, \
|
|
16
17
|
_M12_, _M21_, _s12_, _S12_, _UNDER_
|
|
17
18
|
from pygeodesy.interns import _UNUSED_, _not_ # PYCHOK used!
|
|
18
19
|
from pygeodesy.karney import _Azi, Caps, _Deg, GeodesicError, _GTuple, \
|
|
19
|
-
_Pass, _Lat, _Lon, _M, _M2, _sincos2d
|
|
20
|
+
_Pass, _Lat, _Lon, _M, _M2, _sincos2d, \
|
|
21
|
+
_0_0, NAN
|
|
20
22
|
from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS, \
|
|
21
23
|
_getenv, _PYGEODESY_GEODSOLVE_
|
|
22
24
|
from pygeodesy.named import _name1__
|
|
23
25
|
from pygeodesy.namedTuples import Destination3Tuple, Distance3Tuple
|
|
24
|
-
from pygeodesy.props import Property, Property_RO
|
|
26
|
+
from pygeodesy.props import Property, Property_RO, property_RO
|
|
25
27
|
from pygeodesy.solveBase import _SolveBase, _SolveLineBase
|
|
26
28
|
from pygeodesy.utily import _unrollon, _Wrap, wrap360
|
|
27
29
|
|
|
28
30
|
__all__ = _ALL_LAZY.geodsolve
|
|
29
|
-
__version__ = '24.06.
|
|
31
|
+
__version__ = '24.06.26'
|
|
30
32
|
|
|
31
33
|
|
|
32
34
|
class GeodSolve12Tuple(_GTuple):
|
|
33
35
|
'''12-Tuple C{(lat1, lon1, azi1, lat2, lon2, azi2, s12, a12, m12, M12, M21, S12)} with
|
|
34
36
|
angles C{lat1}, C{lon1}, C{azi1}, C{lat2}, C{lon2} and C{azi2} and arc C{a12} all in
|
|
35
37
|
C{degrees}, initial C{azi1} and final C{azi2} forward azimuths, distance C{s12} and
|
|
36
|
-
reduced length C{m12} in C{meter}, area C{S12} in C{meter} I{squared}
|
|
38
|
+
reduced length C{m12} in C{meter}, area C{S12} in C{meter} I{squared} and geodesic
|
|
37
39
|
scale factors C{M12} and C{M21}, both C{scalar}, see U{GeodSolve
|
|
38
40
|
<https://GeographicLib.SourceForge.io/C++/doc/GeodSolve.1.html>}.
|
|
39
41
|
'''
|
|
@@ -222,8 +224,11 @@ class GeodesicSolve(_GeodesicSolveBase):
|
|
|
222
224
|
<https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1GeodesicExact.html>} and
|
|
223
225
|
Python U{Geodesic.InverseLine<https://GeographicLib.SourceForge.io/Python/doc/code.html>}.
|
|
224
226
|
'''
|
|
225
|
-
r
|
|
226
|
-
|
|
227
|
+
r = self.Inverse(lat1, lon1, lat2, lon2)
|
|
228
|
+
gl = GeodesicLineSolve(self, lat1, lon1, r.azi1, **_name1__(caps_name, _or_nameof=self))
|
|
229
|
+
gl._a13 = r.a12 # gl.SetArc(r.a12)
|
|
230
|
+
gl._s13 = r.s12 # gl.SetDistance(r.s12)
|
|
231
|
+
return gl
|
|
227
232
|
|
|
228
233
|
|
|
229
234
|
class GeodesicLineSolve(_GeodesicSolveBase, _SolveLineBase):
|
|
@@ -237,6 +242,8 @@ class GeodesicLineSolve(_GeodesicSolveBase, _SolveLineBase):
|
|
|
237
242
|
@note: This C{geodesic} is intended I{for testing purposes only}, it invokes the C{GeodSolve}
|
|
238
243
|
executable for I{every} method call.
|
|
239
244
|
'''
|
|
245
|
+
_a13 = \
|
|
246
|
+
_s13 = NAN # see GeodesicSolve._InverseLine
|
|
240
247
|
|
|
241
248
|
def __init__(self, geodesic, lat1, lon1, azi1, caps=Caps.ALL, **name):
|
|
242
249
|
'''New L{GeodesicLineSolve} instance, allowing points to be found along
|
|
@@ -268,7 +275,22 @@ class GeodesicLineSolve(_GeodesicSolveBase, _SolveLineBase):
|
|
|
268
275
|
except GeodesicError:
|
|
269
276
|
pass
|
|
270
277
|
|
|
271
|
-
|
|
278
|
+
@Property_RO
|
|
279
|
+
def a13(self):
|
|
280
|
+
'''Get the arc length to reference point 3 (C{degrees}).
|
|
281
|
+
|
|
282
|
+
@see: Methods L{Arc} and L{SetArc}.
|
|
283
|
+
'''
|
|
284
|
+
return self._a13
|
|
285
|
+
|
|
286
|
+
def Arc(self):
|
|
287
|
+
'''Return the arc length to reference point 3 (C{degrees} or C{NAN}).
|
|
288
|
+
|
|
289
|
+
@see: Method L{SetArc} and property L{a13}.
|
|
290
|
+
'''
|
|
291
|
+
return self.a13
|
|
292
|
+
|
|
293
|
+
def ArcPosition(self, a12, outmask=Caps.STANDARD): # PYCHOK unused
|
|
272
294
|
'''Find the position on the line given B{C{a12}}.
|
|
273
295
|
|
|
274
296
|
@arg a12: Spherical arc length from the first point to the
|
|
@@ -277,7 +299,7 @@ class GeodesicLineSolve(_GeodesicSolveBase, _SolveLineBase):
|
|
|
277
299
|
@return: A C{GDict} with 12 items C{lat1, lon1, azi1, lat2, lon2,
|
|
278
300
|
azi2, m12, a12, s12, M12, M21, S12}.
|
|
279
301
|
'''
|
|
280
|
-
return self._GDictInvoke(self._cmdArc, True, self._Names_Direct, a12)
|
|
302
|
+
return self._GDictInvoke(self._cmdArc, True, self._Names_Direct, a12)._unCaps(outmask)
|
|
281
303
|
|
|
282
304
|
@Property_RO
|
|
283
305
|
def azi1(self):
|
|
@@ -301,6 +323,17 @@ class GeodesicLineSolve(_GeodesicSolveBase, _SolveLineBase):
|
|
|
301
323
|
'''
|
|
302
324
|
return self._cmdDistance + ('-a',)
|
|
303
325
|
|
|
326
|
+
def Distance(self):
|
|
327
|
+
'''Return the distance to reference point 3 (C{meter} or C{NAN}).
|
|
328
|
+
'''
|
|
329
|
+
return self.s13
|
|
330
|
+
|
|
331
|
+
@property_RO
|
|
332
|
+
def geodesic(self):
|
|
333
|
+
'''Get the geodesic (L{GeodesicSolve}).
|
|
334
|
+
'''
|
|
335
|
+
return self._solve # see .solveBase._SolveLineBase
|
|
336
|
+
|
|
304
337
|
def Intersecant2(self, lat0, lon0, radius, **kwds): # PYCHOK no cover
|
|
305
338
|
'''B{Not implemented}, throws a C{NotImplementedError} always.'''
|
|
306
339
|
self._notImplemented(lat0, lon0, radius, **kwds)
|
|
@@ -309,7 +342,7 @@ class GeodesicLineSolve(_GeodesicSolveBase, _SolveLineBase):
|
|
|
309
342
|
'''B{Not implemented}, throws a C{NotImplementedError} always.'''
|
|
310
343
|
self._notImplemented(lat0, lon0, **kwds)
|
|
311
344
|
|
|
312
|
-
def Position(self, s12, outmask=
|
|
345
|
+
def Position(self, s12, outmask=Caps.STANDARD):
|
|
313
346
|
'''Find the position on the line given B{C{s12}}.
|
|
314
347
|
|
|
315
348
|
@arg s12: Distance from the first point to the second (C{meter}).
|
|
@@ -317,7 +350,44 @@ class GeodesicLineSolve(_GeodesicSolveBase, _SolveLineBase):
|
|
|
317
350
|
@return: A C{GDict} with 12 items C{lat1, lon1, azi1, lat2, lon2,
|
|
318
351
|
azi2, m12, a12, s12, M12, M21, S12}, possibly C{a12=NAN}.
|
|
319
352
|
'''
|
|
320
|
-
return self._GDictInvoke(self._cmdDistance, True, self._Names_Direct, s12)
|
|
353
|
+
return self._GDictInvoke(self._cmdDistance, True, self._Names_Direct, s12)._unCaps(outmask)
|
|
354
|
+
|
|
355
|
+
@Property_RO
|
|
356
|
+
def s13(self):
|
|
357
|
+
'''Get the distance to reference point 3 (C{meter} or C{NAN}).
|
|
358
|
+
|
|
359
|
+
@see: Methods L{Distance} and L{SetDistance}.
|
|
360
|
+
'''
|
|
361
|
+
return self._s13
|
|
362
|
+
|
|
363
|
+
def SetArc(self, a13):
|
|
364
|
+
'''Set reference point 3 in terms relative to the first point.
|
|
365
|
+
|
|
366
|
+
@arg a13: Spherical arc length from the first to the reference
|
|
367
|
+
point (C{degrees}).
|
|
368
|
+
|
|
369
|
+
@return: The distance C{s13} (C{meter}) between the first and
|
|
370
|
+
the reference point or C{NAN}.
|
|
371
|
+
'''
|
|
372
|
+
if self._a13 != a13:
|
|
373
|
+
self._a13 = a13
|
|
374
|
+
self._s13 = self.ArcPosition(a13, outmask=Caps.DISTANCE).s12 # if a13 else _0_0
|
|
375
|
+
# _update_all(self)
|
|
376
|
+
return self._s13
|
|
377
|
+
|
|
378
|
+
def SetDistance(self, s13):
|
|
379
|
+
'''Set reference point 3 in terms relative to the first point.
|
|
380
|
+
|
|
381
|
+
@arg s13: Distance from the first to the reference point (C{meter}).
|
|
382
|
+
|
|
383
|
+
@return: The arc length C{a13} (C{degrees}) between the first
|
|
384
|
+
and the reference point or C{NAN}.
|
|
385
|
+
'''
|
|
386
|
+
if self._s13 != s13:
|
|
387
|
+
self._s13 = s13
|
|
388
|
+
self._a13 = self.Position(s13, outmask=Caps.DISTANCE).a12 if s13 else _0_0
|
|
389
|
+
# _update_all(self)
|
|
390
|
+
return self._a13 # NAN for GeodesicLineExact without Cap.DISTANCE_IN
|
|
321
391
|
|
|
322
392
|
def toStr(self, **prec_sep): # PYCHOK signature
|
|
323
393
|
'''Return this C{GeodesicLineSolve} as string.
|
pygeodesy/geohash.py
CHANGED
|
@@ -20,7 +20,7 @@ from pygeodesy.basics import isodd, isstr, map2
|
|
|
20
20
|
from pygeodesy.constants import EPS, R_M, _floatuple, _0_0, _0_5, _180_0, \
|
|
21
21
|
_360_0, _90_0, _N_90_0, _N_180_0 # PYCHOK used!
|
|
22
22
|
from pygeodesy.dms import parse3llh # parseDMS2
|
|
23
|
-
from pygeodesy.errors import _ValueError, _xkwds
|
|
23
|
+
from pygeodesy.errors import _ValueError, _xkwds, _xStrError
|
|
24
24
|
from pygeodesy.fmath import favg
|
|
25
25
|
# from pygeodesy import formy as _formy # _MODS
|
|
26
26
|
from pygeodesy.interns import NN, _COMMA_, _DOT_, _E_, _N_, _NE_, _NW_, \
|
|
@@ -32,13 +32,12 @@ from pygeodesy.namedTuples import Bounds2Tuple, Bounds4Tuple, LatLon2Tuple, \
|
|
|
32
32
|
from pygeodesy.props import deprecated_function, deprecated_method, \
|
|
33
33
|
deprecated_property_RO, Property_RO
|
|
34
34
|
from pygeodesy.streprs import fstr
|
|
35
|
-
from pygeodesy.units import Degrees_, Int, Lat, Lon, Precision_, Str
|
|
36
|
-
_xStrError
|
|
35
|
+
from pygeodesy.units import Degrees_, Int, Lat, Lon, Precision_, Str
|
|
37
36
|
|
|
38
37
|
from math import fabs, ldexp, log10, radians
|
|
39
38
|
|
|
40
39
|
__all__ = _ALL_LAZY.geohash
|
|
41
|
-
__version__ = '24.06.
|
|
40
|
+
__version__ = '24.06.15'
|
|
42
41
|
|
|
43
42
|
_formy = _MODS.into(formy=__name__)
|
|
44
43
|
|
|
@@ -237,7 +236,7 @@ class Geohash(Str):
|
|
|
237
236
|
@kwarg LatLon: Optional class to return I{bounds} (C{LatLon})
|
|
238
237
|
or C{None}.
|
|
239
238
|
@kwarg LatLon_kwds: Optional, additional B{C{LatLon}} keyword
|
|
240
|
-
arguments, ignored if B{
|
|
239
|
+
arguments, ignored if C{B{LatLon} is None}.
|
|
241
240
|
|
|
242
241
|
@return: A L{Bounds2Tuple}C{(latlonSW, latlonNE)} of B{C{LatLon}}s
|
|
243
242
|
or a L{Bounds4Tuple}C{(latS, lonW, latN, lonE)} if
|
|
@@ -300,16 +299,15 @@ class Geohash(Str):
|
|
|
300
299
|
|
|
301
300
|
@arg other: The other geohash (L{Geohash}, C{LatLon} or C{str}).
|
|
302
301
|
@kwarg radius: Mean earth radius, ellipsoid or datum (C{meter},
|
|
303
|
-
L{Ellipsoid}, L{Ellipsoid2}, L{Datum} or
|
|
304
|
-
|
|
305
|
-
L{pygeodesy.equirectangular}.
|
|
302
|
+
L{Ellipsoid}, L{Ellipsoid2}, L{Datum} or L{a_f2Tuple})
|
|
303
|
+
or C{None}, see function L{pygeodesy.equirectangular}.
|
|
306
304
|
@kwarg adjust_limit_wrap: Optional keyword arguments for function
|
|
307
305
|
L{pygeodesy.equirectangular4}, overriding defaults
|
|
308
306
|
C{B{adjust}=False, B{limit}=None} and C{B{wrap}=False}.
|
|
309
307
|
|
|
310
|
-
@return: Distance (C{meter}, same units as B{C{radius}} or the
|
|
311
|
-
|
|
312
|
-
|
|
308
|
+
@return: Distance (C{meter}, same units as B{C{radius}} or the ellipsoid
|
|
309
|
+
or datum axes or C{radians I{squared}} if B{C{radius} is None}
|
|
310
|
+
or C{0}).
|
|
313
311
|
|
|
314
312
|
@raise TypeError: The B{C{other}} is not a L{Geohash}, C{LatLon} or
|
|
315
313
|
C{str} or invalid B{C{radius}}.
|
|
@@ -398,13 +396,11 @@ class Geohash(Str):
|
|
|
398
396
|
as an instance of the supplied C{LatLon} class.
|
|
399
397
|
|
|
400
398
|
@arg LatLon: Class to use (C{LatLon}) or C{None}.
|
|
401
|
-
@kwarg LatLon_kwds: Optional, additional B{C{LatLon}}
|
|
402
|
-
|
|
403
|
-
C{B{LatLon} is None}.
|
|
399
|
+
@kwarg LatLon_kwds: Optional, additional B{C{LatLon}} keyword
|
|
400
|
+
arguments, ignored if C{B{LatLon} is None}.
|
|
404
401
|
|
|
405
|
-
@return: This geohash location (B{C{LatLon}}) or
|
|
406
|
-
L{LatLon2Tuple}C{(lat, lon)}
|
|
407
|
-
is C{None}.
|
|
402
|
+
@return: This geohash location (B{C{LatLon}}) or if C{B{LatLon}
|
|
403
|
+
is None}, a L{LatLon2Tuple}C{(lat, lon)}.
|
|
408
404
|
|
|
409
405
|
@raise TypeError: Invalid B{C{LatLon}} or B{C{LatLon_kwds}}.
|
|
410
406
|
'''
|
|
@@ -500,19 +496,17 @@ _Neighbors8Defaults = dict(zip(Neighbors8Dict._Keys_, (None,) *
|
|
|
500
496
|
def bounds(geohash, LatLon=None, **LatLon_kwds):
|
|
501
497
|
'''Returns the lower-left SW and upper-right NE corners of a geohash.
|
|
502
498
|
|
|
503
|
-
@arg geohash: To be bound (L{Geohash}).
|
|
504
|
-
@kwarg LatLon: Optional class to return the bounds (C{LatLon})
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
arguments, ignored if C{B{LatLon} is None}.
|
|
499
|
+
@arg geohash: To be "bound" (L{Geohash}).
|
|
500
|
+
@kwarg LatLon: Optional class to return the bounds (C{LatLon}) or C{None}.
|
|
501
|
+
@kwarg LatLon_kwds: Optional, additional B{C{LatLon}} keyword arguments,
|
|
502
|
+
ignored if C{B{LatLon} is None}.
|
|
508
503
|
|
|
509
|
-
@return: A L{Bounds2Tuple}C{(latlonSW, latlonNE)}
|
|
510
|
-
or if B{
|
|
511
|
-
|
|
504
|
+
@return: A L{Bounds2Tuple}C{(latlonSW, latlonNE)}, each a B{C{LatLon}}
|
|
505
|
+
or if C{B{LatLon} is None}, a L{Bounds4Tuple}C{(latS, lonW,
|
|
506
|
+
latN, lonE)}.
|
|
512
507
|
|
|
513
|
-
@raise TypeError: The B{C{geohash}} is not a L{Geohash}, C{LatLon}
|
|
514
|
-
|
|
515
|
-
B{C{LatLon_kwds}}.
|
|
508
|
+
@raise TypeError: The B{C{geohash}} is not a L{Geohash}, C{LatLon} or
|
|
509
|
+
C{str} or invalid B{C{LatLon}} or invalid B{C{LatLon_kwds}}.
|
|
516
510
|
|
|
517
511
|
@raise GeohashError: Invalid or C{null} B{C{geohash}}.
|
|
518
512
|
'''
|
|
@@ -847,14 +841,12 @@ def resolution2(prec1, prec2=None):
|
|
|
847
841
|
def sizes(geohash):
|
|
848
842
|
'''Return the lat- and longitudinal size of this L{Geohash} cell.
|
|
849
843
|
|
|
850
|
-
@arg geohash: Cell for which size are required (L{Geohash} or
|
|
851
|
-
C{str}).
|
|
844
|
+
@arg geohash: Cell for which size are required (L{Geohash} or C{str}).
|
|
852
845
|
|
|
853
|
-
@return: A L{LatLon2Tuple}C{(lat, lon)} with the latitudinal
|
|
854
|
-
|
|
846
|
+
@return: A L{LatLon2Tuple}C{(lat, lon)} with the latitudinal height and
|
|
847
|
+
longitudinal width in (C{meter}).
|
|
855
848
|
|
|
856
|
-
@raise TypeError: The B{C{geohash}} is not a L{Geohash},
|
|
857
|
-
C{LatLon} or C{str}.
|
|
849
|
+
@raise TypeError: The B{C{geohash}} is not a L{Geohash}, C{LatLon} or C{str}.
|
|
858
850
|
'''
|
|
859
851
|
return _2Geohash(geohash).sizes
|
|
860
852
|
|