pygeodesy 24.5.24__py2.py3-none-any.whl → 24.6.1__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.1.dist-info}/METADATA +6 -5
- {PyGeodesy-24.5.24.dist-info → PyGeodesy-24.6.1.dist-info}/RECORD +57 -57
- 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 +3 -3
- pygeodesy/constants.py +3 -3
- pygeodesy/deprecated/functions.py +9 -3
- pygeodesy/ecef.py +22 -21
- pygeodesy/ellipsoidalBase.py +15 -16
- pygeodesy/ellipsoidalGeodSolve.py +2 -2
- pygeodesy/ellipsoidalKarney.py +3 -3
- pygeodesy/ellipsoids.py +6 -5
- pygeodesy/errors.py +19 -9
- pygeodesy/etm.py +16 -21
- pygeodesy/fmath.py +9 -20
- pygeodesy/formy.py +60 -74
- pygeodesy/frechet.py +11 -11
- pygeodesy/fsums.py +59 -25
- pygeodesy/geodesicx/__init__.py +1 -1
- pygeodesy/geodesicx/__main__.py +2 -2
- pygeodesy/geodesicx/gx.py +3 -5
- pygeodesy/geodsolve.py +2 -2
- pygeodesy/geohash.py +14 -14
- pygeodesy/hausdorff.py +12 -12
- pygeodesy/heights.py +5 -5
- pygeodesy/internals.py +3 -3
- pygeodesy/karney.py +8 -7
- pygeodesy/lazily.py +2 -2
- pygeodesy/ltp.py +62 -44
- pygeodesy/ltpTuples.py +202 -147
- pygeodesy/mgrs.py +24 -24
- pygeodesy/named.py +68 -70
- pygeodesy/nvectorBase.py +2 -2
- pygeodesy/osgr.py +40 -48
- pygeodesy/points.py +10 -10
- 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 +13 -10
- pygeodesy/simplify.py +16 -16
- pygeodesy/solveBase.py +14 -14
- pygeodesy/sphericalBase.py +17 -21
- pygeodesy/sphericalTrigonometry.py +17 -17
- pygeodesy/trf.py +9 -7
- pygeodesy/triaxials.py +2 -2
- pygeodesy/ups.py +66 -70
- pygeodesy/utily.py +3 -3
- pygeodesy/utm.py +152 -156
- pygeodesy/utmups.py +38 -38
- pygeodesy/utmupsBase.py +102 -106
- pygeodesy/webmercator.py +43 -51
- {PyGeodesy-24.5.24.dist-info → PyGeodesy-24.6.1.dist-info}/WHEEL +0 -0
- {PyGeodesy-24.5.24.dist-info → PyGeodesy-24.6.1.dist-info}/top_level.txt +0 -0
pygeodesy/mgrs.py
CHANGED
|
@@ -44,7 +44,7 @@ from pygeodesy.interns import NN, _0_, _A_, _AtoZnoIO_, _band_, _B_, \
|
|
|
44
44
|
_COMMASPACE_, _datum_, _easting_, _invalid_, \
|
|
45
45
|
_northing_, _SPACE_, _W_, _Y_, _Z_, _zone_
|
|
46
46
|
from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS, _PYGEODESY_GEOCONVERT_
|
|
47
|
-
from pygeodesy.named import _NamedBase, _NamedTuple, _Pass
|
|
47
|
+
from pygeodesy.named import _name2__, _NamedBase, _NamedTuple, _Pass
|
|
48
48
|
from pygeodesy.namedTuples import EasNor2Tuple, UtmUps5Tuple
|
|
49
49
|
from pygeodesy.props import deprecated_property_RO, property_RO, Property_RO
|
|
50
50
|
from pygeodesy.streprs import enstr2, _enstr2m3, Fmt, _resolution10, _xzipairs
|
|
@@ -55,7 +55,7 @@ from pygeodesy.utm import toUtm8, _to3zBlat, Utm, _UTM_ZONE_MAX, _UTM_ZONE_MIN
|
|
|
55
55
|
# from pygeodesy.utmupsBase import _UTM_ZONE_MAX, _UTM_ZONE_MIN # from .utm
|
|
56
56
|
|
|
57
57
|
__all__ = _ALL_LAZY.mgrs
|
|
58
|
-
__version__ = '24.05.
|
|
58
|
+
__version__ = '24.05.31'
|
|
59
59
|
|
|
60
60
|
_AN_ = 'AN' # default south pole grid tile and band B
|
|
61
61
|
_AtoPx_ = _AtoZnoIO_.tillP
|
|
@@ -87,7 +87,7 @@ class Mgrs(_NamedBase):
|
|
|
87
87
|
_zone = 0 # longitudinal or polar zone (C{int}), 0..60
|
|
88
88
|
|
|
89
89
|
def __init__(self, zone=0, EN=NN, easting=0, northing=0, band=NN,
|
|
90
|
-
datum=_WGS84, resolution=0, name
|
|
90
|
+
datum=_WGS84, resolution=0, **name):
|
|
91
91
|
'''New L{Mgrs} Military grid reference.
|
|
92
92
|
|
|
93
93
|
@arg zone: The 6° I{longitudinal} zone (C{int}), 1..60 covering
|
|
@@ -104,7 +104,7 @@ class Mgrs(_NamedBase):
|
|
|
104
104
|
@kwarg datum: This reference's datum (L{Datum}, L{Ellipsoid},
|
|
105
105
|
L{Ellipsoid2} or L{a_f2Tuple}).
|
|
106
106
|
@kwarg resolution: Optional resolution (C{meter}), C{0} for default.
|
|
107
|
-
@kwarg name: Optional name (C{str}).
|
|
107
|
+
@kwarg name: Optional C{B{name}=NN} (C{str}).
|
|
108
108
|
|
|
109
109
|
@raise MGRSError: Invalid B{C{zone}}, B{C{EN}}, B{C{easting}},
|
|
110
110
|
B{C{northing}}, B{C{band}} or B{C{resolution}}.
|
|
@@ -235,20 +235,18 @@ class Mgrs(_NamedBase):
|
|
|
235
235
|
toUps8(a, 0, datum=self.datum, Ups=None)
|
|
236
236
|
return int(u.northing / _100km) * _100km
|
|
237
237
|
|
|
238
|
-
def parse(self, strMGRS, name
|
|
238
|
+
def parse(self, strMGRS, **name):
|
|
239
239
|
'''Parse a string to a similar L{Mgrs} instance.
|
|
240
240
|
|
|
241
|
-
@arg strMGRS: The MGRS reference (C{str}),
|
|
242
|
-
|
|
243
|
-
@kwarg name: Optional instance name (C{str}),
|
|
244
|
-
overriding this name.
|
|
241
|
+
@arg strMGRS: The MGRS reference (C{str}), see function L{parseMGRS}.
|
|
242
|
+
@kwarg name: Optional C{B{name}=NN} (C{str}), overriding this name.
|
|
245
243
|
|
|
246
244
|
@return: The similar instance (L{Mgrs}).
|
|
247
245
|
|
|
248
246
|
@raise MGRSError: Invalid B{C{strMGRS}}.
|
|
249
247
|
'''
|
|
250
248
|
return parseMGRS(strMGRS, datum=self.datum, Mgrs=self.classof,
|
|
251
|
-
|
|
249
|
+
name=self._name__(name))
|
|
252
250
|
|
|
253
251
|
@property
|
|
254
252
|
def resolution(self):
|
|
@@ -536,7 +534,7 @@ class _RE(object):
|
|
|
536
534
|
_RE = _RE() # PYCHOK singleton
|
|
537
535
|
|
|
538
536
|
|
|
539
|
-
def parseMGRS(strMGRS, datum=_WGS84, Mgrs=Mgrs, name
|
|
537
|
+
def parseMGRS(strMGRS, datum=_WGS84, Mgrs=Mgrs, **name):
|
|
540
538
|
'''Parse a string representing a MGRS grid reference,
|
|
541
539
|
consisting of C{"[zone]Band, EN, easting, northing"}.
|
|
542
540
|
|
|
@@ -544,7 +542,7 @@ def parseMGRS(strMGRS, datum=_WGS84, Mgrs=Mgrs, name=NN):
|
|
|
544
542
|
@kwarg datum: Optional datum to use (L{Datum}).
|
|
545
543
|
@kwarg Mgrs: Optional class to return the MGRS grid
|
|
546
544
|
reference (L{Mgrs}) or C{None}.
|
|
547
|
-
@kwarg name: Optional B{C{Mgrs}} name (C{str}).
|
|
545
|
+
@kwarg name: Optional B{C{Mgrs}} C{B{name}=NN} (C{str}).
|
|
548
546
|
|
|
549
547
|
@return: The MGRS grid reference as B{C{Mgrs}} or if
|
|
550
548
|
C{B{Mgrs} is None} as an L{Mgrs4Tuple}C{(zone,
|
|
@@ -582,29 +580,29 @@ def parseMGRS(strMGRS, datum=_WGS84, Mgrs=Mgrs, name=NN):
|
|
|
582
580
|
e, n, m = _enstr2m3(*m[2:])
|
|
583
581
|
|
|
584
582
|
if Mgrs is None:
|
|
585
|
-
r = Mgrs4Tuple(zB, EN, e, n, name
|
|
583
|
+
r = Mgrs4Tuple(zB, EN, e, n, **name)
|
|
586
584
|
_ = r.toMgrs(resolution=m) # validate
|
|
587
585
|
else:
|
|
588
|
-
r = Mgrs(zB, EN, e, n, datum=datum, resolution=m, name
|
|
586
|
+
r = Mgrs(zB, EN, e, n, datum=datum, resolution=m, **name)
|
|
589
587
|
return r
|
|
590
588
|
|
|
591
589
|
return _parseX(_MGRS, strMGRS, datum, Mgrs, name,
|
|
592
590
|
strMGRS=strMGRS, Error=MGRSError)
|
|
593
591
|
|
|
594
592
|
|
|
595
|
-
def toMgrs(utmups, Mgrs=Mgrs,
|
|
593
|
+
def toMgrs(utmups, Mgrs=Mgrs, **name_Mgrs_kwds):
|
|
596
594
|
'''Convert a UTM or UPS coordinate to an MGRS grid reference.
|
|
597
595
|
|
|
598
596
|
@arg utmups: A UTM or UPS coordinate (L{Utm}, L{Etm} or L{Ups}).
|
|
599
597
|
@kwarg Mgrs: Optional class to return the MGRS grid reference
|
|
600
598
|
(L{Mgrs}) or C{None}.
|
|
601
|
-
@kwarg
|
|
602
|
-
|
|
603
|
-
|
|
599
|
+
@kwarg name_Mgrs_kwds: Optional C{B{name}=NN} (C{str}) and
|
|
600
|
+
optional, additional B{C{Mgrs}} keyword arguments,
|
|
601
|
+
ignored if C{B{Mgrs} is None}.
|
|
604
602
|
|
|
605
|
-
@return: The MGRS grid reference as B{C{Mgrs}} or if
|
|
606
|
-
|
|
607
|
-
|
|
603
|
+
@return: The MGRS grid reference as B{C{Mgrs}} or if C{B{Mgrs}
|
|
604
|
+
is None} as an L{Mgrs6Tuple}C{(zone, EN, easting,
|
|
605
|
+
northing, band, datum)}.
|
|
608
606
|
|
|
609
607
|
@raise MGRSError: Invalid B{C{utmups}}.
|
|
610
608
|
|
|
@@ -634,12 +632,14 @@ def toMgrs(utmups, Mgrs=Mgrs, name=NN, **Mgrs_kwds):
|
|
|
634
632
|
except (IndexError, TypeError, ValueError) as x:
|
|
635
633
|
raise MGRSError(B=B, E=E, N=N, utmups=utmups, cause=x)
|
|
636
634
|
|
|
635
|
+
t, kwds = _name2__(name_Mgrs_kwds, _or_nameof=utmups)
|
|
637
636
|
if Mgrs is None:
|
|
638
|
-
r = Mgrs4Tuple(Fmt.zone(z), EN, e, n
|
|
637
|
+
r = Mgrs4Tuple(Fmt.zone(z), EN, e, n, name=t) \
|
|
638
|
+
.to6Tuple(B, utmups.datum)
|
|
639
639
|
else:
|
|
640
|
-
kwds = _xkwds(
|
|
640
|
+
kwds = _xkwds(kwds, band=B, datum=utmups.datum, name=t)
|
|
641
641
|
r = Mgrs(z, EN, e, n, **kwds)
|
|
642
|
-
return
|
|
642
|
+
return r
|
|
643
643
|
|
|
644
644
|
|
|
645
645
|
def _um100km2(m):
|
pygeodesy/named.py
CHANGED
|
@@ -33,7 +33,7 @@ from pygeodesy.props import _allPropertiesOf_n, deprecated_method, _hasProperty,
|
|
|
33
33
|
from pygeodesy.streprs import attrs, Fmt, lrstrip, pairs, reprs, unstr
|
|
34
34
|
|
|
35
35
|
__all__ = _ALL_LAZY.named
|
|
36
|
-
__version__ = '24.05.
|
|
36
|
+
__version__ = '24.05.31'
|
|
37
37
|
|
|
38
38
|
_COMMANL_ = _COMMA_ + _NL_
|
|
39
39
|
_COMMASPACEDOT_ = _COMMASPACE_ + _DOT_
|
|
@@ -50,69 +50,6 @@ _Units_ = '_Units_'
|
|
|
50
50
|
_UP = 2
|
|
51
51
|
|
|
52
52
|
|
|
53
|
-
def _xjoined_(prefix, name=NN, enquote=True, **name__of_name):
|
|
54
|
-
'''(INTERNAL) Join C{prefix} and non-empty C{name}.
|
|
55
|
-
'''
|
|
56
|
-
if name__of_name:
|
|
57
|
-
name = _name__(name, **name__of_name)
|
|
58
|
-
if name and prefix:
|
|
59
|
-
if enquote:
|
|
60
|
-
name = repr(name)
|
|
61
|
-
t = _SPACE_(prefix, name)
|
|
62
|
-
else:
|
|
63
|
-
t = prefix or name
|
|
64
|
-
return t
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
def _xnamed(inst, name=NN, force=False, **name__of_name):
|
|
68
|
-
'''(INTERNAL) Set the instance' C{.name = B{name}}.
|
|
69
|
-
|
|
70
|
-
@arg inst: The instance (C{_Named}).
|
|
71
|
-
@kwarg name: The name (C{str}).
|
|
72
|
-
@kwarg force: If C{True}, force rename (C{bool}).
|
|
73
|
-
|
|
74
|
-
@return: The B{C{inst}}, renamed if B{C{force}}d
|
|
75
|
-
or if not named before.
|
|
76
|
-
'''
|
|
77
|
-
if name__of_name:
|
|
78
|
-
name = _name__(name, **name__of_name)
|
|
79
|
-
if name and isinstance(inst, _Named):
|
|
80
|
-
if not inst.name:
|
|
81
|
-
inst.name = name
|
|
82
|
-
elif force:
|
|
83
|
-
inst.rename(name)
|
|
84
|
-
return inst
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
def _xother3(inst, other, name=_other_, up=1, **name_other):
|
|
88
|
-
'''(INTERNAL) Get C{name} and C{up} for a named C{other}.
|
|
89
|
-
'''
|
|
90
|
-
if name_other: # and other is None
|
|
91
|
-
name, other = _xkwds_item2(name_other)
|
|
92
|
-
elif other and len(other) == 1:
|
|
93
|
-
name, other = _name__(name), other[0]
|
|
94
|
-
else:
|
|
95
|
-
raise _AssertionError(name, other, txt=classname(inst, prefixed=True))
|
|
96
|
-
return other, name, up
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
def _xotherError(inst, other, name=_other_, up=1):
|
|
100
|
-
'''(INTERNAL) Return a C{_TypeError} for an incompatible, named C{other}.
|
|
101
|
-
'''
|
|
102
|
-
n = _callname(name, classname(inst, prefixed=True), inst.name, up=up + 1)
|
|
103
|
-
return _TypeError(name, other, txt=_incompatible(n))
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
def _xvalid(name, underOK=False):
|
|
107
|
-
'''(INTERNAL) Check valid attribute name C{name}.
|
|
108
|
-
'''
|
|
109
|
-
return bool(name and isstr(name)
|
|
110
|
-
and name != _name_
|
|
111
|
-
and (underOK or not name.startswith(_UNDER_))
|
|
112
|
-
and (not iskeyword(name))
|
|
113
|
-
and isidentifier(name))
|
|
114
|
-
|
|
115
|
-
|
|
116
53
|
class ADict(dict):
|
|
117
54
|
'''A C{dict} with both key I{and} attribute access to
|
|
118
55
|
the C{dict} items.
|
|
@@ -170,7 +107,6 @@ class ADict(dict):
|
|
|
170
107
|
C{floats} formatted by function L{pygeodesy.fstr}.
|
|
171
108
|
'''
|
|
172
109
|
n = _xattr(self, name=NN) or self.__class__.__name__
|
|
173
|
-
print(1, n)
|
|
174
110
|
return Fmt.PAREN(n, self._toT(_EQUAL_, **prec_fmt))
|
|
175
111
|
|
|
176
112
|
def toStr(self, **prec_fmt):
|
|
@@ -1300,13 +1236,12 @@ def _name__(name=NN, **kwds):
|
|
|
1300
1236
|
return name if name or name is None else NN
|
|
1301
1237
|
|
|
1302
1238
|
|
|
1303
|
-
def _name1__(kwds_name,
|
|
1239
|
+
def _name1__(kwds_name, **name__or_nameof):
|
|
1304
1240
|
'''(INTERNAL) Resolve and set the C{B{name}=NN}.
|
|
1305
1241
|
'''
|
|
1306
|
-
if kwds_name:
|
|
1307
|
-
n, kwds_name = _name2__(kwds_name,
|
|
1308
|
-
|
|
1309
|
-
kwds_name.update(name=n)
|
|
1242
|
+
if kwds_name or name__or_nameof:
|
|
1243
|
+
n, kwds_name = _name2__(kwds_name, **name__or_nameof)
|
|
1244
|
+
kwds_name.update(name=n)
|
|
1310
1245
|
return kwds_name
|
|
1311
1246
|
|
|
1312
1247
|
|
|
@@ -1406,6 +1341,69 @@ def _Pass(arg, **unused): # PYCHOK no cover
|
|
|
1406
1341
|
return arg
|
|
1407
1342
|
|
|
1408
1343
|
|
|
1344
|
+
def _xjoined_(prefix, name=NN, enquote=True, **name__or_nameof):
|
|
1345
|
+
'''(INTERNAL) Join C{prefix} and non-empty C{name}.
|
|
1346
|
+
'''
|
|
1347
|
+
if name__or_nameof:
|
|
1348
|
+
name = _name__(name, **name__or_nameof)
|
|
1349
|
+
if name and prefix:
|
|
1350
|
+
if enquote:
|
|
1351
|
+
name = repr(name)
|
|
1352
|
+
t = _SPACE_(prefix, name)
|
|
1353
|
+
else:
|
|
1354
|
+
t = prefix or name
|
|
1355
|
+
return t
|
|
1356
|
+
|
|
1357
|
+
|
|
1358
|
+
def _xnamed(inst, name=NN, force=False, **name__or_nameof):
|
|
1359
|
+
'''(INTERNAL) Set the instance' C{.name = B{name}}.
|
|
1360
|
+
|
|
1361
|
+
@arg inst: The instance (C{_Named}).
|
|
1362
|
+
@kwarg name: The name (C{str}).
|
|
1363
|
+
@kwarg force: If C{True}, force rename (C{bool}).
|
|
1364
|
+
|
|
1365
|
+
@return: The B{C{inst}}, renamed if B{C{force}}d
|
|
1366
|
+
or if not named before.
|
|
1367
|
+
'''
|
|
1368
|
+
if name__or_nameof:
|
|
1369
|
+
name = _name__(name, **name__or_nameof)
|
|
1370
|
+
if name and isinstance(inst, _Named):
|
|
1371
|
+
if not inst.name:
|
|
1372
|
+
inst.name = name
|
|
1373
|
+
elif force:
|
|
1374
|
+
inst.rename(name)
|
|
1375
|
+
return inst
|
|
1376
|
+
|
|
1377
|
+
|
|
1378
|
+
def _xother3(inst, other, name=_other_, up=1, **name_other):
|
|
1379
|
+
'''(INTERNAL) Get C{name} and C{up} for a named C{other}.
|
|
1380
|
+
'''
|
|
1381
|
+
if name_other: # and other is None
|
|
1382
|
+
name, other = _xkwds_item2(name_other)
|
|
1383
|
+
elif other and len(other) == 1:
|
|
1384
|
+
name, other = _name__(name), other[0]
|
|
1385
|
+
else:
|
|
1386
|
+
raise _AssertionError(name, other, txt=classname(inst, prefixed=True))
|
|
1387
|
+
return other, name, up
|
|
1388
|
+
|
|
1389
|
+
|
|
1390
|
+
def _xotherError(inst, other, name=_other_, up=1):
|
|
1391
|
+
'''(INTERNAL) Return a C{_TypeError} for an incompatible, named C{other}.
|
|
1392
|
+
'''
|
|
1393
|
+
n = _callname(name, classname(inst, prefixed=True), inst.name, up=up + 1)
|
|
1394
|
+
return _TypeError(name, other, txt=_incompatible(n))
|
|
1395
|
+
|
|
1396
|
+
|
|
1397
|
+
def _xvalid(name, underOK=False):
|
|
1398
|
+
'''(INTERNAL) Check valid attribute name C{name}.
|
|
1399
|
+
'''
|
|
1400
|
+
return bool(name and isstr(name)
|
|
1401
|
+
and name != _name_
|
|
1402
|
+
and (underOK or not name.startswith(_UNDER_))
|
|
1403
|
+
and (not iskeyword(name))
|
|
1404
|
+
and isidentifier(name))
|
|
1405
|
+
|
|
1406
|
+
|
|
1409
1407
|
__all__ += _ALL_DOCS(_Named,
|
|
1410
1408
|
_NamedBase, # _NamedDict,
|
|
1411
1409
|
_NamedEnum, _NamedEnumItem,
|
pygeodesy/nvectorBase.py
CHANGED
|
@@ -39,7 +39,7 @@ from pygeodesy.vector3d import Vector3d, _xyzhdn3
|
|
|
39
39
|
from math import fabs, sqrt
|
|
40
40
|
|
|
41
41
|
__all__ = _ALL_LAZY.nvectorBase
|
|
42
|
-
__version__ = '24.05.
|
|
42
|
+
__version__ = '24.05.31'
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
class NvectorBase(Vector3d): # XXX kept private
|
|
@@ -385,7 +385,7 @@ SouthPole = NvectorBase(0, 0, -1, name=_SouthPole_) # South pole (C{Nvector})
|
|
|
385
385
|
class _N_vector_(NvectorBase):
|
|
386
386
|
'''(INTERNAL) Minimal, low-overhead C{n-vector}.
|
|
387
387
|
'''
|
|
388
|
-
def __init__(self, x, y, z, h=0, name
|
|
388
|
+
def __init__(self, x, y, z, h=0, **name):
|
|
389
389
|
self._x, self._y, self._z = x, y, z
|
|
390
390
|
if h:
|
|
391
391
|
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.05.
|
|
65
|
+
__version__ = '24.05.25'
|
|
66
66
|
|
|
67
67
|
_ilat_ = 'ilat'
|
|
68
68
|
_ilon_ = 'ilon'
|
|
@@ -1473,8 +1473,8 @@ 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
|
|
@@ -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
|