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/latlonBase.py
CHANGED
|
@@ -10,7 +10,7 @@ u'''(INTERNAL) Base class L{LatLonBase} for all elliposiodal, spherical and N-ve
|
|
|
10
10
|
U{RhumbLine<https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1RhumbLine.html>} classes.
|
|
11
11
|
'''
|
|
12
12
|
|
|
13
|
-
from pygeodesy.basics import isstr, map1, _xinstanceof
|
|
13
|
+
from pygeodesy.basics import isstr, map1, _xinstanceof, _passarg
|
|
14
14
|
from pygeodesy.constants import EPS, EPS0, EPS1, EPS4, INT0, R_M, \
|
|
15
15
|
_EPSqrt as _TOL, _0_0, _0_5, _1_0, \
|
|
16
16
|
_360_0, _umod_360
|
|
@@ -28,14 +28,15 @@ from pygeodesy.errors import _AttributeError, IntersectionError, \
|
|
|
28
28
|
# flatPolar, _hartzell, haversine, isantipode, \
|
|
29
29
|
# _isequalTo, isnormal, normal, philam2n_xyz, \
|
|
30
30
|
# thomas_, vincentys # as _formy
|
|
31
|
+
# from pygeodesy.internals import _passarg # from .basics
|
|
31
32
|
from pygeodesy.interns import NN, _COMMASPACE_, _concentric_, _height_, \
|
|
32
33
|
_intersection_, _LatLon_, _m_, _negative_, \
|
|
33
34
|
_no_, _overlap_, _too_, _point_ # PYCHOK used!
|
|
34
|
-
# from pygeodesy.iters import PointsIter, points2 #
|
|
35
|
+
# from pygeodesy.iters import PointsIter, points2 # _MODS
|
|
35
36
|
# from pygeodesy.karney import Caps # _MODS
|
|
36
37
|
from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS
|
|
37
38
|
# from pygeodesy.ltp import Ltp, _xLtp # _MODS
|
|
38
|
-
from pygeodesy.named import _NamedBase, Fmt
|
|
39
|
+
from pygeodesy.named import _name2__, _NamedBase, Fmt
|
|
39
40
|
from pygeodesy.namedTuples import Bounds2Tuple, LatLon2Tuple, PhiLam2Tuple, \
|
|
40
41
|
Trilaterate5Tuple
|
|
41
42
|
# from pygeodesy.nvectorBase import _N_vector_ # _MODS
|
|
@@ -45,15 +46,17 @@ from pygeodesy.props import deprecated_method, Property, Property_RO, \
|
|
|
45
46
|
from pygeodesy.units import _isDegrees, _isRadius, Distance_, Lat, Lon, \
|
|
46
47
|
Height, Radius, Radius_, Scalar, Scalar_
|
|
47
48
|
from pygeodesy.utily import _unrollon, _unrollon3, _Wrap
|
|
48
|
-
from pygeodesy.vector2d import _circin6,
|
|
49
|
-
|
|
50
|
-
from pygeodesy.vector3d import nearestOn6, Vector3d
|
|
49
|
+
# from pygeodesy.vector2d import _circin6, Circin6Tuple, _circum3, circum4_, \
|
|
50
|
+
# Circum3Tuple, _radii11ABC # _MODS
|
|
51
|
+
# from pygeodesy.vector3d import nearestOn6, Vector3d # _MODS
|
|
51
52
|
|
|
52
53
|
from contextlib import contextmanager
|
|
53
54
|
from math import asin, cos, degrees, fabs, radians
|
|
54
55
|
|
|
55
56
|
__all__ = _ALL_LAZY.latlonBase
|
|
56
|
-
__version__ = '24.
|
|
57
|
+
__version__ = '24.06.07'
|
|
58
|
+
|
|
59
|
+
_formy = _MODS.into(formy=__name__)
|
|
57
60
|
|
|
58
61
|
|
|
59
62
|
class LatLonBase(_NamedBase):
|
|
@@ -66,7 +69,7 @@ class LatLonBase(_NamedBase):
|
|
|
66
69
|
_lat = 0 # latitude (C{degrees})
|
|
67
70
|
_lon = 0 # longitude (C{degrees})
|
|
68
71
|
|
|
69
|
-
def __init__(self, latlonh, lon=None, height=0,
|
|
72
|
+
def __init__(self, latlonh, lon=None, height=0, datum=None, **wrap_name):
|
|
70
73
|
'''New C{LatLon}.
|
|
71
74
|
|
|
72
75
|
@arg latlonh: Latitude (C{degrees} or DMS C{str} with N or S suffix) or
|
|
@@ -75,11 +78,11 @@ class LatLonBase(_NamedBase):
|
|
|
75
78
|
C(None), indicating B{C{latlonh}} is a C{LatLon}.
|
|
76
79
|
@kwarg height: Optional height above (or below) the earth surface
|
|
77
80
|
(C{meter}, conventionally).
|
|
78
|
-
@kwarg wrap: If C{True}, wrap or I{normalize} B{C{lat}} and B{C{lon}}
|
|
79
|
-
(C{bool}).
|
|
80
81
|
@kwarg datum: Optional datum (L{Datum}, L{Ellipsoid}, L{Ellipsoid2},
|
|
81
82
|
L{a_f2Tuple} or I{scalar} radius) or C{None}.
|
|
82
|
-
@kwarg
|
|
83
|
+
@kwarg wrap_name: Optional C{B{name}=NN} (C{str}) and optional keyword
|
|
84
|
+
argument C{B{wrap}=False}, if C{True}, wrap or I{normalize}
|
|
85
|
+
B{C{lat}} and B{C{lon}} (C{bool}).
|
|
83
86
|
|
|
84
87
|
@return: New instance (C{LatLon}).
|
|
85
88
|
|
|
@@ -90,12 +93,13 @@ class LatLonBase(_NamedBase):
|
|
|
90
93
|
|
|
91
94
|
@raise UnitError: Invalid B{C{lat}}, B{C{lon}} or B{C{height}}.
|
|
92
95
|
'''
|
|
93
|
-
|
|
94
|
-
|
|
96
|
+
w, n = self._wrap_name2(**wrap_name)
|
|
97
|
+
if n:
|
|
98
|
+
self.name = n
|
|
95
99
|
|
|
96
100
|
if lon is None:
|
|
97
|
-
lat, lon, height = _latlonheight3(latlonh, height,
|
|
98
|
-
elif
|
|
101
|
+
lat, lon, height = _latlonheight3(latlonh, height, w)
|
|
102
|
+
elif w:
|
|
99
103
|
lat, lon = _Wrap.latlonDMS2(latlonh, lon)
|
|
100
104
|
else:
|
|
101
105
|
lat = latlonh
|
|
@@ -125,8 +129,8 @@ class LatLonBase(_NamedBase):
|
|
|
125
129
|
|
|
126
130
|
@return: The antipodal point (C{LatLon}).
|
|
127
131
|
'''
|
|
128
|
-
a =
|
|
129
|
-
h =
|
|
132
|
+
a = _formy.antipode(*self.latlon)
|
|
133
|
+
h = self._heigHt(height)
|
|
130
134
|
return self.classof(*a, height=h)
|
|
131
135
|
|
|
132
136
|
@deprecated_method
|
|
@@ -134,7 +138,7 @@ class LatLonBase(_NamedBase):
|
|
|
134
138
|
'''DEPRECATED, use method C{boundsOf}.'''
|
|
135
139
|
return self.boundsOf(wide, tall, radius=radius)
|
|
136
140
|
|
|
137
|
-
def boundsOf(self, wide, tall, radius=R_M, height=None):
|
|
141
|
+
def boundsOf(self, wide, tall, radius=R_M, height=None, **name):
|
|
138
142
|
'''Return the SW and NE lat-/longitude of a great circle
|
|
139
143
|
bounding box centered at this location.
|
|
140
144
|
|
|
@@ -146,6 +150,7 @@ class LatLonBase(_NamedBase):
|
|
|
146
150
|
B{C{wide}} and B{C{tall}} are in C{degrees}.
|
|
147
151
|
@kwarg height: Height for C{latlonSW} and C{latlonNE} (C{meter}),
|
|
148
152
|
overriding the point's height.
|
|
153
|
+
@kwarg name: Optional C{B{name}=NN} (C{str}).
|
|
149
154
|
|
|
150
155
|
@return: A L{Bounds2Tuple}C{(latlonSW, latlonNE)}, the
|
|
151
156
|
lower-left and upper-right corner (C{LatLon}).
|
|
@@ -165,15 +170,15 @@ class LatLonBase(_NamedBase):
|
|
|
165
170
|
h = self._heigHt(height)
|
|
166
171
|
sw = self.classof(y - t, x - w, height=h)
|
|
167
172
|
ne = self.classof(y + t, x + w, height=h)
|
|
168
|
-
return Bounds2Tuple(sw, ne, name=self.name)
|
|
173
|
+
return Bounds2Tuple(sw, ne, name=self._name__(name))
|
|
169
174
|
|
|
170
175
|
def chordTo(self, other, height=None, wrap=False):
|
|
171
176
|
'''Compute the length of the chord through the earth between
|
|
172
177
|
this and an other point.
|
|
173
178
|
|
|
174
179
|
@arg other: The other point (C{LatLon}).
|
|
175
|
-
@kwarg height: Overriding height for both points (C{meter})
|
|
176
|
-
or C{None}
|
|
180
|
+
@kwarg height: Overriding height for both points (C{meter}),
|
|
181
|
+
or if C{None}, use each point's height.
|
|
177
182
|
@kwarg wrap: If C{True}, wrap or I{normalize} the B{C{other}}
|
|
178
183
|
point (C{bool}).
|
|
179
184
|
|
|
@@ -181,24 +186,25 @@ class LatLonBase(_NamedBase):
|
|
|
181
186
|
|
|
182
187
|
@raise TypeError: The B{C{other}} point is not C{LatLon}.
|
|
183
188
|
'''
|
|
184
|
-
def _v3d(ll):
|
|
185
|
-
t = ll.toEcef(height=height) # .toVector(Vector=
|
|
186
|
-
return
|
|
189
|
+
def _v3d(ll, V3d=_MODS.vector3d.Vector3d):
|
|
190
|
+
t = ll.toEcef(height=height) # .toVector(Vector=V3d)
|
|
191
|
+
return V3d(t.x, t.y, t.z)
|
|
187
192
|
|
|
188
193
|
p = self.others(other)
|
|
189
194
|
if wrap:
|
|
190
195
|
p = _Wrap.point(p)
|
|
191
196
|
return _v3d(self).minus(_v3d(p)).length
|
|
192
197
|
|
|
193
|
-
def circin6(self, point2, point3, eps=EPS4,
|
|
198
|
+
def circin6(self, point2, point3, eps=EPS4, **wrap_name):
|
|
194
199
|
'''Return the radius and center of the I{inscribed} aka I{In-}circle
|
|
195
200
|
of the (planar) triangle formed by this and two other points.
|
|
196
201
|
|
|
197
202
|
@arg point2: Second point (C{LatLon}).
|
|
198
203
|
@arg point3: Third point (C{LatLon}).
|
|
199
204
|
@kwarg eps: Tolerance for function L{pygeodesy.trilaterate3d2}.
|
|
200
|
-
@kwarg
|
|
201
|
-
|
|
205
|
+
@kwarg wrap_name: Optional C{B{name}=NN} (C{str}) and optional keyword
|
|
206
|
+
argument C{B{wrap}=False}, if C{True}, wrap or I{normalize}
|
|
207
|
+
the B{C{points}} (C{bool}).
|
|
202
208
|
|
|
203
209
|
@return: L{Circin6Tuple}C{(radius, center, deltas, cA, cB, cC)}. The
|
|
204
210
|
C{center} and contact points C{cA}, C{cB} and C{cC}, each an
|
|
@@ -225,12 +231,17 @@ class LatLonBase(_NamedBase):
|
|
|
225
231
|
<https://MathWorld.Wolfram.com/Incircle.html>} and U{Contact Triangle
|
|
226
232
|
<https://MathWorld.Wolfram.com/ContactTriangle.html>}.
|
|
227
233
|
'''
|
|
228
|
-
|
|
229
|
-
r, c, d, cA, cB, cC = _circin6(*cs, eps=eps, useZ=True, dLL3=True,
|
|
230
|
-
datum=self.datum) # PYCHOK unpack
|
|
231
|
-
return Circin6Tuple(r, c.toLatLon(), d, cA.toLatLon(), cB.toLatLon(), cC.toLatLon())
|
|
234
|
+
w, n = self._wrap_name2(**wrap_name)
|
|
232
235
|
|
|
233
|
-
|
|
236
|
+
with _toCartesian3(self, point2, point3, w) as cs:
|
|
237
|
+
m = _MODS.vector2d
|
|
238
|
+
r, c, d, A, B, C = m._circin6(*cs, eps=eps, useZ=True, dLL3=True,
|
|
239
|
+
datum=self.datum) # PYCHOK unpack
|
|
240
|
+
return m.Circin6Tuple(r, c.toLatLon(), d, A.toLatLon(),
|
|
241
|
+
B.toLatLon(),
|
|
242
|
+
C.toLatLon(), name=n)
|
|
243
|
+
|
|
244
|
+
def circum3(self, point2, point3, circum=True, eps=EPS4, **wrap_name):
|
|
234
245
|
'''Return the radius and center of the smallest circle I{through} or I{containing}
|
|
235
246
|
this and two other points.
|
|
236
247
|
|
|
@@ -239,8 +250,9 @@ class LatLonBase(_NamedBase):
|
|
|
239
250
|
@kwarg circum: If C{True} return the C{circumradius} and C{circumcenter},
|
|
240
251
|
always, ignoring the I{Meeus}' Type I case (C{bool}).
|
|
241
252
|
@kwarg eps: Tolerance for function L{pygeodesy.trilaterate3d2}.
|
|
242
|
-
@kwarg
|
|
243
|
-
|
|
253
|
+
@kwarg wrap_name: Optional C{B{name}=NN} (C{str}) and optional keyword
|
|
254
|
+
argument C{B{wrap}=False}, if C{True}, wrap or I{normalize}
|
|
255
|
+
the B{C{points}} (C{bool}).
|
|
244
256
|
|
|
245
257
|
@return: A L{Circum3Tuple}C{(radius, center, deltas)}. The C{center}, an
|
|
246
258
|
instance of this (sub-)class, is co-planar with this and the two
|
|
@@ -268,20 +280,24 @@ class LatLonBase(_NamedBase):
|
|
|
268
280
|
|
|
269
281
|
@see: Function L{pygeodesy.circum3} and methods L{circin6} and L{circum4_}.
|
|
270
282
|
'''
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
283
|
+
w, n = self._wrap_name2(**wrap_name)
|
|
284
|
+
|
|
285
|
+
with _toCartesian3(self, point2, point3, w, circum=circum) as cs:
|
|
286
|
+
m = _MODS.vector2d
|
|
287
|
+
r, c, d = m._circum3(*cs, circum=circum, eps=eps, useZ=True, dLL3=True, # XXX -3d2
|
|
288
|
+
clas=cs[0].classof, datum=self.datum) # PYCHOK unpack
|
|
289
|
+
return m.Circum3Tuple(r, c.toLatLon(), d, name=n)
|
|
275
290
|
|
|
276
|
-
def circum4_(self, *points, **
|
|
291
|
+
def circum4_(self, *points, **wrap_name):
|
|
277
292
|
'''Best-fit a sphere through this and two or more other points.
|
|
278
293
|
|
|
279
294
|
@arg points: The other points (each a C{LatLon}).
|
|
280
|
-
@kwarg
|
|
281
|
-
|
|
295
|
+
@kwarg wrap_name: Optional C{B{name}=NN} (C{str}) and optional keyword argument
|
|
296
|
+
C{B{wrap}=False}, if C{True}, wrap or I{normalize} the B{C{points}}
|
|
297
|
+
(C{bool}).
|
|
282
298
|
|
|
283
|
-
@return: L{Circum4Tuple}C{(radius, center, rank, residuals)} with C{center}
|
|
284
|
-
|
|
299
|
+
@return: L{Circum4Tuple}C{(radius, center, rank, residuals)} with C{center} an
|
|
300
|
+
instance of this (sub-)class.
|
|
285
301
|
|
|
286
302
|
@raise ImportError: Package C{numpy} not found, not installed or older than
|
|
287
303
|
version 1.10.
|
|
@@ -294,16 +310,18 @@ class LatLonBase(_NamedBase):
|
|
|
294
310
|
|
|
295
311
|
@see: Function L{pygeodesy.circum4_} and L{circum3}.
|
|
296
312
|
'''
|
|
297
|
-
|
|
298
|
-
|
|
313
|
+
w, n = self._wrap_name2(**wrap_name)
|
|
314
|
+
|
|
315
|
+
def _cs(ps, C, w):
|
|
316
|
+
_wp = _Wrap.point if w else _passarg
|
|
299
317
|
for i, p in enumerate(ps):
|
|
300
318
|
yield C(i=i, points=_wp(p))
|
|
301
319
|
|
|
302
|
-
C =
|
|
303
|
-
c =
|
|
304
|
-
t = circum4_(c, Vector=c.classof, *_cs(points, C,
|
|
305
|
-
c =
|
|
306
|
-
return t.dup(center=c)
|
|
320
|
+
C = self._toCartesianEcef
|
|
321
|
+
c = C(point=self)
|
|
322
|
+
t = _MODS.vector2d.circum4_(c, Vector=c.classof, *_cs(points, C, w))
|
|
323
|
+
c = t.center.toLatLon(LatLon=self.classof)
|
|
324
|
+
return t.dup(center=c, name=n)
|
|
307
325
|
|
|
308
326
|
@property
|
|
309
327
|
def clipid(self):
|
|
@@ -344,19 +362,19 @@ class LatLonBase(_NamedBase):
|
|
|
344
362
|
<https://www.EdWilliams.org/avform.htm#flat>}.
|
|
345
363
|
'''
|
|
346
364
|
p = self.others(other)
|
|
347
|
-
return
|
|
365
|
+
return _formy.compassAngle(self.lat, self.lon, p.lat, p.lon, **adjust_wrap)
|
|
348
366
|
|
|
349
|
-
def cosineAndoyerLambertTo(self, other, wrap
|
|
367
|
+
def cosineAndoyerLambertTo(self, other, **wrap):
|
|
350
368
|
'''Compute the distance between this and an other point using the U{Andoyer-Lambert correction<https://
|
|
351
369
|
navlib.net/wp-content/uploads/2013/10/admiralty-manual-of-navigation-vol-1-1964-english501c.pdf>}
|
|
352
370
|
of the U{Law of Cosines<https://www.Movable-Type.co.UK/scripts/latlong.html#cosine-law>} formula.
|
|
353
371
|
|
|
354
372
|
@arg other: The other point (C{LatLon}).
|
|
355
|
-
@kwarg wrap:
|
|
356
|
-
the B{C{other}} point (C{bool}).
|
|
373
|
+
@kwarg wrap: Optional keyword argument C{B{wrap}=False}, if C{True}, wrap
|
|
374
|
+
or I{normalize} and unroll the B{C{other}} point (C{bool}).
|
|
357
375
|
|
|
358
|
-
@return: Distance (C{meter}, same units as the axes of this
|
|
359
|
-
|
|
376
|
+
@return: Distance (C{meter}, same units as the axes of this point's datum
|
|
377
|
+
ellipsoid).
|
|
360
378
|
|
|
361
379
|
@raise TypeError: The B{C{other}} point is not C{LatLon}.
|
|
362
380
|
|
|
@@ -366,9 +384,9 @@ class LatLonBase(_NamedBase):
|
|
|
366
384
|
L{flatLocalTo}/L{hubenyTo}, L{flatPolarTo}, L{haversineTo},
|
|
367
385
|
L{thomasTo} and L{vincentysTo}.
|
|
368
386
|
'''
|
|
369
|
-
return self._distanceTo_(
|
|
387
|
+
return self._distanceTo_(_formy.cosineAndoyerLambert_, other, **wrap)
|
|
370
388
|
|
|
371
|
-
def cosineForsytheAndoyerLambertTo(self, other, wrap
|
|
389
|
+
def cosineForsytheAndoyerLambertTo(self, other, **wrap):
|
|
372
390
|
'''Compute the distance between this and an other point using
|
|
373
391
|
the U{Forsythe-Andoyer-Lambert correction
|
|
374
392
|
<https://www2.UNB.Ca/gge/Pubs/TR77.pdf>} of the U{Law of Cosines
|
|
@@ -376,11 +394,11 @@ class LatLonBase(_NamedBase):
|
|
|
376
394
|
formula.
|
|
377
395
|
|
|
378
396
|
@arg other: The other point (C{LatLon}).
|
|
379
|
-
@kwarg wrap:
|
|
380
|
-
the B{C{other}} point (C{bool}).
|
|
397
|
+
@kwarg wrap: Optional keyword argument C{B{wrap}=False}, if C{True}, wrap
|
|
398
|
+
or I{normalize} and unroll the B{C{other}} point (C{bool}).
|
|
381
399
|
|
|
382
|
-
@return: Distance (C{meter}, same units as the axes of
|
|
383
|
-
|
|
400
|
+
@return: Distance (C{meter}, same units as the axes of this point's datum
|
|
401
|
+
ellipsoid).
|
|
384
402
|
|
|
385
403
|
@raise TypeError: The B{C{other}} point is not C{LatLon}.
|
|
386
404
|
|
|
@@ -389,20 +407,19 @@ class LatLonBase(_NamedBase):
|
|
|
389
407
|
L{equirectangularTo}, L{euclideanTo}, L{flatLocalTo}/L{hubenyTo},
|
|
390
408
|
L{flatPolarTo}, L{haversineTo}, L{thomasTo} and L{vincentysTo}.
|
|
391
409
|
'''
|
|
392
|
-
return self._distanceTo_(
|
|
410
|
+
return self._distanceTo_(_formy.cosineForsytheAndoyerLambert_, other, **wrap)
|
|
393
411
|
|
|
394
|
-
def cosineLawTo(self, other, radius=None, wrap
|
|
412
|
+
def cosineLawTo(self, other, radius=None, **wrap):
|
|
395
413
|
'''Compute the distance between this and an other point using the
|
|
396
414
|
U{spherical Law of Cosines
|
|
397
415
|
<https://www.Movable-Type.co.UK/scripts/latlong.html#cosine-law>}
|
|
398
416
|
formula.
|
|
399
417
|
|
|
400
418
|
@arg other: The other point (C{LatLon}).
|
|
401
|
-
@kwarg radius: Mean earth radius (C{meter}) or C{None}
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
the B{C{other}} point (C{bool}).
|
|
419
|
+
@kwarg radius: Mean earth radius (C{meter}) or C{None} for the mean radius
|
|
420
|
+
of this point's datum ellipsoid.
|
|
421
|
+
@kwarg wrap: Optional keyword argument C{B{wrap}=False}, if C{True}, wrap
|
|
422
|
+
or I{normalize} and unroll the B{C{other}} point (C{bool}).
|
|
406
423
|
|
|
407
424
|
@return: Distance (C{meter}, same units as B{C{radius}}).
|
|
408
425
|
|
|
@@ -413,7 +430,7 @@ class LatLonBase(_NamedBase):
|
|
|
413
430
|
L{euclideanTo}, L{flatLocalTo}/L{hubenyTo}, L{flatPolarTo},
|
|
414
431
|
L{haversineTo}, L{thomasTo} and L{vincentysTo}.
|
|
415
432
|
'''
|
|
416
|
-
return self._distanceTo(
|
|
433
|
+
return self._distanceTo(_formy.cosineLaw, other, radius, **wrap)
|
|
417
434
|
|
|
418
435
|
@property_RO
|
|
419
436
|
def datum(self): # PYCHOK no cover
|
|
@@ -517,7 +534,7 @@ class LatLonBase(_NamedBase):
|
|
|
517
534
|
C{euclideanTo}, L{flatLocalTo}/L{hubenyTo}, L{flatPolarTo},
|
|
518
535
|
L{haversineTo}, L{thomasTo} and L{vincentysTo}.
|
|
519
536
|
'''
|
|
520
|
-
return self._distanceTo(
|
|
537
|
+
return self._distanceTo(_formy.equirectangular, other, **radius_adjust_limit_wrap)
|
|
521
538
|
|
|
522
539
|
def euclideanTo(self, other, **radius_adjust_wrap):
|
|
523
540
|
'''Approximate the C{Euclidian} distance between this and
|
|
@@ -539,20 +556,19 @@ class LatLonBase(_NamedBase):
|
|
|
539
556
|
L{equirectangularTo}, L{flatLocalTo}/L{hubenyTo}, L{flatPolarTo},
|
|
540
557
|
L{haversineTo}, L{thomasTo} and L{vincentysTo}.
|
|
541
558
|
'''
|
|
542
|
-
return self._distanceTo(
|
|
559
|
+
return self._distanceTo(_formy.euclidean, other, **radius_adjust_wrap)
|
|
543
560
|
|
|
544
|
-
def flatLocalTo(self, other, radius=None, wrap
|
|
561
|
+
def flatLocalTo(self, other, radius=None, **wrap):
|
|
545
562
|
'''Compute the distance between this and an other point using the
|
|
546
563
|
U{ellipsoidal Earth to plane projection
|
|
547
564
|
<https://WikiPedia.org/wiki/Geographical_distance#Ellipsoidal_Earth_projected_to_a_plane>}
|
|
548
565
|
aka U{Hubeny<https://www.OVG.AT/de/vgi/files/pdf/3781/>} formula.
|
|
549
566
|
|
|
550
567
|
@arg other: The other point (C{LatLon}).
|
|
551
|
-
@kwarg radius: Mean earth radius (C{meter}) or C{None} for
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
the B{C{other}} point (C{bool}).
|
|
568
|
+
@kwarg radius: Mean earth radius (C{meter}) or C{None} for the I{equatorial
|
|
569
|
+
radius} of this point's datum ellipsoid.
|
|
570
|
+
@kwarg wrap: Optional keyword argument C{B{wrap}=False}, if C{True}, wrap
|
|
571
|
+
or I{normalize} and unroll the B{C{other}} point (C{bool}).
|
|
556
572
|
|
|
557
573
|
@return: Distance (C{meter}, same units as B{C{radius}}).
|
|
558
574
|
|
|
@@ -566,8 +582,8 @@ class LatLonBase(_NamedBase):
|
|
|
566
582
|
L{flatPolarTo}, L{haversineTo}, L{thomasTo} and L{vincentysTo} and
|
|
567
583
|
U{local, flat Earth approximation<https://www.edwilliams.org/avform.htm#flat>}.
|
|
568
584
|
'''
|
|
569
|
-
|
|
570
|
-
|
|
585
|
+
r = radius if radius in (None, R_M, _1_0, 1) else Radius(radius)
|
|
586
|
+
return self._distanceTo_(_formy.flatLocal_, other, radius=r, **wrap) # PYCHOK kwargs
|
|
571
587
|
|
|
572
588
|
hubenyTo = flatLocalTo # for Karl Hubeny
|
|
573
589
|
|
|
@@ -591,14 +607,7 @@ class LatLonBase(_NamedBase):
|
|
|
591
607
|
L{equirectangularTo}, L{euclideanTo}, L{flatLocalTo}/L{hubenyTo},
|
|
592
608
|
L{haversineTo}, L{thomasTo} and L{vincentysTo}.
|
|
593
609
|
'''
|
|
594
|
-
return self._distanceTo(
|
|
595
|
-
|
|
596
|
-
@property_RO
|
|
597
|
-
def _formy(self):
|
|
598
|
-
'''(INTERNAL) Get module C{formy}, I{once}.
|
|
599
|
-
'''
|
|
600
|
-
LatLonBase._formy = f = _MODS.formy # overwrite property_RO
|
|
601
|
-
return f
|
|
610
|
+
return self._distanceTo(_formy.flatPolar, other, **radius_wrap)
|
|
602
611
|
|
|
603
612
|
def hartzell(self, los=False, earth=None):
|
|
604
613
|
'''Compute the intersection of a Line-Of-Sight from this (geodetic) Point-Of-View
|
|
@@ -622,7 +631,7 @@ class LatLonBase(_NamedBase):
|
|
|
622
631
|
|
|
623
632
|
@see: Function L{hartzell<pygeodesy.formy.hartzell>} for further details.
|
|
624
633
|
'''
|
|
625
|
-
return
|
|
634
|
+
return _formy._hartzell(self, los, earth, LatLon=self.classof)
|
|
626
635
|
|
|
627
636
|
def haversineTo(self, other, **radius_wrap):
|
|
628
637
|
'''Compute the distance between this and an other point using the
|
|
@@ -644,7 +653,7 @@ class LatLonBase(_NamedBase):
|
|
|
644
653
|
L{equirectangularTo}, L{euclideanTo}, L{flatLocalTo}/L{hubenyTo},
|
|
645
654
|
L{flatPolarTo}, L{thomasTo} and L{vincentysTo}.
|
|
646
655
|
'''
|
|
647
|
-
return self._distanceTo(
|
|
656
|
+
return self._distanceTo(_formy.haversine, other, **radius_wrap)
|
|
648
657
|
|
|
649
658
|
def _havg(self, other, f=_0_5, h=None):
|
|
650
659
|
'''(INTERNAL) Weighted, average height.
|
|
@@ -779,13 +788,13 @@ class LatLonBase(_NamedBase):
|
|
|
779
788
|
tolerance, C{False} otherwise.
|
|
780
789
|
'''
|
|
781
790
|
p = self.others(other)
|
|
782
|
-
return
|
|
791
|
+
return _formy.isantipode(*(self.latlon + p.latlon), eps=eps)
|
|
783
792
|
|
|
784
793
|
@Property_RO
|
|
785
794
|
def isEllipsoidal(self):
|
|
786
795
|
'''Check whether this point is ellipsoidal (C{bool} or C{None} if unknown).
|
|
787
796
|
'''
|
|
788
|
-
return self.datum
|
|
797
|
+
return _xattr(self.datum, isEllipsoidal=None)
|
|
789
798
|
|
|
790
799
|
def isequalTo(self, other, eps=None):
|
|
791
800
|
'''Compare this point with an other point, I{ignoring} height.
|
|
@@ -804,7 +813,7 @@ class LatLonBase(_NamedBase):
|
|
|
804
813
|
|
|
805
814
|
@see: Method L{isequalTo3}.
|
|
806
815
|
'''
|
|
807
|
-
return
|
|
816
|
+
return _formy._isequalTo(self, self.others(other), eps=eps)
|
|
808
817
|
|
|
809
818
|
def isequalTo3(self, other, eps=None):
|
|
810
819
|
'''Compare this point with an other point, I{including} height.
|
|
@@ -822,7 +831,7 @@ class LatLonBase(_NamedBase):
|
|
|
822
831
|
@see: Method L{isequalTo}.
|
|
823
832
|
'''
|
|
824
833
|
return self.height == self.others(other).height and \
|
|
825
|
-
|
|
834
|
+
_formy._isequalTo(self, other, eps=eps)
|
|
826
835
|
|
|
827
836
|
@Property_RO
|
|
828
837
|
def isnormal(self):
|
|
@@ -832,13 +841,13 @@ class LatLonBase(_NamedBase):
|
|
|
832
841
|
@see: Methods L{normal}, L{toNormal} and functions L{isnormal
|
|
833
842
|
<pygeodesy.isnormal>} and L{normal<pygeodesy.normal>}.
|
|
834
843
|
'''
|
|
835
|
-
return
|
|
844
|
+
return _formy.isnormal(self.lat, self.lon, eps=0)
|
|
836
845
|
|
|
837
846
|
@Property_RO
|
|
838
847
|
def isSpherical(self):
|
|
839
848
|
'''Check whether this point is spherical (C{bool} or C{None} if unknown).
|
|
840
849
|
'''
|
|
841
|
-
return self.datum
|
|
850
|
+
return _xattr(self.datum, isSpherical=None)
|
|
842
851
|
|
|
843
852
|
@Property_RO
|
|
844
853
|
def lam(self):
|
|
@@ -953,18 +962,11 @@ class LatLonBase(_NamedBase):
|
|
|
953
962
|
_update_all(self)
|
|
954
963
|
self._lon = lon
|
|
955
964
|
|
|
956
|
-
@property_RO
|
|
957
|
-
def _ltp(self):
|
|
958
|
-
'''(INTERNAL) Get the C{.ltp} module, I{once}.
|
|
959
|
-
'''
|
|
960
|
-
LatLonBase._ltp = m = _MODS.ltp # overwrite property_RO
|
|
961
|
-
return m
|
|
962
|
-
|
|
963
965
|
@Property_RO
|
|
964
966
|
def _Ltp(self):
|
|
965
967
|
'''(INTERNAL) Cache for L{toLtp}.
|
|
966
968
|
'''
|
|
967
|
-
return
|
|
969
|
+
return _MODS.ltp.Ltp(self, ecef=self.Ecef(self.datum), name=self.name)
|
|
968
970
|
|
|
969
971
|
def nearestOn6(self, points, closed=False, height=None, wrap=False):
|
|
970
972
|
'''Locate the point on a path or polygon closest to this point.
|
|
@@ -1007,8 +1009,8 @@ class LatLonBase(_NamedBase):
|
|
|
1007
1009
|
C = self._toCartesianEcef # to verify datum and Ecef
|
|
1008
1010
|
Ps = self.PointsIter(points, wrap=wrap)
|
|
1009
1011
|
|
|
1010
|
-
c =
|
|
1011
|
-
t = nearestOn6(c, _cs(Ps, height, wrap, C), closed=closed)
|
|
1012
|
+
c = C(height=height, this=self) # this Cartesian
|
|
1013
|
+
t = _MODS.vector3d.nearestOn6(c, _cs(Ps, height, wrap, C), closed=closed)
|
|
1012
1014
|
c, s, e = t.closest, t.start, t.end
|
|
1013
1015
|
|
|
1014
1016
|
kwds = _xkwds_not(None, LatLon=self.classof, # this LatLon
|
|
@@ -1034,21 +1036,21 @@ class LatLonBase(_NamedBase):
|
|
|
1034
1036
|
'''
|
|
1035
1037
|
n = self.isnormal
|
|
1036
1038
|
if not n:
|
|
1037
|
-
self.latlon =
|
|
1039
|
+
self.latlon = _formy.normal(*self.latlon)
|
|
1038
1040
|
return n
|
|
1039
1041
|
|
|
1040
1042
|
@property_RO
|
|
1041
1043
|
def _N_vector(self):
|
|
1042
1044
|
'''(INTERNAL) Get the C{Nvector} (C{nvectorBase._N_vector_})
|
|
1043
1045
|
'''
|
|
1044
|
-
|
|
1045
|
-
return
|
|
1046
|
+
_N = _MODS.nvectorBase._N_vector_
|
|
1047
|
+
return _N(*self._n_xyz3, h=self.height, name=self.name)
|
|
1046
1048
|
|
|
1047
1049
|
@Property_RO
|
|
1048
1050
|
def _n_xyz3(self):
|
|
1049
1051
|
'''(INTERNAL) Get the n-vector components as L{Vector3Tuple}.
|
|
1050
1052
|
'''
|
|
1051
|
-
return
|
|
1053
|
+
return _formy.philam2n_xyz(self.phi, self.lam, name=self.name)
|
|
1052
1054
|
|
|
1053
1055
|
@Property_RO
|
|
1054
1056
|
def phi(self):
|
|
@@ -1083,9 +1085,9 @@ class LatLonBase(_NamedBase):
|
|
|
1083
1085
|
return self.philam.to3Tuple(self.height)
|
|
1084
1086
|
|
|
1085
1087
|
@deprecated_method
|
|
1086
|
-
def points(self, points, closed
|
|
1088
|
+
def points(self, points, **closed): # PYCHOK no cover
|
|
1087
1089
|
'''DEPRECATED, use method L{points2}.'''
|
|
1088
|
-
return self.points2(points, closed
|
|
1090
|
+
return self.points2(points, **closed)
|
|
1089
1091
|
|
|
1090
1092
|
def points2(self, points, closed=True):
|
|
1091
1093
|
'''Check a path or polygon represented by points.
|
|
@@ -1109,7 +1111,7 @@ class LatLonBase(_NamedBase):
|
|
|
1109
1111
|
|
|
1110
1112
|
@arg points: The path or polygon points (C{LatLon}[])
|
|
1111
1113
|
@kwarg loop: Number of loop-back points (non-negative C{int}).
|
|
1112
|
-
@kwarg dedup:
|
|
1114
|
+
@kwarg dedup: If C{True}, skip duplicate points (C{bool}).
|
|
1113
1115
|
@kwarg wrap: If C{True}, wrap or I{normalize} the
|
|
1114
1116
|
enum-/iterated B{C{points}} (C{bool}).
|
|
1115
1117
|
|
|
@@ -1117,7 +1119,8 @@ class LatLonBase(_NamedBase):
|
|
|
1117
1119
|
|
|
1118
1120
|
@raise PointsError: Insufficient number of B{C{points}}.
|
|
1119
1121
|
'''
|
|
1120
|
-
return PointsIter(points, base=self, loop=loop,
|
|
1122
|
+
return _MODS.iters.PointsIter(points, base=self, loop=loop,
|
|
1123
|
+
dedup=dedup, wrap=wrap)
|
|
1121
1124
|
|
|
1122
1125
|
def radii11(self, point2, point3, wrap=False):
|
|
1123
1126
|
'''Return the radii of the C{Circum-}, C{In-}, I{Soddy} and C{Tangent}
|
|
@@ -1140,7 +1143,7 @@ class LatLonBase(_NamedBase):
|
|
|
1140
1143
|
Circles<https://MathWorld.Wolfram.com/TangentCircles.html>}.
|
|
1141
1144
|
'''
|
|
1142
1145
|
with _toCartesian3(self, point2, point3, wrap) as cs:
|
|
1143
|
-
return _radii11ABC(*cs, useZ=True)[0]
|
|
1146
|
+
return _MODS.vector2d._radii11ABC(*cs, useZ=True)[0]
|
|
1144
1147
|
|
|
1145
1148
|
def _rhumb3(self, exact, radius): # != .sphericalBase._rhumbs3
|
|
1146
1149
|
'''(INTERNAL) Get the C{rhumb} for this point's datum or for
|
|
@@ -1157,14 +1160,14 @@ class LatLonBase(_NamedBase):
|
|
|
1157
1160
|
except AttributeError as x:
|
|
1158
1161
|
raise _AttributeError(datum=D, radius=radius, cause=x)
|
|
1159
1162
|
t = r, D, _MODS.karney.Caps
|
|
1160
|
-
|
|
1161
|
-
d.
|
|
1163
|
+
if len(d) > 2:
|
|
1164
|
+
d.clear() # d[:] = {}
|
|
1162
1165
|
d[(exact, radius)] = t # cache 3-tuple
|
|
1163
1166
|
return t
|
|
1164
1167
|
|
|
1165
1168
|
@Property_RO
|
|
1166
|
-
def _rhumb3dict(self): # in
|
|
1167
|
-
return {} #
|
|
1169
|
+
def _rhumb3dict(self): # in ._update
|
|
1170
|
+
return {} # 3-item cache
|
|
1168
1171
|
|
|
1169
1172
|
def rhumbAzimuthTo(self, other, exact=False, radius=None, wrap=False, b360=False):
|
|
1170
1173
|
'''Return the azimuth (bearing) of a rhumb line (loxodrome) between this
|
|
@@ -1178,9 +1181,10 @@ class LatLonBase(_NamedBase):
|
|
|
1178
1181
|
this point's datum.
|
|
1179
1182
|
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll the B{C{other}}
|
|
1180
1183
|
point (C{bool}).
|
|
1181
|
-
@kwarg b360: If C{True}, return the azimuth
|
|
1184
|
+
@kwarg b360: If C{True}, return the azimuth as bearing in compass
|
|
1185
|
+
degrees (C{bool}).
|
|
1182
1186
|
|
|
1183
|
-
@return: Rhumb azimuth (
|
|
1187
|
+
@return: Rhumb azimuth (C{degrees180} or compass C{degrees360}).
|
|
1184
1188
|
|
|
1185
1189
|
@raise TypeError: The B{C{other}} point is incompatible or B{C{radius}}
|
|
1186
1190
|
is invalid.
|
|
@@ -1189,19 +1193,21 @@ class LatLonBase(_NamedBase):
|
|
|
1189
1193
|
z = r._Inverse(self, other, wrap, outmask=Cs.AZIMUTH).azi12
|
|
1190
1194
|
return _umod_360(z + _360_0) if b360 else z
|
|
1191
1195
|
|
|
1192
|
-
def rhumbDestination(self, distance, azimuth,
|
|
1196
|
+
def rhumbDestination(self, distance, azimuth, radius=None, height=None,
|
|
1197
|
+
exact=False, **name):
|
|
1193
1198
|
'''Return the destination point having travelled the given distance from
|
|
1194
1199
|
this point along a rhumb line (loxodrome) of the given azimuth.
|
|
1195
1200
|
|
|
1196
1201
|
@arg distance: Distance travelled (C{meter}, same units as this point's
|
|
1197
1202
|
datum (ellipsoid) axes or B{C{radius}}, may be negative.
|
|
1198
1203
|
@arg azimuth: Azimuth (bearing) of the rhumb line (compass C{degrees}).
|
|
1199
|
-
@kwarg exact: Exact C{Rhumb...} to use (C{bool} or C{Rhumb...}), see
|
|
1200
|
-
method L{Ellipsoid.rhumb_}.
|
|
1201
1204
|
@kwarg radius: Optional earth radius (C{meter}) or earth model (L{Datum},
|
|
1202
1205
|
L{Ellipsoid}, L{Ellipsoid2} or L{a_f2Tuple}), overriding
|
|
1203
1206
|
this point's datum.
|
|
1204
1207
|
@kwarg height: Optional height, overriding the default height (C{meter}).
|
|
1208
|
+
@kwarg exact: Exact C{Rhumb...} to use (C{bool} or C{Rhumb...}), see
|
|
1209
|
+
method L{Ellipsoid.rhumb_}.
|
|
1210
|
+
@kwarg name: Optional C{B{name}=NN} (C{str}).
|
|
1205
1211
|
|
|
1206
1212
|
@return: The destination point (ellipsoidal C{LatLon}).
|
|
1207
1213
|
|
|
@@ -1213,7 +1219,7 @@ class LatLonBase(_NamedBase):
|
|
|
1213
1219
|
r, D, _ = self._rhumb3(exact, radius)
|
|
1214
1220
|
d = r._Direct(self, azimuth, distance)
|
|
1215
1221
|
h = self._heigHt(height)
|
|
1216
|
-
return self.classof(d.lat2, d.lon2, datum=D, height=h)
|
|
1222
|
+
return self.classof(d.lat2, d.lon2, datum=D, height=h, **name)
|
|
1217
1223
|
|
|
1218
1224
|
def rhumbDistanceTo(self, other, exact=False, radius=None, wrap=False):
|
|
1219
1225
|
'''Return the distance from this to an other point along a rhumb line
|
|
@@ -1283,7 +1289,6 @@ class LatLonBase(_NamedBase):
|
|
|
1283
1289
|
|
|
1284
1290
|
return self._intersecend2(p, other, w, height, rl.rhumb, P, Q,
|
|
1285
1291
|
self.rhumbIntersecant2)
|
|
1286
|
-
|
|
1287
1292
|
except (TypeError, ValueError) as x:
|
|
1288
1293
|
raise _xError(x, center=self, circle=circle, point=point, other=other,
|
|
1289
1294
|
**exact_radius_wrap_eps_tol)
|
|
@@ -1318,7 +1323,7 @@ class LatLonBase(_NamedBase):
|
|
|
1318
1323
|
return rl
|
|
1319
1324
|
|
|
1320
1325
|
def rhumbMidpointTo(self, other, exact=False, radius=None,
|
|
1321
|
-
height=None, fraction=_0_5,
|
|
1326
|
+
height=None, fraction=_0_5, **wrap_name):
|
|
1322
1327
|
'''Return the (loxodromic) midpoint on the rhumb line between this and
|
|
1323
1328
|
an other point.
|
|
1324
1329
|
|
|
@@ -1332,8 +1337,9 @@ class LatLonBase(_NamedBase):
|
|
|
1332
1337
|
@kwarg fraction: Midpoint location from this point (C{scalar}), 0 for this,
|
|
1333
1338
|
1 for the B{C{other}}, 0.5 for halfway between this and
|
|
1334
1339
|
the B{C{other}} point, may be negative or greater than 1.
|
|
1335
|
-
@kwarg
|
|
1336
|
-
|
|
1340
|
+
@kwarg wrap_name: Optional C{B{name}=NN} (C{str}) and optional keyword
|
|
1341
|
+
argument C{B{wrap}=False}, if C{True}, wrap or I{normalize}
|
|
1342
|
+
and unroll the B{C{other}} point (C{bool}).
|
|
1337
1343
|
|
|
1338
1344
|
@return: The midpoint at the given B{C{fraction}} along the rhumb line
|
|
1339
1345
|
(this C{LatLon}).
|
|
@@ -1343,12 +1349,13 @@ class LatLonBase(_NamedBase):
|
|
|
1343
1349
|
|
|
1344
1350
|
@raise ValueError: Invalid B{C{height}} or B{C{fraction}}.
|
|
1345
1351
|
'''
|
|
1352
|
+
w, n = self._wrap_name2(**wrap_name)
|
|
1346
1353
|
r, D, _ = self._rhumb3(exact, radius)
|
|
1347
1354
|
f = Scalar(fraction=fraction)
|
|
1348
|
-
d = r._Inverse(self, self.others(other),
|
|
1355
|
+
d = r._Inverse(self, self.others(other), w) # C.AZIMUTH_DISTANCE
|
|
1349
1356
|
d = r._Direct( self, d.azi12, d.s12 * f)
|
|
1350
1357
|
h = self._havg(other, f=f, h=height)
|
|
1351
|
-
return self.classof(d.lat2, d.lon2, datum=D, height=h)
|
|
1358
|
+
return self.classof(d.lat2, d.lon2, datum=D, height=h, name=n)
|
|
1352
1359
|
|
|
1353
1360
|
@property_RO
|
|
1354
1361
|
def sphericalLatLon(self):
|
|
@@ -1356,17 +1363,16 @@ class LatLonBase(_NamedBase):
|
|
|
1356
1363
|
'''
|
|
1357
1364
|
return False
|
|
1358
1365
|
|
|
1359
|
-
def thomasTo(self, other, wrap
|
|
1360
|
-
'''Compute the distance between this and an other point using
|
|
1361
|
-
|
|
1362
|
-
formula.
|
|
1366
|
+
def thomasTo(self, other, **wrap):
|
|
1367
|
+
'''Compute the distance between this and an other point using U{Thomas'
|
|
1368
|
+
<https://apps.DTIC.mil/dtic/tr/fulltext/u2/703541.pdf>} formula.
|
|
1363
1369
|
|
|
1364
1370
|
@arg other: The other point (C{LatLon}).
|
|
1365
|
-
@kwarg wrap:
|
|
1366
|
-
the B{C{other}} point (C{bool}).
|
|
1371
|
+
@kwarg wrap: Optional keyword argument C{B{wrap}=False}, if C{True}, wrap
|
|
1372
|
+
or I{normalize} and unroll the B{C{other}} point (C{bool}).
|
|
1367
1373
|
|
|
1368
|
-
@return: Distance (C{meter}, same units as the axes of
|
|
1369
|
-
|
|
1374
|
+
@return: Distance (C{meter}, same units as the axes of this point's datum
|
|
1375
|
+
ellipsoid).
|
|
1370
1376
|
|
|
1371
1377
|
@raise TypeError: The B{C{other}} point is not C{LatLon}.
|
|
1372
1378
|
|
|
@@ -1375,7 +1381,7 @@ class LatLonBase(_NamedBase):
|
|
|
1375
1381
|
L{equirectangularTo}, L{euclideanTo}, L{flatLocalTo}/L{hubenyTo},
|
|
1376
1382
|
L{flatPolarTo}, L{haversineTo} and L{vincentysTo}.
|
|
1377
1383
|
'''
|
|
1378
|
-
return self._distanceTo_(
|
|
1384
|
+
return self._distanceTo_(_formy.thomas_, other, **wrap)
|
|
1379
1385
|
|
|
1380
1386
|
@deprecated_method
|
|
1381
1387
|
def to2ab(self): # PYCHOK no cover
|
|
@@ -1404,7 +1410,7 @@ class LatLonBase(_NamedBase):
|
|
|
1404
1410
|
'''
|
|
1405
1411
|
r = self._ecef9 if height is None else self.toEcef(height=height)
|
|
1406
1412
|
if Cartesian is not None: # class or .classof
|
|
1407
|
-
r = Cartesian(r, **
|
|
1413
|
+
r = Cartesian(r, **self._name1__(Cartesian_kwds))
|
|
1408
1414
|
_xdatum(r.datum, self.datum)
|
|
1409
1415
|
return r
|
|
1410
1416
|
|
|
@@ -1452,30 +1458,28 @@ class LatLonBase(_NamedBase):
|
|
|
1452
1458
|
def toLocal(self, Xyz=None, ltp=None, **Xyz_kwds):
|
|
1453
1459
|
'''Convert this I{geodetic} point to I{local} C{X}, C{Y} and C{Z}.
|
|
1454
1460
|
|
|
1455
|
-
@kwarg Xyz: Optional class to return C{X}, C{Y} and C{Z}
|
|
1456
|
-
|
|
1457
|
-
@kwarg ltp: The I{local tangent plane} (LTP) to use,
|
|
1458
|
-
|
|
1459
|
-
@kwarg Xyz_kwds: Optional, additional B{C{Xyz}} keyword
|
|
1460
|
-
|
|
1461
|
+
@kwarg Xyz: Optional class to return C{X}, C{Y} and C{Z} (L{XyzLocal},
|
|
1462
|
+
L{Enu}, L{Ned}) or C{None}.
|
|
1463
|
+
@kwarg ltp: The I{local tangent plane} (LTP) to use, overriding this
|
|
1464
|
+
point's LTP (L{Ltp}).
|
|
1465
|
+
@kwarg Xyz_kwds: Optional, additional B{C{Xyz}} keyword arguments,
|
|
1466
|
+
ignored if C{B{Xyz} is None}.
|
|
1461
1467
|
|
|
1462
|
-
@return: An B{C{Xyz}} instance or
|
|
1463
|
-
|
|
1464
|
-
ltp, ecef, M)} with C{M=None}, always.
|
|
1468
|
+
@return: An B{C{Xyz}} instance or a L{Local9Tuple}C{(x, y, z, lat, lon,
|
|
1469
|
+
height, ltp, ecef, M)} if C{B{Xyz} is None} (with C{M=None}).
|
|
1465
1470
|
|
|
1466
1471
|
@raise TypeError: Invalid B{C{ltp}}.
|
|
1467
1472
|
'''
|
|
1468
|
-
|
|
1469
|
-
return p._ecef2local(self._ecef9, Xyz, Xyz_kwds)
|
|
1473
|
+
return _MODS.ltp._toLocal(self, ltp, Xyz, Xyz_kwds) # self._ecef9
|
|
1470
1474
|
|
|
1471
|
-
def toLtp(self, Ecef=None):
|
|
1475
|
+
def toLtp(self, Ecef=None, **name):
|
|
1472
1476
|
'''Return the I{local tangent plane} (LTP) for this point.
|
|
1473
1477
|
|
|
1474
1478
|
@kwarg Ecef: Optional ECEF I{class} (L{EcefKarney}, ...
|
|
1475
1479
|
L{EcefYou}), overriding this point's C{Ecef}.
|
|
1480
|
+
@kwarg name: Optional C{B{name}=NN} (C{str}).
|
|
1476
1481
|
'''
|
|
1477
|
-
return self
|
|
1478
|
-
self, ecef=Ecef(self.datum), name=self.name)
|
|
1482
|
+
return _MODS.ltp._toLtp(self, Ecef, self, name) # self._Ltp
|
|
1479
1483
|
|
|
1480
1484
|
def toNormal(self, deep=False, **name):
|
|
1481
1485
|
'''Get this point I{normalized} to C{abs(lat) <= 90}
|
|
@@ -1497,30 +1501,34 @@ class LatLonBase(_NamedBase):
|
|
|
1497
1501
|
ll.rename(name)
|
|
1498
1502
|
return ll
|
|
1499
1503
|
|
|
1500
|
-
def toNvector(self, h=None, Nvector=None, **
|
|
1504
|
+
def toNvector(self, h=None, Nvector=None, **name_Nvector_kwds):
|
|
1501
1505
|
'''Convert this point to C{n-vector} (normal to the earth's surface)
|
|
1502
1506
|
components, I{including height}.
|
|
1503
1507
|
|
|
1504
1508
|
@kwarg h: Optional height, overriding this point's height (C{meter}).
|
|
1505
1509
|
@kwarg Nvector: Optional class to return the C{n-vector} components
|
|
1506
1510
|
(C{Nvector}) or C{None}.
|
|
1507
|
-
@kwarg
|
|
1508
|
-
|
|
1511
|
+
@kwarg name_Nvector_kwds: Optional C{B{name}=NN} (C{str}) and optional,
|
|
1512
|
+
additional B{C{Nvector}} keyword arguments, ignored if
|
|
1513
|
+
C{B{Nvector} is None}.
|
|
1509
1514
|
|
|
1510
1515
|
@return: An B{C{Nvector}} or a L{Vector4Tuple}C{(x, y, z, h)} if
|
|
1511
1516
|
B{C{Nvector}} is C{None}.
|
|
1512
1517
|
|
|
1513
|
-
@raise TypeError: Invalid B{C{h}}, B{C{Nvector}} or
|
|
1514
|
-
item.
|
|
1518
|
+
@raise TypeError: Invalid B{C{h}}, B{C{Nvector}} or
|
|
1519
|
+
B{C{name_Nvector_kwds}} item.
|
|
1515
1520
|
|
|
1516
1521
|
@see: Methods C{toCartesian}, C{toVector} and C{toVector3d}.
|
|
1517
1522
|
'''
|
|
1518
1523
|
h = self._heigHt(h)
|
|
1519
1524
|
if Nvector is None:
|
|
1520
1525
|
r = self._n_xyz3.to4Tuple(h)
|
|
1526
|
+
n, _ = _name2__(name_Nvector_kwds, _or_nameof=self)
|
|
1527
|
+
if n:
|
|
1528
|
+
r.rename(n)
|
|
1521
1529
|
else:
|
|
1522
1530
|
x, y, z = self._n_xyz3
|
|
1523
|
-
r = Nvector(x, y, z, h=h, ll=self, **
|
|
1531
|
+
r = Nvector(x, y, z, h=h, ll=self, **self._name1__(name_Nvector_kwds))
|
|
1524
1532
|
return r
|
|
1525
1533
|
|
|
1526
1534
|
def toStr(self, form=F_DMS, joined=_COMMASPACE_, m=_m_, **prec_sep_s_D_M_S): # PYCHOK expected
|
|
@@ -1561,29 +1569,29 @@ class LatLonBase(_NamedBase):
|
|
|
1561
1569
|
@kwarg Vector_kwds: Optional, additional B{C{Vector}} keyword
|
|
1562
1570
|
arguments, ignored if C{B{Vector} is None}.
|
|
1563
1571
|
|
|
1564
|
-
@return: A B{C{Vector}} or
|
|
1565
|
-
|
|
1572
|
+
@return: A named B{C{Vector}} or if B{C{Vector}} is C{None} a
|
|
1573
|
+
named L{Vector3Tuple}C{(x, y, z)}.
|
|
1566
1574
|
|
|
1567
1575
|
@raise TypeError: Invalid B{C{Vector}} or B{C{Vector_kwds}} item.
|
|
1568
1576
|
|
|
1569
1577
|
@see: Methods C{toCartesian}, C{toNvector} and C{toVector3d}.
|
|
1570
1578
|
'''
|
|
1571
|
-
return self._ecef9.toVector(Vector=Vector, **Vector_kwds)
|
|
1579
|
+
return self._ecef9.toVector(Vector=Vector, **self._name1__(Vector_kwds))
|
|
1572
1580
|
|
|
1573
1581
|
def toVector3d(self, norm=True, **Vector3d_kwds):
|
|
1574
|
-
'''Convert this point to a L{Vector3d} with the I{geocentric} C{(x,
|
|
1575
|
-
|
|
1582
|
+
'''Convert this point to a L{Vector3d} with the I{geocentric} C{(x, y,
|
|
1583
|
+
z)} (ECEF) coordinates, I{ignoring height}.
|
|
1576
1584
|
|
|
1577
|
-
@kwarg norm:
|
|
1585
|
+
@kwarg norm: If C{False}, don't normalize the coordinates (C{bool}).
|
|
1578
1586
|
@kwarg Vector3d_kwds: Optional L{Vector3d} keyword arguments.
|
|
1579
1587
|
|
|
1580
|
-
@return:
|
|
1588
|
+
@return: Named, unit vector or vector (L{Vector3d}).
|
|
1581
1589
|
|
|
1582
1590
|
@raise TypeError: Invalid B{C{Vector3d_kwds}} item.
|
|
1583
1591
|
|
|
1584
1592
|
@see: Methods C{toCartesian}, C{toNvector} and C{toVector}.
|
|
1585
1593
|
'''
|
|
1586
|
-
r = self.toVector(Vector=Vector3d, **Vector3d_kwds)
|
|
1594
|
+
r = self.toVector(Vector=_MODS.vector3d.Vector3d, **Vector3d_kwds)
|
|
1587
1595
|
if norm:
|
|
1588
1596
|
r = r.unit(ll=self)
|
|
1589
1597
|
return r
|
|
@@ -1597,8 +1605,7 @@ class LatLonBase(_NamedBase):
|
|
|
1597
1605
|
|
|
1598
1606
|
@see: Function L{pygeodesy.toWm}.
|
|
1599
1607
|
'''
|
|
1600
|
-
return
|
|
1601
|
-
self, **_xkwds(toWm_kwds, name=self.name))
|
|
1608
|
+
return _MODS.webmercator.toWm(self, **self._name1__(toWm_kwds))
|
|
1602
1609
|
|
|
1603
1610
|
@deprecated_method
|
|
1604
1611
|
def to3xyz(self): # PYCHOK no cover
|
|
@@ -1606,6 +1613,13 @@ class LatLonBase(_NamedBase):
|
|
|
1606
1613
|
L{toVector3d} or perhaps (geocentric) L{toEcef}.'''
|
|
1607
1614
|
return self.xyz # self.toVector()
|
|
1608
1615
|
|
|
1616
|
+
# def _update(self, updated, *attrs, **setters):
|
|
1617
|
+
# '''(INTERNAL) See C{_NamedBase._update}.
|
|
1618
|
+
# '''
|
|
1619
|
+
# if updated:
|
|
1620
|
+
# self._rhumb3dict.clear()
|
|
1621
|
+
# return _NamedBase._update(self, updated, *attrs, **setters)
|
|
1622
|
+
|
|
1609
1623
|
def vincentysTo(self, other, **radius_wrap):
|
|
1610
1624
|
'''Compute the distance between this and an other point using
|
|
1611
1625
|
U{Vincenty's<https://WikiPedia.org/wiki/Great-circle_distance>}
|
|
@@ -1626,13 +1640,12 @@ class LatLonBase(_NamedBase):
|
|
|
1626
1640
|
L{equirectangularTo}, L{euclideanTo}, L{flatLocalTo}/L{hubenyTo},
|
|
1627
1641
|
L{flatPolarTo}, L{haversineTo} and L{thomasTo}.
|
|
1628
1642
|
'''
|
|
1629
|
-
return self._distanceTo(
|
|
1643
|
+
return self._distanceTo(_formy.vincentys, other, **_xkwds(radius_wrap, radius=None))
|
|
1630
1644
|
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
'''(INTERNAL) Get this point as webmercator (L{Wm}).
|
|
1645
|
+
def _wrap_name2(self, wrap=False, **name):
|
|
1646
|
+
'''(INTERNAL) Return the C{wrap} and C{name} value.
|
|
1634
1647
|
'''
|
|
1635
|
-
return
|
|
1648
|
+
return wrap, (self._name__(name) if name else NN)
|
|
1636
1649
|
|
|
1637
1650
|
@property_RO
|
|
1638
1651
|
def xyz(self):
|