pygeodesy 24.5.24__py2.py3-none-any.whl → 24.6.9__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.5.24.dist-info → PyGeodesy-24.6.9.dist-info}/METADATA +6 -5
- PyGeodesy-24.6.9.dist-info/RECORD +116 -0
- pygeodesy/__init__.py +4 -4
- pygeodesy/auxilats/__init__.py +1 -1
- pygeodesy/auxilats/__main__.py +2 -2
- pygeodesy/auxilats/auxAngle.py +4 -4
- pygeodesy/basics.py +39 -5
- pygeodesy/booleans.py +54 -67
- pygeodesy/cartesianBase.py +138 -147
- pygeodesy/constants.py +3 -3
- pygeodesy/deprecated/functions.py +9 -3
- pygeodesy/ecef.py +67 -72
- pygeodesy/ellipsoidalBase.py +18 -56
- pygeodesy/ellipsoidalGeodSolve.py +2 -2
- pygeodesy/ellipsoidalKarney.py +3 -3
- pygeodesy/ellipsoidalNvector.py +7 -7
- pygeodesy/ellipsoids.py +6 -5
- pygeodesy/errors.py +20 -10
- pygeodesy/etm.py +16 -21
- pygeodesy/fmath.py +9 -20
- pygeodesy/formy.py +60 -74
- pygeodesy/frechet.py +13 -14
- pygeodesy/fsums.py +60 -26
- pygeodesy/geodesicx/__init__.py +1 -1
- pygeodesy/geodesicx/__main__.py +2 -2
- pygeodesy/geodesicx/gx.py +3 -5
- pygeodesy/geodsolve.py +24 -26
- pygeodesy/geohash.py +27 -40
- pygeodesy/geoids.py +1 -1
- pygeodesy/hausdorff.py +17 -18
- pygeodesy/heights.py +17 -30
- pygeodesy/internals.py +15 -14
- pygeodesy/interns.py +3 -9
- pygeodesy/iters.py +2 -2
- pygeodesy/karney.py +8 -7
- pygeodesy/latlonBase.py +189 -176
- pygeodesy/lazily.py +92 -56
- pygeodesy/lcc.py +2 -2
- pygeodesy/ltp.py +93 -55
- pygeodesy/ltpTuples.py +304 -240
- pygeodesy/mgrs.py +51 -24
- pygeodesy/named.py +159 -136
- pygeodesy/namedTuples.py +43 -14
- pygeodesy/nvectorBase.py +20 -23
- pygeodesy/osgr.py +40 -48
- pygeodesy/points.py +11 -11
- pygeodesy/props.py +29 -16
- pygeodesy/rhumb/aux_.py +13 -15
- pygeodesy/rhumb/bases.py +12 -5
- pygeodesy/rhumb/ekx.py +24 -18
- pygeodesy/rhumb/solve.py +20 -70
- pygeodesy/simplify.py +16 -16
- pygeodesy/solveBase.py +35 -32
- pygeodesy/sphericalBase.py +33 -31
- pygeodesy/sphericalTrigonometry.py +17 -17
- pygeodesy/streprs.py +6 -4
- pygeodesy/trf.py +11 -9
- pygeodesy/triaxials.py +71 -50
- pygeodesy/units.py +40 -65
- pygeodesy/unitsBase.py +2 -2
- pygeodesy/ups.py +66 -70
- pygeodesy/utily.py +7 -6
- pygeodesy/utm.py +152 -156
- pygeodesy/utmups.py +38 -38
- pygeodesy/utmupsBase.py +102 -106
- pygeodesy/vector3d.py +34 -36
- pygeodesy/vector3dBase.py +12 -9
- pygeodesy/webmercator.py +43 -51
- PyGeodesy-24.5.24.dist-info/RECORD +0 -116
- {PyGeodesy-24.5.24.dist-info → PyGeodesy-24.6.9.dist-info}/WHEEL +0 -0
- {PyGeodesy-24.5.24.dist-info → PyGeodesy-24.6.9.dist-info}/top_level.txt +0 -0
pygeodesy/namedTuples.py
CHANGED
|
@@ -8,26 +8,27 @@ are all instances of some C{Named...Tuple} class, all sub-classes
|
|
|
8
8
|
of C{_NamedTuple} defined in C{pygeodesy.named}.
|
|
9
9
|
'''
|
|
10
10
|
|
|
11
|
-
from pygeodesy.basics import map1, _xinstanceof
|
|
11
|
+
from pygeodesy.basics import isinstanceof, map1, _xinstanceof
|
|
12
12
|
# from pygeodesy.constants import INT0 # from .units
|
|
13
|
-
from pygeodesy.
|
|
14
|
-
from pygeodesy.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
13
|
+
# from pygeodesy.dms import toDMS # _MODS
|
|
14
|
+
from pygeodesy.errors import _xattr, _xkwds, _xkwds_not, _ALL_LAZY, _MODS
|
|
15
|
+
from pygeodesy.interns import NN, _1_, _2_, _a_, _A_, _area_, _angle_, _b_, _B_, \
|
|
16
|
+
_band_, _c_, _C_, _D_, _datum_, _distance_, _E_, \
|
|
17
|
+
_easting_, _end_, _fi_, _gamma_, _h_, _height_, \
|
|
18
|
+
_hemipole_, _initial_, _j_, _lam_, _lat_, _lon_, \
|
|
19
|
+
_n_, _northing_, _number_, _outside_, _phi_, \
|
|
20
|
+
_point_, _precision_, _points_, _radius_, _scale_, \
|
|
21
|
+
_start_, _x_, _y_, _z_, _zone_
|
|
21
22
|
# from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS # from .errors
|
|
22
23
|
from pygeodesy.named import _NamedTuple, _Pass
|
|
23
24
|
from pygeodesy.props import deprecated_property_RO, property_RO
|
|
24
|
-
from pygeodesy.units import Band, Bearing, Degrees, Degrees2, Easting, \
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
from pygeodesy.units import Band, Bearing, Degrees, Degrees2, Easting, FIx, \
|
|
26
|
+
Height, Int, Lam, Lat, Lon, Meter, Meter2, \
|
|
27
|
+
Northing, Number_, Phi, Precision_, Radians, \
|
|
28
|
+
Radius, Scalar, Str, INT0
|
|
28
29
|
|
|
29
30
|
__all__ = _ALL_LAZY.namedTuples
|
|
30
|
-
__version__ = '24.
|
|
31
|
+
__version__ = '24.06.08'
|
|
31
32
|
|
|
32
33
|
# __DUNDER gets mangled in class
|
|
33
34
|
_closest_ = 'closest'
|
|
@@ -324,6 +325,34 @@ class LatLonPrec5Tuple(LatLonPrec3Tuple): # .wgrs.py
|
|
|
324
325
|
_Units_ = LatLonPrec3Tuple._Units_ + ( Height, Radius)
|
|
325
326
|
|
|
326
327
|
|
|
328
|
+
class _NamedTupleTo(_NamedTuple): # in .testNamedTuples
|
|
329
|
+
'''(INTERNAL) Base for C{-.toDegrees}, C{-.toRadians}.
|
|
330
|
+
'''
|
|
331
|
+
def _Degrees3(self, *xs, **toDMS_kwds):
|
|
332
|
+
'''(INTERNAL) Convert C{xs} from C{Radians} to C{Degrees} or C{toDMS}.
|
|
333
|
+
'''
|
|
334
|
+
if toDMS_kwds:
|
|
335
|
+
toDMS_kwds = _xkwds(toDMS_kwds, ddd=1, pos=NN)
|
|
336
|
+
toDMS, s = _MODS.dms.toDMS, None
|
|
337
|
+
else:
|
|
338
|
+
toDMS, s = None, self
|
|
339
|
+
for x in xs:
|
|
340
|
+
if not isinstanceof(x, Degrees):
|
|
341
|
+
x, s = x.toDegrees(), None
|
|
342
|
+
yield toDMS(x, **toDMS_kwds) if toDMS else x
|
|
343
|
+
yield s
|
|
344
|
+
|
|
345
|
+
def _Radians3(self, *xs, **unused):
|
|
346
|
+
'''(INTERNAL) Convert C{xs} from C{Degrees} to C{Radians}.
|
|
347
|
+
'''
|
|
348
|
+
s = self
|
|
349
|
+
for x in xs:
|
|
350
|
+
if not isinstanceof(x, Radians):
|
|
351
|
+
x, s = x.toRadians(), None
|
|
352
|
+
yield x
|
|
353
|
+
yield s
|
|
354
|
+
|
|
355
|
+
|
|
327
356
|
class NearestOn2Tuple(_NamedTuple): # .ellipsoidalBaseDI
|
|
328
357
|
'''2-Tuple C{(closest, fraction)} of the C{closest} point
|
|
329
358
|
on and C{fraction} along a line (segment) between two
|
pygeodesy/nvectorBase.py
CHANGED
|
@@ -22,8 +22,7 @@ from pygeodesy.formy import _isequalTo, n_xyz2latlon, n_xyz2philam, \
|
|
|
22
22
|
# from pygeodesy.internals import _under # from .named
|
|
23
23
|
from pygeodesy.interns import NN, _1_, _2_, _3_, _bearing_, _coincident_, \
|
|
24
24
|
_COMMASPACE_, _distance_, _h_, _insufficient_, \
|
|
25
|
-
_intersection_, _no_,
|
|
26
|
-
_pole_, _SPACE_, _SouthPole_
|
|
25
|
+
_intersection_, _no_, _point_, _pole_, _SPACE_
|
|
27
26
|
from pygeodesy.latlonBase import LatLonBase, _ALL_DOCS, _ALL_LAZY, _MODS
|
|
28
27
|
# from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS # from .latlonBase
|
|
29
28
|
from pygeodesy.named import _xother3, _under
|
|
@@ -34,12 +33,12 @@ from pygeodesy.props import deprecated_method, Property_RO, property_doc_, \
|
|
|
34
33
|
from pygeodesy.streprs import Fmt, hstr, unstr, _xattrs
|
|
35
34
|
from pygeodesy.units import Bearing, Height, Radius_, Scalar
|
|
36
35
|
from pygeodesy.utily import sincos2d, _unrollon, _unrollon3
|
|
37
|
-
from pygeodesy.vector3d import Vector3d,
|
|
36
|
+
from pygeodesy.vector3d import Vector3d, _xyzhdlln4
|
|
38
37
|
|
|
39
38
|
from math import fabs, sqrt
|
|
40
39
|
|
|
41
40
|
__all__ = _ALL_LAZY.nvectorBase
|
|
42
|
-
__version__ = '24.
|
|
41
|
+
__version__ = '24.06.06'
|
|
43
42
|
|
|
44
43
|
|
|
45
44
|
class NvectorBase(Vector3d): # XXX kept private
|
|
@@ -49,32 +48,30 @@ class NvectorBase(Vector3d): # XXX kept private
|
|
|
49
48
|
_h = Height(h=0) # height (C{meter})
|
|
50
49
|
_H = NN # height prefix (C{str}), '↑' in JS version
|
|
51
50
|
|
|
52
|
-
def __init__(self, x_xyz, y=None, z=None, h=0,
|
|
51
|
+
def __init__(self, x_xyz, y=None, z=None, h=0, datum=None, **ll_name):
|
|
53
52
|
'''New n-vector normal to the earth's surface.
|
|
54
53
|
|
|
55
54
|
@arg x_xyz: X component of vector (C{scalar}) or (3-D) vector
|
|
56
|
-
(C{Nvector}, L{Vector3d}, L{Vector3Tuple} or
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
is not C{scalar}, otherwise same units as B{C{x_xyz}}.
|
|
55
|
+
(C{Nvector}, L{Vector3d}, L{Vector3Tuple} or L{Vector4Tuple}).
|
|
56
|
+
@kwarg y: Y component of vector (C{scalar}), ignored if B{C{x_xyz}} is not
|
|
57
|
+
C{scalar}, otherwise same units as B{C{x_xyz}}.
|
|
58
|
+
@kwarg z: Z component of vector (C{scalar}), ignored if B{C{x_xyz}} is not
|
|
59
|
+
C{scalar}, otherwise same units as B{C{x_xyz}}.
|
|
62
60
|
@kwarg h: Optional height above surface (C{meter}).
|
|
63
|
-
@kwarg ll: Optional, original latlon (C{LatLon}).
|
|
64
61
|
@kwarg datum: Optional, I{pass-thru} datum (L{Datum}).
|
|
65
|
-
@kwarg
|
|
62
|
+
@kwarg ll_name: Optional C{B{name}=NN} (C{str}) and optional, original
|
|
63
|
+
latlon C{B{ll}=None} (C{LatLon}).
|
|
66
64
|
|
|
67
|
-
@raise TypeError: Non-scalar B{C{x}}, B{C{y}} or B{C{z}}
|
|
68
|
-
|
|
69
|
-
L{
|
|
70
|
-
invalid B{C{datum}}.
|
|
65
|
+
@raise TypeError: Non-scalar B{C{x}}, B{C{y}} or B{C{z}} coordinate or
|
|
66
|
+
B{C{x_xyz}} not an C{Nvector}, L{Vector3Tuple} or
|
|
67
|
+
L{Vector4Tuple} or invalid B{C{datum}}.
|
|
71
68
|
'''
|
|
72
|
-
h, d, n =
|
|
69
|
+
h, d, ll, n = _xyzhdlln4(x_xyz, h, datum, **ll_name)
|
|
73
70
|
Vector3d.__init__(self, x_xyz, y=y, z=z, ll=ll, name=n)
|
|
74
71
|
if h:
|
|
75
72
|
self.h = h
|
|
76
73
|
if d is not None:
|
|
77
|
-
self._datum = _spherical_datum(d, name=
|
|
74
|
+
self._datum = _spherical_datum(d, name=n) # pass-thru
|
|
78
75
|
|
|
79
76
|
@Property_RO
|
|
80
77
|
def datum(self):
|
|
@@ -326,7 +323,7 @@ class NvectorBase(Vector3d): # XXX kept private
|
|
|
326
323
|
r = self.toCartesian(h=h, Cartesian=None, datum=d)
|
|
327
324
|
else:
|
|
328
325
|
kwds = _xkwds(LatLon_kwds, height=h, datum=d)
|
|
329
|
-
r =
|
|
326
|
+
r = LatLon(self.lat, self.lon, **self._name1__(kwds))
|
|
330
327
|
return r
|
|
331
328
|
|
|
332
329
|
def toStr(self, prec=5, fmt=Fmt.PAREN, sep=_COMMASPACE_): # PYCHOK expected
|
|
@@ -378,14 +375,14 @@ class NvectorBase(Vector3d): # XXX kept private
|
|
|
378
375
|
return self.xyz.to4Tuple(self.h)
|
|
379
376
|
|
|
380
377
|
|
|
381
|
-
NorthPole = NvectorBase(0, 0, +1, name=
|
|
382
|
-
SouthPole = NvectorBase(0, 0, -1, name=
|
|
378
|
+
NorthPole = NvectorBase(0, 0, +1, name='NorthPole') # North pole (C{Nvector})
|
|
379
|
+
SouthPole = NvectorBase(0, 0, -1, name='SouthPole') # South pole (C{Nvector})
|
|
383
380
|
|
|
384
381
|
|
|
385
382
|
class _N_vector_(NvectorBase):
|
|
386
383
|
'''(INTERNAL) Minimal, low-overhead C{n-vector}.
|
|
387
384
|
'''
|
|
388
|
-
def __init__(self, x, y, z, h=0, name
|
|
385
|
+
def __init__(self, x, y, z, h=0, **name):
|
|
389
386
|
self._x, self._y, self._z = x, y, z
|
|
390
387
|
if h:
|
|
391
388
|
self._h = h
|
pygeodesy/osgr.py
CHANGED
|
@@ -33,14 +33,14 @@ from pygeodesy.datums import Datums, _ellipsoidal_datum, _WGS84
|
|
|
33
33
|
# from pygeodesy.dms import parseDMS2 # _MODS
|
|
34
34
|
from pygeodesy.ellipsoidalBase import LatLonEllipsoidalBase as _LLEB
|
|
35
35
|
from pygeodesy.errors import _parseX, _TypeError, _ValueError, \
|
|
36
|
-
_xkwds, _xkwds_get
|
|
36
|
+
_xkwds, _xkwds_get, _xkwds_pop2
|
|
37
37
|
from pygeodesy.fmath import Fdot, fpowers
|
|
38
38
|
from pygeodesy.fsums import _Fsumf_
|
|
39
39
|
from pygeodesy.interns import MISSING, NN, _A_, _COLON_, _COMMA_, \
|
|
40
40
|
_COMMASPACE_, _DOT_, _ellipsoidal_, \
|
|
41
41
|
_latlon_, _not_, _SPACE_
|
|
42
42
|
from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS
|
|
43
|
-
from pygeodesy.named import _NamedBase, nameof
|
|
43
|
+
from pygeodesy.named import _name2__, _NamedBase, nameof
|
|
44
44
|
from pygeodesy.namedTuples import EasNor2Tuple, LatLon2Tuple, \
|
|
45
45
|
LatLonDatum3Tuple
|
|
46
46
|
from pygeodesy.props import Property_RO, property_RO
|
|
@@ -53,7 +53,7 @@ from pygeodesy.utily import degrees90, degrees180, sincostan3, truncate
|
|
|
53
53
|
from math import cos, fabs, radians, sin, sqrt
|
|
54
54
|
|
|
55
55
|
__all__ = _ALL_LAZY.osgr
|
|
56
|
-
__version__ = '24.05.
|
|
56
|
+
__version__ = '24.05.31'
|
|
57
57
|
|
|
58
58
|
_equivalent_ = 'equivalent'
|
|
59
59
|
_OSGR_ = 'OSGR'
|
|
@@ -194,22 +194,17 @@ class Osgr(_NamedBase):
|
|
|
194
194
|
_northing = 0 # Nothing (C{meter})
|
|
195
195
|
_resolution = 0 # from L{parseOSGR} (C{meter})
|
|
196
196
|
|
|
197
|
-
def __init__(self, easting, northing, datum=None,
|
|
198
|
-
resolution=0):
|
|
197
|
+
def __init__(self, easting, northing, datum=None, resolution=0, **name):
|
|
199
198
|
'''New L{Osgr} coordinate.
|
|
200
199
|
|
|
201
|
-
@arg easting: Easting from the OS C{National Grid}
|
|
202
|
-
|
|
203
|
-
@arg northing: Northing from the OS C{National Grid}
|
|
204
|
-
origin (C{meter}).
|
|
200
|
+
@arg easting: Easting from the OS C{National Grid} origin (C{meter}).
|
|
201
|
+
@arg northing: Northing from the OS C{National Grid} origin (C{meter}).
|
|
205
202
|
@kwarg datum: Override default datum (C{Datums.OSGB36}).
|
|
206
|
-
@kwarg
|
|
207
|
-
@kwarg
|
|
208
|
-
C{0} for default.
|
|
203
|
+
@kwarg resolution: Optional resolution (C{meter}), C{0} for default.
|
|
204
|
+
@kwarg name: Optional C{B{name}=NN} (C{str}).
|
|
209
205
|
|
|
210
|
-
@raise OSGRError: Invalid or negative B{C{easting}} or
|
|
211
|
-
|
|
212
|
-
C{Datums.OSGB36} equivalent.
|
|
206
|
+
@raise OSGRError: Invalid or negative B{C{easting}} or B{C{northing}}
|
|
207
|
+
or B{C{datum}} not an C{Datums.OSGB36} equivalent.
|
|
213
208
|
'''
|
|
214
209
|
if datum: # PYCHOK no cover
|
|
215
210
|
try:
|
|
@@ -267,17 +262,17 @@ class Osgr(_NamedBase):
|
|
|
267
262
|
'''
|
|
268
263
|
return self._northing
|
|
269
264
|
|
|
270
|
-
def parse(self, strOSGR, name
|
|
265
|
+
def parse(self, strOSGR, **name):
|
|
271
266
|
'''Parse an OSGR reference to a similar L{Osgr} instance.
|
|
272
267
|
|
|
273
268
|
@arg strOSGR: The OSGR reference (C{str}), see function L{parseOSGR}.
|
|
274
|
-
@kwarg name: Optional
|
|
269
|
+
@kwarg name: Optional C{B{name}=NN} (C{str}), overriding this name.
|
|
275
270
|
|
|
276
271
|
@return: The similar instance (L{Osgr})
|
|
277
272
|
|
|
278
273
|
@raise OSGRError: Invalid B{C{strOSGR}}.
|
|
279
274
|
'''
|
|
280
|
-
return parseOSGR(strOSGR, Osgr=self.classof, name=
|
|
275
|
+
return parseOSGR(strOSGR, Osgr=self.classof, name=self._name__(name))
|
|
281
276
|
|
|
282
277
|
@property_RO
|
|
283
278
|
def resolution(self):
|
|
@@ -496,19 +491,20 @@ def _ll2datum(ll, datum, name):
|
|
|
496
491
|
def _ll2LatLon3(ll, LatLon, datum, LatLon_kwds):
|
|
497
492
|
'''(INTERNAL) Convert C{ll} to C{LatLon}
|
|
498
493
|
'''
|
|
494
|
+
n = nameof(ll)
|
|
499
495
|
if LatLon is None:
|
|
500
496
|
r = _ll2datum(ll, datum, LatLonDatum3Tuple.__name__)
|
|
501
|
-
r = LatLonDatum3Tuple(r.lat, r.lon, r.datum)
|
|
497
|
+
r = LatLonDatum3Tuple(r.lat, r.lon, r.datum, name=n)
|
|
502
498
|
else: # must be ellipsoidal
|
|
503
499
|
_xsubclassof(_LLEB, LatLon=LatLon)
|
|
504
500
|
r = _ll2datum(ll, datum, LatLon.__name__)
|
|
505
|
-
r = LatLon(r.lat, r.lon, datum=r.datum, **LatLon_kwds)
|
|
501
|
+
r = LatLon(r.lat, r.lon, datum=r.datum, **_xkwds(LatLon_kwds, name=n))
|
|
506
502
|
if r._iteration != ll._iteration:
|
|
507
503
|
r._iteration = ll._iteration
|
|
508
|
-
return
|
|
504
|
+
return r
|
|
509
505
|
|
|
510
506
|
|
|
511
|
-
def parseOSGR(strOSGR, Osgr=Osgr,
|
|
507
|
+
def parseOSGR(strOSGR, Osgr=Osgr, **name_Osgr_kwds):
|
|
512
508
|
'''Parse a string representing an OS Grid Reference, consisting
|
|
513
509
|
of C{"[GD] easting northing"}.
|
|
514
510
|
|
|
@@ -520,9 +516,9 @@ def parseOSGR(strOSGR, Osgr=Osgr, name=NN, **Osgr_kwds):
|
|
|
520
516
|
@arg strOSGR: An OSGR coordinate (C{str}).
|
|
521
517
|
@kwarg Osgr: Optional class to return the OSGR coordinate
|
|
522
518
|
(L{Osgr}) or C{None}.
|
|
523
|
-
@kwarg
|
|
524
|
-
|
|
525
|
-
|
|
519
|
+
@kwarg name_Osgr_kwds: Optional C{B{name}=NN} (C{str}) and
|
|
520
|
+
optional, additional B{C{Osgr}} keyword arguments,
|
|
521
|
+
ignored if C{B{Osgr} is None}.
|
|
526
522
|
|
|
527
523
|
@return: An (B{C{Osgr}}) instance or if B{C{Osgr}} is
|
|
528
524
|
C{None} an L{EasNor2Tuple}C{(easting, northing)}.
|
|
@@ -537,7 +533,7 @@ def parseOSGR(strOSGR, Osgr=Osgr, name=NN, **Osgr_kwds):
|
|
|
537
533
|
raise ValueError
|
|
538
534
|
return g
|
|
539
535
|
|
|
540
|
-
def _OSGR(strOSGR, Osgr,
|
|
536
|
+
def _OSGR(strOSGR, Osgr, kwds):
|
|
541
537
|
s = _splituple(strOSGR.strip())
|
|
542
538
|
p = len(s)
|
|
543
539
|
if not p:
|
|
@@ -570,20 +566,20 @@ def parseOSGR(strOSGR, Osgr=Osgr, name=NN, **Osgr_kwds):
|
|
|
570
566
|
e += E * _100km
|
|
571
567
|
n += N * _100km
|
|
572
568
|
|
|
569
|
+
name, kwds = _name2__(**kwds)
|
|
573
570
|
if Osgr is None:
|
|
574
571
|
_ = _MODS.osgr.Osgr(e, n, resolution=m) # validate
|
|
575
572
|
r = EasNor2Tuple(e, n, name=name)
|
|
576
573
|
else:
|
|
577
|
-
r = Osgr(e, n, name=name,
|
|
578
|
-
**_xkwds(Osgr_kwds, resolution=m))
|
|
574
|
+
r = Osgr(e, n, name=name, **_xkwds(kwds, resolution=m))
|
|
579
575
|
return r
|
|
580
576
|
|
|
581
|
-
return _parseX(_OSGR, strOSGR, Osgr,
|
|
577
|
+
return _parseX(_OSGR, strOSGR, Osgr, name_Osgr_kwds,
|
|
582
578
|
strOSGR=strOSGR, Error=OSGRError)
|
|
583
579
|
|
|
584
580
|
|
|
585
|
-
def toOsgr(latlon, lon=None, kTM=False, datum=_WGS84, Osgr=Osgr,
|
|
586
|
-
|
|
581
|
+
def toOsgr(latlon, lon=None, kTM=False, datum=_WGS84, Osgr=Osgr, # MCCABE 14
|
|
582
|
+
**prec_name_Osgr_kwds):
|
|
587
583
|
'''Convert a lat-/longitude point to an OSGR coordinate.
|
|
588
584
|
|
|
589
585
|
@arg latlon: Latitude (C{degrees}) or an (ellipsoidal) geodetic
|
|
@@ -597,11 +593,10 @@ def toOsgr(latlon, lon=None, kTM=False, datum=_WGS84, Osgr=Osgr, name=NN, # MCC
|
|
|
597
593
|
L{a_f2Tuple}).
|
|
598
594
|
@kwarg Osgr: Optional class to return the OSGR coordinate
|
|
599
595
|
(L{Osgr}) or C{None}.
|
|
600
|
-
@kwarg
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
if C{B{Osgr} is None}.
|
|
596
|
+
@kwarg prec_name_Osgr_kwds: Optional C{B{name}=NN} (C{str}),
|
|
597
|
+
optional L{truncate} precision C{B{prec}=ndigits}
|
|
598
|
+
and additional B{C{Osgr}} keyword arguments,
|
|
599
|
+
ignored if C{B{Osgr} is None}.
|
|
605
600
|
|
|
606
601
|
@return: An (B{C{Osgr}}) instance or if B{C{Osgr}} is C{None}
|
|
607
602
|
an L{EasNor2Tuple}C{(easting, northing)}.
|
|
@@ -615,9 +610,6 @@ def toOsgr(latlon, lon=None, kTM=False, datum=_WGS84, Osgr=Osgr, name=NN, # MCC
|
|
|
615
610
|
B{C{datum}}, B{C{Osgr}}, B{C{Osgr_kwds}}
|
|
616
611
|
or conversion to C{Datums.OSGB36} failed.
|
|
617
612
|
'''
|
|
618
|
-
def _prec_kwds2(prec=MISSING, **kwds):
|
|
619
|
-
return prec, kwds
|
|
620
|
-
|
|
621
613
|
if lon is not None:
|
|
622
614
|
try:
|
|
623
615
|
lat, lon = _MODS.dms.parseDMS2(latlon, lon)
|
|
@@ -626,8 +618,6 @@ def toOsgr(latlon, lon=None, kTM=False, datum=_WGS84, Osgr=Osgr, name=NN, # MCC
|
|
|
626
618
|
raise OSGRError(latlon=latlon, lon=lon, datum=datum, cause=x)
|
|
627
619
|
elif not isinstance(latlon, _LLEB):
|
|
628
620
|
raise _TypeError(latlon=latlon, txt=_not_(_ellipsoidal_))
|
|
629
|
-
elif not name: # use latlon.name
|
|
630
|
-
name = nameof(latlon)
|
|
631
621
|
|
|
632
622
|
NG = _NG
|
|
633
623
|
# convert latlon to OSGB36 first
|
|
@@ -663,22 +653,24 @@ def toOsgr(latlon, lon=None, kTM=False, datum=_WGS84, Osgr=Osgr, name=NN, # MCC
|
|
|
663
653
|
d2 / 12 * (_Fsumf_( 5, ta2, 9 * n2) +
|
|
664
654
|
d2 / 30 * _Fsumf_(61, ta4, 58 * ta2)))).fsum_(m0, NG.nor0)
|
|
665
655
|
|
|
666
|
-
|
|
667
|
-
if
|
|
668
|
-
|
|
669
|
-
|
|
656
|
+
t, kwds = _name2__(prec_name_Osgr_kwds, _or_nameof=latlon)
|
|
657
|
+
if kwds:
|
|
658
|
+
p, kwds = _xkwds_pop2(kwds, prec=MISSING)
|
|
659
|
+
if p is not MISSING:
|
|
660
|
+
e = truncate(e, p)
|
|
661
|
+
n = truncate(n, p)
|
|
670
662
|
|
|
671
663
|
if Osgr is None:
|
|
672
664
|
_ = _MODS.osgr.Osgr(e, n) # validate
|
|
673
|
-
r = EasNor2Tuple(e, n)
|
|
665
|
+
r = EasNor2Tuple(e, n, name=t)
|
|
674
666
|
else:
|
|
675
|
-
r =
|
|
667
|
+
r = Osgr(e, n, name=t, **kwds) # datum=NG.datum
|
|
676
668
|
if lon is None and isinstance(latlon, _LLEB):
|
|
677
669
|
if kTM:
|
|
678
670
|
r._latlonTM = latlon # XXX weakref(latlon)?
|
|
679
671
|
else:
|
|
680
672
|
r._latlon = latlon # XXX weakref(latlon)?
|
|
681
|
-
return
|
|
673
|
+
return r
|
|
682
674
|
|
|
683
675
|
|
|
684
676
|
if __name__ == '__main__':
|
pygeodesy/points.py
CHANGED
|
@@ -38,7 +38,7 @@ from pygeodesy.errors import CrossError, crosserrors, _IndexError, \
|
|
|
38
38
|
_xattr, _xkwds, _xkwds_item2, _xkwds_pop2
|
|
39
39
|
from pygeodesy.fmath import favg, fdot, hypot, Fsum, fsum
|
|
40
40
|
# from pygeodesy.fsums import Fsum, fsum # from .fmath
|
|
41
|
-
from pygeodesy.formy import _bearingTo2,
|
|
41
|
+
from pygeodesy.formy import _bearingTo2, equirectangular4, _spherical_datum
|
|
42
42
|
from pygeodesy.interns import NN, _colinear_, _COMMASPACE_, _composite_, \
|
|
43
43
|
_DEQUALSPACED_, _ELLIPSIS_, _EW_, _immutable_, \
|
|
44
44
|
_near_, _no_, _NS_, _point_, _SPACE_, _UNDER_, \
|
|
@@ -62,7 +62,7 @@ from pygeodesy.utily import atan2b, degrees90, degrees180, degrees2m, \
|
|
|
62
62
|
from math import cos, fabs, fmod as _fmod, radians, sin
|
|
63
63
|
|
|
64
64
|
__all__ = _ALL_LAZY.points
|
|
65
|
-
__version__ = '24.
|
|
65
|
+
__version__ = '24.06.06'
|
|
66
66
|
|
|
67
67
|
_ilat_ = 'ilat'
|
|
68
68
|
_ilon_ = 'ilon'
|
|
@@ -1473,13 +1473,13 @@ def nearestOn5(point, points, closed=False, wrap=False, adjust=True,
|
|
|
1473
1473
|
@kwarg closed: Optionally, close the path or polygon (C{bool}).
|
|
1474
1474
|
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll the
|
|
1475
1475
|
B{C{points}} (C{bool}).
|
|
1476
|
-
@kwarg adjust: See function L{pygeodesy.
|
|
1477
|
-
@kwarg limit: See function L{pygeodesy.
|
|
1476
|
+
@kwarg adjust: See function L{pygeodesy.equirectangular4} (C{bool}).
|
|
1477
|
+
@kwarg limit: See function L{pygeodesy.equirectangular4} (C{degrees}),
|
|
1478
1478
|
default C{9 degrees} is about C{1,000 Kmeter} (for mean
|
|
1479
1479
|
spherical earth radius L{R_KM}).
|
|
1480
1480
|
@kwarg LatLon_and_kwds: Optional, C{B{LatLon}=None} class to use for
|
|
1481
1481
|
the closest point and additional B{C{LatLon}} keyword
|
|
1482
|
-
arguments, ignored if C{B{LatLon}
|
|
1482
|
+
arguments, ignored if C{B{LatLon} is None} or not given.
|
|
1483
1483
|
|
|
1484
1484
|
@return: A L{NearestOn3Tuple}C{(closest, distance, angle)} with the
|
|
1485
1485
|
{closest} point (B{C{LatLon}}) or if C{B{LatLon} is None},
|
|
@@ -1490,24 +1490,24 @@ def nearestOn5(point, points, closed=False, wrap=False, adjust=True,
|
|
|
1490
1490
|
compass C{degrees}, like function L{pygeodesy.compassAngle}.
|
|
1491
1491
|
|
|
1492
1492
|
@raise LimitError: Lat- and/or longitudinal delta exceeds the B{C{limit}},
|
|
1493
|
-
see function L{pygeodesy.
|
|
1493
|
+
see function L{pygeodesy.equirectangular4}.
|
|
1494
1494
|
|
|
1495
1495
|
@raise PointsError: Insufficient number of B{C{points}}
|
|
1496
1496
|
|
|
1497
1497
|
@raise TypeError: Some B{C{points}} are not C{LatLon}.
|
|
1498
1498
|
|
|
1499
|
-
@note: Distances are I{approximated} by function L{pygeodesy.
|
|
1499
|
+
@note: Distances are I{approximated} by function L{pygeodesy.equirectangular4}.
|
|
1500
1500
|
For more accuracy use one of the C{LatLon.nearestOn6} methods.
|
|
1501
1501
|
|
|
1502
1502
|
@see: Function L{pygeodesy.degrees2m}.
|
|
1503
1503
|
'''
|
|
1504
1504
|
def _d2yx4(p2, p1, u, alw):
|
|
1505
1505
|
# w = wrap if (i < (n - 1) or not closed) else False
|
|
1506
|
-
#
|
|
1506
|
+
# equirectangular4 returns a Distance4Tuple(distance
|
|
1507
1507
|
# in degrees squared, delta lat, delta lon, p2.lon
|
|
1508
1508
|
# unroll/wrap'd); the previous p2.lon unroll/wrap'd
|
|
1509
1509
|
# is also applied to the next edge's p1.lon
|
|
1510
|
-
return
|
|
1510
|
+
return equirectangular4(p1.lat, p1.lon + u,
|
|
1511
1511
|
p2.lat, p2.lon, **alw)
|
|
1512
1512
|
|
|
1513
1513
|
def _h(p): # get height or default 0
|
|
@@ -1604,7 +1604,7 @@ def perimeterOf(points, closed=False, adjust=True, radius=R_M, wrap=True):
|
|
|
1604
1604
|
@raise ValueError: Invalid B{C{radius}} or C{B{closed}=False} with
|
|
1605
1605
|
C{B{points}} a composite.
|
|
1606
1606
|
|
|
1607
|
-
@note: This perimeter is based on the L{pygeodesy.
|
|
1607
|
+
@note: This perimeter is based on the L{pygeodesy.equirectangular4}
|
|
1608
1608
|
distance approximation and is ill-suited for regions exceeding
|
|
1609
1609
|
several hundred Km or Miles or with near-polar latitudes.
|
|
1610
1610
|
|
|
@@ -1618,7 +1618,7 @@ def perimeterOf(points, closed=False, adjust=True, radius=R_M, wrap=True):
|
|
|
1618
1618
|
if w and c:
|
|
1619
1619
|
w = not Ps.looped
|
|
1620
1620
|
# apply previous x2's unroll/wrap'd to new x1
|
|
1621
|
-
_, dy, dx, u =
|
|
1621
|
+
_, dy, dx, u = equirectangular4(p1.y, p1.x + u,
|
|
1622
1622
|
p2.y, p2.x,
|
|
1623
1623
|
adjust=a, limit=None,
|
|
1624
1624
|
wrap=w) # PYCHOK non-seq
|
pygeodesy/props.py
CHANGED
|
@@ -10,9 +10,9 @@ with command line option C{-X dev} or with one of the C{-W}
|
|
|
10
10
|
choices, see callable L{DeprecationWarnings} below.
|
|
11
11
|
'''
|
|
12
12
|
|
|
13
|
-
from pygeodesy.basics import isclass as _isclass
|
|
13
|
+
from pygeodesy.basics import isclass as _isclass
|
|
14
14
|
from pygeodesy.errors import _AssertionError, _AttributeError, \
|
|
15
|
-
_xkwds, _xkwds_get
|
|
15
|
+
_xcallable, _xkwds, _xkwds_get
|
|
16
16
|
from pygeodesy.interns import MISSING, NN, _an_, _COMMASPACE_, \
|
|
17
17
|
_DEPRECATED_, _DOT_, _EQUALSPACED_, \
|
|
18
18
|
_immutable_, _invalid_, _module_, _N_A_, \
|
|
@@ -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.05.
|
|
28
|
+
__version__ = '24.05.26'
|
|
29
29
|
|
|
30
30
|
_class_ = 'class'
|
|
31
31
|
_dont_use_ = _DEPRECATED_ + ", don't use."
|
|
@@ -157,8 +157,7 @@ class _PropertyBase(property):
|
|
|
157
157
|
'''
|
|
158
158
|
def __init__(self, method, fget, fset, doc=NN):
|
|
159
159
|
|
|
160
|
-
|
|
161
|
-
self.getter(method) # PYCHOK no cover
|
|
160
|
+
_xcallable(getter=method, fget=fget)
|
|
162
161
|
|
|
163
162
|
self.method = method
|
|
164
163
|
self.name = method.__name__
|
|
@@ -288,20 +287,34 @@ class Property(Property_RO):
|
|
|
288
287
|
@note: Setting a new property value always clears the previously I{cached}
|
|
289
288
|
or I{memoized} value I{after} invoking the B{C{method}}.
|
|
290
289
|
'''
|
|
291
|
-
|
|
292
|
-
|
|
290
|
+
def _fset(inst, val):
|
|
291
|
+
'''Set and I{cache}, I{memoize} the C{property} value.
|
|
292
|
+
'''
|
|
293
|
+
_ = method(inst, val)
|
|
294
|
+
self._update(inst) # un-cache this item
|
|
293
295
|
|
|
294
|
-
|
|
295
|
-
_PropertyBase.__init__(self, self.method, self.method, method)
|
|
296
|
-
else:
|
|
296
|
+
return self._setters(method, _fset)
|
|
297
297
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
'''
|
|
301
|
-
method(inst, val)
|
|
302
|
-
self._update(inst) # un-cache this item
|
|
298
|
+
def setter_(self, method):
|
|
299
|
+
'''Make this C{Property} I{mutable}.
|
|
303
300
|
|
|
304
|
-
|
|
301
|
+
@arg method: The callable being decorated as this C{Property}'s C{setter}
|
|
302
|
+
and returning the new property value to be I{cached} or
|
|
303
|
+
I{memoized}.
|
|
304
|
+
'''
|
|
305
|
+
def _fset(inst, val):
|
|
306
|
+
'''Set and I{cache}, I{memoize} the C{property} value.
|
|
307
|
+
'''
|
|
308
|
+
val = method(inst, val)
|
|
309
|
+
inst.__dict__[self.name] = val
|
|
310
|
+
|
|
311
|
+
return self._setters(method, _fset)
|
|
312
|
+
|
|
313
|
+
def _setters(self, method, _fset):
|
|
314
|
+
_xcallable(setter=method, fset=_fset)
|
|
315
|
+
if _FOR_DOCS: # XXX force method.__doc__ into epydoc
|
|
316
|
+
_PropertyBase.__init__(self, self.method, self.method, method)
|
|
317
|
+
else: # class Property <https://docs.Python.org/3/howto/descriptor.html>
|
|
305
318
|
_PropertyBase.__init__(self, self.method, self._fget, _fset)
|
|
306
319
|
return self
|
|
307
320
|
|
pygeodesy/rhumb/aux_.py
CHANGED
|
@@ -32,22 +32,22 @@ from pygeodesy.auxilats.auxAngle import AuxMu, AuxPhi, hypot
|
|
|
32
32
|
from pygeodesy.auxilats.auxDLat import AuxDLat, _DClenshaw
|
|
33
33
|
# from pygeodesy.auxilats.auxDST import AuxDST # _MODS
|
|
34
34
|
from pygeodesy.auxilats.auxily import _Dlam, _Dp0Dpsi, _Ufloats
|
|
35
|
-
from pygeodesy.basics import copysign0, _reverange,
|
|
35
|
+
from pygeodesy.basics import copysign0, _reverange, _xkwds_get1
|
|
36
36
|
from pygeodesy.constants import EPS_2, MANT_DIG, PI4, isinf, \
|
|
37
37
|
_0_0, _4_0, _720_0, _log2, _over
|
|
38
|
-
from pygeodesy.datums import _WGS84
|
|
39
|
-
# from pygeodesy.errors import
|
|
38
|
+
# from pygeodesy.datums import _WGS84 # from .rhumb.bases
|
|
39
|
+
# from pygeodesy.errors import _xkwds_get1 # from .basics
|
|
40
40
|
from pygeodesy.karney import Caps, _polynomial
|
|
41
41
|
# from pygeodesy.fmath import hypot # from .auxilats.auxAngle
|
|
42
|
-
# from pygeodesy.interns import NN # from .datums
|
|
43
42
|
from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS
|
|
44
|
-
# from pygeodesy.props import Property_RO # from .
|
|
45
|
-
from pygeodesy.rhumb.bases import RhumbBase, RhumbLineBase,
|
|
43
|
+
# from pygeodesy.props import Property_RO # from .rhumb.bases
|
|
44
|
+
from pygeodesy.rhumb.bases import RhumbBase, RhumbLineBase, \
|
|
45
|
+
Property_RO, _WGS84
|
|
46
46
|
|
|
47
47
|
from math import ceil as _ceil, fabs, radians
|
|
48
48
|
|
|
49
49
|
__all__ = _ALL_LAZY.rhumb_aux_
|
|
50
|
-
__version__ = '
|
|
50
|
+
__version__ = '24.05.29'
|
|
51
51
|
|
|
52
52
|
# DIGITS = (sizeof(real) * 8) bits
|
|
53
53
|
# = (ctypes.sizeof(ctypes.c_double(1.0)) * 8) bits
|
|
@@ -68,7 +68,7 @@ class RhumbAux(RhumbBase):
|
|
|
68
68
|
installed, version 1.16 or later.
|
|
69
69
|
'''
|
|
70
70
|
|
|
71
|
-
def __init__(self, a_earth=_WGS84, f=None, exact=True,
|
|
71
|
+
def __init__(self, a_earth=_WGS84, f=None, exact=True, **TMorder_name): # PYCHOK signature
|
|
72
72
|
'''New C{RhumbAux}.
|
|
73
73
|
|
|
74
74
|
@kwarg a_earth: This rhumb's earth model (L{Datum}, L{Ellipsoid},
|
|
@@ -79,18 +79,16 @@ class RhumbAux(RhumbBase):
|
|
|
79
79
|
@kwarg exact: If C{True}, use the exact expressions for the I{Auxiliary
|
|
80
80
|
Latitudes}, otherwise use the I{Fourier} series expansion
|
|
81
81
|
(C{bool}), see also property C{exact}.
|
|
82
|
-
@kwarg
|
|
83
|
-
|
|
84
|
-
|
|
82
|
+
@kwarg TMorder_name: Optional C{B{name}=NN} (C{str}) and optional
|
|
83
|
+
keyword argument C{B{TMorder}=6} for the order of
|
|
84
|
+
the L{KTransverseMercator}, see property C{TMorder}.
|
|
85
85
|
|
|
86
86
|
@raise ImportError: Package C{numpy} not found or not installed, only
|
|
87
87
|
required for area C{S12} when C{B{exact} is True}.
|
|
88
88
|
|
|
89
89
|
@raise RhumbError: Invalid B{C{a_earth}}, B{C{f}} or B{C{TMorder}}.
|
|
90
90
|
'''
|
|
91
|
-
RhumbBase.__init__(self, a_earth, f, exact,
|
|
92
|
-
if TMorder:
|
|
93
|
-
self.Tmorder = _xkwds_get(TMorder, TMorder=RhumbBase._mTM)
|
|
91
|
+
RhumbBase.__init__(self, a_earth, f, exact, TMorder_name)
|
|
94
92
|
|
|
95
93
|
def areaux(self, **exact):
|
|
96
94
|
'''Get this ellipsoid's B{C{exact}} surface area (C{meter} I{squared}).
|
|
@@ -110,7 +108,7 @@ class RhumbAux(RhumbBase):
|
|
|
110
108
|
@see: U{The area of rhumb polygons<https://ArXiv.org/pdf/2303.03219.pdf>}
|
|
111
109
|
and method L{auxilats.AuxLat.AuthalicRadius2}.
|
|
112
110
|
'''
|
|
113
|
-
x =
|
|
111
|
+
x = _xkwds_get1(exact, exact=self.exact)
|
|
114
112
|
a = (self._c2 * _720_0) if bool(x) is self.exact else (
|
|
115
113
|
self._auxD.AuthalicRadius2(exact=x, f_max=self.f_max) * PI4)
|
|
116
114
|
return a
|