pygeodesy 24.11.11__py2.py3-none-any.whl → 25.1.5__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.11.11.dist-info → PyGeodesy-25.1.5.dist-info}/METADATA +34 -35
- PyGeodesy-25.1.5.dist-info/RECORD +118 -0
- {PyGeodesy-24.11.11.dist-info → PyGeodesy-25.1.5.dist-info}/WHEEL +1 -1
- pygeodesy/__init__.py +19 -19
- pygeodesy/__main__.py +1 -1
- pygeodesy/albers.py +5 -5
- pygeodesy/auxilats/_CX_4.py +1 -1
- pygeodesy/auxilats/_CX_6.py +1 -1
- pygeodesy/auxilats/_CX_8.py +1 -1
- pygeodesy/auxilats/_CX_Rs.py +1 -1
- pygeodesy/auxilats/__init__.py +1 -1
- pygeodesy/auxilats/__main__.py +1 -1
- pygeodesy/auxilats/auxAngle.py +5 -5
- pygeodesy/auxilats/auxDLat.py +6 -6
- pygeodesy/auxilats/auxDST.py +2 -2
- pygeodesy/auxilats/auxLat.py +5 -5
- pygeodesy/auxilats/auxily.py +2 -2
- pygeodesy/azimuthal.py +5 -5
- pygeodesy/basics.py +60 -8
- pygeodesy/booleans.py +1 -1
- pygeodesy/cartesianBase.py +22 -61
- pygeodesy/clipy.py +1 -1
- pygeodesy/constants.py +5 -5
- pygeodesy/css.py +1 -1
- pygeodesy/datums.py +1 -1
- pygeodesy/deprecated/__init__.py +2 -2
- pygeodesy/deprecated/bases.py +1 -1
- pygeodesy/deprecated/classes.py +86 -2
- pygeodesy/deprecated/consterns.py +1 -1
- pygeodesy/deprecated/datum.py +5 -5
- pygeodesy/deprecated/functions.py +42 -8
- pygeodesy/deprecated/nvector.py +1 -1
- pygeodesy/deprecated/rhumbBase.py +1 -1
- pygeodesy/deprecated/rhumbaux.py +1 -1
- pygeodesy/deprecated/rhumbsolve.py +1 -1
- pygeodesy/deprecated/rhumbx.py +1 -1
- pygeodesy/dms.py +1 -1
- pygeodesy/ecef.py +53 -56
- pygeodesy/elevations.py +1 -1
- pygeodesy/ellipsoidalBase.py +3 -3
- pygeodesy/ellipsoidalBaseDI.py +1 -1
- pygeodesy/ellipsoidalExact.py +1 -1
- pygeodesy/ellipsoidalGeodSolve.py +1 -1
- pygeodesy/ellipsoidalKarney.py +1 -1
- pygeodesy/ellipsoidalNvector.py +1 -1
- pygeodesy/ellipsoidalVincenty.py +6 -5
- pygeodesy/ellipsoids.py +4 -5
- pygeodesy/elliptic.py +6 -6
- pygeodesy/epsg.py +1 -1
- pygeodesy/errors.py +1 -1
- pygeodesy/etm.py +5 -5
- pygeodesy/fmath.py +18 -17
- pygeodesy/formy.py +409 -555
- pygeodesy/frechet.py +29 -86
- pygeodesy/fstats.py +1 -1
- pygeodesy/fsums.py +32 -33
- pygeodesy/gars.py +1 -1
- pygeodesy/geodesici.py +7 -7
- pygeodesy/geodesicw.py +1 -1
- pygeodesy/geodesicx/_C4_24.py +2 -2
- pygeodesy/geodesicx/_C4_27.py +2 -2
- pygeodesy/geodesicx/_C4_30.py +2 -2
- pygeodesy/geodesicx/__init__.py +2 -2
- pygeodesy/geodesicx/__main__.py +4 -5
- pygeodesy/geodesicx/gx.py +6 -5
- pygeodesy/geodesicx/gxarea.py +2 -2
- pygeodesy/geodesicx/gxbases.py +2 -2
- pygeodesy/geodesicx/gxline.py +16 -12
- pygeodesy/geodsolve.py +1 -1
- pygeodesy/geohash.py +1 -1
- pygeodesy/geoids.py +277 -203
- pygeodesy/hausdorff.py +23 -81
- pygeodesy/heights.py +115 -150
- pygeodesy/internals.py +1 -1
- pygeodesy/interns.py +2 -3
- pygeodesy/iters.py +1 -1
- pygeodesy/karney.py +3 -3
- pygeodesy/ktm.py +16 -15
- pygeodesy/latlonBase.py +323 -409
- pygeodesy/lazily.py +53 -44
- pygeodesy/lcc.py +1 -1
- pygeodesy/ltp.py +46 -50
- pygeodesy/ltpTuples.py +147 -130
- pygeodesy/mgrs.py +1 -1
- pygeodesy/named.py +149 -3
- pygeodesy/namedTuples.py +58 -7
- pygeodesy/nvectorBase.py +122 -105
- pygeodesy/osgr.py +1 -1
- pygeodesy/points.py +1 -1
- pygeodesy/props.py +1 -1
- pygeodesy/resections.py +18 -17
- pygeodesy/rhumb/__init__.py +1 -1
- pygeodesy/rhumb/aux_.py +2 -2
- pygeodesy/rhumb/bases.py +2 -2
- pygeodesy/rhumb/ekx.py +4 -4
- pygeodesy/rhumb/solve.py +1 -1
- pygeodesy/simplify.py +289 -401
- pygeodesy/solveBase.py +1 -1
- pygeodesy/sphericalBase.py +1 -1
- pygeodesy/sphericalNvector.py +5 -5
- pygeodesy/sphericalTrigonometry.py +7 -6
- pygeodesy/streprs.py +10 -5
- pygeodesy/trf.py +1 -1
- pygeodesy/triaxials.py +23 -16
- pygeodesy/units.py +16 -16
- pygeodesy/unitsBase.py +1 -1
- pygeodesy/ups.py +4 -4
- pygeodesy/utily.py +341 -211
- pygeodesy/utm.py +5 -5
- pygeodesy/utmups.py +1 -1
- pygeodesy/utmupsBase.py +1 -1
- pygeodesy/vector2d.py +5 -5
- pygeodesy/vector3d.py +14 -3
- pygeodesy/vector3dBase.py +5 -5
- pygeodesy/webmercator.py +1 -1
- pygeodesy/wgrs.py +1 -1
- PyGeodesy-24.11.11.dist-info/RECORD +0 -118
- {PyGeodesy-24.11.11.dist-info → PyGeodesy-25.1.5.dist-info}/top_level.txt +0 -0
pygeodesy/formy.py
CHANGED
|
@@ -6,19 +6,19 @@ u'''Formulary of basic geodesy functions and approximations.
|
|
|
6
6
|
# make sure int/int division yields float quotient, see .basics
|
|
7
7
|
from __future__ import division as _; del _ # PYCHOK semicolon
|
|
8
8
|
|
|
9
|
-
# from pygeodesy.basics import
|
|
9
|
+
# from pygeodesy.basics import _args_kwds_count2, _copysign # from .constants
|
|
10
10
|
# from pygeodesy.cartesianBase import CartesianBase # _MODS
|
|
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_
|
|
@@ -26,30 +26,47 @@ from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS
|
|
|
26
26
|
from pygeodesy.named import _name__, _name2__, _NamedTuple, _xnamed, \
|
|
27
27
|
_DUNDER_nameof
|
|
28
28
|
from pygeodesy.namedTuples import Bearing2Tuple, Distance4Tuple, LatLon2Tuple, \
|
|
29
|
-
Intersection3Tuple, PhiLam2Tuple
|
|
29
|
+
Intersection3Tuple, PhiLam2Tuple
|
|
30
30
|
# from pygeodesy.streprs import Fmt, unstr # from .fsums
|
|
31
31
|
# from pygeodesy.triaxials import _hartzell3 # _MODS
|
|
32
|
-
from pygeodesy.units import _isHeight, _isRadius, Bearing, Degrees_,
|
|
33
|
-
Distance_, Height, Lamd, Lat, Lon, Meter_,
|
|
34
|
-
Radians, Radians_, Radius, Radius_, Scalar, _100km
|
|
35
|
-
from pygeodesy.utily import acos1,
|
|
36
|
-
tan_2, sincos2, sincos2_,
|
|
32
|
+
from pygeodesy.units import _isDegrees, _isHeight, _isRadius, Bearing, Degrees_, \
|
|
33
|
+
Distance, Distance_, Height, Lamd, Lat, Lon, Meter_, \
|
|
34
|
+
Phid, Radians, Radians_, Radius, Radius_, Scalar, _100km
|
|
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
|
|
|
52
52
|
|
|
53
|
+
def angle2chord(rad, radius=R_M):
|
|
54
|
+
'''Get the chord length of a (central) angle or I{angular} distance.
|
|
55
|
+
|
|
56
|
+
@arg rad: Central angle (C{radians}).
|
|
57
|
+
@kwarg radius: Mean earth radius (C{meter}, conventionally), datum (L{Datum}) or ellipsoid
|
|
58
|
+
(L{Ellipsoid}, L{Ellipsoid2} or L{a_f2Tuple}) to use or C{None}.
|
|
59
|
+
|
|
60
|
+
@return: Chord length (C{meter}, same units as B{C{radius}} or if C{B{radius} is None}, C{radians}).
|
|
61
|
+
|
|
62
|
+
@see: Function L{chord2angle}, method L{intermediateChordTo<sphericalNvector.LatLon.intermediateChordTo>} and
|
|
63
|
+
U{great-circle-distance<https://WikiPedia.org/wiki/Great-circle_distance#Relation_between_central_angle_and_chord_length>}.
|
|
64
|
+
'''
|
|
65
|
+
d = _isDegrees(rad, iscalar=False)
|
|
66
|
+
r = sin((radians(rad) if d else rad) / _2_0) * _2_0
|
|
67
|
+
return (degrees(r) if d else r) if radius is None else (_mean_radius(radius) * r)
|
|
68
|
+
|
|
69
|
+
|
|
53
70
|
def _anti2(a, b, n_2, n, n2):
|
|
54
71
|
'''(INTERNAL) Helper for C{antipode} and C{antipode_}.
|
|
55
72
|
'''
|
|
@@ -95,18 +112,17 @@ def antipode_(phi, lam, **name):
|
|
|
95
112
|
|
|
96
113
|
|
|
97
114
|
def bearing(lat1, lon1, lat2, lon2, **final_wrap):
|
|
98
|
-
'''Compute the initial or final bearing (forward or reverse azimuth)
|
|
99
|
-
|
|
115
|
+
'''Compute the initial or final bearing (forward or reverse azimuth) between two
|
|
116
|
+
(spherical) points.
|
|
100
117
|
|
|
101
118
|
@arg lat1: Start latitude (C{degrees}).
|
|
102
119
|
@arg lon1: Start longitude (C{degrees}).
|
|
103
120
|
@arg lat2: End latitude (C{degrees}).
|
|
104
121
|
@arg lon2: End longitude (C{degrees}).
|
|
105
|
-
@kwarg final_wrap: Optional keyword arguments for function
|
|
106
|
-
L{pygeodesy.bearing_}.
|
|
122
|
+
@kwarg final_wrap: Optional keyword arguments for function L{pygeodesy.bearing_}.
|
|
107
123
|
|
|
108
|
-
@return: Initial or final bearing (compass C{degrees360}) or zero if
|
|
109
|
-
|
|
124
|
+
@return: Initial or final bearing (compass C{degrees360}) or zero if both points
|
|
125
|
+
coincide.
|
|
110
126
|
'''
|
|
111
127
|
r = bearing_(Phid(lat1=lat1), Lamd(lon1=lon1),
|
|
112
128
|
Phid(lat2=lat2), Lamd(lon2=lon2), **final_wrap)
|
|
@@ -114,20 +130,19 @@ def bearing(lat1, lon1, lat2, lon2, **final_wrap):
|
|
|
114
130
|
|
|
115
131
|
|
|
116
132
|
def bearing_(phi1, lam1, phi2, lam2, final=False, wrap=False):
|
|
117
|
-
'''Compute the initial or final bearing (forward or reverse azimuth) between
|
|
118
|
-
|
|
133
|
+
'''Compute the initial or final bearing (forward or reverse azimuth) between two
|
|
134
|
+
(spherical) points.
|
|
119
135
|
|
|
120
136
|
@arg phi1: Start latitude (C{radians}).
|
|
121
137
|
@arg lam1: Start longitude (C{radians}).
|
|
122
138
|
@arg phi2: End latitude (C{radians}).
|
|
123
139
|
@arg lam2: End longitude (C{radians}).
|
|
124
|
-
@kwarg final: If C{True}, return the final, otherwise the initial bearing
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
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}).
|
|
128
143
|
|
|
129
|
-
@return: Initial or final bearing (compass C{radiansPI2}) or zero if both
|
|
130
|
-
|
|
144
|
+
@return: Initial or final bearing (compass C{radiansPI2}) or zero if both points
|
|
145
|
+
coincide.
|
|
131
146
|
|
|
132
147
|
@see: U{Bearing<https://www.Movable-Type.co.UK/scripts/latlong.html>}, U{Course
|
|
133
148
|
between two points<https://www.EdWilliams.org/avform147.htm#Crs>} and
|
|
@@ -156,11 +171,36 @@ def _bearingTo2(p1, p2, wrap=False): # for points.ispolar, sphericalTrigonometr
|
|
|
156
171
|
pass
|
|
157
172
|
# XXX spherical version, OK for ellipsoidal ispolar?
|
|
158
173
|
t = p1.philam + p2.philam
|
|
159
|
-
|
|
160
|
-
|
|
174
|
+
i = bearing_(*t, final=False, wrap=wrap)
|
|
175
|
+
f = bearing_(*t, final=True, wrap=wrap)
|
|
176
|
+
return Bearing2Tuple(degrees(i), degrees(f),
|
|
161
177
|
name__=_bearingTo2)
|
|
162
178
|
|
|
163
179
|
|
|
180
|
+
def chord2angle(chord, radius=R_M):
|
|
181
|
+
'''Get the (central) angle from a chord length or distance.
|
|
182
|
+
|
|
183
|
+
@arg chord: Length or distance (C{meter}, same units as B{C{radius}}).
|
|
184
|
+
@kwarg radius: Mean earth radius (C{meter}, conventionally), datum (L{Datum}) or
|
|
185
|
+
ellipsoid (L{Ellipsoid}, L{Ellipsoid2} or L{a_f2Tuple}) to use.
|
|
186
|
+
|
|
187
|
+
@return: Angle (C{radians} with sign of B{C{chord}}) or C{0} if C{B{radius}=0}.
|
|
188
|
+
|
|
189
|
+
@note: The angle will exceed C{PI} if C{B{chord} > B{radius} * 2}.
|
|
190
|
+
|
|
191
|
+
@see: Function L{angle2chord}.
|
|
192
|
+
'''
|
|
193
|
+
m = _mean_radius(radius)
|
|
194
|
+
r = fabs(chord / (m * _2_0)) if m > 0 else _0_0
|
|
195
|
+
if r:
|
|
196
|
+
i = int(r)
|
|
197
|
+
if i > 0:
|
|
198
|
+
r -= i
|
|
199
|
+
i *= PI
|
|
200
|
+
r = (asin1(r) + i) * _2_0
|
|
201
|
+
return _copysign(r, chord)
|
|
202
|
+
|
|
203
|
+
|
|
164
204
|
def compassAngle(lat1, lon1, lat2, lon2, adjust=True, wrap=False):
|
|
165
205
|
'''Return the angle from North for the direction vector M{(lon2 - lon1,
|
|
166
206
|
lat2 - lat1)} between two points.
|
|
@@ -172,10 +212,10 @@ def compassAngle(lat1, lon1, lat2, lon2, adjust=True, wrap=False):
|
|
|
172
212
|
@arg lon1: From longitude (C{degrees}).
|
|
173
213
|
@arg lat2: To latitude (C{degrees}).
|
|
174
214
|
@arg lon2: To longitude (C{degrees}).
|
|
175
|
-
@kwarg adjust: Adjust the longitudinal delta by the cosine of the
|
|
176
|
-
|
|
177
|
-
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll B{C{lat2}}
|
|
178
|
-
|
|
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}).
|
|
179
219
|
|
|
180
220
|
@return: Compass angle from North (C{degrees360}).
|
|
181
221
|
|
|
@@ -190,230 +230,144 @@ def compassAngle(lat1, lon1, lat2, lon2, adjust=True, wrap=False):
|
|
|
190
230
|
return atan2b(d_lon, lat2 - lat1)
|
|
191
231
|
|
|
192
232
|
|
|
193
|
-
def
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
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.
|
|
197
238
|
|
|
198
239
|
@arg lat1: Start latitude (C{degrees}).
|
|
199
240
|
@arg lon1: Start longitude (C{degrees}).
|
|
200
241
|
@arg lat2: End latitude (C{degrees}).
|
|
201
242
|
@arg lon2: End longitude (C{degrees}).
|
|
202
|
-
@kwarg
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
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).
|
|
206
254
|
|
|
207
|
-
@return: Distance (C{meter}, same units as
|
|
208
|
-
|
|
255
|
+
@return: Distance (C{meter}, same units as B{C{radius}} or the datum's or
|
|
256
|
+
ellipsoid axes).
|
|
209
257
|
|
|
210
|
-
@raise TypeError: Invalid B{C{datum}}.
|
|
258
|
+
@raise TypeError: Invalid B{C{earth}}, B{C{datum}} or B{C{radius}}.
|
|
211
259
|
|
|
212
|
-
@
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
L{
|
|
260
|
+
@raise ValueError: Invalid B{C{corr}}.
|
|
261
|
+
|
|
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_}.
|
|
216
267
|
'''
|
|
217
|
-
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)
|
|
218
270
|
|
|
219
271
|
|
|
220
|
-
def
|
|
221
|
-
'''Compute the I{angular} distance between two
|
|
222
|
-
<https://
|
|
223
|
-
|
|
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.
|
|
224
276
|
|
|
225
277
|
@arg phi2: End latitude (C{radians}).
|
|
226
278
|
@arg phi1: Start latitude (C{radians}).
|
|
227
279
|
@arg lam21: Longitudinal delta, M{end-start} (C{radians}).
|
|
228
|
-
@kwarg
|
|
229
|
-
|
|
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).
|
|
230
288
|
|
|
231
289
|
@return: Angular distance (C{radians}).
|
|
232
290
|
|
|
233
|
-
@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}}.
|
|
234
294
|
|
|
235
|
-
@see: Functions L{
|
|
236
|
-
L{
|
|
237
|
-
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
|
|
238
297
|
<https://GitHub.com/jtejido/geodesy-php/blob/master/src/Geodesy/Distance/
|
|
239
298
|
AndoyerLambert.php>}.
|
|
240
299
|
'''
|
|
241
300
|
s2, c2, s1, c1, r, c21 = _sincosa6(phi2, phi1, lam21)
|
|
242
|
-
if isnon0(c1) and isnon0(c2):
|
|
243
|
-
E = _ellipsoidal(datum,
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
if
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
@see: Functions L{cosineForsytheAndoyerLambert_}, L{cosineAndoyerLambert},
|
|
278
|
-
L{cosineLaw}, L{equirectangular}, L{euclidean}, L{flatLocal}/L{hubeny},
|
|
279
|
-
L{flatPolar}, L{haversine}, L{thomas} and L{vincentys} and method
|
|
280
|
-
L{Ellipsoid.distance2}.
|
|
281
|
-
'''
|
|
282
|
-
return _dE(cosineForsytheAndoyerLambert_, datum, wrap, lat1, lon1, lat2, lon2)
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
def cosineForsytheAndoyerLambert_(phi2, phi1, lam21, datum=_WGS84):
|
|
286
|
-
'''Compute the I{angular} distance between two (ellipsoidal) points using the
|
|
287
|
-
U{Forsythe-Andoyer-Lambert<https://www2.UNB.Ca/gge/Pubs/TR77.pdf>} correction of
|
|
288
|
-
the U{Law of Cosines<https://www.Movable-Type.co.UK/scripts/latlong.html#cosine-law>}
|
|
289
|
-
formula.
|
|
290
|
-
|
|
291
|
-
@arg phi2: End latitude (C{radians}).
|
|
292
|
-
@arg phi1: Start latitude (C{radians}).
|
|
293
|
-
@arg lam21: Longitudinal delta, M{end-start} (C{radians}).
|
|
294
|
-
@kwarg datum: Datum (L{Datum}) or ellipsoid to use (L{Ellipsoid},
|
|
295
|
-
L{Ellipsoid2} or L{a_f2Tuple}).
|
|
296
|
-
|
|
297
|
-
@return: Angular distance (C{radians}).
|
|
298
|
-
|
|
299
|
-
@raise TypeError: Invalid B{C{datum}}.
|
|
300
|
-
|
|
301
|
-
@see: Functions L{cosineForsytheAndoyerLambert}, L{cosineAndoyerLambert_},
|
|
302
|
-
L{cosineLaw_}, L{euclidean_}, L{flatLocal_}/L{hubeny_}, L{flatPolar_},
|
|
303
|
-
L{haversine_}, L{thomas_} and L{vincentys_} and U{Geodesy-PHP
|
|
304
|
-
<https://GitHub.com/jtejido/geodesy-php/blob/master/src/Geodesy/
|
|
305
|
-
Distance/ForsytheCorrection.php>}.
|
|
306
|
-
'''
|
|
307
|
-
s2, c2, s1, c1, r, _ = _sincosa6(phi2, phi1, lam21)
|
|
308
|
-
if r and isnon0(c1) and isnon0(c2):
|
|
309
|
-
E = _ellipsoidal(datum, cosineForsytheAndoyerLambert_)
|
|
310
|
-
if E.f: # ellipsoidal
|
|
311
|
-
sr, cr, s2r, _ = sincos2_(r, r * 2)
|
|
312
|
-
if isnon0(sr) and fabs(cr) < EPS1:
|
|
313
|
-
s = (s1 + s2)**2 / (1 + cr)
|
|
314
|
-
t = (s1 - s2)**2 / (1 - cr)
|
|
315
|
-
x = s + t
|
|
316
|
-
y = s - t
|
|
317
|
-
|
|
318
|
-
s = 8 * r**2 / sr
|
|
319
|
-
a = 64 * r + s * cr * 2 # 16 * r**2 / tan(r)
|
|
320
|
-
d = 48 * sr + s # 8 * r**2 / tan(r)
|
|
321
|
-
b = -2 * d
|
|
322
|
-
e = 30 * s2r
|
|
323
|
-
c = fsumf_(30 * r, e * _0_5, s * cr) # 8 * r**2 / tan(r)
|
|
324
|
-
t = fsumf_( a * x, e * y**2, b * y, -c * x**2, d * x * y)
|
|
325
|
-
|
|
326
|
-
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)
|
|
327
336
|
return r
|
|
328
337
|
|
|
329
338
|
|
|
330
|
-
def cosineLaw(lat1, lon1, lat2, lon2, radius=R_M, wrap=False):
|
|
331
|
-
'''Compute the distance between two points using the U{spherical Law of Cosines
|
|
332
|
-
<https://www.Movable-Type.co.UK/scripts/latlong.html#cosine-law>} formula.
|
|
333
|
-
|
|
334
|
-
@arg lat1: Start latitude (C{degrees}).
|
|
335
|
-
@arg lon1: Start longitude (C{degrees}).
|
|
336
|
-
@arg lat2: End latitude (C{degrees}).
|
|
337
|
-
@arg lon2: End longitude (C{degrees}).
|
|
338
|
-
@kwarg radius: Mean earth radius (C{meter}), datum (L{Datum})
|
|
339
|
-
or ellipsoid (L{Ellipsoid}, L{Ellipsoid2} or
|
|
340
|
-
L{a_f2Tuple}) to use.
|
|
341
|
-
@kwarg wrap: If C{True}, wrap or I{normalize} and B{C{lat2}}
|
|
342
|
-
and B{C{lon2}} (C{bool}).
|
|
343
|
-
|
|
344
|
-
@return: Distance (C{meter}, same units as B{C{radius}} or the
|
|
345
|
-
ellipsoid or datum axes).
|
|
346
|
-
|
|
347
|
-
@raise TypeError: Invalid B{C{radius}}.
|
|
348
|
-
|
|
349
|
-
@see: Functions L{cosineLaw_}, L{cosineAndoyerLambert},
|
|
350
|
-
L{cosineForsytheAndoyerLambert}, L{equirectangular}, L{euclidean},
|
|
351
|
-
L{flatLocal}/L{hubeny}, L{flatPolar}, L{haversine}, L{thomas} and
|
|
352
|
-
L{vincentys} and method L{Ellipsoid.distance2}.
|
|
353
|
-
|
|
354
|
-
@note: See note at function L{vincentys_}.
|
|
355
|
-
'''
|
|
356
|
-
return _dS(cosineLaw_, radius, wrap, lat1, lon1, lat2, lon2)
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
def cosineLaw_(phi2, phi1, lam21):
|
|
360
|
-
'''Compute the I{angular} distance between two points using the U{spherical Law of
|
|
361
|
-
Cosines<https://www.Movable-Type.co.UK/scripts/latlong.html#cosine-law>} formula.
|
|
362
|
-
|
|
363
|
-
@arg phi2: End latitude (C{radians}).
|
|
364
|
-
@arg phi1: Start latitude (C{radians}).
|
|
365
|
-
@arg lam21: Longitudinal delta, M{end-start} (C{radians}).
|
|
366
|
-
|
|
367
|
-
@return: Angular distance (C{radians}).
|
|
368
|
-
|
|
369
|
-
@see: Functions L{cosineLaw}, L{cosineAndoyerLambert_},
|
|
370
|
-
L{cosineForsytheAndoyerLambert_}, L{euclidean_},
|
|
371
|
-
L{flatLocal_}/L{hubeny_}, L{flatPolar_}, L{haversine_},
|
|
372
|
-
L{thomas_} and L{vincentys_}.
|
|
373
|
-
|
|
374
|
-
@note: See note at function L{vincentys_}.
|
|
375
|
-
'''
|
|
376
|
-
return _sincosa6(phi2, phi1, lam21)[4]
|
|
377
|
-
|
|
378
|
-
|
|
379
339
|
def _d3(wrap, lat1, lon1, lat2, lon2):
|
|
380
|
-
'''(INTERNAL) Helper for _dE, _dS
|
|
340
|
+
'''(INTERNAL) Helper for _dE, _dS, ....
|
|
381
341
|
'''
|
|
382
342
|
if wrap:
|
|
383
343
|
d_lon, lat2, _ = _Wrap.latlon3(lon1, lat2, lon2, wrap)
|
|
384
344
|
return radians(lat2), Phid(lat1=lat1), radians(d_lon)
|
|
385
345
|
else: # for backward compaibility
|
|
386
|
-
return Phid(lat2=lat2), Phid(lat1=lat1),
|
|
346
|
+
return Phid(lat2=lat2), Phid(lat1=lat1), radians(lon2 - lon1)
|
|
387
347
|
|
|
388
348
|
|
|
389
|
-
def _dE(
|
|
349
|
+
def _dE(fun_, earth, wrap, *lls, **corr):
|
|
390
350
|
'''(INTERNAL) Helper for ellipsoidal distances.
|
|
391
351
|
'''
|
|
392
|
-
E = _ellipsoidal(earth,
|
|
393
|
-
r =
|
|
352
|
+
E = _ellipsoidal(earth, fun_)
|
|
353
|
+
r = fun_(*_d3(wrap, *lls), datum=E, **corr)
|
|
394
354
|
return r * E.a
|
|
395
355
|
|
|
396
356
|
|
|
397
|
-
def _dS(
|
|
357
|
+
def _dS(fun_, radius, wrap, *lls, **adjust):
|
|
398
358
|
'''(INTERNAL) Helper for spherical distances.
|
|
399
359
|
'''
|
|
400
|
-
r =
|
|
360
|
+
r = fun_(*_d3(wrap, *lls), **adjust)
|
|
401
361
|
if radius is not R_M:
|
|
402
|
-
|
|
362
|
+
try: # datum?
|
|
363
|
+
radius = radius.ellipsoid.R1
|
|
364
|
+
except AttributeError:
|
|
365
|
+
pass # scalar?
|
|
366
|
+
lat1, _, lat2, _ = lls
|
|
403
367
|
radius = _mean_radius(radius, lat1, lat2)
|
|
404
368
|
return r * radius
|
|
405
369
|
|
|
406
370
|
|
|
407
|
-
def _eA(excess_, radius, *wrap_lls):
|
|
408
|
-
'''(INTERNAL) Helper for spherical excess or area.
|
|
409
|
-
'''
|
|
410
|
-
r = excess_(*_d3(*wrap_lls))
|
|
411
|
-
if radius:
|
|
412
|
-
_, lat1, _, lat2, _ = wrap_lls
|
|
413
|
-
r *= _mean_radius(radius, lat1, lat2)**2
|
|
414
|
-
return r
|
|
415
|
-
|
|
416
|
-
|
|
417
371
|
def _ellipsoidal(earth, where):
|
|
418
372
|
'''(INTERNAL) Helper for distances.
|
|
419
373
|
'''
|
|
@@ -424,7 +378,7 @@ def _ellipsoidal(earth, where):
|
|
|
424
378
|
|
|
425
379
|
|
|
426
380
|
def equirectangular(lat1, lon1, lat2, lon2, radius=R_M, **adjust_limit_wrap):
|
|
427
|
-
'''
|
|
381
|
+
'''Approximate the distance between two points using the U{Equirectangular Approximation
|
|
428
382
|
/ Projection<https://www.Movable-Type.co.UK/scripts/latlong.html#equirectangular>}.
|
|
429
383
|
|
|
430
384
|
@arg lat1: Start latitude (C{degrees}).
|
|
@@ -433,30 +387,33 @@ def equirectangular(lat1, lon1, lat2, lon2, radius=R_M, **adjust_limit_wrap):
|
|
|
433
387
|
@arg lon2: End longitude (C{degrees}).
|
|
434
388
|
@kwarg radius: Mean earth radius (C{meter}), datum (L{Datum}) or ellipsoid
|
|
435
389
|
(L{Ellipsoid}, L{Ellipsoid2} or L{a_f2Tuple}).
|
|
436
|
-
@kwarg adjust_limit_wrap:
|
|
390
|
+
@kwarg adjust_limit_wrap: Optionally, keyword arguments for function L{equirectangular4}.
|
|
437
391
|
|
|
438
|
-
@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).
|
|
439
394
|
|
|
440
395
|
@raise TypeError: Invalid B{C{radius}}.
|
|
441
396
|
|
|
442
397
|
@see: Function L{equirectangular4} for more details, the available B{C{options}},
|
|
443
398
|
errors, restrictions and other, approximate or accurate distance functions.
|
|
444
399
|
'''
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
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)
|
|
449
405
|
|
|
450
406
|
|
|
451
407
|
def _equirectangular(lat1, lon1, lat2, lon2, **adjust_limit_wrap):
|
|
452
|
-
'''(INTERNAL) Helper for
|
|
453
|
-
|
|
408
|
+
'''(INTERNAL) Helper for classes L{frechet._FrechetMeterRadians} and
|
|
409
|
+
L{hausdorff._HausdorffMeterRedians}.
|
|
454
410
|
'''
|
|
455
|
-
|
|
411
|
+
t = equirectangular4(lat1, lon1, lat2, lon2, **adjust_limit_wrap)
|
|
412
|
+
return t.distance2 * _RADIANS2
|
|
456
413
|
|
|
457
414
|
|
|
458
415
|
def equirectangular4(lat1, lon1, lat2, lon2, adjust=True, limit=45, wrap=False):
|
|
459
|
-
'''
|
|
416
|
+
'''Approximate the distance between two points using the U{Equirectangular Approximation
|
|
460
417
|
/ Projection<https://www.Movable-Type.co.UK/scripts/latlong.html#equirectangular>}.
|
|
461
418
|
|
|
462
419
|
This approximation is valid for short distance of several hundred Km or Miles, see
|
|
@@ -466,26 +423,28 @@ def equirectangular4(lat1, lon1, lat2, lon2, adjust=True, limit=45, wrap=False):
|
|
|
466
423
|
@arg lon1: Start longitude (C{degrees}).
|
|
467
424
|
@arg lat2: End latitude (C{degrees}).
|
|
468
425
|
@arg lon2: End longitude (C{degrees}).
|
|
469
|
-
@kwarg adjust: Adjust the wrapped, unrolled longitudinal delta by the cosine of the
|
|
470
|
-
latitude (C{bool}).
|
|
426
|
+
@kwarg adjust: Adjust the wrapped, unrolled longitudinal delta by the cosine of the
|
|
427
|
+
mean latitude (C{bool}).
|
|
471
428
|
@kwarg limit: Optional limit for lat- and longitudinal deltas (C{degrees}) or C{None}
|
|
472
429
|
or C{0} for unlimited.
|
|
473
430
|
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll B{C{lat2}} and B{C{lon2}}
|
|
474
431
|
(C{bool}).
|
|
475
432
|
|
|
476
|
-
@return: A L{Distance4Tuple}C{(distance2, delta_lat, delta_lon, unroll_lon2)}
|
|
477
|
-
in C{degrees squared}.
|
|
433
|
+
@return: A L{Distance4Tuple}C{(distance2, delta_lat, delta_lon, unroll_lon2)} with
|
|
434
|
+
C{distance2} in C{degrees squared}.
|
|
478
435
|
|
|
479
|
-
@raise LimitError:
|
|
436
|
+
@raise LimitError: The lat- or longitudinal delta exceeds the B{C{-limit..limit}}
|
|
480
437
|
range and L{limiterrors<pygeodesy.limiterrors>} is C{True}.
|
|
481
438
|
|
|
482
439
|
@see: U{Local, flat earth approximation<https://www.EdWilliams.org/avform.htm#flat>},
|
|
483
|
-
functions L{equirectangular}, L{
|
|
484
|
-
L{
|
|
485
|
-
L{
|
|
486
|
-
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}.
|
|
487
443
|
'''
|
|
488
|
-
|
|
444
|
+
if wrap:
|
|
445
|
+
d_lon, lat2, ulon2 = _Wrap.latlon3(lon1, lat2, lon2, wrap)
|
|
446
|
+
else:
|
|
447
|
+
d_lon, ulon2 = (lon2 - lon1), lon2
|
|
489
448
|
d_lat = lat2 - lat1
|
|
490
449
|
|
|
491
450
|
if limit and limit > 0 and limiterrors():
|
|
@@ -510,25 +469,24 @@ def euclidean(lat1, lon1, lat2, lon2, radius=R_M, adjust=True, wrap=False):
|
|
|
510
469
|
@arg lon1: Start longitude (C{degrees}).
|
|
511
470
|
@arg lat2: End latitude (C{degrees}).
|
|
512
471
|
@arg lon2: End longitude (C{degrees}).
|
|
513
|
-
@kwarg radius: Mean earth radius (C{meter}), datum (L{Datum})
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
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}).
|
|
520
478
|
|
|
521
|
-
@return: Distance (C{meter}, same units as B{C{radius}} or the
|
|
522
|
-
|
|
479
|
+
@return: Distance (C{meter}, same units as B{C{radius}} or the ellipsoid
|
|
480
|
+
or datum axes).
|
|
523
481
|
|
|
524
482
|
@raise TypeError: Invalid B{C{radius}}.
|
|
525
483
|
|
|
526
484
|
@see: U{Distance between two (spherical) points
|
|
527
485
|
<https://www.EdWilliams.org/avform.htm#Dist>}, functions L{euclid},
|
|
528
|
-
L{euclidean_}, L{
|
|
529
|
-
L{
|
|
530
|
-
|
|
531
|
-
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}.
|
|
532
490
|
'''
|
|
533
491
|
return _dS(euclidean_, radius, wrap, lat1, lon1, lat2, lon2, adjust=adjust)
|
|
534
492
|
|
|
@@ -539,15 +497,13 @@ def euclidean_(phi2, phi1, lam21, adjust=True):
|
|
|
539
497
|
@arg phi2: End latitude (C{radians}).
|
|
540
498
|
@arg phi1: Start latitude (C{radians}).
|
|
541
499
|
@arg lam21: Longitudinal delta, M{end-start} (C{radians}).
|
|
542
|
-
@kwarg adjust: Adjust the longitudinal delta by the cosine
|
|
543
|
-
|
|
500
|
+
@kwarg adjust: Adjust the longitudinal delta by the cosine of the mean
|
|
501
|
+
latitude (C{bool}).
|
|
544
502
|
|
|
545
503
|
@return: Angular distance (C{radians}).
|
|
546
504
|
|
|
547
|
-
@see: Functions L{euclid}, L{euclidean}, L{
|
|
548
|
-
L{
|
|
549
|
-
L{flatLocal_}/L{hubeny_}, L{flatPolar_}, L{haversine_},
|
|
550
|
-
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_}.
|
|
551
507
|
'''
|
|
552
508
|
if adjust:
|
|
553
509
|
lam21 *= _scale_rad(phi2, phi1)
|
|
@@ -574,7 +530,9 @@ def excessAbc_(A, b, c):
|
|
|
574
530
|
c = Radians_(c=c) * _0_5
|
|
575
531
|
|
|
576
532
|
sA, cA, sb, cb, sc, cc = sincos2_(A, b, c)
|
|
577
|
-
|
|
533
|
+
s = sA * sb * sc
|
|
534
|
+
c = cA * sb * sc + cc * cb
|
|
535
|
+
return atan2(s, c) * _2_0
|
|
578
536
|
|
|
579
537
|
|
|
580
538
|
def excessCagnoli_(a, b, c):
|
|
@@ -596,11 +554,11 @@ def excessCagnoli_(a, b, c):
|
|
|
596
554
|
b = Radians_(b=b)
|
|
597
555
|
c = Radians_(c=c)
|
|
598
556
|
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
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
|
|
604
562
|
return Radians(Cagnoli=r * _2_0)
|
|
605
563
|
|
|
606
564
|
|
|
@@ -619,9 +577,10 @@ def excessGirard_(A, B, C):
|
|
|
619
577
|
@see: Function L{excessLHuilier_} and U{Spherical trigonometry
|
|
620
578
|
<https://WikiPedia.org/wiki/Spherical_trigonometry>}.
|
|
621
579
|
'''
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
580
|
+
r = fsumf_(Radians_(A=A),
|
|
581
|
+
Radians_(B=B),
|
|
582
|
+
Radians_(C=C), -PI)
|
|
583
|
+
return Radians(Girard=r)
|
|
625
584
|
|
|
626
585
|
|
|
627
586
|
def excessLHuilier_(a, b, c):
|
|
@@ -643,10 +602,9 @@ def excessLHuilier_(a, b, c):
|
|
|
643
602
|
b = Radians_(b=b)
|
|
644
603
|
c = Radians_(c=c)
|
|
645
604
|
|
|
646
|
-
s
|
|
647
|
-
|
|
648
|
-
r
|
|
649
|
-
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
|
|
650
608
|
return Radians(LHuilier=r * _4_0)
|
|
651
609
|
|
|
652
610
|
|
|
@@ -660,11 +618,10 @@ def excessKarney(lat1, lon1, lat2, lon2, radius=R_M, wrap=False):
|
|
|
660
618
|
@arg lon1: Start longitude (C{degrees}).
|
|
661
619
|
@arg lat2: End latitude (C{degrees}).
|
|
662
620
|
@arg lon2: End longitude (C{degrees}).
|
|
663
|
-
@kwarg radius: Mean earth radius (C{meter}), datum (L{Datum})
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
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}).
|
|
668
625
|
|
|
669
626
|
@return: Surface area, I{signed} (I{square} C{meter} or the same units as
|
|
670
627
|
B{C{radius}} I{squared}) or the I{spherical excess} (C{radians})
|
|
@@ -678,7 +635,10 @@ def excessKarney(lat1, lon1, lat2, lon2, radius=R_M, wrap=False):
|
|
|
678
635
|
|
|
679
636
|
@see: Functions L{excessKarney_} and L{excessQuad}.
|
|
680
637
|
'''
|
|
681
|
-
|
|
638
|
+
r = excessKarney_(*_d3(wrap, lat1, lon1, lat2, lon2))
|
|
639
|
+
if radius:
|
|
640
|
+
r *= _mean_radius(radius, lat1, lat2)**2
|
|
641
|
+
return r
|
|
682
642
|
|
|
683
643
|
|
|
684
644
|
def excessKarney_(phi2, phi1, lam21):
|
|
@@ -707,12 +667,11 @@ def excessKarney_(phi2, phi1, lam21):
|
|
|
707
667
|
#
|
|
708
668
|
# where E is the spherical excess of the trapezium obtained by extending
|
|
709
669
|
# the edge to the equator-circle vector for each edge (see also ***).
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
t1
|
|
713
|
-
|
|
714
|
-
return Radians(Karney=atan2(
|
|
715
|
-
_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)
|
|
716
675
|
|
|
717
676
|
|
|
718
677
|
# ***) Original post no longer available, following is a copy of the main part
|
|
@@ -762,11 +721,10 @@ def excessQuad(lat1, lon1, lat2, lon2, radius=R_M, wrap=False):
|
|
|
762
721
|
@arg lon1: Start longitude (C{degrees}).
|
|
763
722
|
@arg lat2: End latitude (C{degrees}).
|
|
764
723
|
@arg lon2: End longitude (C{degrees}).
|
|
765
|
-
@kwarg radius: Mean earth radius (C{meter}), datum (L{Datum})
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
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}).
|
|
770
728
|
|
|
771
729
|
@return: Surface area, I{signed} (I{square} C{meter} or the same units as
|
|
772
730
|
B{C{radius}} I{squared}) or the I{spherical excess} (C{radians})
|
|
@@ -778,7 +736,10 @@ def excessQuad(lat1, lon1, lat2, lon2, radius=R_M, wrap=False):
|
|
|
778
736
|
|
|
779
737
|
@see: Function L{excessQuad_} and L{excessKarney}.
|
|
780
738
|
'''
|
|
781
|
-
|
|
739
|
+
r = excessQuad_(*_d3(wrap, lat1, lon1, lat2, lon2))
|
|
740
|
+
if radius:
|
|
741
|
+
r *= _mean_radius(radius, lat1, lat2)**2
|
|
742
|
+
return r
|
|
782
743
|
|
|
783
744
|
|
|
784
745
|
def excessQuad_(phi2, phi1, lam21):
|
|
@@ -794,9 +755,9 @@ def excessQuad_(phi2, phi1, lam21):
|
|
|
794
755
|
@see: Function L{excessQuad} and U{Spherical trigonometry
|
|
795
756
|
<https://WikiPedia.org/wiki/Spherical_trigonometry>}.
|
|
796
757
|
'''
|
|
797
|
-
s = sin((phi2 + phi1) * _0_5)
|
|
798
758
|
c = cos((phi2 - phi1) * _0_5)
|
|
799
|
-
|
|
759
|
+
s = sin((phi2 + phi1) * _0_5) * tan_2(lam21)
|
|
760
|
+
return Radians(Quad=atan2(s, c) * _2_0)
|
|
800
761
|
|
|
801
762
|
|
|
802
763
|
def flatLocal(lat1, lon1, lat2, lon2, datum=_WGS84, scaled=True, wrap=False):
|
|
@@ -809,30 +770,28 @@ def flatLocal(lat1, lon1, lat2, lon2, datum=_WGS84, scaled=True, wrap=False):
|
|
|
809
770
|
@arg lon1: Start longitude (C{degrees}).
|
|
810
771
|
@arg lat2: End latitude (C{degrees}).
|
|
811
772
|
@arg lon2: End longitude (C{degrees}).
|
|
812
|
-
@kwarg datum: Datum (L{Datum}) or ellipsoid (L{Ellipsoid},
|
|
813
|
-
|
|
814
|
-
@kwarg scaled: Scale prime_vertical by C{cos(B{phi})} (C{bool}),
|
|
815
|
-
|
|
816
|
-
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll
|
|
817
|
-
B{C{
|
|
818
|
-
|
|
819
|
-
@return: Distance (C{meter}, same units as the B{C{datum}}'s
|
|
820
|
-
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).
|
|
821
781
|
|
|
822
782
|
@raise TypeError: Invalid B{C{datum}}.
|
|
823
783
|
|
|
824
|
-
@note: The meridional and prime_vertical radii of curvature
|
|
825
|
-
|
|
784
|
+
@note: The meridional and prime_vertical radii of curvature are taken and
|
|
785
|
+
scaled at the mean of both latitude.
|
|
826
786
|
|
|
827
|
-
@see: Functions L{flatLocal_} or L{hubeny_}, L{cosineLaw}, L{
|
|
828
|
-
L{
|
|
829
|
-
L{
|
|
830
|
-
|
|
831
|
-
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>}.
|
|
832
791
|
'''
|
|
792
|
+
t = _d3(wrap, lat1, lon1, lat2, lon2)
|
|
833
793
|
E = _ellipsoidal(datum, flatLocal)
|
|
834
|
-
return E._hubeny_2(*
|
|
835
|
-
scaled=scaled, squared=False) * E.a
|
|
794
|
+
return E._hubeny_2(*t, scaled=scaled, squared=False) * E.a
|
|
836
795
|
|
|
837
796
|
hubeny = flatLocal # PYCHOK for Karl Hubeny
|
|
838
797
|
|
|
@@ -846,23 +805,21 @@ def flatLocal_(phi2, phi1, lam21, datum=_WGS84, scaled=True):
|
|
|
846
805
|
@arg phi2: End latitude (C{radians}).
|
|
847
806
|
@arg phi1: Start latitude (C{radians}).
|
|
848
807
|
@arg lam21: Longitudinal delta, M{end-start} (C{radians}).
|
|
849
|
-
@kwarg datum: Datum (L{Datum}) or ellipsoid (L{Ellipsoid},
|
|
850
|
-
|
|
851
|
-
@kwarg scaled: Scale prime_vertical by C{cos(B{phi})} (C{bool}),
|
|
852
|
-
|
|
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_}.
|
|
853
812
|
|
|
854
813
|
@return: Angular distance (C{radians}).
|
|
855
814
|
|
|
856
815
|
@raise TypeError: Invalid B{C{datum}}.
|
|
857
816
|
|
|
858
|
-
@note: The meridional and prime_vertical radii of curvature
|
|
859
|
-
|
|
817
|
+
@note: The meridional and prime_vertical radii of curvature are taken and
|
|
818
|
+
scaled I{at the mean of both latitude}.
|
|
860
819
|
|
|
861
|
-
@see: Functions L{flatLocal} or L{hubeny}, L{
|
|
862
|
-
L{
|
|
863
|
-
|
|
864
|
-
U{local, flat earth approximation
|
|
865
|
-
<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>}.
|
|
866
823
|
'''
|
|
867
824
|
E = _ellipsoidal(datum, flatLocal_)
|
|
868
825
|
return E._hubeny_2(phi2, phi1, lam21, scaled=scaled, squared=False)
|
|
@@ -871,40 +828,34 @@ hubeny_ = flatLocal_ # PYCHOK for Karl Hubeny
|
|
|
871
828
|
|
|
872
829
|
|
|
873
830
|
def flatPolar(lat1, lon1, lat2, lon2, radius=R_M, wrap=False):
|
|
874
|
-
'''Compute the distance between two (spherical) points using
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
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.
|
|
878
834
|
|
|
879
835
|
@arg lat1: Start latitude (C{degrees}).
|
|
880
836
|
@arg lon1: Start longitude (C{degrees}).
|
|
881
837
|
@arg lat2: End latitude (C{degrees}).
|
|
882
838
|
@arg lon2: End longitude (C{degrees}).
|
|
883
|
-
@kwarg radius: Mean earth radius (C{meter}), datum (L{Datum})
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
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}).
|
|
888
843
|
|
|
889
|
-
@return: Distance (C{meter}, same units as B{C{radius}} or the
|
|
890
|
-
ellipsoid
|
|
844
|
+
@return: Distance (C{meter}, same units as B{C{radius}} or the datum's or
|
|
845
|
+
ellipsoid axes).
|
|
891
846
|
|
|
892
847
|
@raise TypeError: Invalid B{C{radius}}.
|
|
893
848
|
|
|
894
|
-
@see: Functions L{flatPolar_}, L{
|
|
895
|
-
L{
|
|
896
|
-
L{flatLocal}/L{hubeny}, L{equirectangular},
|
|
897
|
-
L{euclidean}, L{haversine}, L{thomas} and
|
|
898
|
-
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}.
|
|
899
851
|
'''
|
|
900
852
|
return _dS(flatPolar_, radius, wrap, lat1, lon1, lat2, lon2)
|
|
901
853
|
|
|
902
854
|
|
|
903
855
|
def flatPolar_(phi2, phi1, lam21):
|
|
904
|
-
'''Compute the I{angular} distance between two (spherical) points
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
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.
|
|
908
859
|
|
|
909
860
|
@arg phi2: End latitude (C{radians}).
|
|
910
861
|
@arg phi1: Start latitude (C{radians}).
|
|
@@ -912,10 +863,8 @@ def flatPolar_(phi2, phi1, lam21):
|
|
|
912
863
|
|
|
913
864
|
@return: Angular distance (C{radians}).
|
|
914
865
|
|
|
915
|
-
@see: Functions L{flatPolar}, L{
|
|
916
|
-
L{
|
|
917
|
-
L{euclidean_}, L{flatLocal_}/L{hubeny_}, L{haversine_},
|
|
918
|
-
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_}.
|
|
919
868
|
'''
|
|
920
869
|
a = fabs(PI_2 - phi1) # co-latitude
|
|
921
870
|
b = fabs(PI_2 - phi2) # co-latitude
|
|
@@ -957,14 +906,14 @@ def hartzell(pov, los=False, earth=_WGS84, **name_LatLon_and_kwds):
|
|
|
957
906
|
or C{None} to point to the center of the earth.
|
|
958
907
|
@kwarg earth: The earth model (L{Datum}, L{Ellipsoid}, L{Ellipsoid2},
|
|
959
908
|
L{a_f2Tuple} or a C{scalar} earth radius in C{meter}).
|
|
960
|
-
@kwarg name_LatLon_and_kwds: Optional
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
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}}.
|
|
964
913
|
|
|
965
|
-
@return: The intersection (L{Vector3d}, B{C{pov}}'s C{cartesian type} or
|
|
966
|
-
given B{C{LatLon}} instance) with attribute C{height} set to
|
|
967
|
-
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}}.
|
|
968
917
|
|
|
969
918
|
@raise IntersectionError: Invalid B{C{pov}} or B{C{pov}} inside the earth or
|
|
970
919
|
invalid B{C{los}} or B{C{los}} points outside or
|
|
@@ -973,50 +922,46 @@ def hartzell(pov, los=False, earth=_WGS84, **name_LatLon_and_kwds):
|
|
|
973
922
|
@raise TypeError: Invalid B{C{earth}}, C{ellipsoid} or C{datum}.
|
|
974
923
|
|
|
975
924
|
@see: Class L{Los}, functions L{tyr3d} and L{hartzell4} and methods
|
|
976
|
-
L{Ellipsoid.hartzell4}
|
|
925
|
+
L{Ellipsoid.hartzell4}, any C{Cartesian.hartzell} and C{LatLon.hartzell}.
|
|
977
926
|
'''
|
|
978
|
-
n,
|
|
927
|
+
n, kwds = _name2__(name_LatLon_and_kwds, name__=hartzell)
|
|
979
928
|
try:
|
|
980
929
|
D = _spherical_datum(earth, name__=hartzell)
|
|
981
930
|
r, h, i = _MODS.triaxials._hartzell3(pov, los, D.ellipsoid._triaxial)
|
|
982
931
|
|
|
983
932
|
C = _MODS.cartesianBase.CartesianBase
|
|
984
|
-
if
|
|
933
|
+
if kwds:
|
|
985
934
|
c = C(r, datum=D)
|
|
986
|
-
r = c.toLatLon(**_xkwds(
|
|
935
|
+
r = c.toLatLon(**_xkwds(kwds, height=h))
|
|
987
936
|
elif isinstance(r, C):
|
|
988
937
|
r.height = h
|
|
989
938
|
if i:
|
|
990
939
|
r._iteration = i
|
|
991
940
|
except Exception as x:
|
|
992
|
-
raise IntersectionError(pov=pov, los=los, earth=earth, cause=x,
|
|
993
|
-
**LatLon_and_kwds)
|
|
941
|
+
raise IntersectionError(pov=pov, los=los, earth=earth, cause=x, **kwds)
|
|
994
942
|
return _xnamed(r, n) if n else r
|
|
995
943
|
|
|
996
944
|
|
|
997
945
|
def haversine(lat1, lon1, lat2, lon2, radius=R_M, wrap=False):
|
|
998
|
-
'''Compute the distance between two (spherical) points using the
|
|
999
|
-
|
|
1000
|
-
formula.
|
|
946
|
+
'''Compute the distance between two (spherical) points using the U{Haversine
|
|
947
|
+
<https://www.Movable-Type.co.UK/scripts/latlong.html>} formula.
|
|
1001
948
|
|
|
1002
949
|
@arg lat1: Start latitude (C{degrees}).
|
|
1003
950
|
@arg lon1: Start longitude (C{degrees}).
|
|
1004
951
|
@arg lat2: End latitude (C{degrees}).
|
|
1005
952
|
@arg lon2: End longitude (C{degrees}).
|
|
1006
|
-
@kwarg radius: Mean earth radius (C{meter}), datum (L{Datum})
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
B{C{lat2}} and B{C{lon2}} (C{bool}).
|
|
953
|
+
@kwarg radius: Mean earth radius (C{meter}), datum (L{Datum}) or ellipsoid
|
|
954
|
+
(L{Ellipsoid}, L{Ellipsoid2} or L{a_f2Tuple}) to use.
|
|
955
|
+
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll B{C{lat2}} and
|
|
956
|
+
B{C{lon2}} (C{bool}).
|
|
1011
957
|
|
|
1012
958
|
@return: Distance (C{meter}, same units as B{C{radius}}).
|
|
1013
959
|
|
|
1014
960
|
@raise TypeError: Invalid B{C{radius}}.
|
|
1015
961
|
|
|
1016
962
|
@see: U{Distance between two (spherical) points
|
|
1017
|
-
<https://www.EdWilliams.org/avform.htm#Dist>}, functions
|
|
1018
|
-
L{
|
|
1019
|
-
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},
|
|
1020
965
|
L{thomas} and L{vincentys} and methods L{Ellipsoid.distance2},
|
|
1021
966
|
C{LatLon.distanceTo*} and C{LatLon.equirectangularTo}.
|
|
1022
967
|
|
|
@@ -1026,9 +971,8 @@ def haversine(lat1, lon1, lat2, lon2, radius=R_M, wrap=False):
|
|
|
1026
971
|
|
|
1027
972
|
|
|
1028
973
|
def haversine_(phi2, phi1, lam21):
|
|
1029
|
-
'''Compute the I{angular} distance between two (spherical) points
|
|
1030
|
-
|
|
1031
|
-
formula.
|
|
974
|
+
'''Compute the I{angular} distance between two (spherical) points using the
|
|
975
|
+
U{Haversine<https://www.Movable-Type.co.UK/scripts/latlong.html>} formula.
|
|
1032
976
|
|
|
1033
977
|
@arg phi2: End latitude (C{radians}).
|
|
1034
978
|
@arg phi1: Start latitude (C{radians}).
|
|
@@ -1036,18 +980,13 @@ def haversine_(phi2, phi1, lam21):
|
|
|
1036
980
|
|
|
1037
981
|
@return: Angular distance (C{radians}).
|
|
1038
982
|
|
|
1039
|
-
@see: Functions L{haversine}, L{
|
|
1040
|
-
L{
|
|
1041
|
-
L{euclidean_}, L{flatLocal_}/L{hubeny_}, L{flatPolar_},
|
|
1042
|
-
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_}.
|
|
1043
985
|
|
|
1044
986
|
@note: See note at function L{vincentys_}.
|
|
1045
987
|
'''
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
h = _hsin(phi2 - phi1) + cos(phi1) * cos(phi2) * _hsin(lam21) # haversine
|
|
1050
|
-
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
|
|
1051
990
|
|
|
1052
991
|
|
|
1053
992
|
def heightOf(angle, distance, radius=R_M):
|
|
@@ -1084,22 +1023,23 @@ def heightOf(angle, distance, radius=R_M):
|
|
|
1084
1023
|
raise _ValueError(angle=angle, distance=distance, radius=radius)
|
|
1085
1024
|
|
|
1086
1025
|
|
|
1087
|
-
def heightOrthometric(
|
|
1026
|
+
def heightOrthometric(h_loc, N):
|
|
1088
1027
|
'''Get the I{orthometric} height B{H}, the height above the geoid, earth surface.
|
|
1089
1028
|
|
|
1090
|
-
@arg
|
|
1091
|
-
|
|
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}.
|
|
1092
1032
|
@arg N: The I{geoid} height (C{meter}), the height of the geoid above the
|
|
1093
|
-
ellipsoid at the same B{C{
|
|
1033
|
+
ellipsoid at the same B{C{h_loc}} location.
|
|
1094
1034
|
|
|
1095
1035
|
@return: I{Orthometric} height C{B{H} = B{h} - B{N}} (C{meter}, same units
|
|
1096
1036
|
as B{C{h}} and B{C{N}}).
|
|
1097
1037
|
|
|
1098
|
-
@see: U{Ellipsoid, Geoid, and
|
|
1038
|
+
@see: U{Ellipsoid, Geoid, and Orthometric Heights<https://www.NGS.NOAA.gov/
|
|
1099
1039
|
GEOID/PRESENTATIONS/2007_02_24_CCPS/Roman_A_PLSC2007notes.pdf>}, page
|
|
1100
1040
|
6 and module L{pygeodesy.geoids}.
|
|
1101
1041
|
'''
|
|
1102
|
-
h =
|
|
1042
|
+
h = h_loc if _isHeight(h_loc) else _xattr(h_loc, height=_xattr(h_loc, h=0))
|
|
1103
1043
|
return Height(H=Height(h=h) - Height(N=N))
|
|
1104
1044
|
|
|
1105
1045
|
|
|
@@ -1121,9 +1061,11 @@ def horizon(height, radius=R_M, refraction=False):
|
|
|
1121
1061
|
if min(h, r) < 0:
|
|
1122
1062
|
raise _ValueError(height=height, radius=radius)
|
|
1123
1063
|
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1064
|
+
if refraction:
|
|
1065
|
+
r *= 2.415750694528 # 2.0 / 0.8279
|
|
1066
|
+
else:
|
|
1067
|
+
r += r + h
|
|
1068
|
+
return sqrt0(r * h)
|
|
1127
1069
|
|
|
1128
1070
|
|
|
1129
1071
|
class _idllmn6(object): # see also .geodesicw._wargs, .latlonBase._toCartesian3, .vector2d._numpy
|
|
@@ -1170,8 +1112,8 @@ _idllmn6 = _idllmn6() # PYCHOK singleton
|
|
|
1170
1112
|
|
|
1171
1113
|
def intersection2(lat1, lon1, bearing1,
|
|
1172
1114
|
lat2, lon2, bearing2, datum=None, wrap=False, small=_100km): # was=True
|
|
1173
|
-
'''I{Conveniently} compute the intersection of two lines each defined
|
|
1174
|
-
|
|
1115
|
+
'''I{Conveniently} compute the intersection of two lines each defined by
|
|
1116
|
+
a (geodetic) point and a bearing from North, using either ...
|
|
1175
1117
|
|
|
1176
1118
|
1) L{vector3d.intersection3d3} for B{C{small}} distances (below 100 Km
|
|
1177
1119
|
or about 0.88 degrees) or if I{no} B{C{datum}} is specified, or ...
|
|
@@ -1191,33 +1133,29 @@ def intersection2(lat1, lon1, bearing1,
|
|
|
1191
1133
|
|
|
1192
1134
|
@arg lat1: Latitude of the first point (C{degrees}).
|
|
1193
1135
|
@arg lon1: Longitude of the first point (C{degrees}).
|
|
1194
|
-
@arg bearing1: Bearing at the first point (compass C{
|
|
1136
|
+
@arg bearing1: Bearing at the first point (compass C{degrees360}).
|
|
1195
1137
|
@arg lat2: Latitude of the second point (C{degrees}).
|
|
1196
1138
|
@arg lon2: Longitude of the second point (C{degrees}).
|
|
1197
|
-
@arg bearing2: Bearing at the second point (compass C{
|
|
1139
|
+
@arg bearing2: Bearing at the second point (compass C{degrees360}).
|
|
1198
1140
|
@kwarg datum: Optional datum (L{Datum}) or ellipsoid (L{Ellipsoid},
|
|
1199
|
-
L{Ellipsoid2} or L{a_f2Tuple}) or C{scalar} earth
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll B{C{lat2}}
|
|
1203
|
-
|
|
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}).
|
|
1204
1146
|
@kwarg small: Upper limit for small distances (C{meter}).
|
|
1205
1147
|
|
|
1206
|
-
@return:
|
|
1207
|
-
longitude of the intersection point.
|
|
1148
|
+
@return: Intersection point (L{LatLon2Tuple}C{(lat, lon)}).
|
|
1208
1149
|
|
|
1209
|
-
@raise IntersectionError:
|
|
1210
|
-
|
|
1211
|
-
non-intersecting lines.
|
|
1150
|
+
@raise IntersectionError: No or an ambiguous intersection or colinear,
|
|
1151
|
+
parallel or otherwise non-intersecting lines.
|
|
1212
1152
|
|
|
1213
1153
|
@raise TypeError: Invalid B{C{datum}}.
|
|
1214
1154
|
|
|
1215
|
-
@raise UnitError: Invalid B{C{lat1}}, B{C{lon1}}, B{C{bearing1}},
|
|
1216
|
-
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}}.
|
|
1217
1157
|
|
|
1218
1158
|
@see: Method L{RhumbLine.intersection2}.
|
|
1219
|
-
|
|
1220
|
-
@note: The returned intersections may be near-antipodal.
|
|
1221
1159
|
'''
|
|
1222
1160
|
b1 = Bearing(bearing1=bearing1)
|
|
1223
1161
|
b2 = Bearing(bearing2=bearing2)
|
|
@@ -1263,26 +1201,24 @@ def intersections2(lat1, lon1, radius1,
|
|
|
1263
1201
|
@arg lat2: Latitude of the second circle center (C{degrees}).
|
|
1264
1202
|
@arg lon2: Longitude of the second circle center (C{degrees}).
|
|
1265
1203
|
@arg radius2: Radius of the second circle (C{meter}, same units as B{C{radius1}}).
|
|
1266
|
-
@kwarg datum: Optional datum (L{Datum}) or ellipsoid (L{Ellipsoid},
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
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}).
|
|
1272
1209
|
@kwarg small: Upper limit for small distances (C{meter}).
|
|
1273
1210
|
|
|
1274
|
-
@return: 2-Tuple of the intersection points, each a
|
|
1275
|
-
|
|
1276
|
-
|
|
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
|
|
1277
1214
|
|
|
1278
|
-
@raise IntersectionError: Concentric, antipodal, invalid or
|
|
1279
|
-
|
|
1280
|
-
convergence.
|
|
1215
|
+
@raise IntersectionError: Concentric, antipodal, invalid or non-intersecting
|
|
1216
|
+
circles or no convergence.
|
|
1281
1217
|
|
|
1282
1218
|
@raise TypeError: Invalid B{C{datum}}.
|
|
1283
1219
|
|
|
1284
|
-
@raise UnitError: Invalid B{C{lat1}}, B{C{lon1}}, B{C{radius1}},
|
|
1285
|
-
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}}.
|
|
1286
1222
|
'''
|
|
1287
1223
|
r1 = Radius_(radius1=radius1)
|
|
1288
1224
|
r2 = Radius_(radius2=radius2)
|
|
@@ -1356,7 +1292,7 @@ def _isequalTo(p1, p2, eps=EPS):
|
|
|
1356
1292
|
fabs(p1.lon - p2.lon) <= eps) if eps else (p1.latlon == p2.latlon)
|
|
1357
1293
|
|
|
1358
1294
|
|
|
1359
|
-
def _isequalTo_(p1, p2, eps=EPS):
|
|
1295
|
+
def _isequalTo_(p1, p2, eps=EPS): # underscore_!
|
|
1360
1296
|
'''(INTERNAL) Compare 2 point phi-/lams ignoring C{class}.
|
|
1361
1297
|
'''
|
|
1362
1298
|
return (fabs(p1.phi - p2.phi) <= eps and
|
|
@@ -1372,11 +1308,11 @@ def isnormal(lat, lon, eps=0):
|
|
|
1372
1308
|
@kwarg eps: Optional tolerance C{degrees}).
|
|
1373
1309
|
|
|
1374
1310
|
@return: C{True} if C{(abs(B{lat}) + B{eps}) <= 90} and
|
|
1375
|
-
C{(abs(B{lon}) + B{eps}) <= 180}, C{False}
|
|
1311
|
+
C{(abs(B{lon}) + B{eps}) <= 180}, C{False} otherwise.
|
|
1376
1312
|
|
|
1377
1313
|
@see: Functions L{isnormal_} and L{normal}.
|
|
1378
1314
|
'''
|
|
1379
|
-
return (
|
|
1315
|
+
return _loneg(fabs(lon)) >= eps and (_90_0 - fabs(lat)) >= eps # co-latitude
|
|
1380
1316
|
|
|
1381
1317
|
|
|
1382
1318
|
def isnormal_(phi, lam, eps=0):
|
|
@@ -1395,22 +1331,10 @@ def isnormal_(phi, lam, eps=0):
|
|
|
1395
1331
|
return (PI_2 - fabs(phi)) >= eps and (PI - fabs(lam)) >= eps
|
|
1396
1332
|
|
|
1397
1333
|
|
|
1398
|
-
def
|
|
1399
|
-
'''
|
|
1400
|
-
earth's surface) X, Y and Z components.
|
|
1401
|
-
|
|
1402
|
-
@arg lat: Latitude (C{degrees}).
|
|
1403
|
-
@arg lon: Longitude (C{degrees}).
|
|
1404
|
-
@kwarg name: Optional C{B{name}=NN} (C{str}).
|
|
1405
|
-
|
|
1406
|
-
@return: A L{Vector3Tuple}C{(x, y, z)}.
|
|
1407
|
-
|
|
1408
|
-
@see: Function L{philam2n_xyz}.
|
|
1409
|
-
|
|
1410
|
-
@note: These are C{n-vector} x, y and z components,
|
|
1411
|
-
I{NOT} geocentric ECEF x, y and z coordinates!
|
|
1334
|
+
def _maprod(fun_, *ts):
|
|
1335
|
+
'''(INTERNAL) Helper for C{excessCagnoli_} and C{excessLHuilier_}.
|
|
1412
1336
|
'''
|
|
1413
|
-
return
|
|
1337
|
+
return fprod(map(fun_, ts))
|
|
1414
1338
|
|
|
1415
1339
|
|
|
1416
1340
|
def _normal2(a, b, n_2, n, n2):
|
|
@@ -1431,10 +1355,10 @@ def normal(lat, lon, **name):
|
|
|
1431
1355
|
|
|
1432
1356
|
@arg lat: Latitude (C{degrees}).
|
|
1433
1357
|
@arg lon: Longitude (C{degrees}).
|
|
1434
|
-
@kwarg name: Optional
|
|
1358
|
+
@kwarg name: Optional C{B{name}="normal"} (C{str}).
|
|
1435
1359
|
|
|
1436
|
-
@return: L{LatLon2Tuple}C{(lat, lon)} with C{
|
|
1437
|
-
and C{
|
|
1360
|
+
@return: L{LatLon2Tuple}C{(lat, lon)} with C{-90 <= lat <= 90}
|
|
1361
|
+
and C{-180 <= lon <= 180}.
|
|
1438
1362
|
|
|
1439
1363
|
@see: Functions L{normal_} and L{isnormal}.
|
|
1440
1364
|
'''
|
|
@@ -1447,7 +1371,7 @@ def normal_(phi, lam, **name):
|
|
|
1447
1371
|
|
|
1448
1372
|
@arg phi: Latitude (C{radians}).
|
|
1449
1373
|
@arg lam: Longitude (C{radians}).
|
|
1450
|
-
@kwarg name: Optional
|
|
1374
|
+
@kwarg name: Optional C{B{name}="normal_"} (C{str}).
|
|
1451
1375
|
|
|
1452
1376
|
@return: L{PhiLam2Tuple}C{(phi, lam)} with C{abs(phi) <= PI/2}
|
|
1453
1377
|
and C{abs(lam) <= PI}.
|
|
@@ -1458,44 +1382,6 @@ def normal_(phi, lam, **name):
|
|
|
1458
1382
|
name=_name__(name, name__=normal_))
|
|
1459
1383
|
|
|
1460
1384
|
|
|
1461
|
-
def _2n_xyz(name, sa, ca, sb, cb): # name always **name
|
|
1462
|
-
'''(INTERNAL) Helper for C{latlon2n_xyz} and C{philam2n_xyz}.
|
|
1463
|
-
'''
|
|
1464
|
-
# Kenneth Gade eqn 3, but using right-handed
|
|
1465
|
-
# vector x -> 0°E,0°N, y -> 90°E,0°N, z -> 90°N
|
|
1466
|
-
return Vector3Tuple(ca * cb, ca * sb, sa, **name)
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
def n_xyz2latlon(x, y, z, **name):
|
|
1470
|
-
'''Convert C{n-vector} components to lat- and longitude in C{degrees}.
|
|
1471
|
-
|
|
1472
|
-
@arg x: X component (C{scalar}).
|
|
1473
|
-
@arg y: Y component (C{scalar}).
|
|
1474
|
-
@arg z: Z component (C{scalar}).
|
|
1475
|
-
@kwarg name: Optional C{B{name}=NN} (C{str}).
|
|
1476
|
-
|
|
1477
|
-
@return: A L{LatLon2Tuple}C{(lat, lon)}.
|
|
1478
|
-
|
|
1479
|
-
@see: Function L{n_xyz2philam}.
|
|
1480
|
-
'''
|
|
1481
|
-
return LatLon2Tuple(atan2d(z, hypot(x, y)), atan2d(y, x), **name)
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
def n_xyz2philam(x, y, z, **name):
|
|
1485
|
-
'''Convert C{n-vector} components to lat- and longitude in C{radians}.
|
|
1486
|
-
|
|
1487
|
-
@arg x: X component (C{scalar}).
|
|
1488
|
-
@arg y: Y component (C{scalar}).
|
|
1489
|
-
@arg z: Z component (C{scalar}).
|
|
1490
|
-
@kwarg name: Optional C{B{name}=NN} (C{str}).
|
|
1491
|
-
|
|
1492
|
-
@return: A L{PhiLam2Tuple}C{(phi, lam)}.
|
|
1493
|
-
|
|
1494
|
-
@see: Function L{n_xyz2latlon}.
|
|
1495
|
-
'''
|
|
1496
|
-
return PhiLam2Tuple(atan2(z, hypot(x, y)), atan2(y, x), **name)
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
1385
|
def _opposes(d, m, n, n2):
|
|
1500
1386
|
'''(INTERNAL) Helper for C{opposing} and C{opposing_}.
|
|
1501
1387
|
'''
|
|
@@ -1536,24 +1422,6 @@ def opposing_(radians1, radians2, margin=PI_2):
|
|
|
1536
1422
|
return _opposes(radians2 - radians1, m, PI, PI2)
|
|
1537
1423
|
|
|
1538
1424
|
|
|
1539
|
-
def philam2n_xyz(phi, lam, **name):
|
|
1540
|
-
'''Convert lat-, longitude to C{n-vector} (I{normal} to the
|
|
1541
|
-
earth's surface) X, Y and Z components.
|
|
1542
|
-
|
|
1543
|
-
@arg phi: Latitude (C{radians}).
|
|
1544
|
-
@arg lam: Longitude (C{radians}).
|
|
1545
|
-
@kwarg name: Optional name (C{str}).
|
|
1546
|
-
|
|
1547
|
-
@return: A L{Vector3Tuple}C{(x, y, z)}.
|
|
1548
|
-
|
|
1549
|
-
@see: Function L{latlon2n_xyz}.
|
|
1550
|
-
|
|
1551
|
-
@note: These are C{n-vector} x, y and z components,
|
|
1552
|
-
I{NOT} geocentric ECEF x, y and z coordinates!
|
|
1553
|
-
'''
|
|
1554
|
-
return _2n_xyz(name, *sincos2_(phi, lam))
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
1425
|
def _Propy(func, nargs, kwds):
|
|
1558
1426
|
'''(INTERNAL) Helper for the C{frechet.[-]Frechet**} and
|
|
1559
1427
|
C{hausdorff.[-]Hausdorff*} classes.
|
|
@@ -1577,29 +1445,24 @@ def _radical2(d, r1, r2, **name): # in .ellipsoidalBaseDI, .sphericalTrigonomet
|
|
|
1577
1445
|
|
|
1578
1446
|
|
|
1579
1447
|
def radical2(distance, radius1, radius2, **name):
|
|
1580
|
-
'''Compute the I{radical ratio} and I{radical line} of two
|
|
1581
|
-
|
|
1582
|
-
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>}.
|
|
1583
1450
|
|
|
1584
|
-
The I{radical line} is perpendicular to the axis thru the
|
|
1585
|
-
|
|
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)}.
|
|
1586
1453
|
|
|
1587
1454
|
@arg distance: Distance between the circle centers (C{scalar}).
|
|
1588
1455
|
@arg radius1: Radius of the first circle (C{scalar}).
|
|
1589
1456
|
@arg radius2: Radius of the second circle (C{scalar}).
|
|
1590
1457
|
@kwarg name: Optional C{B{name}=NN} (C{str}).
|
|
1591
1458
|
|
|
1592
|
-
@return: A L{Radical2Tuple}C{(ratio, xline)} where C{0.0 <=
|
|
1593
|
-
|
|
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}}.
|
|
1594
1461
|
|
|
1595
|
-
@raise IntersectionError: The B{C{distance}} exceeds the sum
|
|
1596
|
-
|
|
1462
|
+
@raise IntersectionError: The B{C{distance}} exceeds the sum of
|
|
1463
|
+
B{C{radius1}} and B{C{radius2}}.
|
|
1597
1464
|
|
|
1598
|
-
@raise UnitError: Invalid B{C{distance}}, B{C{radius1}} or
|
|
1599
|
-
B{C{radius2}}.
|
|
1600
|
-
|
|
1601
|
-
@see: U{Circle-Circle Intersection
|
|
1602
|
-
<https://MathWorld.Wolfram.com/Circle-CircleIntersection.html>}.
|
|
1465
|
+
@raise UnitError: Invalid B{C{distance}}, B{C{radius1}} or B{C{radius2}}.
|
|
1603
1466
|
'''
|
|
1604
1467
|
d = Distance_(distance, low=_0_0)
|
|
1605
1468
|
r1 = Radius_(radius1=radius1)
|
|
@@ -1649,7 +1512,7 @@ def _radistance(inst):
|
|
|
1649
1512
|
def _scale_deg(lat1, lat2): # degrees
|
|
1650
1513
|
# scale factor cos(mean of lats) for delta lon
|
|
1651
1514
|
m = fabs(lat1 + lat2) * _0_5
|
|
1652
|
-
return cos(radians(m)) if m <
|
|
1515
|
+
return cos(radians(m)) if m < _90_0 else _0_0
|
|
1653
1516
|
|
|
1654
1517
|
|
|
1655
1518
|
def _scale_rad(phi1, phi2): # radians, by .frechet, .hausdorff, .heights
|
|
@@ -1666,57 +1529,53 @@ def _sincosa6(phi2, phi1, lam21): # [4] in cosineLaw
|
|
|
1666
1529
|
|
|
1667
1530
|
|
|
1668
1531
|
def thomas(lat1, lon1, lat2, lon2, datum=_WGS84, wrap=False):
|
|
1669
|
-
'''Compute the distance between two (ellipsoidal) points using
|
|
1670
|
-
|
|
1671
|
-
formula.
|
|
1532
|
+
'''Compute the distance between two (ellipsoidal) points using U{Thomas'
|
|
1533
|
+
<https://apps.DTIC.mil/dtic/tr/fulltext/u2/703541.pdf>} formula.
|
|
1672
1534
|
|
|
1673
1535
|
@arg lat1: Start latitude (C{degrees}).
|
|
1674
1536
|
@arg lon1: Start longitude (C{degrees}).
|
|
1675
1537
|
@arg lat2: End latitude (C{degrees}).
|
|
1676
1538
|
@arg lon2: End longitude (C{degrees}).
|
|
1677
|
-
@kwarg datum: Datum (L{Datum}) or ellipsoid (L{Ellipsoid},
|
|
1678
|
-
|
|
1679
|
-
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll
|
|
1680
|
-
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}).
|
|
1681
1543
|
|
|
1682
|
-
@return: Distance (C{meter}, same units as the B{C{datum}}'s
|
|
1683
|
-
ellipsoid axes).
|
|
1544
|
+
@return: Distance (C{meter}, same units as the B{C{datum}}'s or ellipsoid axes).
|
|
1684
1545
|
|
|
1685
1546
|
@raise TypeError: Invalid B{C{datum}}.
|
|
1686
1547
|
|
|
1687
|
-
@see: Functions L{thomas_}, L{
|
|
1688
|
-
L{
|
|
1689
|
-
|
|
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}.
|
|
1690
1551
|
'''
|
|
1691
1552
|
return _dE(thomas_, datum, wrap, lat1, lon1, lat2, lon2)
|
|
1692
1553
|
|
|
1693
1554
|
|
|
1694
1555
|
def thomas_(phi2, phi1, lam21, datum=_WGS84):
|
|
1695
1556
|
'''Compute the I{angular} distance between two (ellipsoidal) points using
|
|
1696
|
-
U{Thomas'<https://apps.DTIC.mil/dtic/tr/fulltext/u2/703541.pdf>}
|
|
1697
|
-
formula.
|
|
1557
|
+
U{Thomas'<https://apps.DTIC.mil/dtic/tr/fulltext/u2/703541.pdf>} formula.
|
|
1698
1558
|
|
|
1699
1559
|
@arg phi2: End latitude (C{radians}).
|
|
1700
1560
|
@arg phi1: Start latitude (C{radians}).
|
|
1701
1561
|
@arg lam21: Longitudinal delta, M{end-start} (C{radians}).
|
|
1702
|
-
@kwarg datum: Datum or ellipsoid to use (L{
|
|
1562
|
+
@kwarg datum: Datum (L{Datum}) ?or ellipsoid to use (L{Ellipsoid},
|
|
1703
1563
|
L{Ellipsoid2} or L{a_f2Tuple}).
|
|
1704
1564
|
|
|
1705
1565
|
@return: Angular distance (C{radians}).
|
|
1706
1566
|
|
|
1707
1567
|
@raise TypeError: Invalid B{C{datum}}.
|
|
1708
1568
|
|
|
1709
|
-
@see: Functions L{thomas}, L{
|
|
1710
|
-
L{
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
<https://GitHub.com/jtejido/geodesy-php/blob/master/src/Geodesy/
|
|
1714
|
-
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>}.
|
|
1715
1573
|
'''
|
|
1716
1574
|
s2, c2, s1, c1, r, _ = _sincosa6(phi2, phi1, lam21)
|
|
1717
1575
|
if r and isnon0(c1) and isnon0(c2):
|
|
1718
1576
|
E = _ellipsoidal(datum, thomas_)
|
|
1719
|
-
|
|
1577
|
+
f = E.f * _0_25
|
|
1578
|
+
if f: # ellipsoidal
|
|
1720
1579
|
r1 = atan2(E.b_a * s1, c1)
|
|
1721
1580
|
r2 = atan2(E.b_a * s2, c2)
|
|
1722
1581
|
|
|
@@ -1730,21 +1589,20 @@ def thomas_(phi2, phi1, lam21, datum=_WGS84):
|
|
|
1730
1589
|
r = atan(sqrt0(h / u)) * 2 # == acos(1 - 2 * h)
|
|
1731
1590
|
sr, cr = sincos2(r)
|
|
1732
1591
|
if isnon0(sr):
|
|
1733
|
-
u =
|
|
1734
|
-
h =
|
|
1592
|
+
u = (sj * ck)**2 * 2 / u
|
|
1593
|
+
h = (sk * cj)**2 * 2 / h
|
|
1735
1594
|
x = u + h
|
|
1736
1595
|
y = u - h
|
|
1737
1596
|
|
|
1597
|
+
b = r * 2
|
|
1738
1598
|
s = r / sr
|
|
1739
1599
|
e = 4 * s**2
|
|
1740
1600
|
d = 2 * cr
|
|
1741
1601
|
a = e * d
|
|
1742
|
-
b = 2 * r
|
|
1743
1602
|
c = s - (a - d) * _0_5
|
|
1744
|
-
f = E.f * _0_25
|
|
1745
1603
|
|
|
1746
|
-
t =
|
|
1747
|
-
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
|
|
1748
1606
|
return r
|
|
1749
1607
|
|
|
1750
1608
|
|
|
@@ -1757,21 +1615,20 @@ def vincentys(lat1, lon1, lat2, lon2, radius=R_M, wrap=False):
|
|
|
1757
1615
|
@arg lon1: Start longitude (C{degrees}).
|
|
1758
1616
|
@arg lat2: End latitude (C{degrees}).
|
|
1759
1617
|
@arg lon2: End longitude (C{degrees}).
|
|
1760
|
-
@kwarg radius: Mean earth radius (C{meter}), datum (L{Datum})
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
@kwarg wrap: If C{True}, wrap or I{normalize} and unroll
|
|
1764
|
-
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}).
|
|
1765
1623
|
|
|
1766
1624
|
@return: Distance (C{meter}, same units as B{C{radius}}).
|
|
1767
1625
|
|
|
1768
1626
|
@raise UnitError: Invalid B{C{radius}}.
|
|
1769
1627
|
|
|
1770
|
-
@see: Functions L{vincentys_}, L{
|
|
1771
|
-
L{
|
|
1772
|
-
L{
|
|
1773
|
-
|
|
1774
|
-
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}.
|
|
1775
1632
|
|
|
1776
1633
|
@note: See note at function L{vincentys_}.
|
|
1777
1634
|
'''
|
|
@@ -1789,17 +1646,14 @@ def vincentys_(phi2, phi1, lam21):
|
|
|
1789
1646
|
|
|
1790
1647
|
@return: Angular distance (C{radians}).
|
|
1791
1648
|
|
|
1792
|
-
@see: Functions L{vincentys}, L{
|
|
1793
|
-
L{
|
|
1794
|
-
L{euclidean_}, L{flatLocal_}/L{hubeny_}, L{flatPolar_},
|
|
1795
|
-
L{haversine_} and L{thomas_}.
|
|
1649
|
+
@see: Functions L{vincentys}, L{cosineLaw_}, L{euclidean_}, L{flatLocal_} /
|
|
1650
|
+
L{hubeny_}, L{flatPolar_}, L{haversine_} and L{thomas_}.
|
|
1796
1651
|
|
|
1797
|
-
@note: Functions L{vincentys_}, L{haversine_} and L{cosineLaw_}
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
(M{
|
|
1802
|
-
L{cosineLaw_} (M{3 cos, 3 sin, 1 acos, 3 mul, 1 add}).
|
|
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}).
|
|
1803
1657
|
'''
|
|
1804
1658
|
s1, c1, s2, c2, s21, c21 = sincos2_(phi1, phi2, lam21)
|
|
1805
1659
|
|
|
@@ -1810,7 +1664,7 @@ def vincentys_(phi2, phi1, lam21):
|
|
|
1810
1664
|
|
|
1811
1665
|
# **) MIT License
|
|
1812
1666
|
#
|
|
1813
|
-
# Copyright (C) 2016-
|
|
1667
|
+
# Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
|
|
1814
1668
|
#
|
|
1815
1669
|
# Permission is hereby granted, free of charge, to any person obtaining a
|
|
1816
1670
|
# copy of this software and associated documentation files (the "Software"),
|