pygeodesy 24.12.12__py2.py3-none-any.whl → 25.1.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/__init__.py +25 -25
- pygeodesy/basics.py +59 -7
- pygeodesy/constants.py +2 -2
- pygeodesy/deprecated/__init__.py +1 -1
- pygeodesy/deprecated/classes.py +85 -1
- pygeodesy/deprecated/datum.py +4 -4
- pygeodesy/deprecated/functions.py +25 -1
- pygeodesy/ecef.py +4 -4
- pygeodesy/fmath.py +3 -3
- pygeodesy/formy.py +350 -463
- pygeodesy/frechet.py +28 -85
- pygeodesy/geodesici.py +4 -4
- pygeodesy/geodesicx/__init__.py +1 -1
- pygeodesy/geodesicx/__main__.py +3 -4
- pygeodesy/geoids.py +276 -202
- pygeodesy/hausdorff.py +22 -80
- pygeodesy/heights.py +114 -149
- pygeodesy/latlonBase.py +51 -87
- pygeodesy/lazily.py +44 -35
- pygeodesy/ltpTuples.py +2 -2
- pygeodesy/named.py +11 -11
- pygeodesy/utily.py +188 -115
- {PyGeodesy-24.12.12.dist-info → pygeodesy-25.1.9.dist-info}/METADATA +52 -53
- {PyGeodesy-24.12.12.dist-info → pygeodesy-25.1.9.dist-info}/RECORD +26 -26
- {PyGeodesy-24.12.12.dist-info → pygeodesy-25.1.9.dist-info}/WHEEL +0 -0
- {PyGeodesy-24.12.12.dist-info → pygeodesy-25.1.9.dist-info}/top_level.txt +0 -0
pygeodesy/formy.py
CHANGED
|
@@ -11,14 +11,14 @@ from __future__ import division as _; del _ # PYCHOK semicolon
|
|
|
11
11
|
from pygeodesy.constants import EPS, EPS0, EPS1, PI, PI2, PI3, PI_2, R_M, \
|
|
12
12
|
_0_0s, float0_, isnon0, remainder, _umod_PI2, \
|
|
13
13
|
_0_0, _0_125, _0_25, _0_5, _1_0, _2_0, _4_0, \
|
|
14
|
-
|
|
14
|
+
_90_0, _180_0, _360_0, _copysign
|
|
15
15
|
from pygeodesy.datums import Datum, Ellipsoid, _ellipsoidal_datum, \
|
|
16
16
|
_mean_radius, _spherical_datum, _WGS84, _EWGS84
|
|
17
17
|
# from pygeodesy.ellipsoids import Ellipsoid, _EWGS84 # from .datums
|
|
18
18
|
from pygeodesy.errors import IntersectionError, LimitError, limiterrors, \
|
|
19
19
|
_TypeError, _ValueError, _xattr, _xError, \
|
|
20
20
|
_xcallable,_xkwds, _xkwds_pop2
|
|
21
|
-
from pygeodesy.fmath import euclid, hypot, hypot2, sqrt0
|
|
21
|
+
from pygeodesy.fmath import euclid, fdot_, fprod, hypot, hypot2, sqrt0
|
|
22
22
|
from pygeodesy.fsums import fsumf_, Fmt, unstr
|
|
23
23
|
# from pygeodesy.internals import _DUNDER_nameof # from .named
|
|
24
24
|
from pygeodesy.interns import _delta_, _distant_, _inside_, _SPACE_, _too_
|
|
@@ -32,20 +32,20 @@ from pygeodesy.namedTuples import Bearing2Tuple, Distance4Tuple, LatLon2Tuple, \
|
|
|
32
32
|
from pygeodesy.units import _isDegrees, _isHeight, _isRadius, Bearing, Degrees_, \
|
|
33
33
|
Distance, Distance_, Height, Lamd, Lat, Lon, Meter_, \
|
|
34
34
|
Phid, Radians, Radians_, Radius, Radius_, Scalar, _100km
|
|
35
|
-
from pygeodesy.utily import acos1, atan2, atan2b, degrees2m,
|
|
36
|
-
tan_2, sincos2, sincos2_, _Wrap
|
|
35
|
+
from pygeodesy.utily import acos1, asin1, atan2, atan2b, degrees2m, hav, _loneg, \
|
|
36
|
+
m2degrees, tan_2, sincos2, sincos2_, _Wrap
|
|
37
37
|
# from pygeodesy.vector3d import _otherV3d # _MODS
|
|
38
38
|
# from pygeodesy.vector3dBase import _xyz_y_z3 # _MODS
|
|
39
39
|
# from pygeodesy import ellipsoidalExact, ellipsoidalKarney, vector3d, \
|
|
40
40
|
# sphericalNvector, sphericalTrigonometry # _MODS
|
|
41
41
|
|
|
42
42
|
from contextlib import contextmanager
|
|
43
|
-
from math import
|
|
43
|
+
from math import atan, cos, degrees, fabs, radians, sin, sqrt # pow
|
|
44
44
|
|
|
45
45
|
__all__ = _ALL_LAZY.formy
|
|
46
|
-
__version__ = '
|
|
46
|
+
__version__ = '25.01.05'
|
|
47
47
|
|
|
48
|
-
_RADIANS2 =
|
|
48
|
+
_RADIANS2 = radians(_1_0)**2 # degree to radians-squared
|
|
49
49
|
_ratio_ = 'ratio'
|
|
50
50
|
_xline_ = 'xline'
|
|
51
51
|
|
|
@@ -112,18 +112,17 @@ def antipode_(phi, lam, **name):
|
|
|
112
112
|
|
|
113
113
|
|
|
114
114
|
def bearing(lat1, lon1, lat2, lon2, **final_wrap):
|
|
115
|
-
'''Compute the initial or final bearing (forward or reverse azimuth)
|
|
116
|
-
|
|
115
|
+
'''Compute the initial or final bearing (forward or reverse azimuth) between two
|
|
116
|
+
(spherical) points.
|
|
117
117
|
|
|
118
118
|
@arg lat1: Start latitude (C{degrees}).
|
|
119
119
|
@arg lon1: Start longitude (C{degrees}).
|
|
120
120
|
@arg lat2: End latitude (C{degrees}).
|
|
121
121
|
@arg lon2: End longitude (C{degrees}).
|
|
122
|
-
@kwarg final_wrap: Optional keyword arguments for function
|
|
123
|
-
L{pygeodesy.bearing_}.
|
|
122
|
+
@kwarg final_wrap: Optional keyword arguments for function L{pygeodesy.bearing_}.
|
|
124
123
|
|
|
125
|
-
@return: Initial or final bearing (compass C{degrees360}) or zero if
|
|
126
|
-
|
|
124
|
+
@return: Initial or final bearing (compass C{degrees360}) or zero if both points
|
|
125
|
+
coincide.
|
|
127
126
|
'''
|
|
128
127
|
r = bearing_(Phid(lat1=lat1), Lamd(lon1=lon1),
|
|
129
128
|
Phid(lat2=lat2), Lamd(lon2=lon2), **final_wrap)
|
|
@@ -131,20 +130,19 @@ def bearing(lat1, lon1, lat2, lon2, **final_wrap):
|
|
|
131
130
|
|
|
132
131
|
|
|
133
132
|
def bearing_(phi1, lam1, phi2, lam2, final=False, wrap=False):
|
|
134
|
-
'''Compute the initial or final bearing (forward or reverse azimuth) between
|
|
135
|
-
|
|
133
|
+
'''Compute the initial or final bearing (forward or reverse azimuth) between two
|
|
134
|
+
(spherical) points.
|
|
136
135
|
|
|
137
136
|
@arg phi1: Start latitude (C{radians}).
|
|
138
137
|
@arg lam1: Start longitude (C{radians}).
|
|
139
138
|
@arg phi2: End latitude (C{radians}).
|
|
140
139
|
@arg lam2: End longitude (C{radians}).
|
|
141
|
-
@kwarg final: If C{True}, return the final, otherwise the initial bearing
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
B{C{lam2}} (C{bool}).
|
|
140
|
+
@kwarg final: If C{True}, return the final, otherwise the initial bearing (C{bool}).
|
|
141
|
+
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll B{C{phi2}} and B{C{lam2}}
|
|
142
|
+
(C{bool}).
|
|
145
143
|
|
|
146
|
-
@return: Initial or final bearing (compass C{radiansPI2}) or zero if both
|
|
147
|
-
|
|
144
|
+
@return: Initial or final bearing (compass C{radiansPI2}) or zero if both points
|
|
145
|
+
coincide.
|
|
148
146
|
|
|
149
147
|
@see: U{Bearing<https://www.Movable-Type.co.UK/scripts/latlong.html>}, U{Course
|
|
150
148
|
between two points<https://www.EdWilliams.org/avform147.htm#Crs>} and
|
|
@@ -173,8 +171,9 @@ def _bearingTo2(p1, p2, wrap=False): # for points.ispolar, sphericalTrigonometr
|
|
|
173
171
|
pass
|
|
174
172
|
# XXX spherical version, OK for ellipsoidal ispolar?
|
|
175
173
|
t = p1.philam + p2.philam
|
|
176
|
-
|
|
177
|
-
|
|
174
|
+
i = bearing_(*t, final=False, wrap=wrap)
|
|
175
|
+
f = bearing_(*t, final=True, wrap=wrap)
|
|
176
|
+
return Bearing2Tuple(degrees(i), degrees(f),
|
|
178
177
|
name__=_bearingTo2)
|
|
179
178
|
|
|
180
179
|
|
|
@@ -198,8 +197,8 @@ def chord2angle(chord, radius=R_M):
|
|
|
198
197
|
if i > 0:
|
|
199
198
|
r -= i
|
|
200
199
|
i *= PI
|
|
201
|
-
r =
|
|
202
|
-
return _copysign(r
|
|
200
|
+
r = (asin1(r) + i) * _2_0
|
|
201
|
+
return _copysign(r, chord)
|
|
203
202
|
|
|
204
203
|
|
|
205
204
|
def compassAngle(lat1, lon1, lat2, lon2, adjust=True, wrap=False):
|
|
@@ -213,10 +212,10 @@ def compassAngle(lat1, lon1, lat2, lon2, adjust=True, wrap=False):
|
|
|
213
212
|
@arg lon1: From longitude (C{degrees}).
|
|
214
213
|
@arg lat2: To latitude (C{degrees}).
|
|
215
214
|
@arg lon2: To longitude (C{degrees}).
|
|
216
|
-
@kwarg adjust: Adjust the longitudinal delta by the cosine of the
|
|
217
|
-
|
|
218
|
-
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll B{C{lat2}}
|
|
219
|
-
|
|
215
|
+
@kwarg adjust: Adjust the longitudinal delta by the cosine of the mean
|
|
216
|
+
latitude (C{bool}).
|
|
217
|
+
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll B{C{lat2}} and
|
|
218
|
+
B{C{lon2}} (C{bool}).
|
|
220
219
|
|
|
221
220
|
@return: Compass angle from North (C{degrees360}).
|
|
222
221
|
|
|
@@ -231,230 +230,144 @@ def compassAngle(lat1, lon1, lat2, lon2, adjust=True, wrap=False):
|
|
|
231
230
|
return atan2b(d_lon, lat2 - lat1)
|
|
232
231
|
|
|
233
232
|
|
|
234
|
-
def
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
233
|
+
def cosineLaw(lat1, lon1, lat2, lon2, corr=0, earth=None, wrap=False,
|
|
234
|
+
datum=_WGS84, radius=R_M):
|
|
235
|
+
'''Compute the distance between two points using the U{Law of Cosines
|
|
236
|
+
<https://www.Movable-Type.co.UK/scripts/latlong.html#cosine-law>}
|
|
237
|
+
formula, optionally corrected.
|
|
238
238
|
|
|
239
239
|
@arg lat1: Start latitude (C{degrees}).
|
|
240
240
|
@arg lon1: Start longitude (C{degrees}).
|
|
241
241
|
@arg lat2: End latitude (C{degrees}).
|
|
242
242
|
@arg lon2: End longitude (C{degrees}).
|
|
243
|
-
@kwarg
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
B{
|
|
243
|
+
@kwarg corr: Use C{B{corr}=2} to apply the U{Forsythe-Andoyer-Lambert
|
|
244
|
+
<https://www2.UNB.CA/gge/Pubs/TR77.pdf>}, C{B{corr}=1} for the
|
|
245
|
+
U{Andoyer-Lambert<https://Books.Google.com/books?id=x2UiAQAAIAAJ>}
|
|
246
|
+
corrected (ellipsoidal) or keep C{B{corr}=0} for the uncorrected
|
|
247
|
+
(spherical) C{Law of Cosines} formula (C{int}).
|
|
248
|
+
@kwarg earth: Mean earth radius (C{meter}) or datum (L{Datum}) or ellipsoid
|
|
249
|
+
(L{Ellipsoid}, L{Ellipsoid2} or L{a_f2Tuple}) to use.
|
|
250
|
+
@kwarg wrap: If C{True}, wrap or I{normalize} and B{C{lat2}} and B{C{lon2}}
|
|
251
|
+
(C{bool}).
|
|
252
|
+
@kwarg datum: Default ellipsiodal B{C{earth}} (and for backward compatibility).
|
|
253
|
+
@kwarg radius: Default spherical B{C{earth}} (and for backward compatibility).
|
|
247
254
|
|
|
248
|
-
@return: Distance (C{meter}, same units as
|
|
249
|
-
|
|
255
|
+
@return: Distance (C{meter}, same units as B{C{radius}} or the datum's or
|
|
256
|
+
ellipsoid axes).
|
|
250
257
|
|
|
251
|
-
@raise TypeError: Invalid B{C{datum}}.
|
|
258
|
+
@raise TypeError: Invalid B{C{earth}}, B{C{datum}} or B{C{radius}}.
|
|
259
|
+
|
|
260
|
+
@raise ValueError: Invalid B{C{corr}}.
|
|
252
261
|
|
|
253
|
-
@see: Functions L{
|
|
254
|
-
L{
|
|
255
|
-
|
|
256
|
-
|
|
262
|
+
@see: Functions L{cosineLaw_}, L{equirectangular}, L{euclidean}, L{flatLocal} /
|
|
263
|
+
L{hubeny}, L{flatPolar}, L{haversine}, L{thomas} and L{vincentys} and
|
|
264
|
+
method L{Ellipsoid.distance2}.
|
|
265
|
+
|
|
266
|
+
@note: See note at function L{vincentys_}.
|
|
257
267
|
'''
|
|
258
|
-
return _dE(
|
|
268
|
+
return _dE(cosineLaw_, earth or datum, wrap, lat1, lon1, lat2, lon2, corr=corr) if corr else \
|
|
269
|
+
_dS(cosineLaw_, earth or radius, wrap, lat1, lon1, lat2, lon2)
|
|
259
270
|
|
|
260
271
|
|
|
261
|
-
def
|
|
262
|
-
'''Compute the I{angular} distance between two
|
|
263
|
-
<https://
|
|
264
|
-
|
|
272
|
+
def cosineLaw_(phi2, phi1, lam21, corr=0, earth=None, datum=_WGS84):
|
|
273
|
+
'''Compute the I{angular} distance between two points using the U{Law of Cosines
|
|
274
|
+
<https://www.Movable-Type.co.UK/scripts/latlong.html#cosine-law>} formula,
|
|
275
|
+
optionally corrected.
|
|
265
276
|
|
|
266
277
|
@arg phi2: End latitude (C{radians}).
|
|
267
278
|
@arg phi1: Start latitude (C{radians}).
|
|
268
279
|
@arg lam21: Longitudinal delta, M{end-start} (C{radians}).
|
|
269
|
-
@kwarg
|
|
270
|
-
|
|
280
|
+
@kwarg corr: Use C{B{corr}=2} to apply the U{Forsythe-Andoyer-Lambert
|
|
281
|
+
<https://www2.UNB.CA/gge/Pubs/TR77.pdf>}, C{B{corr}=1} for the
|
|
282
|
+
U{Andoyer-Lambert<https://Books.Google.com/books?id=x2UiAQAAIAAJ>}
|
|
283
|
+
corrected (ellipsoidal) or keep C{B{corr}=0} for the uncorrected
|
|
284
|
+
(spherical) C{Law of Cosines} formula (C{int}).
|
|
285
|
+
@kwarg earth: Mean earth radius (C{meter}) or datum (L{Datum}) or ellipsoid
|
|
286
|
+
(L{Ellipsoid}, L{Ellipsoid2} or L{a_f2Tuple}) to use.
|
|
287
|
+
@kwarg datum: Default ellipsoidal B{C{earth}} (and for backward compatibility).
|
|
271
288
|
|
|
272
289
|
@return: Angular distance (C{radians}).
|
|
273
290
|
|
|
274
|
-
@raise TypeError: Invalid B{C{datum}}.
|
|
291
|
+
@raise TypeError: Invalid B{C{earth}} or B{C{datum}}.
|
|
292
|
+
|
|
293
|
+
@raise ValueError: Invalid B{C{corr}}.
|
|
275
294
|
|
|
276
|
-
@see: Functions L{
|
|
277
|
-
L{
|
|
278
|
-
L{haversine_}, L{thomas_} and L{vincentys_} and U{Geodesy-PHP
|
|
295
|
+
@see: Functions L{cosineLaw}, L{euclidean_}, L{flatLocal_} / L{hubeny_},
|
|
296
|
+
L{flatPolar_}, L{haversine_}, L{thomas_} and L{vincentys_} and U{Geodesy-PHP
|
|
279
297
|
<https://GitHub.com/jtejido/geodesy-php/blob/master/src/Geodesy/Distance/
|
|
280
298
|
AndoyerLambert.php>}.
|
|
281
299
|
'''
|
|
282
300
|
s2, c2, s1, c1, r, c21 = _sincosa6(phi2, phi1, lam21)
|
|
283
|
-
if isnon0(c1) and isnon0(c2):
|
|
284
|
-
E = _ellipsoidal(datum,
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
if
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
@see: Functions L{cosineForsytheAndoyerLambert_}, L{cosineAndoyerLambert},
|
|
319
|
-
L{cosineLaw}, L{equirectangular}, L{euclidean}, L{flatLocal}/L{hubeny},
|
|
320
|
-
L{flatPolar}, L{haversine}, L{thomas} and L{vincentys} and method
|
|
321
|
-
L{Ellipsoid.distance2}.
|
|
322
|
-
'''
|
|
323
|
-
return _dE(cosineForsytheAndoyerLambert_, datum, wrap, lat1, lon1, lat2, lon2)
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
def cosineForsytheAndoyerLambert_(phi2, phi1, lam21, datum=_WGS84):
|
|
327
|
-
'''Compute the I{angular} distance between two (ellipsoidal) points using the
|
|
328
|
-
U{Forsythe-Andoyer-Lambert<https://www2.UNB.Ca/gge/Pubs/TR77.pdf>} correction of
|
|
329
|
-
the U{Law of Cosines<https://www.Movable-Type.co.UK/scripts/latlong.html#cosine-law>}
|
|
330
|
-
formula.
|
|
331
|
-
|
|
332
|
-
@arg phi2: End latitude (C{radians}).
|
|
333
|
-
@arg phi1: Start latitude (C{radians}).
|
|
334
|
-
@arg lam21: Longitudinal delta, M{end-start} (C{radians}).
|
|
335
|
-
@kwarg datum: Datum (L{Datum}) or ellipsoid to use (L{Ellipsoid},
|
|
336
|
-
L{Ellipsoid2} or L{a_f2Tuple}).
|
|
337
|
-
|
|
338
|
-
@return: Angular distance (C{radians}).
|
|
339
|
-
|
|
340
|
-
@raise TypeError: Invalid B{C{datum}}.
|
|
341
|
-
|
|
342
|
-
@see: Functions L{cosineForsytheAndoyerLambert}, L{cosineAndoyerLambert_},
|
|
343
|
-
L{cosineLaw_}, L{euclidean_}, L{flatLocal_}/L{hubeny_}, L{flatPolar_},
|
|
344
|
-
L{haversine_}, L{thomas_} and L{vincentys_} and U{Geodesy-PHP
|
|
345
|
-
<https://GitHub.com/jtejido/geodesy-php/blob/master/src/Geodesy/
|
|
346
|
-
Distance/ForsytheCorrection.php>}.
|
|
347
|
-
'''
|
|
348
|
-
s2, c2, s1, c1, r, _ = _sincosa6(phi2, phi1, lam21)
|
|
349
|
-
if r and isnon0(c1) and isnon0(c2):
|
|
350
|
-
E = _ellipsoidal(datum, cosineForsytheAndoyerLambert_)
|
|
351
|
-
if E.f: # ellipsoidal
|
|
352
|
-
sr, cr, s2r, _ = sincos2_(r, r * 2)
|
|
353
|
-
if isnon0(sr) and fabs(cr) < EPS1:
|
|
354
|
-
s = (s1 + s2)**2 / (1 + cr)
|
|
355
|
-
t = (s1 - s2)**2 / (1 - cr)
|
|
356
|
-
x = s + t
|
|
357
|
-
y = s - t
|
|
358
|
-
|
|
359
|
-
s = 8 * r**2 / sr
|
|
360
|
-
a = 64 * r + s * cr * 2 # 16 * r**2 / tan(r)
|
|
361
|
-
d = 48 * sr + s # 8 * r**2 / tan(r)
|
|
362
|
-
b = -2 * d
|
|
363
|
-
e = 30 * s2r
|
|
364
|
-
c = fsumf_(30 * r, e * _0_5, s * cr) # 8 * r**2 / tan(r)
|
|
365
|
-
t = fsumf_( a * x, e * y**2, b * y, -c * x**2, d * x * y)
|
|
366
|
-
|
|
367
|
-
r += fsumf_(-r * x, 3 * y * sr, t * E.f / _32_0) * E.f * _0_25
|
|
301
|
+
if corr and isnon0(c1) and isnon0(c2):
|
|
302
|
+
E = _ellipsoidal(earth or datum, cosineLaw_)
|
|
303
|
+
f = _0_25 * E.f
|
|
304
|
+
if f: # ellipsoidal
|
|
305
|
+
if corr == 1: # Andoyer-Lambert
|
|
306
|
+
r2 = atan2(E.b_a * s2, c2)
|
|
307
|
+
r1 = atan2(E.b_a * s1, c1)
|
|
308
|
+
s2, c2, s1, c1 = sincos2_(r2, r1)
|
|
309
|
+
r = acos1(s1 * s2 + c1 * c2 * c21)
|
|
310
|
+
if r:
|
|
311
|
+
sr, _, sr_2, cr_2 = sincos2_(r, r * _0_5)
|
|
312
|
+
if isnon0(sr_2) and isnon0(cr_2):
|
|
313
|
+
s = (sr + r) * ((s1 - s2) / sr_2)**2
|
|
314
|
+
c = (sr - r) * ((s1 + s2) / cr_2)**2
|
|
315
|
+
r += (c - s) * _0_5 * f
|
|
316
|
+
|
|
317
|
+
elif corr == 2: # Forsythe-Andoyer-Lambert
|
|
318
|
+
sr, cr, s2r, _ = sincos2_(r, r * 2)
|
|
319
|
+
if isnon0(sr) and fabs(cr) < EPS1:
|
|
320
|
+
s = (s1 + s2)**2 / (_1_0 + cr)
|
|
321
|
+
t = (s1 - s2)**2 / (_1_0 - cr)
|
|
322
|
+
x = s + t
|
|
323
|
+
y = s - t
|
|
324
|
+
|
|
325
|
+
s = 8 * r**2 / sr
|
|
326
|
+
a = 64 * r + s * cr * 2 # 16 * r**2 / tan(r)
|
|
327
|
+
d = 48 * sr + s # 8 * r**2 / tan(r)
|
|
328
|
+
b = -2 * d
|
|
329
|
+
e = 30 * s2r
|
|
330
|
+
|
|
331
|
+
c = fdot_(30, r, cr, s, e, _0_5) # 8 * r**2 / tan(r)
|
|
332
|
+
t = fdot_( a, x, b, y, e, y**2, -c, x**2, d, x * y) * _0_125
|
|
333
|
+
r += fdot_(-r, x, sr, y * 3, t, f) * f
|
|
334
|
+
else:
|
|
335
|
+
raise _ValueError(corr=corr)
|
|
368
336
|
return r
|
|
369
337
|
|
|
370
338
|
|
|
371
|
-
def cosineLaw(lat1, lon1, lat2, lon2, radius=R_M, wrap=False):
|
|
372
|
-
'''Compute the distance between two points using the U{spherical Law of Cosines
|
|
373
|
-
<https://www.Movable-Type.co.UK/scripts/latlong.html#cosine-law>} formula.
|
|
374
|
-
|
|
375
|
-
@arg lat1: Start latitude (C{degrees}).
|
|
376
|
-
@arg lon1: Start longitude (C{degrees}).
|
|
377
|
-
@arg lat2: End latitude (C{degrees}).
|
|
378
|
-
@arg lon2: End longitude (C{degrees}).
|
|
379
|
-
@kwarg radius: Mean earth radius (C{meter}), datum (L{Datum})
|
|
380
|
-
or ellipsoid (L{Ellipsoid}, L{Ellipsoid2} or
|
|
381
|
-
L{a_f2Tuple}) to use.
|
|
382
|
-
@kwarg wrap: If C{True}, wrap or I{normalize} and B{C{lat2}}
|
|
383
|
-
and B{C{lon2}} (C{bool}).
|
|
384
|
-
|
|
385
|
-
@return: Distance (C{meter}, same units as B{C{radius}} or the
|
|
386
|
-
ellipsoid or datum axes).
|
|
387
|
-
|
|
388
|
-
@raise TypeError: Invalid B{C{radius}}.
|
|
389
|
-
|
|
390
|
-
@see: Functions L{cosineLaw_}, L{cosineAndoyerLambert},
|
|
391
|
-
L{cosineForsytheAndoyerLambert}, L{equirectangular}, L{euclidean},
|
|
392
|
-
L{flatLocal}/L{hubeny}, L{flatPolar}, L{haversine}, L{thomas} and
|
|
393
|
-
L{vincentys} and method L{Ellipsoid.distance2}.
|
|
394
|
-
|
|
395
|
-
@note: See note at function L{vincentys_}.
|
|
396
|
-
'''
|
|
397
|
-
return _dS(cosineLaw_, radius, wrap, lat1, lon1, lat2, lon2)
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
def cosineLaw_(phi2, phi1, lam21):
|
|
401
|
-
'''Compute the I{angular} distance between two points using the U{spherical Law of
|
|
402
|
-
Cosines<https://www.Movable-Type.co.UK/scripts/latlong.html#cosine-law>} formula.
|
|
403
|
-
|
|
404
|
-
@arg phi2: End latitude (C{radians}).
|
|
405
|
-
@arg phi1: Start latitude (C{radians}).
|
|
406
|
-
@arg lam21: Longitudinal delta, M{end-start} (C{radians}).
|
|
407
|
-
|
|
408
|
-
@return: Angular distance (C{radians}).
|
|
409
|
-
|
|
410
|
-
@see: Functions L{cosineLaw}, L{cosineAndoyerLambert_},
|
|
411
|
-
L{cosineForsytheAndoyerLambert_}, L{euclidean_},
|
|
412
|
-
L{flatLocal_}/L{hubeny_}, L{flatPolar_}, L{haversine_},
|
|
413
|
-
L{thomas_} and L{vincentys_}.
|
|
414
|
-
|
|
415
|
-
@note: See note at function L{vincentys_}.
|
|
416
|
-
'''
|
|
417
|
-
return _sincosa6(phi2, phi1, lam21)[4]
|
|
418
|
-
|
|
419
|
-
|
|
420
339
|
def _d3(wrap, lat1, lon1, lat2, lon2):
|
|
421
|
-
'''(INTERNAL) Helper for _dE, _dS
|
|
340
|
+
'''(INTERNAL) Helper for _dE, _dS, ....
|
|
422
341
|
'''
|
|
423
342
|
if wrap:
|
|
424
343
|
d_lon, lat2, _ = _Wrap.latlon3(lon1, lat2, lon2, wrap)
|
|
425
344
|
return radians(lat2), Phid(lat1=lat1), radians(d_lon)
|
|
426
345
|
else: # for backward compaibility
|
|
427
|
-
return Phid(lat2=lat2), Phid(lat1=lat1),
|
|
346
|
+
return Phid(lat2=lat2), Phid(lat1=lat1), radians(lon2 - lon1)
|
|
428
347
|
|
|
429
348
|
|
|
430
|
-
def _dE(
|
|
349
|
+
def _dE(fun_, earth, wrap, *lls, **corr):
|
|
431
350
|
'''(INTERNAL) Helper for ellipsoidal distances.
|
|
432
351
|
'''
|
|
433
|
-
E = _ellipsoidal(earth,
|
|
434
|
-
r =
|
|
352
|
+
E = _ellipsoidal(earth, fun_)
|
|
353
|
+
r = fun_(*_d3(wrap, *lls), datum=E, **corr)
|
|
435
354
|
return r * E.a
|
|
436
355
|
|
|
437
356
|
|
|
438
|
-
def _dS(
|
|
357
|
+
def _dS(fun_, radius, wrap, *lls, **adjust):
|
|
439
358
|
'''(INTERNAL) Helper for spherical distances.
|
|
440
359
|
'''
|
|
441
|
-
r =
|
|
360
|
+
r = fun_(*_d3(wrap, *lls), **adjust)
|
|
442
361
|
if radius is not R_M:
|
|
443
|
-
|
|
362
|
+
try: # datum?
|
|
363
|
+
radius = radius.ellipsoid.R1
|
|
364
|
+
except AttributeError:
|
|
365
|
+
pass # scalar?
|
|
366
|
+
lat1, _, lat2, _ = lls
|
|
444
367
|
radius = _mean_radius(radius, lat1, lat2)
|
|
445
368
|
return r * radius
|
|
446
369
|
|
|
447
370
|
|
|
448
|
-
def _eA(excess_, radius, *wrap_lls):
|
|
449
|
-
'''(INTERNAL) Helper for spherical excess or area.
|
|
450
|
-
'''
|
|
451
|
-
r = excess_(*_d3(*wrap_lls))
|
|
452
|
-
if radius:
|
|
453
|
-
_, lat1, _, lat2, _ = wrap_lls
|
|
454
|
-
r *= _mean_radius(radius, lat1, lat2)**2
|
|
455
|
-
return r
|
|
456
|
-
|
|
457
|
-
|
|
458
371
|
def _ellipsoidal(earth, where):
|
|
459
372
|
'''(INTERNAL) Helper for distances.
|
|
460
373
|
'''
|
|
@@ -474,26 +387,29 @@ def equirectangular(lat1, lon1, lat2, lon2, radius=R_M, **adjust_limit_wrap):
|
|
|
474
387
|
@arg lon2: End longitude (C{degrees}).
|
|
475
388
|
@kwarg radius: Mean earth radius (C{meter}), datum (L{Datum}) or ellipsoid
|
|
476
389
|
(L{Ellipsoid}, L{Ellipsoid2} or L{a_f2Tuple}).
|
|
477
|
-
@kwarg adjust_limit_wrap:
|
|
390
|
+
@kwarg adjust_limit_wrap: Optionally, keyword arguments for function L{equirectangular4}.
|
|
478
391
|
|
|
479
|
-
@return: Distance (C{meter}, same units as B{C{radius}} or the
|
|
392
|
+
@return: Distance (C{meter}, same units as B{C{radius}} or the datum's
|
|
393
|
+
ellipsoid axes).
|
|
480
394
|
|
|
481
395
|
@raise TypeError: Invalid B{C{radius}}.
|
|
482
396
|
|
|
483
397
|
@see: Function L{equirectangular4} for more details, the available B{C{options}},
|
|
484
398
|
errors, restrictions and other, approximate or accurate distance functions.
|
|
485
399
|
'''
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
400
|
+
r = _mean_radius(radius, lat1, lat2)
|
|
401
|
+
t = equirectangular4(Lat(lat1=lat1), Lon(lon1=lon1),
|
|
402
|
+
Lat(lat2=lat2), Lon(lon2=lon2),
|
|
403
|
+
**adjust_limit_wrap) # PYCHOK 4 vs 2-3
|
|
404
|
+
return degrees2m(sqrt(t.distance2), radius=r)
|
|
490
405
|
|
|
491
406
|
|
|
492
407
|
def _equirectangular(lat1, lon1, lat2, lon2, **adjust_limit_wrap):
|
|
493
408
|
'''(INTERNAL) Helper for classes L{frechet._FrechetMeterRadians} and
|
|
494
409
|
L{hausdorff._HausdorffMeterRedians}.
|
|
495
410
|
'''
|
|
496
|
-
|
|
411
|
+
t = equirectangular4(lat1, lon1, lat2, lon2, **adjust_limit_wrap)
|
|
412
|
+
return t.distance2 * _RADIANS2
|
|
497
413
|
|
|
498
414
|
|
|
499
415
|
def equirectangular4(lat1, lon1, lat2, lon2, adjust=True, limit=45, wrap=False):
|
|
@@ -507,8 +423,8 @@ def equirectangular4(lat1, lon1, lat2, lon2, adjust=True, limit=45, wrap=False):
|
|
|
507
423
|
@arg lon1: Start longitude (C{degrees}).
|
|
508
424
|
@arg lat2: End latitude (C{degrees}).
|
|
509
425
|
@arg lon2: End longitude (C{degrees}).
|
|
510
|
-
@kwarg adjust: Adjust the wrapped, unrolled longitudinal delta by the cosine of the
|
|
511
|
-
latitude (C{bool}).
|
|
426
|
+
@kwarg adjust: Adjust the wrapped, unrolled longitudinal delta by the cosine of the
|
|
427
|
+
mean latitude (C{bool}).
|
|
512
428
|
@kwarg limit: Optional limit for lat- and longitudinal deltas (C{degrees}) or C{None}
|
|
513
429
|
or C{0} for unlimited.
|
|
514
430
|
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll B{C{lat2}} and B{C{lon2}}
|
|
@@ -521,10 +437,9 @@ def equirectangular4(lat1, lon1, lat2, lon2, adjust=True, limit=45, wrap=False):
|
|
|
521
437
|
range and L{limiterrors<pygeodesy.limiterrors>} is C{True}.
|
|
522
438
|
|
|
523
439
|
@see: U{Local, flat earth approximation<https://www.EdWilliams.org/avform.htm#flat>},
|
|
524
|
-
functions L{equirectangular}, L{
|
|
525
|
-
L{
|
|
526
|
-
L{
|
|
527
|
-
and C{LatLon.equirectangularTo}.
|
|
440
|
+
functions L{equirectangular}, L{cosineLaw}, L{euclidean}, L{flatLocal} /
|
|
441
|
+
L{hubeny}, L{flatPolar}, L{haversine}, L{thomas} and L{vincentys} and methods
|
|
442
|
+
L{Ellipsoid.distance2}, C{LatLon.distanceTo*} and C{LatLon.equirectangularTo}.
|
|
528
443
|
'''
|
|
529
444
|
if wrap:
|
|
530
445
|
d_lon, lat2, ulon2 = _Wrap.latlon3(lon1, lat2, lon2, wrap)
|
|
@@ -554,25 +469,24 @@ def euclidean(lat1, lon1, lat2, lon2, radius=R_M, adjust=True, wrap=False):
|
|
|
554
469
|
@arg lon1: Start longitude (C{degrees}).
|
|
555
470
|
@arg lat2: End latitude (C{degrees}).
|
|
556
471
|
@arg lon2: End longitude (C{degrees}).
|
|
557
|
-
@kwarg radius: Mean earth radius (C{meter}), datum (L{Datum})
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
and B{C{lon2}} (C{bool}).
|
|
472
|
+
@kwarg radius: Mean earth radius (C{meter}), datum (L{Datum}) or ellipsoid
|
|
473
|
+
(L{Ellipsoid}, L{Ellipsoid2} or L{a_f2Tuple}) to use.
|
|
474
|
+
@kwarg adjust: Adjust the longitudinal delta by the cosine of the mean
|
|
475
|
+
latitude (C{bool}).
|
|
476
|
+
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll B{C{lat2}} and
|
|
477
|
+
B{C{lon2}} (C{bool}).
|
|
564
478
|
|
|
565
|
-
@return: Distance (C{meter}, same units as B{C{radius}} or the
|
|
566
|
-
|
|
479
|
+
@return: Distance (C{meter}, same units as B{C{radius}} or the ellipsoid
|
|
480
|
+
or datum axes).
|
|
567
481
|
|
|
568
482
|
@raise TypeError: Invalid B{C{radius}}.
|
|
569
483
|
|
|
570
484
|
@see: U{Distance between two (spherical) points
|
|
571
485
|
<https://www.EdWilliams.org/avform.htm#Dist>}, functions L{euclid},
|
|
572
|
-
L{euclidean_}, L{
|
|
573
|
-
L{
|
|
574
|
-
|
|
575
|
-
C{LatLon.
|
|
486
|
+
L{euclidean_}, L{cosineLaw}, L{equirectangular}, L{flatLocal} /
|
|
487
|
+
L{hubeny}, L{flatPolar}, L{haversine}, L{thomas} and L{vincentys}
|
|
488
|
+
and methods L{Ellipsoid.distance2}, C{LatLon.distanceTo*} and
|
|
489
|
+
C{LatLon.equirectangularTo}.
|
|
576
490
|
'''
|
|
577
491
|
return _dS(euclidean_, radius, wrap, lat1, lon1, lat2, lon2, adjust=adjust)
|
|
578
492
|
|
|
@@ -583,15 +497,13 @@ def euclidean_(phi2, phi1, lam21, adjust=True):
|
|
|
583
497
|
@arg phi2: End latitude (C{radians}).
|
|
584
498
|
@arg phi1: Start latitude (C{radians}).
|
|
585
499
|
@arg lam21: Longitudinal delta, M{end-start} (C{radians}).
|
|
586
|
-
@kwarg adjust: Adjust the longitudinal delta by the cosine
|
|
587
|
-
|
|
500
|
+
@kwarg adjust: Adjust the longitudinal delta by the cosine of the mean
|
|
501
|
+
latitude (C{bool}).
|
|
588
502
|
|
|
589
503
|
@return: Angular distance (C{radians}).
|
|
590
504
|
|
|
591
|
-
@see: Functions L{euclid}, L{euclidean}, L{
|
|
592
|
-
L{
|
|
593
|
-
L{flatLocal_}/L{hubeny_}, L{flatPolar_}, L{haversine_},
|
|
594
|
-
L{thomas_} and L{vincentys_}.
|
|
505
|
+
@see: Functions L{euclid}, L{euclidean}, L{cosineLaw_}, L{flatLocal_} /
|
|
506
|
+
L{hubeny_}, L{flatPolar_}, L{haversine_}, L{thomas_} and L{vincentys_}.
|
|
595
507
|
'''
|
|
596
508
|
if adjust:
|
|
597
509
|
lam21 *= _scale_rad(phi2, phi1)
|
|
@@ -618,7 +530,9 @@ def excessAbc_(A, b, c):
|
|
|
618
530
|
c = Radians_(c=c) * _0_5
|
|
619
531
|
|
|
620
532
|
sA, cA, sb, cb, sc, cc = sincos2_(A, b, c)
|
|
621
|
-
|
|
533
|
+
s = sA * sb * sc
|
|
534
|
+
c = cA * sb * sc + cc * cb
|
|
535
|
+
return atan2(s, c) * _2_0
|
|
622
536
|
|
|
623
537
|
|
|
624
538
|
def excessCagnoli_(a, b, c):
|
|
@@ -640,11 +554,11 @@ def excessCagnoli_(a, b, c):
|
|
|
640
554
|
b = Radians_(b=b)
|
|
641
555
|
c = Radians_(c=c)
|
|
642
556
|
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
557
|
+
r = _maprod(cos, a * _0_5, b * _0_5, c * _0_5)
|
|
558
|
+
if r:
|
|
559
|
+
s = fsumf_(a, b, c) * _0_5
|
|
560
|
+
t = _maprod(sin, s, s - a, s - b, s - c)
|
|
561
|
+
r = asin1(sqrt(t) * _0_5 / r) if t > 0 else _0_0
|
|
648
562
|
return Radians(Cagnoli=r * _2_0)
|
|
649
563
|
|
|
650
564
|
|
|
@@ -663,9 +577,10 @@ def excessGirard_(A, B, C):
|
|
|
663
577
|
@see: Function L{excessLHuilier_} and U{Spherical trigonometry
|
|
664
578
|
<https://WikiPedia.org/wiki/Spherical_trigonometry>}.
|
|
665
579
|
'''
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
580
|
+
r = fsumf_(Radians_(A=A),
|
|
581
|
+
Radians_(B=B),
|
|
582
|
+
Radians_(C=C), -PI)
|
|
583
|
+
return Radians(Girard=r)
|
|
669
584
|
|
|
670
585
|
|
|
671
586
|
def excessLHuilier_(a, b, c):
|
|
@@ -687,10 +602,9 @@ def excessLHuilier_(a, b, c):
|
|
|
687
602
|
b = Radians_(b=b)
|
|
688
603
|
c = Radians_(c=c)
|
|
689
604
|
|
|
690
|
-
s
|
|
691
|
-
|
|
692
|
-
r
|
|
693
|
-
r = atan(sqrt(r)) if r > 0 else _0_0
|
|
605
|
+
s = fsumf_(a, b, c) * _0_5
|
|
606
|
+
r = _maprod(tan_2, s, s - a, s - b, s - c)
|
|
607
|
+
r = atan(sqrt(r)) if r > 0 else _0_0
|
|
694
608
|
return Radians(LHuilier=r * _4_0)
|
|
695
609
|
|
|
696
610
|
|
|
@@ -704,11 +618,10 @@ def excessKarney(lat1, lon1, lat2, lon2, radius=R_M, wrap=False):
|
|
|
704
618
|
@arg lon1: Start longitude (C{degrees}).
|
|
705
619
|
@arg lat2: End latitude (C{degrees}).
|
|
706
620
|
@arg lon2: End longitude (C{degrees}).
|
|
707
|
-
@kwarg radius: Mean earth radius (C{meter}), datum (L{Datum})
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
B{C{lat2}} and B{C{lon2}} (C{bool}).
|
|
621
|
+
@kwarg radius: Mean earth radius (C{meter}), datum (L{Datum}) or ellipsoid
|
|
622
|
+
(L{Ellipsoid}, L{Ellipsoid2} or L{a_f2Tuple}) or C{None}.
|
|
623
|
+
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll B{C{lat2}} and
|
|
624
|
+
B{C{lon2}} (C{bool}).
|
|
712
625
|
|
|
713
626
|
@return: Surface area, I{signed} (I{square} C{meter} or the same units as
|
|
714
627
|
B{C{radius}} I{squared}) or the I{spherical excess} (C{radians})
|
|
@@ -722,7 +635,10 @@ def excessKarney(lat1, lon1, lat2, lon2, radius=R_M, wrap=False):
|
|
|
722
635
|
|
|
723
636
|
@see: Functions L{excessKarney_} and L{excessQuad}.
|
|
724
637
|
'''
|
|
725
|
-
|
|
638
|
+
r = excessKarney_(*_d3(wrap, lat1, lon1, lat2, lon2))
|
|
639
|
+
if radius:
|
|
640
|
+
r *= _mean_radius(radius, lat1, lat2)**2
|
|
641
|
+
return r
|
|
726
642
|
|
|
727
643
|
|
|
728
644
|
def excessKarney_(phi2, phi1, lam21):
|
|
@@ -751,12 +667,11 @@ def excessKarney_(phi2, phi1, lam21):
|
|
|
751
667
|
#
|
|
752
668
|
# where E is the spherical excess of the trapezium obtained by extending
|
|
753
669
|
# the edge to the equator-circle vector for each edge (see also ***).
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
t1
|
|
757
|
-
|
|
758
|
-
return Radians(Karney=atan2(
|
|
759
|
-
_1_0 + (t1 * t2)) * _2_0)
|
|
670
|
+
t2 = tan_2(phi2)
|
|
671
|
+
t1 = tan_2(phi1)
|
|
672
|
+
c = (t1 * t2) + _1_0
|
|
673
|
+
s = (t1 + t2) * tan_2(lam21, lam21=None)
|
|
674
|
+
return Radians(Karney=atan2(s, c) * _2_0)
|
|
760
675
|
|
|
761
676
|
|
|
762
677
|
# ***) Original post no longer available, following is a copy of the main part
|
|
@@ -806,11 +721,10 @@ def excessQuad(lat1, lon1, lat2, lon2, radius=R_M, wrap=False):
|
|
|
806
721
|
@arg lon1: Start longitude (C{degrees}).
|
|
807
722
|
@arg lat2: End latitude (C{degrees}).
|
|
808
723
|
@arg lon2: End longitude (C{degrees}).
|
|
809
|
-
@kwarg radius: Mean earth radius (C{meter}), datum (L{Datum})
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
B{C{lat2}} and B{C{lon2}} (C{bool}).
|
|
724
|
+
@kwarg radius: Mean earth radius (C{meter}), datum (L{Datum}) or ellipsoid
|
|
725
|
+
(L{Ellipsoid}, L{Ellipsoid2} or L{a_f2Tuple}) or C{None}.
|
|
726
|
+
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll B{C{lat2}} and
|
|
727
|
+
B{C{lon2}} (C{bool}).
|
|
814
728
|
|
|
815
729
|
@return: Surface area, I{signed} (I{square} C{meter} or the same units as
|
|
816
730
|
B{C{radius}} I{squared}) or the I{spherical excess} (C{radians})
|
|
@@ -822,7 +736,10 @@ def excessQuad(lat1, lon1, lat2, lon2, radius=R_M, wrap=False):
|
|
|
822
736
|
|
|
823
737
|
@see: Function L{excessQuad_} and L{excessKarney}.
|
|
824
738
|
'''
|
|
825
|
-
|
|
739
|
+
r = excessQuad_(*_d3(wrap, lat1, lon1, lat2, lon2))
|
|
740
|
+
if radius:
|
|
741
|
+
r *= _mean_radius(radius, lat1, lat2)**2
|
|
742
|
+
return r
|
|
826
743
|
|
|
827
744
|
|
|
828
745
|
def excessQuad_(phi2, phi1, lam21):
|
|
@@ -838,9 +755,9 @@ def excessQuad_(phi2, phi1, lam21):
|
|
|
838
755
|
@see: Function L{excessQuad} and U{Spherical trigonometry
|
|
839
756
|
<https://WikiPedia.org/wiki/Spherical_trigonometry>}.
|
|
840
757
|
'''
|
|
841
|
-
s = sin((phi2 + phi1) * _0_5)
|
|
842
758
|
c = cos((phi2 - phi1) * _0_5)
|
|
843
|
-
|
|
759
|
+
s = sin((phi2 + phi1) * _0_5) * tan_2(lam21)
|
|
760
|
+
return Radians(Quad=atan2(s, c) * _2_0)
|
|
844
761
|
|
|
845
762
|
|
|
846
763
|
def flatLocal(lat1, lon1, lat2, lon2, datum=_WGS84, scaled=True, wrap=False):
|
|
@@ -853,30 +770,28 @@ def flatLocal(lat1, lon1, lat2, lon2, datum=_WGS84, scaled=True, wrap=False):
|
|
|
853
770
|
@arg lon1: Start longitude (C{degrees}).
|
|
854
771
|
@arg lat2: End latitude (C{degrees}).
|
|
855
772
|
@arg lon2: End longitude (C{degrees}).
|
|
856
|
-
@kwarg datum: Datum (L{Datum}) or ellipsoid (L{Ellipsoid},
|
|
857
|
-
|
|
858
|
-
@kwarg scaled: Scale prime_vertical by C{cos(B{phi})} (C{bool}),
|
|
859
|
-
|
|
860
|
-
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll
|
|
861
|
-
B{C{
|
|
862
|
-
|
|
863
|
-
@return: Distance (C{meter}, same units as the B{C{datum}}'s
|
|
864
|
-
ellipsoid axes).
|
|
773
|
+
@kwarg datum: Datum (L{Datum}) or ellipsoid (L{Ellipsoid}, L{Ellipsoid2}
|
|
774
|
+
or L{a_f2Tuple}) to use.
|
|
775
|
+
@kwarg scaled: Scale prime_vertical by C{cos(B{phi})} (C{bool}), see
|
|
776
|
+
method L{pygeodesy.Ellipsoid.roc2_}.
|
|
777
|
+
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll B{C{lat2}} and
|
|
778
|
+
B{C{lon2}} (C{bool}).
|
|
779
|
+
|
|
780
|
+
@return: Distance (C{meter}, same units as the B{C{datum}}'s or ellipsoid axes).
|
|
865
781
|
|
|
866
782
|
@raise TypeError: Invalid B{C{datum}}.
|
|
867
783
|
|
|
868
|
-
@note: The meridional and prime_vertical radii of curvature
|
|
869
|
-
|
|
784
|
+
@note: The meridional and prime_vertical radii of curvature are taken and
|
|
785
|
+
scaled at the mean of both latitude.
|
|
870
786
|
|
|
871
|
-
@see: Functions L{flatLocal_} or L{hubeny_}, L{cosineLaw}, L{
|
|
872
|
-
L{
|
|
873
|
-
L{
|
|
874
|
-
|
|
875
|
-
earth approximation<https://www.EdWilliams.org/avform.htm#flat>}.
|
|
787
|
+
@see: Functions L{flatLocal_} or L{hubeny_}, L{cosineLaw}, L{equirectangular},
|
|
788
|
+
L{euclidean}, L{flatPolar}, L{haversine}, L{thomas} and L{vincentys}, method
|
|
789
|
+
L{Ellipsoid.distance2} and U{local, flat earth approximation
|
|
790
|
+
<https://www.EdWilliams.org/avform.htm#flat>}.
|
|
876
791
|
'''
|
|
792
|
+
t = _d3(wrap, lat1, lon1, lat2, lon2)
|
|
877
793
|
E = _ellipsoidal(datum, flatLocal)
|
|
878
|
-
return E._hubeny_2(*
|
|
879
|
-
scaled=scaled, squared=False) * E.a
|
|
794
|
+
return E._hubeny_2(*t, scaled=scaled, squared=False) * E.a
|
|
880
795
|
|
|
881
796
|
hubeny = flatLocal # PYCHOK for Karl Hubeny
|
|
882
797
|
|
|
@@ -890,23 +805,21 @@ def flatLocal_(phi2, phi1, lam21, datum=_WGS84, scaled=True):
|
|
|
890
805
|
@arg phi2: End latitude (C{radians}).
|
|
891
806
|
@arg phi1: Start latitude (C{radians}).
|
|
892
807
|
@arg lam21: Longitudinal delta, M{end-start} (C{radians}).
|
|
893
|
-
@kwarg datum: Datum (L{Datum}) or ellipsoid (L{Ellipsoid},
|
|
894
|
-
|
|
895
|
-
@kwarg scaled: Scale prime_vertical by C{cos(B{phi})} (C{bool}),
|
|
896
|
-
|
|
808
|
+
@kwarg datum: Datum (L{Datum}) or ellipsoid (L{Ellipsoid}, L{Ellipsoid2}
|
|
809
|
+
or L{a_f2Tuple}) to use.
|
|
810
|
+
@kwarg scaled: Scale prime_vertical by C{cos(B{phi})} (C{bool}), see
|
|
811
|
+
method L{pygeodesy.Ellipsoid.roc2_}.
|
|
897
812
|
|
|
898
813
|
@return: Angular distance (C{radians}).
|
|
899
814
|
|
|
900
815
|
@raise TypeError: Invalid B{C{datum}}.
|
|
901
816
|
|
|
902
|
-
@note: The meridional and prime_vertical radii of curvature
|
|
903
|
-
|
|
817
|
+
@note: The meridional and prime_vertical radii of curvature are taken and
|
|
818
|
+
scaled I{at the mean of both latitude}.
|
|
904
819
|
|
|
905
|
-
@see: Functions L{flatLocal} or L{hubeny}, L{
|
|
906
|
-
L{
|
|
907
|
-
|
|
908
|
-
U{local, flat earth approximation
|
|
909
|
-
<https://www.EdWilliams.org/avform.htm#flat>}.
|
|
820
|
+
@see: Functions L{flatLocal} or L{hubeny}, L{cosineLaw_}, L{flatPolar_},
|
|
821
|
+
L{euclidean_}, L{haversine_}, L{thomas_} and L{vincentys_} and U{local,
|
|
822
|
+
flat earth approximation<https://www.EdWilliams.org/avform.htm#flat>}.
|
|
910
823
|
'''
|
|
911
824
|
E = _ellipsoidal(datum, flatLocal_)
|
|
912
825
|
return E._hubeny_2(phi2, phi1, lam21, scaled=scaled, squared=False)
|
|
@@ -915,40 +828,34 @@ hubeny_ = flatLocal_ # PYCHOK for Karl Hubeny
|
|
|
915
828
|
|
|
916
829
|
|
|
917
830
|
def flatPolar(lat1, lon1, lat2, lon2, radius=R_M, wrap=False):
|
|
918
|
-
'''Compute the distance between two (spherical) points using
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
formula.
|
|
831
|
+
'''Compute the distance between two (spherical) points using the U{polar
|
|
832
|
+
coordinate flat-Earth<https://WikiPedia.org/wiki/Geographical_distance
|
|
833
|
+
#Polar_coordinate_flat-Earth_formula>} formula.
|
|
922
834
|
|
|
923
835
|
@arg lat1: Start latitude (C{degrees}).
|
|
924
836
|
@arg lon1: Start longitude (C{degrees}).
|
|
925
837
|
@arg lat2: End latitude (C{degrees}).
|
|
926
838
|
@arg lon2: End longitude (C{degrees}).
|
|
927
|
-
@kwarg radius: Mean earth radius (C{meter}), datum (L{Datum})
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
and B{C{lon2}} (C{bool}).
|
|
839
|
+
@kwarg radius: Mean earth radius (C{meter}), datum (L{Datum}) or ellipsoid
|
|
840
|
+
(L{Ellipsoid}, L{Ellipsoid2} or L{a_f2Tuple}) to use.
|
|
841
|
+
@kwarg wrap: If C{True}, wrap or I{normalize} and B{C{lat2}} and B{C{lon2}}
|
|
842
|
+
(C{bool}).
|
|
932
843
|
|
|
933
|
-
@return: Distance (C{meter}, same units as B{C{radius}} or the
|
|
934
|
-
ellipsoid
|
|
844
|
+
@return: Distance (C{meter}, same units as B{C{radius}} or the datum's or
|
|
845
|
+
ellipsoid axes).
|
|
935
846
|
|
|
936
847
|
@raise TypeError: Invalid B{C{radius}}.
|
|
937
848
|
|
|
938
|
-
@see: Functions L{flatPolar_}, L{
|
|
939
|
-
L{
|
|
940
|
-
L{flatLocal}/L{hubeny}, L{equirectangular},
|
|
941
|
-
L{euclidean}, L{haversine}, L{thomas} and
|
|
942
|
-
L{vincentys}.
|
|
849
|
+
@see: Functions L{flatPolar_}, L{cosineLaw}, L{flatLocal} / L{hubeny},
|
|
850
|
+
L{equirectangular}, L{euclidean}, L{haversine}, L{thomas} and L{vincentys}.
|
|
943
851
|
'''
|
|
944
852
|
return _dS(flatPolar_, radius, wrap, lat1, lon1, lat2, lon2)
|
|
945
853
|
|
|
946
854
|
|
|
947
855
|
def flatPolar_(phi2, phi1, lam21):
|
|
948
|
-
'''Compute the I{angular} distance between two (spherical) points
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
formula.
|
|
856
|
+
'''Compute the I{angular} distance between two (spherical) points using the
|
|
857
|
+
U{polar coordinate flat-Earth<https://WikiPedia.org/wiki/Geographical_distance
|
|
858
|
+
#Polar_coordinate_flat-Earth_formula>} formula.
|
|
952
859
|
|
|
953
860
|
@arg phi2: End latitude (C{radians}).
|
|
954
861
|
@arg phi1: Start latitude (C{radians}).
|
|
@@ -956,10 +863,8 @@ def flatPolar_(phi2, phi1, lam21):
|
|
|
956
863
|
|
|
957
864
|
@return: Angular distance (C{radians}).
|
|
958
865
|
|
|
959
|
-
@see: Functions L{flatPolar}, L{
|
|
960
|
-
L{
|
|
961
|
-
L{euclidean_}, L{flatLocal_}/L{hubeny_}, L{haversine_},
|
|
962
|
-
L{thomas_} and L{vincentys_}.
|
|
866
|
+
@see: Functions L{flatPolar}, L{cosineLaw_}, L{euclidean_}, L{flatLocal_} /
|
|
867
|
+
L{hubeny_}, L{haversine_}, L{thomas_} and L{vincentys_}.
|
|
963
868
|
'''
|
|
964
869
|
a = fabs(PI_2 - phi1) # co-latitude
|
|
965
870
|
b = fabs(PI_2 - phi2) # co-latitude
|
|
@@ -1001,14 +906,14 @@ def hartzell(pov, los=False, earth=_WGS84, **name_LatLon_and_kwds):
|
|
|
1001
906
|
or C{None} to point to the center of the earth.
|
|
1002
907
|
@kwarg earth: The earth model (L{Datum}, L{Ellipsoid}, L{Ellipsoid2},
|
|
1003
908
|
L{a_f2Tuple} or a C{scalar} earth radius in C{meter}).
|
|
1004
|
-
@kwarg name_LatLon_and_kwds: Optional
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
909
|
+
@kwarg name_LatLon_and_kwds: Optional C{B{name}="hartzell"} (C{str}), class
|
|
910
|
+
C{B{LatLon}=None} to return the intersection and optionally,
|
|
911
|
+
additional C{LatLon} keyword arguments, include the B{C{datum}}
|
|
912
|
+
if different from and to convert from B{C{earth}}.
|
|
1008
913
|
|
|
1009
|
-
@return: The intersection (L{Vector3d}, B{C{pov}}'s C{cartesian type} or
|
|
1010
|
-
given B{C{LatLon}} instance) with attribute C{height} set to
|
|
1011
|
-
distance to the B{C{pov}}.
|
|
914
|
+
@return: The intersection (L{Vector3d}, B{C{pov}}'s C{cartesian type} or
|
|
915
|
+
the given B{C{LatLon}} instance) with attribute C{height} set to
|
|
916
|
+
the distance to the B{C{pov}}.
|
|
1012
917
|
|
|
1013
918
|
@raise IntersectionError: Invalid B{C{pov}} or B{C{pov}} inside the earth or
|
|
1014
919
|
invalid B{C{los}} or B{C{los}} points outside or
|
|
@@ -1017,30 +922,29 @@ def hartzell(pov, los=False, earth=_WGS84, **name_LatLon_and_kwds):
|
|
|
1017
922
|
@raise TypeError: Invalid B{C{earth}}, C{ellipsoid} or C{datum}.
|
|
1018
923
|
|
|
1019
924
|
@see: Class L{Los}, functions L{tyr3d} and L{hartzell4} and methods
|
|
1020
|
-
L{Ellipsoid.hartzell4}
|
|
925
|
+
L{Ellipsoid.hartzell4}, any C{Cartesian.hartzell} and C{LatLon.hartzell}.
|
|
1021
926
|
'''
|
|
1022
|
-
n,
|
|
927
|
+
n, kwds = _name2__(name_LatLon_and_kwds, name__=hartzell)
|
|
1023
928
|
try:
|
|
1024
929
|
D = _spherical_datum(earth, name__=hartzell)
|
|
1025
930
|
r, h, i = _MODS.triaxials._hartzell3(pov, los, D.ellipsoid._triaxial)
|
|
1026
931
|
|
|
1027
932
|
C = _MODS.cartesianBase.CartesianBase
|
|
1028
|
-
if
|
|
933
|
+
if kwds:
|
|
1029
934
|
c = C(r, datum=D)
|
|
1030
|
-
r = c.toLatLon(**_xkwds(
|
|
935
|
+
r = c.toLatLon(**_xkwds(kwds, height=h))
|
|
1031
936
|
elif isinstance(r, C):
|
|
1032
937
|
r.height = h
|
|
1033
938
|
if i:
|
|
1034
939
|
r._iteration = i
|
|
1035
940
|
except Exception as x:
|
|
1036
|
-
raise IntersectionError(pov=pov, los=los, earth=earth, cause=x,
|
|
1037
|
-
**LatLon_and_kwds)
|
|
941
|
+
raise IntersectionError(pov=pov, los=los, earth=earth, cause=x, **kwds)
|
|
1038
942
|
return _xnamed(r, n) if n else r
|
|
1039
943
|
|
|
1040
944
|
|
|
1041
945
|
def haversine(lat1, lon1, lat2, lon2, radius=R_M, wrap=False):
|
|
1042
|
-
'''Compute the distance between two (spherical) points using the
|
|
1043
|
-
|
|
946
|
+
'''Compute the distance between two (spherical) points using the U{Haversine
|
|
947
|
+
<https://www.Movable-Type.co.UK/scripts/latlong.html>} formula.
|
|
1044
948
|
|
|
1045
949
|
@arg lat1: Start latitude (C{degrees}).
|
|
1046
950
|
@arg lon1: Start longitude (C{degrees}).
|
|
@@ -1056,9 +960,8 @@ def haversine(lat1, lon1, lat2, lon2, radius=R_M, wrap=False):
|
|
|
1056
960
|
@raise TypeError: Invalid B{C{radius}}.
|
|
1057
961
|
|
|
1058
962
|
@see: U{Distance between two (spherical) points
|
|
1059
|
-
<https://www.EdWilliams.org/avform.htm#Dist>}, functions
|
|
1060
|
-
L{
|
|
1061
|
-
L{equirectangular}, L{euclidean}, L{flatLocal}/L{hubeny}, L{flatPolar},
|
|
963
|
+
<https://www.EdWilliams.org/avform.htm#Dist>}, functions L{cosineLaw},
|
|
964
|
+
L{equirectangular}, L{euclidean}, L{flatLocal} / L{hubeny}, L{flatPolar},
|
|
1062
965
|
L{thomas} and L{vincentys} and methods L{Ellipsoid.distance2},
|
|
1063
966
|
C{LatLon.distanceTo*} and C{LatLon.equirectangularTo}.
|
|
1064
967
|
|
|
@@ -1077,18 +980,13 @@ def haversine_(phi2, phi1, lam21):
|
|
|
1077
980
|
|
|
1078
981
|
@return: Angular distance (C{radians}).
|
|
1079
982
|
|
|
1080
|
-
@see: Functions L{haversine}, L{
|
|
1081
|
-
L{
|
|
1082
|
-
L{euclidean_}, L{flatLocal_}/L{hubeny_}, L{flatPolar_},
|
|
1083
|
-
L{thomas_} and L{vincentys_}.
|
|
983
|
+
@see: Functions L{haversine}, L{cosineLaw_}, L{euclidean_}, L{flatLocal_} /
|
|
984
|
+
L{hubeny_}, L{flatPolar_}, L{thomas_} and L{vincentys_}.
|
|
1084
985
|
|
|
1085
986
|
@note: See note at function L{vincentys_}.
|
|
1086
987
|
'''
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
h = _hsin(phi2 - phi1) + cos(phi1) * cos(phi2) * _hsin(lam21) # haversine
|
|
1091
|
-
return atan2(sqrt0(h), sqrt0(_1_0 - h)) * _2_0 # == asin(sqrt(h)) * 2
|
|
988
|
+
h = hav(phi2 - phi1) + cos(phi1) * cos(phi2) * hav(lam21) # haversine
|
|
989
|
+
return atan2(sqrt0(h), sqrt0(_1_0 - h)) * _2_0 # == asin1(sqrt(h)) * 2
|
|
1092
990
|
|
|
1093
991
|
|
|
1094
992
|
def heightOf(angle, distance, radius=R_M):
|
|
@@ -1125,22 +1023,23 @@ def heightOf(angle, distance, radius=R_M):
|
|
|
1125
1023
|
raise _ValueError(angle=angle, distance=distance, radius=radius)
|
|
1126
1024
|
|
|
1127
1025
|
|
|
1128
|
-
def heightOrthometric(
|
|
1026
|
+
def heightOrthometric(h_loc, N):
|
|
1129
1027
|
'''Get the I{orthometric} height B{H}, the height above the geoid, earth surface.
|
|
1130
1028
|
|
|
1131
|
-
@arg
|
|
1132
|
-
|
|
1029
|
+
@arg h_loc: The height above the ellipsoid (C{meter}) or an I{ellipsoidal}
|
|
1030
|
+
location (C{LatLon} or C{Cartesian} with a C{height} or C{h}
|
|
1031
|
+
attribute), otherwise C{0 meter}.
|
|
1133
1032
|
@arg N: The I{geoid} height (C{meter}), the height of the geoid above the
|
|
1134
|
-
ellipsoid at the same B{C{
|
|
1033
|
+
ellipsoid at the same B{C{h_loc}} location.
|
|
1135
1034
|
|
|
1136
1035
|
@return: I{Orthometric} height C{B{H} = B{h} - B{N}} (C{meter}, same units
|
|
1137
1036
|
as B{C{h}} and B{C{N}}).
|
|
1138
1037
|
|
|
1139
|
-
@see: U{Ellipsoid, Geoid, and
|
|
1038
|
+
@see: U{Ellipsoid, Geoid, and Orthometric Heights<https://www.NGS.NOAA.gov/
|
|
1140
1039
|
GEOID/PRESENTATIONS/2007_02_24_CCPS/Roman_A_PLSC2007notes.pdf>}, page
|
|
1141
1040
|
6 and module L{pygeodesy.geoids}.
|
|
1142
1041
|
'''
|
|
1143
|
-
h =
|
|
1042
|
+
h = h_loc if _isHeight(h_loc) else _xattr(h_loc, height=_xattr(h_loc, h=0))
|
|
1144
1043
|
return Height(H=Height(h=h) - Height(N=N))
|
|
1145
1044
|
|
|
1146
1045
|
|
|
@@ -1162,9 +1061,11 @@ def horizon(height, radius=R_M, refraction=False):
|
|
|
1162
1061
|
if min(h, r) < 0:
|
|
1163
1062
|
raise _ValueError(height=height, radius=radius)
|
|
1164
1063
|
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1064
|
+
if refraction:
|
|
1065
|
+
r *= 2.415750694528 # 2.0 / 0.8279
|
|
1066
|
+
else:
|
|
1067
|
+
r += r + h
|
|
1068
|
+
return sqrt0(r * h)
|
|
1168
1069
|
|
|
1169
1070
|
|
|
1170
1071
|
class _idllmn6(object): # see also .geodesicw._wargs, .latlonBase._toCartesian3, .vector2d._numpy
|
|
@@ -1211,8 +1112,8 @@ _idllmn6 = _idllmn6() # PYCHOK singleton
|
|
|
1211
1112
|
|
|
1212
1113
|
def intersection2(lat1, lon1, bearing1,
|
|
1213
1114
|
lat2, lon2, bearing2, datum=None, wrap=False, small=_100km): # was=True
|
|
1214
|
-
'''I{Conveniently} compute the intersection of two lines each defined
|
|
1215
|
-
|
|
1115
|
+
'''I{Conveniently} compute the intersection of two lines each defined by
|
|
1116
|
+
a (geodetic) point and a bearing from North, using either ...
|
|
1216
1117
|
|
|
1217
1118
|
1) L{vector3d.intersection3d3} for B{C{small}} distances (below 100 Km
|
|
1218
1119
|
or about 0.88 degrees) or if I{no} B{C{datum}} is specified, or ...
|
|
@@ -1232,33 +1133,29 @@ def intersection2(lat1, lon1, bearing1,
|
|
|
1232
1133
|
|
|
1233
1134
|
@arg lat1: Latitude of the first point (C{degrees}).
|
|
1234
1135
|
@arg lon1: Longitude of the first point (C{degrees}).
|
|
1235
|
-
@arg bearing1: Bearing at the first point (compass C{
|
|
1136
|
+
@arg bearing1: Bearing at the first point (compass C{degrees360}).
|
|
1236
1137
|
@arg lat2: Latitude of the second point (C{degrees}).
|
|
1237
1138
|
@arg lon2: Longitude of the second point (C{degrees}).
|
|
1238
|
-
@arg bearing2: Bearing at the second point (compass C{
|
|
1139
|
+
@arg bearing2: Bearing at the second point (compass C{degrees360}).
|
|
1239
1140
|
@kwarg datum: Optional datum (L{Datum}) or ellipsoid (L{Ellipsoid},
|
|
1240
|
-
L{Ellipsoid2} or L{a_f2Tuple}) or C{scalar} earth
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll B{C{lat2}}
|
|
1244
|
-
|
|
1141
|
+
L{Ellipsoid2} or L{a_f2Tuple}) or C{scalar} earth radius
|
|
1142
|
+
(C{meter}, same units as B{C{radius1}} and B{C{radius2}})
|
|
1143
|
+
or C{None}.
|
|
1144
|
+
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll B{C{lat2}} and
|
|
1145
|
+
B{C{lon2}} (C{bool}).
|
|
1245
1146
|
@kwarg small: Upper limit for small distances (C{meter}).
|
|
1246
1147
|
|
|
1247
|
-
@return:
|
|
1248
|
-
longitude of the intersection point.
|
|
1148
|
+
@return: Intersection point (L{LatLon2Tuple}C{(lat, lon)}).
|
|
1249
1149
|
|
|
1250
|
-
@raise IntersectionError:
|
|
1251
|
-
|
|
1252
|
-
non-intersecting lines.
|
|
1150
|
+
@raise IntersectionError: No or an ambiguous intersection or colinear,
|
|
1151
|
+
parallel or otherwise non-intersecting lines.
|
|
1253
1152
|
|
|
1254
1153
|
@raise TypeError: Invalid B{C{datum}}.
|
|
1255
1154
|
|
|
1256
|
-
@raise UnitError: Invalid B{C{lat1}}, B{C{lon1}}, B{C{bearing1}},
|
|
1257
|
-
B{C{
|
|
1155
|
+
@raise UnitError: Invalid B{C{lat1}}, B{C{lon1}}, B{C{bearing1}}, B{C{lat2}},
|
|
1156
|
+
B{C{lon2}} or B{C{bearing2}}.
|
|
1258
1157
|
|
|
1259
1158
|
@see: Method L{RhumbLine.intersection2}.
|
|
1260
|
-
|
|
1261
|
-
@note: The returned intersections may be near-antipodal.
|
|
1262
1159
|
'''
|
|
1263
1160
|
b1 = Bearing(bearing1=bearing1)
|
|
1264
1161
|
b2 = Bearing(bearing2=bearing2)
|
|
@@ -1304,26 +1201,24 @@ def intersections2(lat1, lon1, radius1,
|
|
|
1304
1201
|
@arg lat2: Latitude of the second circle center (C{degrees}).
|
|
1305
1202
|
@arg lon2: Longitude of the second circle center (C{degrees}).
|
|
1306
1203
|
@arg radius2: Radius of the second circle (C{meter}, same units as B{C{radius1}}).
|
|
1307
|
-
@kwarg datum: Optional datum (L{Datum}) or ellipsoid (L{Ellipsoid},
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
and B{C{lon2}} (C{bool}).
|
|
1204
|
+
@kwarg datum: Optional datum (L{Datum}) or ellipsoid (L{Ellipsoid}, L{Ellipsoid2}
|
|
1205
|
+
or L{a_f2Tuple}) or C{scalar} earth radius (C{meter}, same units as
|
|
1206
|
+
B{C{radius1}} and B{C{radius2}}) or C{None}.
|
|
1207
|
+
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll B{C{lat2}} and B{C{lon2}}
|
|
1208
|
+
(C{bool}).
|
|
1313
1209
|
@kwarg small: Upper limit for small distances (C{meter}).
|
|
1314
1210
|
|
|
1315
|
-
@return: 2-Tuple of the intersection points, each a
|
|
1316
|
-
|
|
1317
|
-
|
|
1211
|
+
@return: 2-Tuple of the intersection points, each a L{LatLon2Tuple}C{(lat, lon)}.
|
|
1212
|
+
Both points are the same instance, aka the I{radical center} if the
|
|
1213
|
+
circles are abutting
|
|
1318
1214
|
|
|
1319
|
-
@raise IntersectionError: Concentric, antipodal, invalid or
|
|
1320
|
-
|
|
1321
|
-
convergence.
|
|
1215
|
+
@raise IntersectionError: Concentric, antipodal, invalid or non-intersecting
|
|
1216
|
+
circles or no convergence.
|
|
1322
1217
|
|
|
1323
1218
|
@raise TypeError: Invalid B{C{datum}}.
|
|
1324
1219
|
|
|
1325
|
-
@raise UnitError: Invalid B{C{lat1}}, B{C{lon1}}, B{C{radius1}},
|
|
1326
|
-
B{C{
|
|
1220
|
+
@raise UnitError: Invalid B{C{lat1}}, B{C{lon1}}, B{C{radius1}}, B{C{lat2}},
|
|
1221
|
+
B{C{lon2}} or B{C{radius2}}.
|
|
1327
1222
|
'''
|
|
1328
1223
|
r1 = Radius_(radius1=radius1)
|
|
1329
1224
|
r2 = Radius_(radius2=radius2)
|
|
@@ -1397,7 +1292,7 @@ def _isequalTo(p1, p2, eps=EPS):
|
|
|
1397
1292
|
fabs(p1.lon - p2.lon) <= eps) if eps else (p1.latlon == p2.latlon)
|
|
1398
1293
|
|
|
1399
1294
|
|
|
1400
|
-
def _isequalTo_(p1, p2, eps=EPS):
|
|
1295
|
+
def _isequalTo_(p1, p2, eps=EPS): # underscore_!
|
|
1401
1296
|
'''(INTERNAL) Compare 2 point phi-/lams ignoring C{class}.
|
|
1402
1297
|
'''
|
|
1403
1298
|
return (fabs(p1.phi - p2.phi) <= eps and
|
|
@@ -1413,11 +1308,11 @@ def isnormal(lat, lon, eps=0):
|
|
|
1413
1308
|
@kwarg eps: Optional tolerance C{degrees}).
|
|
1414
1309
|
|
|
1415
1310
|
@return: C{True} if C{(abs(B{lat}) + B{eps}) <= 90} and
|
|
1416
|
-
C{(abs(B{lon}) + B{eps}) <= 180}, C{False}
|
|
1311
|
+
C{(abs(B{lon}) + B{eps}) <= 180}, C{False} otherwise.
|
|
1417
1312
|
|
|
1418
1313
|
@see: Functions L{isnormal_} and L{normal}.
|
|
1419
1314
|
'''
|
|
1420
|
-
return (
|
|
1315
|
+
return _loneg(fabs(lon)) >= eps and (_90_0 - fabs(lat)) >= eps # co-latitude
|
|
1421
1316
|
|
|
1422
1317
|
|
|
1423
1318
|
def isnormal_(phi, lam, eps=0):
|
|
@@ -1436,6 +1331,12 @@ def isnormal_(phi, lam, eps=0):
|
|
|
1436
1331
|
return (PI_2 - fabs(phi)) >= eps and (PI - fabs(lam)) >= eps
|
|
1437
1332
|
|
|
1438
1333
|
|
|
1334
|
+
def _maprod(fun_, *ts):
|
|
1335
|
+
'''(INTERNAL) Helper for C{excessCagnoli_} and C{excessLHuilier_}.
|
|
1336
|
+
'''
|
|
1337
|
+
return fprod(map(fun_, ts))
|
|
1338
|
+
|
|
1339
|
+
|
|
1439
1340
|
def _normal2(a, b, n_2, n, n2):
|
|
1440
1341
|
'''(INTERNAL) Helper for C{normal} and C{normal_}.
|
|
1441
1342
|
'''
|
|
@@ -1454,10 +1355,10 @@ def normal(lat, lon, **name):
|
|
|
1454
1355
|
|
|
1455
1356
|
@arg lat: Latitude (C{degrees}).
|
|
1456
1357
|
@arg lon: Longitude (C{degrees}).
|
|
1457
|
-
@kwarg name: Optional
|
|
1358
|
+
@kwarg name: Optional C{B{name}="normal"} (C{str}).
|
|
1458
1359
|
|
|
1459
|
-
@return: L{LatLon2Tuple}C{(lat, lon)} with C{
|
|
1460
|
-
and C{
|
|
1360
|
+
@return: L{LatLon2Tuple}C{(lat, lon)} with C{-90 <= lat <= 90}
|
|
1361
|
+
and C{-180 <= lon <= 180}.
|
|
1461
1362
|
|
|
1462
1363
|
@see: Functions L{normal_} and L{isnormal}.
|
|
1463
1364
|
'''
|
|
@@ -1470,7 +1371,7 @@ def normal_(phi, lam, **name):
|
|
|
1470
1371
|
|
|
1471
1372
|
@arg phi: Latitude (C{radians}).
|
|
1472
1373
|
@arg lam: Longitude (C{radians}).
|
|
1473
|
-
@kwarg name: Optional
|
|
1374
|
+
@kwarg name: Optional C{B{name}="normal_"} (C{str}).
|
|
1474
1375
|
|
|
1475
1376
|
@return: L{PhiLam2Tuple}C{(phi, lam)} with C{abs(phi) <= PI/2}
|
|
1476
1377
|
and C{abs(lam) <= PI}.
|
|
@@ -1544,29 +1445,24 @@ def _radical2(d, r1, r2, **name): # in .ellipsoidalBaseDI, .sphericalTrigonomet
|
|
|
1544
1445
|
|
|
1545
1446
|
|
|
1546
1447
|
def radical2(distance, radius1, radius2, **name):
|
|
1547
|
-
'''Compute the I{radical ratio} and I{radical line} of two
|
|
1548
|
-
|
|
1549
|
-
Circle-CircleIntersection.html>}.
|
|
1448
|
+
'''Compute the I{radical ratio} and I{radical line} of two U{intersecting
|
|
1449
|
+
circles<https://MathWorld.Wolfram.com/Circle-CircleIntersection.html>}.
|
|
1550
1450
|
|
|
1551
|
-
The I{radical line} is perpendicular to the axis thru the
|
|
1552
|
-
|
|
1451
|
+
The I{radical line} is perpendicular to the axis thru the centers of
|
|
1452
|
+
the circles at C{(0, 0)} and C{(B{distance}, 0)}.
|
|
1553
1453
|
|
|
1554
1454
|
@arg distance: Distance between the circle centers (C{scalar}).
|
|
1555
1455
|
@arg radius1: Radius of the first circle (C{scalar}).
|
|
1556
1456
|
@arg radius2: Radius of the second circle (C{scalar}).
|
|
1557
1457
|
@kwarg name: Optional C{B{name}=NN} (C{str}).
|
|
1558
1458
|
|
|
1559
|
-
@return: A L{Radical2Tuple}C{(ratio, xline)} where C{0.0 <=
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
@raise IntersectionError: The B{C{distance}} exceeds the sum
|
|
1563
|
-
of B{C{radius1}} and B{C{radius2}}.
|
|
1459
|
+
@return: A L{Radical2Tuple}C{(ratio, xline)} where C{0.0 <= ratio <=
|
|
1460
|
+
1.0} and C{xline} is along the B{C{distance}}.
|
|
1564
1461
|
|
|
1565
|
-
@raise
|
|
1566
|
-
|
|
1462
|
+
@raise IntersectionError: The B{C{distance}} exceeds the sum of
|
|
1463
|
+
B{C{radius1}} and B{C{radius2}}.
|
|
1567
1464
|
|
|
1568
|
-
@
|
|
1569
|
-
<https://MathWorld.Wolfram.com/Circle-CircleIntersection.html>}.
|
|
1465
|
+
@raise UnitError: Invalid B{C{distance}}, B{C{radius1}} or B{C{radius2}}.
|
|
1570
1466
|
'''
|
|
1571
1467
|
d = Distance_(distance, low=_0_0)
|
|
1572
1468
|
r1 = Radius_(radius1=radius1)
|
|
@@ -1633,57 +1529,53 @@ def _sincosa6(phi2, phi1, lam21): # [4] in cosineLaw
|
|
|
1633
1529
|
|
|
1634
1530
|
|
|
1635
1531
|
def thomas(lat1, lon1, lat2, lon2, datum=_WGS84, wrap=False):
|
|
1636
|
-
'''Compute the distance between two (ellipsoidal) points using
|
|
1637
|
-
|
|
1638
|
-
formula.
|
|
1532
|
+
'''Compute the distance between two (ellipsoidal) points using U{Thomas'
|
|
1533
|
+
<https://apps.DTIC.mil/dtic/tr/fulltext/u2/703541.pdf>} formula.
|
|
1639
1534
|
|
|
1640
1535
|
@arg lat1: Start latitude (C{degrees}).
|
|
1641
1536
|
@arg lon1: Start longitude (C{degrees}).
|
|
1642
1537
|
@arg lat2: End latitude (C{degrees}).
|
|
1643
1538
|
@arg lon2: End longitude (C{degrees}).
|
|
1644
|
-
@kwarg datum: Datum (L{Datum}) or ellipsoid (L{Ellipsoid},
|
|
1645
|
-
|
|
1646
|
-
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll
|
|
1647
|
-
B{C{
|
|
1539
|
+
@kwarg datum: Datum (L{Datum}) or ellipsoid (L{Ellipsoid}, L{Ellipsoid2}
|
|
1540
|
+
or L{a_f2Tuple}) to use.
|
|
1541
|
+
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll B{C{lat2}} and
|
|
1542
|
+
B{C{lon2}} (C{bool}).
|
|
1648
1543
|
|
|
1649
|
-
@return: Distance (C{meter}, same units as the B{C{datum}}'s
|
|
1650
|
-
ellipsoid axes).
|
|
1544
|
+
@return: Distance (C{meter}, same units as the B{C{datum}}'s or ellipsoid axes).
|
|
1651
1545
|
|
|
1652
1546
|
@raise TypeError: Invalid B{C{datum}}.
|
|
1653
1547
|
|
|
1654
|
-
@see: Functions L{thomas_}, L{
|
|
1655
|
-
L{
|
|
1656
|
-
|
|
1548
|
+
@see: Functions L{thomas_}, L{cosineLaw}, L{equirectangular}, L{euclidean},
|
|
1549
|
+
L{flatLocal} / L{hubeny}, L{flatPolar}, L{haversine}, L{vincentys} and
|
|
1550
|
+
method L{Ellipsoid.distance2}.
|
|
1657
1551
|
'''
|
|
1658
1552
|
return _dE(thomas_, datum, wrap, lat1, lon1, lat2, lon2)
|
|
1659
1553
|
|
|
1660
1554
|
|
|
1661
1555
|
def thomas_(phi2, phi1, lam21, datum=_WGS84):
|
|
1662
1556
|
'''Compute the I{angular} distance between two (ellipsoidal) points using
|
|
1663
|
-
U{Thomas'<https://apps.DTIC.mil/dtic/tr/fulltext/u2/703541.pdf>}
|
|
1664
|
-
formula.
|
|
1557
|
+
U{Thomas'<https://apps.DTIC.mil/dtic/tr/fulltext/u2/703541.pdf>} formula.
|
|
1665
1558
|
|
|
1666
1559
|
@arg phi2: End latitude (C{radians}).
|
|
1667
1560
|
@arg phi1: Start latitude (C{radians}).
|
|
1668
1561
|
@arg lam21: Longitudinal delta, M{end-start} (C{radians}).
|
|
1669
|
-
@kwarg datum: Datum or ellipsoid to use (L{
|
|
1562
|
+
@kwarg datum: Datum (L{Datum}) ?or ellipsoid to use (L{Ellipsoid},
|
|
1670
1563
|
L{Ellipsoid2} or L{a_f2Tuple}).
|
|
1671
1564
|
|
|
1672
1565
|
@return: Angular distance (C{radians}).
|
|
1673
1566
|
|
|
1674
1567
|
@raise TypeError: Invalid B{C{datum}}.
|
|
1675
1568
|
|
|
1676
|
-
@see: Functions L{thomas}, L{
|
|
1677
|
-
L{
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
<https://GitHub.com/jtejido/geodesy-php/blob/master/src/Geodesy/
|
|
1681
|
-
Distance/ThomasFormula.php>}.
|
|
1569
|
+
@see: Functions L{thomas}, L{cosineLaw_}, L{euclidean_}, L{flatLocal_} /
|
|
1570
|
+
L{hubeny_}, L{flatPolar_}, L{haversine_} and L{vincentys_} and
|
|
1571
|
+
U{Geodesy-PHP<https://GitHub.com/jtejido/geodesy-php/blob/master/
|
|
1572
|
+
src/Geodesy/Distance/ThomasFormula.php>}.
|
|
1682
1573
|
'''
|
|
1683
1574
|
s2, c2, s1, c1, r, _ = _sincosa6(phi2, phi1, lam21)
|
|
1684
1575
|
if r and isnon0(c1) and isnon0(c2):
|
|
1685
1576
|
E = _ellipsoidal(datum, thomas_)
|
|
1686
|
-
|
|
1577
|
+
f = E.f * _0_25
|
|
1578
|
+
if f: # ellipsoidal
|
|
1687
1579
|
r1 = atan2(E.b_a * s1, c1)
|
|
1688
1580
|
r2 = atan2(E.b_a * s2, c2)
|
|
1689
1581
|
|
|
@@ -1697,21 +1589,20 @@ def thomas_(phi2, phi1, lam21, datum=_WGS84):
|
|
|
1697
1589
|
r = atan(sqrt0(h / u)) * 2 # == acos(1 - 2 * h)
|
|
1698
1590
|
sr, cr = sincos2(r)
|
|
1699
1591
|
if isnon0(sr):
|
|
1700
|
-
u =
|
|
1701
|
-
h =
|
|
1592
|
+
u = (sj * ck)**2 * 2 / u
|
|
1593
|
+
h = (sk * cj)**2 * 2 / h
|
|
1702
1594
|
x = u + h
|
|
1703
1595
|
y = u - h
|
|
1704
1596
|
|
|
1597
|
+
b = r * 2
|
|
1705
1598
|
s = r / sr
|
|
1706
1599
|
e = 4 * s**2
|
|
1707
1600
|
d = 2 * cr
|
|
1708
1601
|
a = e * d
|
|
1709
|
-
b = 2 * r
|
|
1710
1602
|
c = s - (a - d) * _0_5
|
|
1711
|
-
f = E.f * _0_25
|
|
1712
1603
|
|
|
1713
|
-
t =
|
|
1714
|
-
r -=
|
|
1604
|
+
t = fdot_(a, x, -b, y, -d, y**2, c, x**2, e, x * y) * _0_25
|
|
1605
|
+
r -= fdot_(s, x, -1, y, -t, f) * f * sr
|
|
1715
1606
|
return r
|
|
1716
1607
|
|
|
1717
1608
|
|
|
@@ -1724,21 +1615,20 @@ def vincentys(lat1, lon1, lat2, lon2, radius=R_M, wrap=False):
|
|
|
1724
1615
|
@arg lon1: Start longitude (C{degrees}).
|
|
1725
1616
|
@arg lat2: End latitude (C{degrees}).
|
|
1726
1617
|
@arg lon2: End longitude (C{degrees}).
|
|
1727
|
-
@kwarg radius: Mean earth radius (C{meter}), datum (L{Datum})
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll
|
|
1731
|
-
B{C{
|
|
1618
|
+
@kwarg radius: Mean earth radius (C{meter}), datum (L{Datum}) or
|
|
1619
|
+
ellipsoid (L{Ellipsoid}, L{Ellipsoid2} or L{a_f2Tuple})
|
|
1620
|
+
to use.
|
|
1621
|
+
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll B{C{lat2}} and
|
|
1622
|
+
B{C{lon2}} (C{bool}).
|
|
1732
1623
|
|
|
1733
1624
|
@return: Distance (C{meter}, same units as B{C{radius}}).
|
|
1734
1625
|
|
|
1735
1626
|
@raise UnitError: Invalid B{C{radius}}.
|
|
1736
1627
|
|
|
1737
|
-
@see: Functions L{vincentys_}, L{
|
|
1738
|
-
L{
|
|
1739
|
-
L{
|
|
1740
|
-
|
|
1741
|
-
C{LatLon.distanceTo*} and C{LatLon.equirectangularTo}.
|
|
1628
|
+
@see: Functions L{vincentys_}, L{cosineLaw}, L{equirectangular}, L{euclidean},
|
|
1629
|
+
L{flatLocal}/L{hubeny}, L{flatPolar}, L{haversine} and L{thomas} and
|
|
1630
|
+
methods L{Ellipsoid.distance2}, C{LatLon.distanceTo*} and
|
|
1631
|
+
C{LatLon.equirectangularTo}.
|
|
1742
1632
|
|
|
1743
1633
|
@note: See note at function L{vincentys_}.
|
|
1744
1634
|
'''
|
|
@@ -1756,17 +1646,14 @@ def vincentys_(phi2, phi1, lam21):
|
|
|
1756
1646
|
|
|
1757
1647
|
@return: Angular distance (C{radians}).
|
|
1758
1648
|
|
|
1759
|
-
@see: Functions L{vincentys}, L{
|
|
1760
|
-
L{
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
3 sin, 1 hypot, 1 atan2, 6 mul, 2 add}) than L{haversine_}
|
|
1768
|
-
(M{2 cos, 2 sin, 2 sqrt, 1 atan2, 5 mul, 1 add}) and
|
|
1769
|
-
L{cosineLaw_} (M{3 cos, 3 sin, 1 acos, 3 mul, 1 add}).
|
|
1649
|
+
@see: Functions L{vincentys}, L{cosineLaw_}, L{euclidean_}, L{flatLocal_} /
|
|
1650
|
+
L{hubeny_}, L{flatPolar_}, L{haversine_} and L{thomas_}.
|
|
1651
|
+
|
|
1652
|
+
@note: Functions L{vincentys_}, L{haversine_} and L{cosineLaw_} produce
|
|
1653
|
+
equivalent results, but L{vincentys_} is suitable for antipodal
|
|
1654
|
+
points and slightly more expensive (M{3 cos, 3 sin, 1 hypot, 1 atan2,
|
|
1655
|
+
6 mul, 2 add}) than L{haversine_} (M{2 cos, 2 sin, 2 sqrt, 1 atan2, 5
|
|
1656
|
+
mul, 1 add}) and L{cosineLaw_} (M{3 cos, 3 sin, 1 acos, 3 mul, 1 add}).
|
|
1770
1657
|
'''
|
|
1771
1658
|
s1, c1, s2, c2, s21, c21 = sincos2_(phi1, phi2, lam21)
|
|
1772
1659
|
|