pygeodesy 24.6.1__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.1.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 +53 -66
- pygeodesy/cartesianBase.py +143 -155
- 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 +49 -55
- pygeodesy/elevations.py +4 -4
- pygeodesy/ellipsoidalBase.py +28 -70
- pygeodesy/ellipsoidalBaseDI.py +19 -23
- pygeodesy/ellipsoidalExact.py +3 -3
- pygeodesy/ellipsoidalGeodSolve.py +15 -23
- pygeodesy/ellipsoidalKarney.py +37 -60
- pygeodesy/ellipsoidalNvector.py +44 -50
- pygeodesy/ellipsoidalVincenty.py +11 -14
- pygeodesy/ellipsoids.py +107 -101
- pygeodesy/errors.py +101 -49
- pygeodesy/etm.py +32 -44
- pygeodesy/formy.py +55 -58
- pygeodesy/frechet.py +20 -23
- pygeodesy/fsums.py +4 -4
- 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 +102 -34
- pygeodesy/geohash.py +39 -60
- pygeodesy/geoids.py +28 -37
- pygeodesy/hausdorff.py +21 -23
- pygeodesy/heights.py +15 -28
- pygeodesy/internals.py +19 -12
- pygeodesy/interns.py +4 -10
- pygeodesy/iters.py +2 -2
- pygeodesy/karney.py +20 -4
- pygeodesy/ktm.py +13 -16
- pygeodesy/latlonBase.py +202 -191
- pygeodesy/lazily.py +96 -59
- pygeodesy/lcc.py +29 -32
- pygeodesy/ltp.py +43 -24
- pygeodesy/ltpTuples.py +190 -183
- pygeodesy/mgrs.py +35 -9
- pygeodesy/named.py +106 -72
- pygeodesy/namedTuples.py +43 -14
- pygeodesy/nvectorBase.py +23 -27
- pygeodesy/osgr.py +9 -9
- pygeodesy/points.py +7 -7
- 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/rhumb/solve.py +8 -61
- pygeodesy/solveBase.py +22 -19
- pygeodesy/sphericalBase.py +26 -21
- pygeodesy/sphericalNvector.py +13 -13
- pygeodesy/sphericalTrigonometry.py +86 -97
- pygeodesy/streprs.py +8 -36
- pygeodesy/trf.py +3 -3
- pygeodesy/triaxials.py +117 -91
- pygeodesy/units.py +229 -321
- pygeodesy/unitsBase.py +116 -108
- pygeodesy/ups.py +26 -31
- pygeodesy/utily.py +12 -11
- pygeodesy/utm.py +35 -40
- pygeodesy/utmups.py +43 -46
- pygeodesy/utmupsBase.py +9 -10
- pygeodesy/vector3d.py +59 -62
- pygeodesy/vector3dBase.py +17 -15
- pygeodesy/webmercator.py +19 -21
- pygeodesy/wgrs.py +18 -20
- PyGeodesy-24.6.1.dist-info/RECORD +0 -116
- {PyGeodesy-24.6.1.dist-info → PyGeodesy-24.6.24.dist-info}/WHEEL +0 -0
- {PyGeodesy-24.6.1.dist-info → PyGeodesy-24.6.24.dist-info}/top_level.txt +0 -0
pygeodesy/utmups.py
CHANGED
|
@@ -31,7 +31,7 @@ from pygeodesy.utmupsBase import Fmt, _to4lldn, _to3zBhp, _UPS_ZONE, \
|
|
|
31
31
|
_UTMUPS_ZONE_MAX, _WGS84
|
|
32
32
|
|
|
33
33
|
__all__ = _ALL_LAZY.utmups
|
|
34
|
-
__version__ = '24.
|
|
34
|
+
__version__ = '24.06.11'
|
|
35
35
|
|
|
36
36
|
_MGRS_TILE = _100km # in .mgrs.Mgrs.tile
|
|
37
37
|
|
|
@@ -111,32 +111,31 @@ def toUtmUps8(latlon, lon=None, datum=None, falsed=True, Utm=Utm, Ups=Ups,
|
|
|
111
111
|
|
|
112
112
|
@arg latlon: Latitude (C{degrees}) or an (ellipsoidal)
|
|
113
113
|
geodetic C{LatLon} point.
|
|
114
|
-
@kwarg lon:
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
@kwarg
|
|
119
|
-
|
|
120
|
-
@kwarg Ups: Optional class to return the UPS coordinate (L{Ups})
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
(C{
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
value is missing of B{C{datum}} is invalid.
|
|
114
|
+
@kwarg lon: Longitude (C{degrees}), required if B{C{latlon}} is C{degrees},
|
|
115
|
+
ignored otherwise.
|
|
116
|
+
@kwarg datum: Optional datum to use this UTM coordinate, overriding the
|
|
117
|
+
B{C{latlon}}'s datum (C{Datum}).
|
|
118
|
+
@kwarg falsed: If C{True}, false both easting and northing (C{bool}).
|
|
119
|
+
@kwarg Utm: Optional class to return the UTM coordinate (L{Utm}) or C{None}.
|
|
120
|
+
@kwarg Ups: Optional class to return the UPS coordinate (L{Ups}) or C{None}.
|
|
121
|
+
@kwarg pole: Optional top/center of UPS (stereographic) projection (C{str},
|
|
122
|
+
C{'N[orth]'} or C{'S[outh]'}).
|
|
123
|
+
@kwarg name_cmoff: Optional C{B{name}=NN} (C{str}) and DEPRECATED keyword
|
|
124
|
+
argument C{B{cmoff}=True} to offset the longitude from the zone's
|
|
125
|
+
central meridian (C{bool}), use B{C{falsed}} instead and I{for
|
|
126
|
+
UTM only}.
|
|
127
|
+
|
|
128
|
+
@return: The UTM or UPS coordinate (B{C{Utm}} respectively B{C{Ups}}) or a
|
|
129
|
+
L{UtmUps8Tuple}C{(zone, hemipole, easting, northing, band, datum,
|
|
130
|
+
gamma, scale)} if B{C{Utm}} respectively C{B{Ups} is None} or if
|
|
131
|
+
C{B{falsed} is False}.
|
|
132
|
+
|
|
133
|
+
@raise RangeError: If B{C{lat}} outside the valid UTM or UPS bands or if
|
|
134
|
+
B{C{lat}} or B{C{lon}} outside the valid range and
|
|
135
|
+
L{rangerrors<pygeodesy.rangerrors>} is C{True}.
|
|
136
|
+
|
|
137
|
+
@raise TypeError: If B{C{latlon}} is not ellipsoidal or B{C{lon}} is missing
|
|
138
|
+
or B{C{datum}} is invalid.
|
|
140
139
|
|
|
141
140
|
@raise UTMUPSError: UTM or UPS validation failed.
|
|
142
141
|
|
|
@@ -154,21 +153,20 @@ def toUtmUps8(latlon, lon=None, datum=None, falsed=True, Utm=Utm, Ups=Ups,
|
|
|
154
153
|
return u
|
|
155
154
|
|
|
156
155
|
|
|
157
|
-
def UtmUps(zone, hemipole, easting, northing, band=NN, datum=_WGS84,
|
|
158
|
-
falsed=True, **name):
|
|
156
|
+
def UtmUps(zone, hemipole, easting, northing, band=NN, datum=_WGS84, falsed=True, **name):
|
|
159
157
|
'''Class-like function to create a UTM/UPS coordinate.
|
|
160
158
|
|
|
161
159
|
@kwarg zone: The UTM zone with/-out I{longitudinal} Band or UPS zone C{0}
|
|
162
160
|
or C{"00"} with/-out I{polar} Band (C{str} or C{int}).
|
|
163
|
-
@kwarg hemipole: UTM hemisphere or UPS top/center of projection
|
|
164
|
-
|
|
161
|
+
@kwarg hemipole: UTM hemisphere or UPS top/center of projection (C{str},
|
|
162
|
+
C{'N[orth]'} or C{'S[outh]'}).
|
|
165
163
|
@arg easting: Easting, see B{C{falsed}} (C{meter}).
|
|
166
164
|
@arg northing: Northing, see B{C{falsed}} (C{meter}).
|
|
167
165
|
@kwarg band: Optional, UTM I{latitudinal} C{'C'|'D'|..|'W'|'X'} or UPS
|
|
168
166
|
I{polar} Band letter C{'A'|'B'|'Y'|'Z'} Band letter (C{str}).
|
|
169
167
|
@kwarg datum: The coordinate's datum (L{Datum}).
|
|
170
|
-
@kwarg falsed: If C{True}, both B{C{easting}} and B{C{northing}} are
|
|
171
|
-
|
|
168
|
+
@kwarg falsed: If C{True}, both B{C{easting}} and B{C{northing}} are falsed
|
|
169
|
+
(C{bool}).
|
|
172
170
|
@kwarg name: Optional L{Utm} or L{Ups} C{B{name}=NN} (C{str}).
|
|
173
171
|
|
|
174
172
|
@return: New UTM or UPS instance (L{Utm} or L{Ups}).
|
|
@@ -182,17 +180,16 @@ def UtmUps(zone, hemipole, easting, northing, band=NN, datum=_WGS84,
|
|
|
182
180
|
'''
|
|
183
181
|
z, B, hp = _to3zBhp(zone, band, hemipole=hemipole)
|
|
184
182
|
U = Ups if z in (_UPS_ZONE, _UPS_ZONE_STR) else Utm
|
|
185
|
-
return U(z, hp, easting, northing, band=B, datum=datum,
|
|
186
|
-
falsed=falsed, **name)
|
|
183
|
+
return U(z, hp, easting, northing, band=B, datum=datum, falsed=falsed, **name)
|
|
187
184
|
|
|
188
185
|
|
|
189
186
|
def utmupsValidate(coord, falsed=False, MGRS=False, Error=UTMUPSError):
|
|
190
187
|
'''Check a UTM or UPS coordinate.
|
|
191
188
|
|
|
192
|
-
@arg coord: The UTM or UPS coordinate (L{Utm}, L{Etm}, L{Ups}
|
|
193
|
-
|
|
194
|
-
@kwarg falsed: C{
|
|
195
|
-
(C{bool}), ignored otherwise.
|
|
189
|
+
@arg coord: The UTM or UPS coordinate (L{Utm}, L{Etm}, L{Ups} or
|
|
190
|
+
C{5+Tuple}).
|
|
191
|
+
@kwarg falsed: If C{True}, easting and northing are falsed in the
|
|
192
|
+
C{B{coord} 5+Tuple} (C{bool}), ignored otherwise.
|
|
196
193
|
@kwarg MGRS: Increase easting and northing ranges (C{bool}).
|
|
197
194
|
@kwarg Error: Optional error to raise, overriding the default
|
|
198
195
|
(L{UTMUPSError}).
|
|
@@ -253,8 +250,8 @@ def utmupsValidateOK(coord, falsed=False, ok=True):
|
|
|
253
250
|
'''Check a UTM or UPS coordinate.
|
|
254
251
|
|
|
255
252
|
@arg coord: The UTM or UPS coordinate (L{Utm}, L{Ups} or C{5+Tuple}).
|
|
256
|
-
@kwarg falsed:
|
|
257
|
-
|
|
253
|
+
@kwarg falsed: If C{True}, easting and northing are falsed in the
|
|
254
|
+
C{B{coord} 5+Tuple} (C{bool}), ignored otherwise.
|
|
258
255
|
@kwarg ok: Result to return if validation passed (B{C{ok}}).
|
|
259
256
|
|
|
260
257
|
@return: B{C{ok}} if validation passed, otherwise the L{UTMUPSError}.
|
|
@@ -263,9 +260,9 @@ def utmupsValidateOK(coord, falsed=False, ok=True):
|
|
|
263
260
|
'''
|
|
264
261
|
try:
|
|
265
262
|
utmupsValidate(coord, falsed=falsed)
|
|
266
|
-
return ok
|
|
267
263
|
except UTMUPSError as x:
|
|
268
264
|
return x
|
|
265
|
+
return ok
|
|
269
266
|
|
|
270
267
|
|
|
271
268
|
def utmupsZoneBand5(lat, lon, cmoff=False, **name):
|
|
@@ -280,11 +277,11 @@ def utmupsZoneBand5(lat, lon, cmoff=False, **name):
|
|
|
280
277
|
|
|
281
278
|
@return: A L{UtmUpsLatLon5Tuple}C{(zone, band, hemipole, lat, lon)}
|
|
282
279
|
where C{hemipole} is C{'N'|'S'}, the UTM hemisphere or UPS
|
|
283
|
-
pole,
|
|
280
|
+
pole, projection top/center.
|
|
284
281
|
|
|
285
|
-
@raise RangeError: If B{C{lat}} outside the valid UTM or UPS bands
|
|
286
|
-
|
|
287
|
-
|
|
282
|
+
@raise RangeError: If B{C{lat}} outside the valid UTM or UPS bands or
|
|
283
|
+
if B{C{lat}} or B{C{lon}} outside the valid range
|
|
284
|
+
and L{rangerrors<pygeodesy.rangerrors>} is C{True}.
|
|
288
285
|
|
|
289
286
|
@raise ValueError: Invalid B{C{lat}} or B{C{lon}}.
|
|
290
287
|
|
pygeodesy/utmupsBase.py
CHANGED
|
@@ -12,22 +12,22 @@ 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
14
|
from pygeodesy.errors import _or, ParseError, _parseX, _ValueError, \
|
|
15
|
-
_xkwds, _xkwds_not
|
|
15
|
+
_xattrs, _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
19
|
_S_, _scale_, _SPACE_, _Y_, _Z_
|
|
20
20
|
from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS
|
|
21
|
-
from pygeodesy.named import
|
|
21
|
+
from pygeodesy.named import _name__, _NamedBase, _under
|
|
22
22
|
from pygeodesy.namedTuples import EasNor2Tuple, LatLonDatum5Tuple
|
|
23
23
|
from pygeodesy.props import deprecated_method, property_doc_, _update_all, \
|
|
24
24
|
deprecated_property_RO, Property_RO, property_RO
|
|
25
|
-
from pygeodesy.streprs import Fmt, fstr, _fstrENH2,
|
|
25
|
+
from pygeodesy.streprs import Fmt, fstr, _fstrENH2, _xzipairs
|
|
26
26
|
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.12'
|
|
31
31
|
|
|
32
32
|
_UPS_BANDS = _A_, _B_, _Y_, _Z_ # UPS polar bands SE, SW, NE, NW
|
|
33
33
|
# _UTM_BANDS = _MODS.utm._Bands
|
|
@@ -210,13 +210,12 @@ class UtmUpsBase(_NamedBase):
|
|
|
210
210
|
ll = self._latlon
|
|
211
211
|
if LatLon is None:
|
|
212
212
|
r = LatLonDatum5Tuple(ll.lat, ll.lon, ll.datum,
|
|
213
|
-
ll.gamma, ll.scale)
|
|
213
|
+
ll.gamma, ll.scale, name=ll.name)
|
|
214
214
|
else:
|
|
215
215
|
_xsubclassof(_LLEB, LatLon=LatLon)
|
|
216
|
-
|
|
217
|
-
r = _xattrs(
|
|
218
|
-
|
|
219
|
-
return _xnamed(r, ll.name)
|
|
216
|
+
r = LatLon(ll.lat, ll.lon, **_xkwds(LatLon_kwds, datum=ll.datum, name=ll.name))
|
|
217
|
+
r = _xattrs(r, ll, _under(_gamma_), _under(_scale_))
|
|
218
|
+
return r
|
|
220
219
|
|
|
221
220
|
def _latlon5args(self, ll, g, k, _toBand, unfalse, *other):
|
|
222
221
|
'''(INTERNAL) See C{._toLLEB} methods, functions C{ups.toUps8} and C{utm._toXtm8}
|
|
@@ -472,7 +471,7 @@ def _to3zBhp(zone, band, hemipole=NN, Error=_ValueError): # in .epsg, .ups, .ut
|
|
|
472
471
|
elif not B:
|
|
473
472
|
return z, B, hp
|
|
474
473
|
|
|
475
|
-
raise ValueError # _invalid_
|
|
474
|
+
raise ValueError() # _invalid_
|
|
476
475
|
except (AttributeError, IndexError, TypeError, ValueError) as x:
|
|
477
476
|
raise Error(zone=zone, band=B, hemipole=hemipole, cause=x)
|
|
478
477
|
|
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.18'
|
|
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,
|
|
@@ -473,7 +475,8 @@ def _intersect3d3(start1, end1, start2, end2, eps=EPS, useZ=False): # MCCABE 16
|
|
|
473
475
|
t = cb.dot(ab)
|
|
474
476
|
o1 = 0 if b1 else _outside(t, ab2, 1)
|
|
475
477
|
v = s1.plus(a.times(t / ab2))
|
|
476
|
-
|
|
478
|
+
t = v.minus(s2).dot(b)
|
|
479
|
+
o2 = 0 if b2 else _outside(t, b.length2, 2)
|
|
477
480
|
return v, o1, o2
|
|
478
481
|
|
|
479
482
|
|
|
@@ -539,16 +542,15 @@ def intersections2(center1, radius1, center2, radius2, sphere=True, **Vector_and
|
|
|
539
542
|
intersection points and optional, additional B{C{Vector}}
|
|
540
543
|
keyword arguments, otherwise B{C{center1}}'s (sub-)class.
|
|
541
544
|
|
|
542
|
-
@return: If B{
|
|
543
|
-
|
|
544
|
-
|
|
545
|
+
@return: If C{B{sphere} is True}, a 2-tuple of the C{center} and C{radius} of the
|
|
546
|
+
intersection of the I{spheres}. For abutting circles, C{radius} is C{0.0}
|
|
547
|
+
and C{center} is the I{radical center}.
|
|
545
548
|
|
|
546
|
-
If B{
|
|
547
|
-
|
|
548
|
-
the
|
|
549
|
+
If C{B{sphere} is False}, a 2-tuple with the two intersection points of the
|
|
550
|
+
I{circles}. For abutting circles, both points are the same instance, aka
|
|
551
|
+
the I{radical center}.
|
|
549
552
|
|
|
550
|
-
@raise IntersectionError: Concentric, invalid or non-intersecting spheres
|
|
551
|
-
or circles.
|
|
553
|
+
@raise IntersectionError: Concentric, invalid or non-intersecting spheres or circles.
|
|
552
554
|
|
|
553
555
|
@raise TypeError: Invalid B{C{center1}} or B{C{center2}}.
|
|
554
556
|
|
|
@@ -635,15 +637,15 @@ def iscolinearWith(point, point1, point2, eps=EPS, useZ=True):
|
|
|
635
637
|
@kwarg eps: Tolerance (C{scalar}), same units as C{x}, C{y} and C{z}.
|
|
636
638
|
@kwarg useZ: If C{True}, use the Z components, otherwise force C{z=INT0} (C{bool}).
|
|
637
639
|
|
|
638
|
-
@return: C{True} if B{C{point}} is colinear B{C{point1}} and B{C{point2}},
|
|
639
|
-
|
|
640
|
+
@return: C{True} if B{C{point}} is colinear B{C{point1}} and B{C{point2}}, C{False}
|
|
641
|
+
otherwise.
|
|
640
642
|
|
|
641
643
|
@raise TypeError: Invalid B{C{point}}, B{C{point1}} or B{C{point2}}.
|
|
642
644
|
|
|
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):
|
|
@@ -659,8 +661,8 @@ def nearestOn(point, point1, point2, within=True, useZ=True, Vector=None, **Vect
|
|
|
659
661
|
points, otherwise the closest point on the extended line
|
|
660
662
|
through both points (C{bool}).
|
|
661
663
|
@kwarg useZ: If C{True}, use the Z components, otherwise force C{z=INT0} (C{bool}).
|
|
662
|
-
@kwarg Vector: Class to return closest point (C{Cartesian}, L{Vector3d}
|
|
663
|
-
|
|
664
|
+
@kwarg Vector: Class to return closest point (C{Cartesian}, L{Vector3d} or
|
|
665
|
+
C{Vector3Tuple}) or C{None}.
|
|
664
666
|
@kwarg Vector_kwds: Optional, additional B{C{Vector}} keyword arguments,
|
|
665
667
|
ignored if C{B{Vector} is None}.
|
|
666
668
|
|
|
@@ -764,23 +766,22 @@ def nearestOn6(point, points, closed=False, useZ=True, **Vector_and_kwds): # ep
|
|
|
764
766
|
return NearestOn6Tuple(v, sqrt(c2), f, j, s, e)
|
|
765
767
|
|
|
766
768
|
|
|
767
|
-
def _nVc(v, clas=None, Vector=None, **
|
|
769
|
+
def _nVc(v, clas=None, Vector=None, **name_Vector_kwds): # in .vector2d
|
|
768
770
|
# return a named C{Vector} or C{clas} instance
|
|
769
|
-
name,
|
|
771
|
+
name, kwds = _name2__(**name_Vector_kwds)
|
|
770
772
|
if Vector is not None:
|
|
771
|
-
v = Vector(v.x, v.y, v.z, **
|
|
773
|
+
v = Vector(v.x, v.y, v.z, **kwds)
|
|
772
774
|
elif clas is not None:
|
|
773
775
|
v = clas(v.x, v.y, v.z) # ignore Vector_kwds
|
|
774
776
|
return _xnamed(v, name) if name else v
|
|
775
777
|
|
|
776
778
|
|
|
777
|
-
def _otherV3d(useZ=True, NN_OK=True, i=None, **
|
|
779
|
+
def _otherV3d(useZ=True, NN_OK=True, i=None, **name_vector):
|
|
778
780
|
# check named vector instance, return Vector3d
|
|
779
|
-
n, v = _xkwds_item2(
|
|
781
|
+
n, v = _xkwds_item2(name_vector)
|
|
782
|
+
n = Fmt.INDEX(n, i)
|
|
780
783
|
if useZ and isinstance(v, Vector3dBase):
|
|
781
|
-
return v if NN_OK or v.name else v.copy(name=
|
|
782
|
-
|
|
783
|
-
n = Fmt.INDEX(n, i)
|
|
784
|
+
return v if NN_OK or v.name else v.copy(name=n)
|
|
784
785
|
try:
|
|
785
786
|
return Vector3d(v.x, v.y, (v.z if useZ else INT0), name=n)
|
|
786
787
|
except AttributeError: # no .x, .y or .z attr
|
|
@@ -797,7 +798,7 @@ def parse3d(str3d, sep=_COMMA_, Vector=Vector3d, **Vector_kwds):
|
|
|
797
798
|
@kwarg Vector_kwds: Optional B{C{Vector}} keyword arguments,
|
|
798
799
|
ignored if C{B{Vector} is None}.
|
|
799
800
|
|
|
800
|
-
@return: A B{C{Vector}} instance or if B{
|
|
801
|
+
@return: A B{C{Vector}} instance or if C{B{Vector} is None},
|
|
801
802
|
a named L{Vector3Tuple}C{(x, y, z)}.
|
|
802
803
|
|
|
803
804
|
@raise VectorError: Invalid B{C{str3d}}.
|
|
@@ -818,11 +819,11 @@ def sumOf(vectors, Vector=Vector3d, **Vector_kwds):
|
|
|
818
819
|
|
|
819
820
|
@arg vectors: Vectors to be added (L{Vector3d}[]).
|
|
820
821
|
@kwarg Vector: Optional class for the vectorial sum (L{Vector3d}).
|
|
821
|
-
@kwarg Vector_kwds: Optional B{C{Vector}} keyword arguments,
|
|
822
|
-
|
|
822
|
+
@kwarg Vector_kwds: Optional B{C{Vector}} keyword arguments, ignored
|
|
823
|
+
if C{B{Vector} is None}.
|
|
823
824
|
|
|
824
|
-
@return: Vectorial sum as B{C{Vector}} or if B{C{Vector}
|
|
825
|
-
|
|
825
|
+
@return: Vectorial sum as B{C{Vector}} or if B{C{Vector} is None},
|
|
826
|
+
a named L{Vector3Tuple}C{(x, y, z)}.
|
|
826
827
|
|
|
827
828
|
@raise VectorError: No B{C{vectors}}.
|
|
828
829
|
'''
|
|
@@ -869,9 +870,9 @@ def trilaterate2d2(x1, y1, radius1, x2, y2, radius2, x3, y3, radius3,
|
|
|
869
870
|
<https://math.StackExchange.com/questions/884807>} and function
|
|
870
871
|
L{pygeodesy.trilaterate3d2}.
|
|
871
872
|
'''
|
|
872
|
-
return
|
|
873
|
-
|
|
874
|
-
|
|
873
|
+
return _vector2d._trilaterate2d2(x1, y1, radius1,
|
|
874
|
+
x2, y2, radius2,
|
|
875
|
+
x3, y3, radius3, eps=eps, **Vector_and_kwds)
|
|
875
876
|
|
|
876
877
|
|
|
877
878
|
def trilaterate3d2(center1, radius1, center2, radius2, center3, radius3,
|
|
@@ -919,27 +920,23 @@ def trilaterate3d2(center1, radius1, center2, radius2, center3, radius3,
|
|
|
919
920
|
288825016>} and function L{pygeodesy.trilaterate2d2}.
|
|
920
921
|
'''
|
|
921
922
|
try:
|
|
922
|
-
return
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
923
|
+
return _vector2d._trilaterate3d2(_otherV3d(center1=center1, NN_OK=False),
|
|
924
|
+
Radius_(radius1=radius1, low=eps),
|
|
925
|
+
center2, radius2, center3, radius3, eps=eps,
|
|
926
|
+
clas=center1.classof, **Vector_and_kwds)
|
|
926
927
|
except (AssertionError, TypeError, ValueError) as x:
|
|
927
928
|
raise _xError(x, center1=center1, radius1=radius1,
|
|
928
929
|
center2=center2, radius2=radius2,
|
|
929
930
|
center3=center3, radius3=radius3)
|
|
930
931
|
|
|
931
932
|
|
|
932
|
-
def
|
|
933
|
-
'''(INTERNAL) Get a C{(h, d, name)}
|
|
933
|
+
def _xyzhdlln4(xyz, height, datum, ll=None, **name): # in .cartesianBase, .nvectorBase
|
|
934
|
+
'''(INTERNAL) Get a C{(h, d, ll, name)} 4-tuple.
|
|
934
935
|
'''
|
|
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)
|
|
936
|
+
_x = _xattr
|
|
937
|
+
h = height or _x(xyz, height=None) or _x(xyz, h=None) or _x(ll, height=None)
|
|
938
|
+
d = datum or _x(xyz, datum=None) or _x(ll, datum=None)
|
|
939
|
+
return h, d, ll, _name__(name, _or_nameof=ll)
|
|
943
940
|
|
|
944
941
|
|
|
945
942
|
__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.11'
|
|
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}}.
|
|
@@ -493,15 +491,14 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
|
|
|
493
491
|
'''Compute the cross product of this and an other vector.
|
|
494
492
|
|
|
495
493
|
@arg other: The other vector (L{Vector3d}).
|
|
496
|
-
@kwarg raiser: Optional, L{CrossError} label if raised (C{str},
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
C{x}, C{y}, and C{z}.
|
|
494
|
+
@kwarg raiser: Optional, L{CrossError} label if raised (C{str}, non-L{NN}).
|
|
495
|
+
@kwarg eps0: Near-zero tolerance (C{scalar}), same units as C{x}, C{y} and
|
|
496
|
+
C{z}.
|
|
500
497
|
|
|
501
498
|
@return: Cross product (L{Vector3d}).
|
|
502
499
|
|
|
503
|
-
@raise CrossError: Zero or near-zero cross product and
|
|
504
|
-
|
|
500
|
+
@raise CrossError: Zero or near-zero cross product and if B{C{raiser}} and
|
|
501
|
+
L{crosserrors<pygeodesy.crosserrors>} are both C{True}.
|
|
505
502
|
|
|
506
503
|
@raise TypeError: Incompatible B{C{other}} C{type}.
|
|
507
504
|
'''
|
|
@@ -759,6 +756,11 @@ class Vector3dBase(_NamedBase): # sync __methods__ with .fsums.Fsum
|
|
|
759
756
|
'''
|
|
760
757
|
return _MODS.nvectorBase._N_vector_(*self.xyz, name=self.name)
|
|
761
758
|
|
|
759
|
+
def _other_cmp(self, other):
|
|
760
|
+
'''(INTERNAL) Return the value for comparison.
|
|
761
|
+
'''
|
|
762
|
+
return other if isscalar(other) else self.others(other).length
|
|
763
|
+
|
|
762
764
|
def others(self, *other, **name_other_up):
|
|
763
765
|
'''Refined class comparison.
|
|
764
766
|
|
pygeodesy/webmercator.py
CHANGED
|
@@ -36,7 +36,7 @@ from pygeodesy.utily import degrees90, degrees180
|
|
|
36
36
|
from math import atan, atanh, exp, radians, sin, tanh
|
|
37
37
|
|
|
38
38
|
__all__ = _ALL_LAZY.webmercator
|
|
39
|
-
__version__ = '24.
|
|
39
|
+
__version__ = '24.06.11'
|
|
40
40
|
|
|
41
41
|
# _FalseEasting = 0 # false Easting (C{meter})
|
|
42
42
|
# _FalseNorthing = 0 # false Northing (C{meter})
|
|
@@ -283,8 +283,8 @@ def parseWM(strWM, radius=R_MA, Wm=Wm, **name):
|
|
|
283
283
|
or C{None}.
|
|
284
284
|
@kwarg name: Optional C{B{name}=NN} (C{str}).
|
|
285
285
|
|
|
286
|
-
@return: The WM coordinate (B{C{Wm}}) or if B{
|
|
287
|
-
|
|
286
|
+
@return: The WM coordinate (B{C{Wm}}) or if C{B{Wm} is None}, an
|
|
287
|
+
L{EasNorRadius3Tuple}C{(easting, northing, radius)}.
|
|
288
288
|
|
|
289
289
|
@raise WebMercatorError: Invalid B{C{strWM}}.
|
|
290
290
|
'''
|
|
@@ -307,27 +307,25 @@ def parseWM(strWM, radius=R_MA, Wm=Wm, **name):
|
|
|
307
307
|
def toWm(latlon, lon=None, earth=R_MA, Wm=Wm, **name_Wm_kwds_radius):
|
|
308
308
|
'''Convert a lat-/longitude point to a WM coordinate.
|
|
309
309
|
|
|
310
|
-
@arg latlon: Latitude (C{degrees}) or an (ellipsoidal or
|
|
311
|
-
|
|
310
|
+
@arg latlon: Latitude (C{degrees}) or an (ellipsoidal or spherical)
|
|
311
|
+
geodetic C{LatLon} point.
|
|
312
312
|
@kwarg lon: Optional longitude (C{degrees} or C{None}).
|
|
313
|
-
@kwarg earth: Earth radius (C{meter}), datum or ellipsoid
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
@kwarg
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
@return: The WM coordinate (B{C{Wm}}) or if B{C{Wm}} is C{None} an
|
|
313
|
+
@kwarg earth: Earth radius (C{meter}), datum or ellipsoid (L{Datum},
|
|
314
|
+
L{a_f2Tuple}, L{Ellipsoid} or L{Ellipsoid2}), overridden
|
|
315
|
+
by B{C{latlon}}'s datum if present.
|
|
316
|
+
@kwarg Wm: Optional class to return the WM coordinate (L{Wm}) or C{None}.
|
|
317
|
+
@kwarg name_Wm_kwds_radius: Optional C{B{name}=NN} (C{str}), optional,
|
|
318
|
+
additional B{C{Wm}} keyword arguments, ignored if C{B{Wm} is
|
|
319
|
+
None} and DEPRECATED keyword argument C{B{radius}=earth},
|
|
320
|
+
use B{C{earth}}.
|
|
321
|
+
|
|
322
|
+
@return: The WM coordinate (B{C{Wm}}) or if C{B{Wm} is None}, an
|
|
325
323
|
L{EasNorRadius3Tuple}C{(easting, northing, radius)}.
|
|
326
324
|
|
|
327
|
-
@raise ValueError: If B{C{
|
|
328
|
-
scalar, if B{C{latlon}} is beyond
|
|
329
|
-
and L{pygeodesy.rangerrors}
|
|
330
|
-
|
|
325
|
+
@raise ValueError: If B{C{earth}} is invalid, if B{C{lon}} value is missing,
|
|
326
|
+
if B{C{latlon}} is not scalar, or if B{C{latlon}} is beyond
|
|
327
|
+
the valid WM range and L{rangerrrors<pygeodesy.rangerrors>}
|
|
328
|
+
is C{True}.
|
|
331
329
|
'''
|
|
332
330
|
name, kwds = _name2__(name_Wm_kwds_radius)
|
|
333
331
|
R, kwds = _xkwds_pop2(kwds, radius=earth)
|