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/utmupsBase.py
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# -*- coding: utf-8 -*-
|
|
3
3
|
|
|
4
4
|
u'''(INTERNAL) Private class C{UtmUpsBase}, functions and constants
|
|
5
|
-
for L{epsg}, L{etm}, L{mgrs}, L{ups} and L{utm}.
|
|
5
|
+
for modules L{epsg}, L{etm}, L{mgrs}, L{ups} and L{utm}.
|
|
6
6
|
'''
|
|
7
7
|
|
|
8
8
|
from pygeodesy.basics import isint, isscalar, isstr, neg_, \
|
|
@@ -11,12 +11,12 @@ from pygeodesy.constants import _float, _0_0, _0_5, _N_90_0, _180_0
|
|
|
11
11
|
from pygeodesy.datums import _ellipsoidal_datum, _WGS84
|
|
12
12
|
from pygeodesy.dms import degDMS, parseDMS2
|
|
13
13
|
from pygeodesy.ellipsoidalBase import LatLonEllipsoidalBase as _LLEB
|
|
14
|
-
from pygeodesy.errors import _or, ParseError, _parseX,
|
|
15
|
-
|
|
14
|
+
from pygeodesy.errors import _or, ParseError, _parseX, _ValueError, \
|
|
15
|
+
_xkwds, _xkwds_not
|
|
16
16
|
# from pygeodesy.internals import _name__, _under # from .named
|
|
17
17
|
from pygeodesy.interns import NN, _A_, _B_, _COMMA_, _Error_, \
|
|
18
18
|
_gamma_, _n_a_, _not_, _N_, _NS_, _PLUS_, \
|
|
19
|
-
_scale_, _SPACE_, _Y_, _Z_
|
|
19
|
+
_S_, _scale_, _SPACE_, _Y_, _Z_
|
|
20
20
|
from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS
|
|
21
21
|
from pygeodesy.named import _NamedBase, _xnamed, _name__, _under
|
|
22
22
|
from pygeodesy.namedTuples import EasNor2Tuple, LatLonDatum5Tuple
|
|
@@ -27,7 +27,7 @@ from pygeodesy.units import Band, Easting, Northing, Scalar, Zone
|
|
|
27
27
|
from pygeodesy.utily import _Wrap, wrap360
|
|
28
28
|
|
|
29
29
|
__all__ = _ALL_LAZY.utmupsBase
|
|
30
|
-
__version__ = '24.
|
|
30
|
+
__version__ = '24.06.09'
|
|
31
31
|
|
|
32
32
|
_UPS_BANDS = _A_, _B_, _Y_, _Z_ # UPS polar bands SE, SW, NE, NW
|
|
33
33
|
# _UTM_BANDS = _MODS.utm._Bands
|
|
@@ -59,94 +59,6 @@ _UTMUPS_ZONE_MIN = _UPS_ZONE # PYCHOK for export too, by .units.py
|
|
|
59
59
|
# _UTM = -2
|
|
60
60
|
|
|
61
61
|
|
|
62
|
-
def _hemi(lat, N=0): # imported by .ups, .utm
|
|
63
|
-
'''Return the hemisphere letter.
|
|
64
|
-
|
|
65
|
-
@arg lat: Latitude (C{degrees} or C{radians}).
|
|
66
|
-
@kwarg N: Minimal North latitude, C{0} or C{_N_}.
|
|
67
|
-
|
|
68
|
-
@return: C{'N'|'S'} for north-/southern hemisphere.
|
|
69
|
-
'''
|
|
70
|
-
return _NS_[int(lat < N)]
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
def _to4lldn(latlon, lon, datum, name, wrap=False):
|
|
74
|
-
'''(INTERNAL) Return 4-tuple (C{lat, lon, datum, name}).
|
|
75
|
-
'''
|
|
76
|
-
try:
|
|
77
|
-
# if lon is not None:
|
|
78
|
-
# raise AttributeError
|
|
79
|
-
lat, lon = float(latlon.lat), float(latlon.lon)
|
|
80
|
-
_xinstanceof(_LLEB, LatLonDatum5Tuple, latlon=latlon)
|
|
81
|
-
if wrap:
|
|
82
|
-
_Wrap.latlon(lat, lon)
|
|
83
|
-
d = datum or latlon.datum
|
|
84
|
-
except AttributeError:
|
|
85
|
-
lat, lon = _Wrap.latlonDMS2(latlon, lon) if wrap else \
|
|
86
|
-
parseDMS2(latlon, lon) # clipped
|
|
87
|
-
d = datum or _WGS84
|
|
88
|
-
return lat, lon, d, _name__(name, _or_nameof=latlon)
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
def _to3zBhp(zone, band, hemipole=NN, Error=_ValueError): # imported by .epsg, .ups, .utm, .utmups
|
|
92
|
-
'''Parse UTM/UPS zone, Band letter and hemisphere/pole letter.
|
|
93
|
-
|
|
94
|
-
@arg zone: Zone with/-out Band (C{scalar} or C{str}).
|
|
95
|
-
@kwarg band: Optional I{longitudinal/polar} Band letter (C{str}).
|
|
96
|
-
@kwarg hemipole: Optional hemisphere/pole letter (C{str}).
|
|
97
|
-
@kwarg Error: Optional error to raise, overriding the default
|
|
98
|
-
C{ValueError}.
|
|
99
|
-
|
|
100
|
-
@return: 3-Tuple (C{zone, Band, hemisphere/pole}) as (C{int, str,
|
|
101
|
-
'N'|'S'}) where C{zone} is C{0} for UPS or C{1..60} for
|
|
102
|
-
UTM and C{Band} is C{'A'..'Z'} I{NOT} checked for valid
|
|
103
|
-
UTM/UPS bands.
|
|
104
|
-
|
|
105
|
-
@raise ValueError: Invalid B{C{zone}}, B{C{band}} or B{C{hemipole}}.
|
|
106
|
-
'''
|
|
107
|
-
try:
|
|
108
|
-
B, z = band, _UTMUPS_ZONE_INVALID
|
|
109
|
-
if isscalar(zone):
|
|
110
|
-
z = int(zone)
|
|
111
|
-
elif zone and isstr(zone):
|
|
112
|
-
if zone.isdigit():
|
|
113
|
-
z = int(zone)
|
|
114
|
-
elif len(zone) > 1:
|
|
115
|
-
B = zone[-1:]
|
|
116
|
-
z = int(zone[:-1])
|
|
117
|
-
elif zone.upper() in _UPS_BANDS: # single letter
|
|
118
|
-
B = zone
|
|
119
|
-
z = _UPS_ZONE
|
|
120
|
-
|
|
121
|
-
if _UTMUPS_ZONE_MIN <= z <= _UTMUPS_ZONE_MAX:
|
|
122
|
-
hp = hemipole[:1].upper()
|
|
123
|
-
if hp in _NS_ or not hp:
|
|
124
|
-
z = Zone(z)
|
|
125
|
-
B = Band(B.upper())
|
|
126
|
-
if B.isalpha():
|
|
127
|
-
return z, B, (hp or _hemi(B, _N_))
|
|
128
|
-
elif not B:
|
|
129
|
-
return z, B, hp
|
|
130
|
-
|
|
131
|
-
raise ValueError # _invalid_
|
|
132
|
-
except (AttributeError, IndexError, TypeError, ValueError) as x:
|
|
133
|
-
raise Error(zone=zone, band=B, hemipole=hemipole, cause=x)
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
def _to3zll(lat, lon): # imported by .ups, .utm
|
|
137
|
-
'''Wrap lat- and longitude and determine UTM zone.
|
|
138
|
-
|
|
139
|
-
@arg lat: Latitude (C{degrees}).
|
|
140
|
-
@arg lon: Longitude (C{degrees}).
|
|
141
|
-
|
|
142
|
-
@return: 3-Tuple (C{zone, lat, lon}) as (C{int}, C{degrees90},
|
|
143
|
-
C{degrees180}) where C{zone} is C{1..60} for UTM.
|
|
144
|
-
'''
|
|
145
|
-
x = wrap360(lon + _180_0) # use wrap360 to get ...
|
|
146
|
-
z = int(x) // 6 + 1 # ... longitudinal UTM zone [1, 60] and ...
|
|
147
|
-
return Zone(z), lat, (x - _180_0) # ... -180 <= lon < 180
|
|
148
|
-
|
|
149
|
-
|
|
150
62
|
class UtmUpsBase(_NamedBase):
|
|
151
63
|
'''(INTERNAL) Base class for L{Utm} and L{Ups} coordinates.
|
|
152
64
|
'''
|
|
@@ -166,7 +78,7 @@ class UtmUpsBase(_NamedBase):
|
|
|
166
78
|
_utm = None # cached toUtm (L{Utm})
|
|
167
79
|
|
|
168
80
|
def __init__(self, easting, northing, band=NN, datum=None, falsed=True,
|
|
169
|
-
|
|
81
|
+
gamma=None, scale=None):
|
|
170
82
|
'''(INTERNAL) New L{UtmUpsBase}.
|
|
171
83
|
'''
|
|
172
84
|
E = self._Error
|
|
@@ -185,10 +97,6 @@ class UtmUpsBase(_NamedBase):
|
|
|
185
97
|
if not falsed:
|
|
186
98
|
self._falsed = False
|
|
187
99
|
|
|
188
|
-
if convergence: # for backward compatibility
|
|
189
|
-
gamma, kwds = _xkwds_pop2(convergence, convergence=gamma)
|
|
190
|
-
if kwds:
|
|
191
|
-
raise _UnexpectedError(**kwds)
|
|
192
100
|
if gamma is not self._gamma:
|
|
193
101
|
self._gamma = Scalar(gamma=gamma, Error=E)
|
|
194
102
|
if scale is not self._scale:
|
|
@@ -272,7 +180,7 @@ class UtmUpsBase(_NamedBase):
|
|
|
272
180
|
|
|
273
181
|
@Property_RO
|
|
274
182
|
def falsed(self):
|
|
275
|
-
'''
|
|
183
|
+
'''Are easting and northing falsed (C{bool})?
|
|
276
184
|
'''
|
|
277
185
|
return self._falsed
|
|
278
186
|
|
|
@@ -310,9 +218,11 @@ class UtmUpsBase(_NamedBase):
|
|
|
310
218
|
ll, _under(_gamma_), _under(_scale_))
|
|
311
219
|
return _xnamed(r, ll.name)
|
|
312
220
|
|
|
313
|
-
def _latlon5args(self, ll, _toBand, unfalse, *other):
|
|
221
|
+
def _latlon5args(self, ll, g, k, _toBand, unfalse, *other):
|
|
314
222
|
'''(INTERNAL) See C{._toLLEB} methods, functions C{ups.toUps8} and C{utm._toXtm8}
|
|
315
223
|
'''
|
|
224
|
+
ll._gamma = g
|
|
225
|
+
ll._scale = k
|
|
316
226
|
ll._toLLEB_args = (unfalse,) + other
|
|
317
227
|
if unfalse:
|
|
318
228
|
if not self._band:
|
|
@@ -418,17 +328,26 @@ class UtmUpsBase(_NamedBase):
|
|
|
418
328
|
return t if sep is None else sep.join(t)
|
|
419
329
|
|
|
420
330
|
|
|
421
|
-
def
|
|
331
|
+
def _hemi(lat, N=0): # in .ups, .utm
|
|
332
|
+
'''Return the hemisphere letter.
|
|
333
|
+
|
|
334
|
+
@arg lat: Latitude (C{degrees} or C{radians}).
|
|
335
|
+
@kwarg N: Minimal North latitude, C{0} or C{_N_}.
|
|
336
|
+
|
|
337
|
+
@return: C{'N'|'S'} for north-/southern hemisphere.
|
|
338
|
+
'''
|
|
339
|
+
return _S_ if lat < N else _N_
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
def _lowerleft(utmups, center): # in .ellipsoidalBase._lowerleft
|
|
422
343
|
'''(INTERNAL) I{Un}-center a B{C{utmups}} to its C{lowerleft} by
|
|
423
344
|
C{B{center} meter} or by a I{guess} if B{C{center}} is C{0}.
|
|
424
345
|
'''
|
|
425
346
|
if center:
|
|
426
347
|
e = n = -center
|
|
427
348
|
else:
|
|
428
|
-
c
|
|
429
|
-
|
|
430
|
-
c *= 10 # 50, 500, 5000
|
|
431
|
-
t = c * 2
|
|
349
|
+
for c in (50, 500, 5000):
|
|
350
|
+
t = c * 2
|
|
432
351
|
e = int(utmups.easting % t)
|
|
433
352
|
n = int(utmups.northing % t)
|
|
434
353
|
if (e == c and n in (c, c - 1)) or \
|
|
@@ -439,7 +358,7 @@ def _lowerleft(utmups, center): # by .ellipsoidalBase._lowerleft
|
|
|
439
358
|
|
|
440
359
|
r = _xkwds_not(None, datum=utmups.datum,
|
|
441
360
|
gamma=utmups.gamma,
|
|
442
|
-
scale=utmups.scale)
|
|
361
|
+
scale=utmups.scale, name=utmups.name)
|
|
443
362
|
return utmups.classof(utmups.zone, utmups.hemisphere,
|
|
444
363
|
utmups.easting - e, utmups.northing - n,
|
|
445
364
|
band=utmups.band, falsed=utmups.falsed, **r)
|
|
@@ -489,12 +408,89 @@ def _parseUTMUPS5(strUTMUPS, UPS, Error=ParseError, band=NN, sep=_COMMA_):
|
|
|
489
408
|
strUTMUPS=strUTMUPS, Error=Error)
|
|
490
409
|
|
|
491
410
|
|
|
411
|
+
def _to4lldn(latlon, lon, datum, name, wrap=False):
|
|
412
|
+
'''(INTERNAL) Return 4-tuple (C{lat, lon, datum, name}).
|
|
413
|
+
'''
|
|
414
|
+
try:
|
|
415
|
+
# if lon is not None:
|
|
416
|
+
# raise AttributeError
|
|
417
|
+
lat, lon = float(latlon.lat), float(latlon.lon)
|
|
418
|
+
_xinstanceof(_LLEB, LatLonDatum5Tuple, latlon=latlon)
|
|
419
|
+
if wrap:
|
|
420
|
+
_Wrap.latlon(lat, lon)
|
|
421
|
+
d = datum or latlon.datum
|
|
422
|
+
except AttributeError: # TypeError
|
|
423
|
+
lat, lon = _Wrap.latlonDMS2(latlon, lon) if wrap else \
|
|
424
|
+
parseDMS2(latlon, lon) # clipped
|
|
425
|
+
d = datum or _WGS84
|
|
426
|
+
return lat, lon, d, _name__(name, _or_nameof=latlon)
|
|
427
|
+
|
|
428
|
+
|
|
492
429
|
def _toMgrs(utmups):
|
|
493
430
|
'''(INTERNAL) Convert a L{Utm} or L{Ups} to an L{Mgrs} instance.
|
|
494
431
|
'''
|
|
495
432
|
return _MODS.mgrs.toMgrs(utmups, datum=utmups.datum, name=utmups.name)
|
|
496
433
|
|
|
497
434
|
|
|
435
|
+
def _to3zBhp(zone, band, hemipole=NN, Error=_ValueError): # in .epsg, .ups, .utm, .utmups
|
|
436
|
+
'''Parse UTM/UPS zone, Band letter and hemisphere/pole letter.
|
|
437
|
+
|
|
438
|
+
@arg zone: Zone with/-out Band (C{scalar} or C{str}).
|
|
439
|
+
@kwarg band: Optional I{longitudinal/polar} Band letter (C{str}).
|
|
440
|
+
@kwarg hemipole: Optional hemisphere/pole letter (C{str}).
|
|
441
|
+
@kwarg Error: Optional error to raise, overriding the default
|
|
442
|
+
C{ValueError}.
|
|
443
|
+
|
|
444
|
+
@return: 3-Tuple (C{zone, Band, hemisphere/pole}) as (C{int, str,
|
|
445
|
+
'N'|'S'}) where C{zone} is C{0} for UPS or C{1..60} for
|
|
446
|
+
UTM and C{Band} is C{'A'..'Z'} I{NOT} checked for valid
|
|
447
|
+
UTM/UPS bands.
|
|
448
|
+
|
|
449
|
+
@raise ValueError: Invalid B{C{zone}}, B{C{band}} or B{C{hemipole}}.
|
|
450
|
+
'''
|
|
451
|
+
try:
|
|
452
|
+
B, z = band, _UTMUPS_ZONE_INVALID
|
|
453
|
+
if isscalar(zone):
|
|
454
|
+
z = int(zone)
|
|
455
|
+
elif zone and isstr(zone):
|
|
456
|
+
if zone.isdigit():
|
|
457
|
+
z = int(zone)
|
|
458
|
+
elif len(zone) > 1:
|
|
459
|
+
B = zone[-1:]
|
|
460
|
+
z = int(zone[:-1])
|
|
461
|
+
elif zone.upper() in _UPS_BANDS: # single letter
|
|
462
|
+
B = zone
|
|
463
|
+
z = _UPS_ZONE
|
|
464
|
+
|
|
465
|
+
if _UTMUPS_ZONE_MIN <= z <= _UTMUPS_ZONE_MAX:
|
|
466
|
+
hp = hemipole[:1].upper()
|
|
467
|
+
if hp in _NS_ or not hp:
|
|
468
|
+
z = Zone(z)
|
|
469
|
+
B = Band(B.upper())
|
|
470
|
+
if B.isalpha():
|
|
471
|
+
return z, B, (hp or _hemi(B, _N_))
|
|
472
|
+
elif not B:
|
|
473
|
+
return z, B, hp
|
|
474
|
+
|
|
475
|
+
raise ValueError() # _invalid_
|
|
476
|
+
except (AttributeError, IndexError, TypeError, ValueError) as x:
|
|
477
|
+
raise Error(zone=zone, band=B, hemipole=hemipole, cause=x)
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
def _to3zll(lat, lon): # in .ups, .utm
|
|
481
|
+
'''Wrap lat- and longitude and determine UTM zone.
|
|
482
|
+
|
|
483
|
+
@arg lat: Latitude (C{degrees}).
|
|
484
|
+
@arg lon: Longitude (C{degrees}).
|
|
485
|
+
|
|
486
|
+
@return: 3-Tuple (C{zone, lat, lon}) as (C{int}, C{degrees90},
|
|
487
|
+
C{degrees180}) where C{zone} is C{1..60} for UTM.
|
|
488
|
+
'''
|
|
489
|
+
x = wrap360(lon + _180_0) # use wrap360 to get ...
|
|
490
|
+
z = int(x) // 6 + 1 # ... longitudinal UTM zone [1, 60] and ...
|
|
491
|
+
return Zone(z), lat, (x - _180_0) # ... -180 <= lon < 180
|
|
492
|
+
|
|
493
|
+
|
|
498
494
|
__all__ += _ALL_DOCS(UtmUpsBase)
|
|
499
495
|
|
|
500
496
|
# **) MIT License
|
pygeodesy/vector3d.py
CHANGED
|
@@ -25,13 +25,15 @@ from pygeodesy.namedTuples import Intersection3Tuple, NearestOn2Tuple, \
|
|
|
25
25
|
# from pygeodesy.streprs import Fmt # from .iters
|
|
26
26
|
from pygeodesy.units import _fi_j2, _isDegrees, Radius, Radius_
|
|
27
27
|
from pygeodesy.utily import atan2b, sincos2d
|
|
28
|
-
#
|
|
28
|
+
# import pygeodesy.vector2d as _vector2d # _MODS.into
|
|
29
29
|
from pygeodesy.vector3dBase import Vector3dBase
|
|
30
30
|
|
|
31
31
|
# from math import fabs, sqrt # from .fmath
|
|
32
32
|
|
|
33
33
|
__all__ = _ALL_LAZY.vector3d
|
|
34
|
-
__version__ = '24.
|
|
34
|
+
__version__ = '24.06.06'
|
|
35
|
+
|
|
36
|
+
_vector2d = _MODS.into(vector2d=__name__)
|
|
35
37
|
|
|
36
38
|
|
|
37
39
|
class Vector3d(Vector3dBase):
|
|
@@ -87,7 +89,7 @@ class Vector3d(Vector3dBase):
|
|
|
87
89
|
Triangle<https://MathWorld.Wolfram.com/ContactTriangle.html>}.
|
|
88
90
|
'''
|
|
89
91
|
try:
|
|
90
|
-
return
|
|
92
|
+
return _vector2d._circin6(self, point2, point3, eps=eps, useZ=True)
|
|
91
93
|
except (AssertionError, TypeError, ValueError) as x:
|
|
92
94
|
raise _xError(x, point=self, point2=point2, point3=point3)
|
|
93
95
|
|
|
@@ -118,8 +120,8 @@ class Vector3d(Vector3dBase):
|
|
|
118
120
|
@see: Function L{pygeodesy.circum3} and methods L{circum4_} and L{meeus2}.
|
|
119
121
|
'''
|
|
120
122
|
try:
|
|
121
|
-
return
|
|
122
|
-
|
|
123
|
+
return _vector2d._circum3(self, point2, point3, circum=circum,
|
|
124
|
+
eps=eps, useZ=True, clas=self.classof)
|
|
123
125
|
except (AssertionError, TypeError, ValueError) as x:
|
|
124
126
|
raise _xError(x, point=self, point2=point2, point3=point3, circum=circum)
|
|
125
127
|
|
|
@@ -143,7 +145,7 @@ class Vector3d(Vector3dBase):
|
|
|
143
145
|
|
|
144
146
|
@see: Function L{pygeodesy.circum4_} and methods L{circum3} and L{meeus2}.
|
|
145
147
|
'''
|
|
146
|
-
return
|
|
148
|
+
return _vector2d.circum4_(self, *points, useZ=True, Vector=self.classof)
|
|
147
149
|
|
|
148
150
|
def iscolinearWith(self, point1, point2, eps=EPS):
|
|
149
151
|
'''Check whether this and two other (3-D) points are colinear.
|
|
@@ -163,7 +165,7 @@ class Vector3d(Vector3dBase):
|
|
|
163
165
|
@see: Method L{nearestOn}.
|
|
164
166
|
'''
|
|
165
167
|
v = self if self.name else _otherV3d(NN_OK=False, this=self)
|
|
166
|
-
return
|
|
168
|
+
return _vector2d._iscolinearWith(v, point1, point2, eps=eps)
|
|
167
169
|
|
|
168
170
|
def meeus2(self, point2, point3, circum=False):
|
|
169
171
|
'''Return the radius and I{Meeus}' Type of the smallest circle I{through}
|
|
@@ -186,7 +188,7 @@ class Vector3d(Vector3dBase):
|
|
|
186
188
|
@see: Function L{pygeodesy.meeus2} and methods L{circum3} and L{circum4_}.
|
|
187
189
|
'''
|
|
188
190
|
try:
|
|
189
|
-
return
|
|
191
|
+
return _vector2d._meeus2(self, point2, point3, circum, clas=self.classof)
|
|
190
192
|
except (TypeError, ValueError) as x:
|
|
191
193
|
raise _xError(x, point=self, point2=point2, point3=point3, circum=circum)
|
|
192
194
|
|
|
@@ -270,7 +272,7 @@ class Vector3d(Vector3dBase):
|
|
|
270
272
|
Circles<https://MathWorld.Wolfram.com/TangentCircles.html>}.
|
|
271
273
|
'''
|
|
272
274
|
try:
|
|
273
|
-
return
|
|
275
|
+
return _vector2d._radii11ABC(self, point2, point3, useZ=True)[0]
|
|
274
276
|
except (TypeError, ValueError) as x:
|
|
275
277
|
raise _xError(x, point=self, point2=point2, point3=point3)
|
|
276
278
|
|
|
@@ -299,7 +301,7 @@ class Vector3d(Vector3dBase):
|
|
|
299
301
|
|
|
300
302
|
@see: Function L{pygeodesy.soddy4}.
|
|
301
303
|
'''
|
|
302
|
-
return
|
|
304
|
+
return _vector2d.soddy4(self, point2, point3, eps=eps, useZ=True)
|
|
303
305
|
|
|
304
306
|
def trilaterate2d2(self, radius, center2, radius2, center3, radius3, eps=EPS4, z=INT0):
|
|
305
307
|
'''Trilaterate this and two other circles, each given as a (2-D) center
|
|
@@ -335,10 +337,10 @@ class Vector3d(Vector3dBase):
|
|
|
335
337
|
return v.x, v.y, r
|
|
336
338
|
|
|
337
339
|
try:
|
|
338
|
-
return
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
340
|
+
return _vector2d._trilaterate2d2(*(_xyr3(radius, center=self) +
|
|
341
|
+
_xyr3(radius2, center2=center2) +
|
|
342
|
+
_xyr3(radius3, center3=center3)),
|
|
343
|
+
eps=eps, Vector=self.classof, z=z)
|
|
342
344
|
except (AssertionError, TypeError, ValueError) as x:
|
|
343
345
|
raise _xError(x, center=self, radius=radius,
|
|
344
346
|
center2=center2, radius2=radius2,
|
|
@@ -386,10 +388,10 @@ class Vector3d(Vector3dBase):
|
|
|
386
388
|
'''
|
|
387
389
|
try:
|
|
388
390
|
c1 = _otherV3d(center=self, NN_OK=False)
|
|
389
|
-
return
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
391
|
+
return _vector2d._trilaterate3d2(c1, Radius_(radius, low=eps),
|
|
392
|
+
center2, radius2,
|
|
393
|
+
center3, radius3,
|
|
394
|
+
eps=eps, clas=self.classof)
|
|
393
395
|
except (AssertionError, TypeError, ValueError) as x:
|
|
394
396
|
raise _xError(x, center=self, radius=radius,
|
|
395
397
|
center2=center2, radius2=radius2,
|
|
@@ -643,7 +645,7 @@ def iscolinearWith(point, point1, point2, eps=EPS, useZ=True):
|
|
|
643
645
|
@see: Function L{nearestOn}.
|
|
644
646
|
'''
|
|
645
647
|
p = _otherV3d(useZ=useZ, point=point)
|
|
646
|
-
return
|
|
648
|
+
return _vector2d._iscolinearWith(p, point1, point2, eps=eps, useZ=useZ)
|
|
647
649
|
|
|
648
650
|
|
|
649
651
|
def nearestOn(point, point1, point2, within=True, useZ=True, Vector=None, **Vector_kwds):
|
|
@@ -869,9 +871,9 @@ def trilaterate2d2(x1, y1, radius1, x2, y2, radius2, x3, y3, radius3,
|
|
|
869
871
|
<https://math.StackExchange.com/questions/884807>} and function
|
|
870
872
|
L{pygeodesy.trilaterate3d2}.
|
|
871
873
|
'''
|
|
872
|
-
return
|
|
873
|
-
|
|
874
|
-
|
|
874
|
+
return _vector2d._trilaterate2d2(x1, y1, radius1,
|
|
875
|
+
x2, y2, radius2,
|
|
876
|
+
x3, y3, radius3, eps=eps, **Vector_and_kwds)
|
|
875
877
|
|
|
876
878
|
|
|
877
879
|
def trilaterate3d2(center1, radius1, center2, radius2, center3, radius3,
|
|
@@ -919,27 +921,23 @@ def trilaterate3d2(center1, radius1, center2, radius2, center3, radius3,
|
|
|
919
921
|
288825016>} and function L{pygeodesy.trilaterate2d2}.
|
|
920
922
|
'''
|
|
921
923
|
try:
|
|
922
|
-
return
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
924
|
+
return _vector2d._trilaterate3d2(_otherV3d(center1=center1, NN_OK=False),
|
|
925
|
+
Radius_(radius1=radius1, low=eps),
|
|
926
|
+
center2, radius2, center3, radius3, eps=eps,
|
|
927
|
+
clas=center1.classof, **Vector_and_kwds)
|
|
926
928
|
except (AssertionError, TypeError, ValueError) as x:
|
|
927
929
|
raise _xError(x, center1=center1, radius1=radius1,
|
|
928
930
|
center2=center2, radius2=radius2,
|
|
929
931
|
center3=center3, radius3=radius3)
|
|
930
932
|
|
|
931
933
|
|
|
932
|
-
def
|
|
933
|
-
'''(INTERNAL) Get a C{(h, d, name)}
|
|
934
|
+
def _xyzhdlln4(xyz, height, datum, ll=None, **name): # in .cartesianBase, .nvectorBase
|
|
935
|
+
'''(INTERNAL) Get a C{(h, d, ll, name)} 4-tuple.
|
|
934
936
|
'''
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
d = datum or _xattr(xyz, datum=None) \
|
|
940
|
-
or _xattr(ll, datum=None)
|
|
941
|
-
|
|
942
|
-
return h, d, _name__(name, _or_nameof=xyz)
|
|
937
|
+
_x = _xattr
|
|
938
|
+
h = height or _x(xyz, height=None) or _x(xyz, h=None) or _x(ll, height=None)
|
|
939
|
+
d = datum or _x(xyz, datum=None) or _x(ll, datum=None)
|
|
940
|
+
return h, d, ll, _name__(name, _or_nameof=ll)
|
|
943
941
|
|
|
944
942
|
|
|
945
943
|
__all__ += _ALL_DOCS(intersections2, sumOf, Vector3dBase)
|
pygeodesy/vector3dBase.py
CHANGED
|
@@ -9,7 +9,7 @@ A pure Python implementation of vector-based functions by I{(C) Chris Veness
|
|
|
9
9
|
'''
|
|
10
10
|
|
|
11
11
|
from pygeodesy.basics import _copysign, islistuple, isscalar, map1, \
|
|
12
|
-
map2, _zip
|
|
12
|
+
map2, _signOf, _zip
|
|
13
13
|
from pygeodesy.constants import EPS, EPS0, INT0, PI, PI2, _copysignINF, \
|
|
14
14
|
_float0, isnear0, isnear1, isneg0, \
|
|
15
15
|
_pos_self, _0_0, _1_0
|
|
@@ -30,7 +30,7 @@ from pygeodesy.units import Float, Scalar
|
|
|
30
30
|
from math import atan2, ceil, fabs, floor, trunc
|
|
31
31
|
|
|
32
32
|
__all__ = _ALL_LAZY.vector3dBase
|
|
33
|
-
__version__ = '24.
|
|
33
|
+
__version__ = '24.06.07'
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
|
|
@@ -107,9 +107,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
|
|
|
107
107
|
|
|
108
108
|
@raise TypeError: Incompatible B{C{other}} C{type}.
|
|
109
109
|
'''
|
|
110
|
-
|
|
111
|
-
return -1 if self.length < n else (
|
|
112
|
-
+1 if self.length > n else 0)
|
|
110
|
+
return _signOf(self.length, self._other_cmp(other))
|
|
113
111
|
|
|
114
112
|
cmp = __cmp__
|
|
115
113
|
|
|
@@ -156,7 +154,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
|
|
|
156
154
|
|
|
157
155
|
@raise TypeError: Incompatible B{C{other}} C{type}.
|
|
158
156
|
'''
|
|
159
|
-
return self.length >= self.
|
|
157
|
+
return self.length >= self._other_cmp(other)
|
|
160
158
|
|
|
161
159
|
# def __getitem__(self, key):
|
|
162
160
|
# '''Return C{item} at index or slice C{[B{key}]}.
|
|
@@ -172,7 +170,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
|
|
|
172
170
|
|
|
173
171
|
@raise TypeError: Incompatible B{C{other}} C{type}.
|
|
174
172
|
'''
|
|
175
|
-
return self.length > self.
|
|
173
|
+
return self.length > self._other_cmp(other)
|
|
176
174
|
|
|
177
175
|
def __hash__(self): # PYCHOK no cover
|
|
178
176
|
'''Return this instance' C{hash}.
|
|
@@ -261,7 +259,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
|
|
|
261
259
|
|
|
262
260
|
@raise TypeError: Incompatible B{C{other}} C{type}.
|
|
263
261
|
'''
|
|
264
|
-
return self.length <= self.
|
|
262
|
+
return self.length <= self._other_cmp(other)
|
|
265
263
|
|
|
266
264
|
# def __len__(self):
|
|
267
265
|
# '''Return C{3}, always.
|
|
@@ -277,7 +275,7 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
|
|
|
277
275
|
|
|
278
276
|
@raise TypeError: Incompatible B{C{other}} C{type}.
|
|
279
277
|
'''
|
|
280
|
-
return self.length < self.
|
|
278
|
+
return self.length < self._other_cmp(other)
|
|
281
279
|
|
|
282
280
|
def __matmul__(self, other): # PYCHOK Python 3.5+
|
|
283
281
|
'''Compute the cross product of this and an other vector, C{this @ B{other}}.
|
|
@@ -759,6 +757,11 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
|
|
|
759
757
|
'''
|
|
760
758
|
return _MODS.nvectorBase._N_vector_(*self.xyz, name=self.name)
|
|
761
759
|
|
|
760
|
+
def _other_cmp(self, other):
|
|
761
|
+
'''(INTERNAL) Return the value for comparison.
|
|
762
|
+
'''
|
|
763
|
+
return other if isscalar(other) else self.others(other).length
|
|
764
|
+
|
|
762
765
|
def others(self, *other, **name_other_up):
|
|
763
766
|
'''Refined class comparison.
|
|
764
767
|
|