pygeodesy 24.3.24__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- PyGeodesy-24.3.24.dist-info/METADATA +272 -0
- PyGeodesy-24.3.24.dist-info/RECORD +115 -0
- PyGeodesy-24.3.24.dist-info/WHEEL +6 -0
- PyGeodesy-24.3.24.dist-info/top_level.txt +1 -0
- pygeodesy/LICENSE +21 -0
- pygeodesy/__init__.py +615 -0
- pygeodesy/__main__.py +103 -0
- pygeodesy/albers.py +867 -0
- pygeodesy/auxilats/_CX_4.py +218 -0
- pygeodesy/auxilats/_CX_6.py +314 -0
- pygeodesy/auxilats/_CX_8.py +475 -0
- pygeodesy/auxilats/__init__.py +54 -0
- pygeodesy/auxilats/__main__.py +86 -0
- pygeodesy/auxilats/auxAngle.py +548 -0
- pygeodesy/auxilats/auxDLat.py +302 -0
- pygeodesy/auxilats/auxDST.py +296 -0
- pygeodesy/auxilats/auxLat.py +848 -0
- pygeodesy/auxilats/auxily.py +272 -0
- pygeodesy/azimuthal.py +1150 -0
- pygeodesy/basics.py +892 -0
- pygeodesy/booleans.py +2031 -0
- pygeodesy/cartesianBase.py +1062 -0
- pygeodesy/clipy.py +704 -0
- pygeodesy/constants.py +516 -0
- pygeodesy/css.py +660 -0
- pygeodesy/datums.py +752 -0
- pygeodesy/deprecated/__init__.py +61 -0
- pygeodesy/deprecated/bases.py +40 -0
- pygeodesy/deprecated/classes.py +262 -0
- pygeodesy/deprecated/consterns.py +54 -0
- pygeodesy/deprecated/datum.py +40 -0
- pygeodesy/deprecated/functions.py +375 -0
- pygeodesy/deprecated/nvector.py +48 -0
- pygeodesy/deprecated/rhumbBase.py +32 -0
- pygeodesy/deprecated/rhumbaux.py +33 -0
- pygeodesy/deprecated/rhumbsolve.py +33 -0
- pygeodesy/deprecated/rhumbx.py +33 -0
- pygeodesy/dms.py +986 -0
- pygeodesy/ecef.py +1348 -0
- pygeodesy/elevations.py +279 -0
- pygeodesy/ellipsoidalBase.py +1224 -0
- pygeodesy/ellipsoidalBaseDI.py +913 -0
- pygeodesy/ellipsoidalExact.py +343 -0
- pygeodesy/ellipsoidalGeodSolve.py +343 -0
- pygeodesy/ellipsoidalKarney.py +403 -0
- pygeodesy/ellipsoidalNvector.py +685 -0
- pygeodesy/ellipsoidalVincenty.py +590 -0
- pygeodesy/ellipsoids.py +2476 -0
- pygeodesy/elliptic.py +1198 -0
- pygeodesy/epsg.py +243 -0
- pygeodesy/errors.py +804 -0
- pygeodesy/etm.py +1190 -0
- pygeodesy/fmath.py +1013 -0
- pygeodesy/formy.py +1818 -0
- pygeodesy/frechet.py +865 -0
- pygeodesy/fstats.py +760 -0
- pygeodesy/fsums.py +1898 -0
- pygeodesy/gars.py +358 -0
- pygeodesy/geodesicw.py +581 -0
- pygeodesy/geodesicx/_C4_24.py +1699 -0
- pygeodesy/geodesicx/_C4_27.py +2395 -0
- pygeodesy/geodesicx/_C4_30.py +3301 -0
- pygeodesy/geodesicx/__init__.py +48 -0
- pygeodesy/geodesicx/__main__.py +91 -0
- pygeodesy/geodesicx/gx.py +1382 -0
- pygeodesy/geodesicx/gxarea.py +535 -0
- pygeodesy/geodesicx/gxbases.py +154 -0
- pygeodesy/geodesicx/gxline.py +669 -0
- pygeodesy/geodsolve.py +426 -0
- pygeodesy/geohash.py +914 -0
- pygeodesy/geoids.py +1884 -0
- pygeodesy/hausdorff.py +892 -0
- pygeodesy/heights.py +1155 -0
- pygeodesy/interns.py +687 -0
- pygeodesy/iters.py +545 -0
- pygeodesy/karney.py +919 -0
- pygeodesy/ktm.py +633 -0
- pygeodesy/latlonBase.py +1766 -0
- pygeodesy/lazily.py +960 -0
- pygeodesy/lcc.py +684 -0
- pygeodesy/ltp.py +1107 -0
- pygeodesy/ltpTuples.py +1563 -0
- pygeodesy/mgrs.py +721 -0
- pygeodesy/named.py +1324 -0
- pygeodesy/namedTuples.py +683 -0
- pygeodesy/nvectorBase.py +695 -0
- pygeodesy/osgr.py +781 -0
- pygeodesy/points.py +1686 -0
- pygeodesy/props.py +628 -0
- pygeodesy/resections.py +1048 -0
- pygeodesy/rhumb/__init__.py +46 -0
- pygeodesy/rhumb/aux_.py +397 -0
- pygeodesy/rhumb/bases.py +1148 -0
- pygeodesy/rhumb/ekx.py +563 -0
- pygeodesy/rhumb/solve.py +572 -0
- pygeodesy/simplify.py +647 -0
- pygeodesy/solveBase.py +472 -0
- pygeodesy/sphericalBase.py +724 -0
- pygeodesy/sphericalNvector.py +1264 -0
- pygeodesy/sphericalTrigonometry.py +1447 -0
- pygeodesy/streprs.py +627 -0
- pygeodesy/trf.py +2079 -0
- pygeodesy/triaxials.py +1484 -0
- pygeodesy/units.py +969 -0
- pygeodesy/unitsBase.py +349 -0
- pygeodesy/ups.py +538 -0
- pygeodesy/utily.py +1231 -0
- pygeodesy/utm.py +762 -0
- pygeodesy/utmups.py +318 -0
- pygeodesy/utmupsBase.py +517 -0
- pygeodesy/vector2d.py +785 -0
- pygeodesy/vector3d.py +968 -0
- pygeodesy/vector3dBase.py +1049 -0
- pygeodesy/webmercator.py +383 -0
- pygeodesy/wgrs.py +439 -0
pygeodesy/geodsolve.py
ADDED
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
|
|
4
|
+
u'''Wrapper to invoke I{Karney}'s U{GeodSolve
|
|
5
|
+
<https://GeographicLib.SourceForge.io/C++/doc/GeodSolve.1.html>} utility
|
|
6
|
+
as an (exact) geodesic, but intended I{for testing purposes only}.
|
|
7
|
+
|
|
8
|
+
Set env variable C{PYGEODESY_GEODSOLVE} to the (fully qualified) path
|
|
9
|
+
of the C{GeodSolve} executable.
|
|
10
|
+
'''
|
|
11
|
+
|
|
12
|
+
from pygeodesy.basics import _xinstanceof
|
|
13
|
+
# from pygeodesy.errors import _xkwds # from .karney
|
|
14
|
+
from pygeodesy.interns import NN, _a12_, _azi1_, _azi2_, \
|
|
15
|
+
_lat1_, _lat2_, _lon1_, _lon2_, _m12_, \
|
|
16
|
+
_M12_, _M21_, _s12_, _S12_, _UNDER_
|
|
17
|
+
from pygeodesy.interns import _UNUSED_, _not_ # PYCHOK used!
|
|
18
|
+
from pygeodesy.karney import _Azi, Caps, _Deg, GeodesicError, _GTuple, \
|
|
19
|
+
_Pass, _Lat, _Lon, _M, _M2, _sincos2d, _xkwds
|
|
20
|
+
from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS, \
|
|
21
|
+
_PYGEODESY_GEODSOLVE_, _getenv, printf
|
|
22
|
+
from pygeodesy.namedTuples import Destination3Tuple, Distance3Tuple
|
|
23
|
+
from pygeodesy.props import Property, Property_RO
|
|
24
|
+
from pygeodesy.solveBase import _SolveBase, _SolveLineBase
|
|
25
|
+
from pygeodesy.utily import _unrollon, _Wrap, wrap360
|
|
26
|
+
|
|
27
|
+
__all__ = _ALL_LAZY.geodsolve
|
|
28
|
+
__version__ = '24.02.21'
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class GeodSolve12Tuple(_GTuple):
|
|
32
|
+
'''12-Tuple C{(lat1, lon1, azi1, lat2, lon2, azi2, s12, a12, m12, M12, M21, S12)} with
|
|
33
|
+
angles C{lat1}, C{lon1}, C{azi1}, C{lat2}, C{lon2} and C{azi2} and arc C{a12} all in
|
|
34
|
+
C{degrees}, initial C{azi1} and final C{azi2} forward azimuths, distance C{s12} and
|
|
35
|
+
reduced length C{m12} in C{meter}, area C{S12} in C{meter} I{squared} and geodesic
|
|
36
|
+
scale factors C{M12} and C{M21}, both C{scalar}, see U{GeodSolve
|
|
37
|
+
<https://GeographicLib.SourceForge.io/C++/doc/GeodSolve.1.html>}.
|
|
38
|
+
'''
|
|
39
|
+
# from GeodSolve --help option -f ... lat1 lon1 azi1 lat2 lon2 azi2 s12 a12 m12 M12 M21 S12
|
|
40
|
+
_Names_ = (_lat1_, _lon1_, _azi1_, _lat2_, _lon2_, _azi2_, _s12_, _a12_, _m12_, _M12_, _M21_, _S12_)
|
|
41
|
+
_Units_ = (_Lat, _Lon, _Azi, _Lat, _Lon, _Azi, _M, _Deg, _Pass, _Pass, _Pass, _M2)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class _GeodesicSolveBase(_SolveBase):
|
|
45
|
+
'''(INTERNAL) Base class for L{GeodesicSolve} and L{GeodesicLineSolve}.
|
|
46
|
+
'''
|
|
47
|
+
_Error = GeodesicError
|
|
48
|
+
_Names_Direct = \
|
|
49
|
+
_Names_Inverse = GeodSolve12Tuple._Names_
|
|
50
|
+
_Solve_name = 'GeodSolve'
|
|
51
|
+
_Solve_path = _getenv(_PYGEODESY_GEODSOLVE_, _PYGEODESY_GEODSOLVE_)
|
|
52
|
+
|
|
53
|
+
@Property_RO
|
|
54
|
+
def _b_option(self):
|
|
55
|
+
return ('-b',) if self.reverse2 else ()
|
|
56
|
+
|
|
57
|
+
@Property_RO
|
|
58
|
+
def _cmdBasic(self):
|
|
59
|
+
'''(INTERNAL) Get the basic C{GeodSolve} cmd (C{tuple}).
|
|
60
|
+
'''
|
|
61
|
+
return (self.GeodSolve,) + self._b_option \
|
|
62
|
+
+ self._e_option \
|
|
63
|
+
+ self._E_option \
|
|
64
|
+
+ self._p_option \
|
|
65
|
+
+ self._u_option + ('-f',)
|
|
66
|
+
|
|
67
|
+
@Property_RO
|
|
68
|
+
def _E_option(self):
|
|
69
|
+
return ('-E',) if self.Exact else ()
|
|
70
|
+
|
|
71
|
+
@Property
|
|
72
|
+
def GeodSolve(self):
|
|
73
|
+
'''Get the U{GeodSolve<https://GeographicLib.SourceForge.io/C++/doc/GeodSolve.1.html>}
|
|
74
|
+
executable (C{filename}).
|
|
75
|
+
'''
|
|
76
|
+
return self._Solve_path
|
|
77
|
+
|
|
78
|
+
@GeodSolve.setter # PYCHOK setter!
|
|
79
|
+
def GeodSolve(self, path):
|
|
80
|
+
'''Set the U{GeodSolve<https://GeographicLib.SourceForge.io/C++/doc/GeodSolve.1.html>}
|
|
81
|
+
executable (C{filename}), the (fully qualified) path to the C{GeodSolve} executable.
|
|
82
|
+
|
|
83
|
+
@raise GeodesicError: Invalid B{C{path}}, B{C{path}} doesn't exist or
|
|
84
|
+
isn't the C{GeodSolve} executable.
|
|
85
|
+
'''
|
|
86
|
+
self._setSolve(path)
|
|
87
|
+
|
|
88
|
+
def toStr(self, **prec_sep): # PYCHOK signature
|
|
89
|
+
'''Return this C{GeodesicSolve} as string.
|
|
90
|
+
|
|
91
|
+
@kwarg prec_sep: Keyword argumens C{B{prec}=6} and C{B{sep}=', '}
|
|
92
|
+
for the C{float} C{prec}ision, number of decimal digits
|
|
93
|
+
(0..9) and the C{sep}arator string to join. Trailing
|
|
94
|
+
zero decimals are stripped for B{C{prec}} values of
|
|
95
|
+
1 and above, but kept for negative B{C{prec}} values.
|
|
96
|
+
|
|
97
|
+
@return: GeodesicSolve items (C{str}).
|
|
98
|
+
'''
|
|
99
|
+
return _SolveBase._toStr(self, GeodSolve=self.GeodSolve, **prec_sep)
|
|
100
|
+
|
|
101
|
+
@Property_RO
|
|
102
|
+
def _u_option(self):
|
|
103
|
+
return ('-u',) if self.unroll else ()
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
class GeodesicSolve(_GeodesicSolveBase):
|
|
107
|
+
'''Wrapper to invoke I{Karney}'s U{GeodSolve<https://GeographicLib.SourceForge.io/C++/doc/GeodSolve.1.html>}
|
|
108
|
+
as an C{Exact} version of I{Karney}'s Python class U{Geodesic<https://GeographicLib.SourceForge.io/C++/doc/
|
|
109
|
+
python/code.html#geographiclib.geodesic.Geodesic>}.
|
|
110
|
+
|
|
111
|
+
@note: Use property C{GeodSolve} or env variable C{PYGEODESY_GEODSOLVE} to specify the (fully
|
|
112
|
+
qualified) path to the C{GeodSolve} executable.
|
|
113
|
+
|
|
114
|
+
@note: This C{geodesic} is intended I{for testing purposes only}, it invokes the C{GeodSolve}
|
|
115
|
+
executable for I{every} method call.
|
|
116
|
+
'''
|
|
117
|
+
|
|
118
|
+
def Area(self, polyline=False, name=NN):
|
|
119
|
+
'''Set up a L{GeodesicAreaExact} to compute area and
|
|
120
|
+
perimeter of a polygon.
|
|
121
|
+
|
|
122
|
+
@kwarg polyline: If C{True} perimeter only, otherwise
|
|
123
|
+
area and perimeter (C{bool}).
|
|
124
|
+
@kwarg name: Optional name (C{str}).
|
|
125
|
+
|
|
126
|
+
@return: A L{GeodesicAreaExact} instance.
|
|
127
|
+
|
|
128
|
+
@note: The B{C{debug}} setting is passed as C{verbose}
|
|
129
|
+
to the returned L{GeodesicAreaExact} instance.
|
|
130
|
+
'''
|
|
131
|
+
gaX = _MODS.geodesicx.GeodesicAreaExact(self, polyline=polyline,
|
|
132
|
+
name=name or self.name)
|
|
133
|
+
if self.verbose or self.debug: # PYCHOK no cover
|
|
134
|
+
gaX.verbose = True
|
|
135
|
+
return gaX
|
|
136
|
+
|
|
137
|
+
Polygon = Area # for C{geographiclib} compatibility
|
|
138
|
+
|
|
139
|
+
def Direct3(self, lat1, lon1, azi1, s12): # PYCHOK outmask
|
|
140
|
+
'''Return the destination lat, lon and reverse azimuth
|
|
141
|
+
(final bearing) in C{degrees}.
|
|
142
|
+
|
|
143
|
+
@return: L{Destination3Tuple}C{(lat, lon, final)}.
|
|
144
|
+
'''
|
|
145
|
+
r = self._GDictDirect(lat1, lon1, azi1, False, s12, floats=False)
|
|
146
|
+
return Destination3Tuple(float(r.lat2), float(r.lon2), wrap360(r.azi2),
|
|
147
|
+
iteration=r._iteration)
|
|
148
|
+
|
|
149
|
+
def _DirectLine(self, ll1, azi12, **caps_name): # PYCHOK no cover
|
|
150
|
+
'''(INTERNAL) Short-cut version.
|
|
151
|
+
'''
|
|
152
|
+
return self.DirectLine(ll1.lat, ll1.lon, azi12, **caps_name)
|
|
153
|
+
|
|
154
|
+
def DirectLine(self, lat1, lon1, azi1, **caps_name):
|
|
155
|
+
'''Set up a L{GeodesicLineSolve} to compute several points
|
|
156
|
+
on a single geodesic.
|
|
157
|
+
|
|
158
|
+
@arg lat1: Latitude of the first point (C{degrees}).
|
|
159
|
+
@arg lon1: Longitude of the first point (C{degrees}).
|
|
160
|
+
@arg azi1: Azimuth at the first point (compass C{degrees}).
|
|
161
|
+
@kwarg caps_name: Bit-or'ed combination of L{Caps} values specifying
|
|
162
|
+
the capabilities the L{GeodesicLineSolve} instance should
|
|
163
|
+
possess, C{caps=Caps.ALL} always.
|
|
164
|
+
|
|
165
|
+
@return: A L{GeodesicLineSolve} instance.
|
|
166
|
+
|
|
167
|
+
@note: If the point is at a pole, the azimuth is defined by keeping
|
|
168
|
+
B{C{lon1}} fixed, writing C{B{lat1} = ±(90 − ε)}, and taking
|
|
169
|
+
the limit C{ε → 0+}.
|
|
170
|
+
|
|
171
|
+
@see: C++ U{GeodesicExact.Line
|
|
172
|
+
<https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1GeodesicExact.html>}
|
|
173
|
+
and Python U{Geodesic.Line<https://GeographicLib.SourceForge.io/Python/doc/code.html>}.
|
|
174
|
+
'''
|
|
175
|
+
return GeodesicLineSolve(self, lat1, lon1, azi1, **_xkwds(caps_name, name=self.name))
|
|
176
|
+
|
|
177
|
+
Line = DirectLine
|
|
178
|
+
|
|
179
|
+
def _Inverse(self, ll1, ll2, wrap, **outmask): # PYCHOK no cover
|
|
180
|
+
'''(INTERNAL) Short-cut version, see .ellipsoidalBaseDI.intersecant2.
|
|
181
|
+
'''
|
|
182
|
+
if wrap:
|
|
183
|
+
ll2 = _unrollon(ll1, _Wrap.point(ll2))
|
|
184
|
+
return self.Inverse(ll1.lat, ll1.lon, ll2.lat, ll2.lon, **outmask)
|
|
185
|
+
|
|
186
|
+
def Inverse3(self, lat1, lon1, lat2, lon2): # PYCHOK outmask
|
|
187
|
+
'''Return the distance in C{meter} and the forward and
|
|
188
|
+
reverse azimuths (initial and final bearing) in C{degrees}.
|
|
189
|
+
|
|
190
|
+
@return: L{Distance3Tuple}C{(distance, initial, final)}.
|
|
191
|
+
'''
|
|
192
|
+
r = self._GDictInverse(lat1, lon1, lat2, lon2, floats=False)
|
|
193
|
+
return Distance3Tuple(float(r.s12), wrap360(r.azi1), wrap360(r.azi2),
|
|
194
|
+
iteration=r._iteration)
|
|
195
|
+
|
|
196
|
+
def _InverseLine(self, ll1, ll2, wrap, **caps_name): # PYCHOK no cover
|
|
197
|
+
'''(INTERNAL) Short-cut version.
|
|
198
|
+
'''
|
|
199
|
+
if wrap:
|
|
200
|
+
ll2 = _unrollon(ll1, _Wrap.point(ll2))
|
|
201
|
+
return self.InverseLine(ll1.lat, ll1.lon, ll2.lat, ll2.lon, **caps_name)
|
|
202
|
+
|
|
203
|
+
def InverseLine(self, lat1, lon1, lat2, lon2, **caps_name): # PYCHOK no cover
|
|
204
|
+
'''Set up a L{GeodesicLineSolve} to compute several points
|
|
205
|
+
on a single geodesic.
|
|
206
|
+
|
|
207
|
+
@arg lat1: Latitude of the first point (C{degrees}).
|
|
208
|
+
@arg lon1: Longitude of the first point (C{degrees}).
|
|
209
|
+
@arg lat2: Latitude of the second point (C{degrees}).
|
|
210
|
+
@arg lon2: Longitude of the second point (C{degrees}).
|
|
211
|
+
@kwarg caps_name: Bit-or'ed combination of L{Caps} values specifying
|
|
212
|
+
the capabilities the L{GeodesicLineSolve} instance should
|
|
213
|
+
possess, C{caps=Caps.ALL} always.
|
|
214
|
+
|
|
215
|
+
@return: A L{GeodesicLineSolve} instance.
|
|
216
|
+
|
|
217
|
+
@note: Both B{C{lat1}} and B{C{lat2}} should in the range C{[-90, +90]}.
|
|
218
|
+
|
|
219
|
+
@see: C++ U{GeodesicExact.InverseLine
|
|
220
|
+
<https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1GeodesicExact.html>} and
|
|
221
|
+
Python U{Geodesic.InverseLine<https://GeographicLib.SourceForge.io/Python/doc/code.html>}.
|
|
222
|
+
'''
|
|
223
|
+
r = self.Inverse(lat1, lon1, lat2, lon2)
|
|
224
|
+
return GeodesicLineSolve(self, lat1, lon1, r.azi1, **_xkwds(caps_name, name=self.name))
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
class GeodesicLineSolve(_GeodesicSolveBase, _SolveLineBase):
|
|
228
|
+
'''Wrapper to invoke I{Karney}'s U{GeodSolve<https://GeographicLib.SourceForge.io/C++/doc/GeodSolve.1.html>}
|
|
229
|
+
as an C{Exact} version of I{Karney}'s Python class U{GeodesicLine<https://GeographicLib.SourceForge.io/C++/doc/
|
|
230
|
+
python/code.html#geographiclib.geodesicline.GeodesicLine>}.
|
|
231
|
+
|
|
232
|
+
@note: Use property C{GeodSolve} or env variable C{PYGEODESY_GEODSOLVE} to specify the (fully
|
|
233
|
+
qualified) path to the C{GeodSolve} executable.
|
|
234
|
+
|
|
235
|
+
@note: This C{geodesic} is intended I{for testing purposes only}, it invokes the C{GeodSolve}
|
|
236
|
+
executable for I{every} method call.
|
|
237
|
+
'''
|
|
238
|
+
|
|
239
|
+
def __init__(self, geodesic, lat1, lon1, azi1, caps=Caps.ALL, name=NN):
|
|
240
|
+
'''New L{GeodesicLineSolve} instance, allowing points to be found along
|
|
241
|
+
a geodesic starting at C{(B{lat1}, B{lon1})} with azimuth B{C{azi1}}.
|
|
242
|
+
|
|
243
|
+
@arg geodesic: The geodesic to use (L{GeodesicSolve}).
|
|
244
|
+
@arg lat1: Latitude of the first point (C{degrees}).
|
|
245
|
+
@arg lon1: Longitude of the first point (C{degrees}).
|
|
246
|
+
@arg azi1: Azimuth at the first points (compass C{degrees}).
|
|
247
|
+
@kwarg caps: Bit-or'ed combination of L{Caps} values specifying
|
|
248
|
+
the capabilities the L{GeodesicLineSolve} instance
|
|
249
|
+
should possess, always C{Caps.ALL}. Use C{Caps.LINE_OFF}
|
|
250
|
+
if updates to the B{C{geodesic}} should I{not} be
|
|
251
|
+
reflected in this L{GeodesicLineSolve} instance.
|
|
252
|
+
@kwarg name: Optional name (C{str}).
|
|
253
|
+
|
|
254
|
+
@raise GeodesicError: Invalid path for the C{GeodSolve} executable or
|
|
255
|
+
or isn't the C{GeodSolve} executable, see
|
|
256
|
+
property C{geodesic.GeodSolve}.
|
|
257
|
+
|
|
258
|
+
@raise TypeError: Invalid B{C{geodesic}}.
|
|
259
|
+
'''
|
|
260
|
+
_xinstanceof(GeodesicSolve, geodesic=geodesic)
|
|
261
|
+
if (caps & Caps.LINE_OFF): # copy to avoid updates
|
|
262
|
+
geodesic = geodesic.copy(deep=False, name=NN(_UNDER_, geodesic.name))
|
|
263
|
+
_SolveLineBase.__init__(self, geodesic, lat1, lon1, caps, name, azi1=azi1)
|
|
264
|
+
try:
|
|
265
|
+
self.GeodSolve = geodesic.GeodSolve # geodesic or copy of geodesic
|
|
266
|
+
except GeodesicError:
|
|
267
|
+
pass
|
|
268
|
+
|
|
269
|
+
def ArcPosition(self, a12, outmask=_UNUSED_): # PYCHOK unused
|
|
270
|
+
'''Find the position on the line given B{C{a12}}.
|
|
271
|
+
|
|
272
|
+
@arg a12: Spherical arc length from the first point to the
|
|
273
|
+
second point (C{degrees}).
|
|
274
|
+
|
|
275
|
+
@return: A C{GDict} with 12 items C{lat1, lon1, azi1, lat2, lon2,
|
|
276
|
+
azi2, m12, a12, s12, M12, M21, S12}.
|
|
277
|
+
'''
|
|
278
|
+
return self._GDictInvoke(self._cmdArc, True, self._Names_Direct, a12)
|
|
279
|
+
|
|
280
|
+
@Property_RO
|
|
281
|
+
def azi1(self):
|
|
282
|
+
'''Get the azimuth at the first point (compass C{degrees}).
|
|
283
|
+
'''
|
|
284
|
+
return self._lla1.azi1
|
|
285
|
+
|
|
286
|
+
azi12 = azi1 # like RhumbLineSolve
|
|
287
|
+
|
|
288
|
+
@Property_RO
|
|
289
|
+
def azi1_sincos2(self):
|
|
290
|
+
'''Get the sine and cosine of the first point's azimuth (2-tuple C{(sin, cos)}).
|
|
291
|
+
'''
|
|
292
|
+
return _sincos2d(self.azi1)
|
|
293
|
+
|
|
294
|
+
azi12_sincos2 = azi1_sincos2
|
|
295
|
+
|
|
296
|
+
@Property_RO
|
|
297
|
+
def _cmdArc(self):
|
|
298
|
+
'''(INTERNAL) Get the C{GeodSolve} I{-a -L} cmd (C{tuple}).
|
|
299
|
+
'''
|
|
300
|
+
return self._cmdDistance + ('-a',)
|
|
301
|
+
|
|
302
|
+
def Intersecant2(self, lat0, lon0, radius, **kwds): # PYCHOK no cover
|
|
303
|
+
'''B{Not implemented}, throws a C{NotImplementedError} always.'''
|
|
304
|
+
_MODS.named.notImplemented(self, lat0, lon0, radius, **kwds)
|
|
305
|
+
|
|
306
|
+
def PlumbTo(self, lat0, lon0, **kwds): # PYCHOK no cover
|
|
307
|
+
'''B{Not implemented}, throws a C{NotImplementedError} always.'''
|
|
308
|
+
_MODS.named.notImplemented(self, lat0, lon0, **kwds)
|
|
309
|
+
|
|
310
|
+
def Position(self, s12, outmask=_UNUSED_): # PYCHOK unused
|
|
311
|
+
'''Find the position on the line given B{C{s12}}.
|
|
312
|
+
|
|
313
|
+
@arg s12: Distance from the first point to the second (C{meter}).
|
|
314
|
+
|
|
315
|
+
@return: A C{GDict} with 12 items C{lat1, lon1, azi1, lat2, lon2,
|
|
316
|
+
azi2, m12, a12, s12, M12, M21, S12}, possibly C{a12=NAN}.
|
|
317
|
+
'''
|
|
318
|
+
return self._GDictInvoke(self._cmdDistance, True, self._Names_Direct, s12)
|
|
319
|
+
|
|
320
|
+
def toStr(self, **prec_sep): # PYCHOK signature
|
|
321
|
+
'''Return this C{GeodesicLineSolve} as string.
|
|
322
|
+
|
|
323
|
+
@kwarg prec_sep: Keyword argumens C{B{prec}=6} and C{B{sep}=', '}
|
|
324
|
+
for the C{float} C{prec}ision, number of decimal digits
|
|
325
|
+
(0..9) and the C{sep}arator string to join. Trailing
|
|
326
|
+
zero decimals are stripped for B{C{prec}} values of
|
|
327
|
+
1 and above, but kept for negative B{C{prec}} values.
|
|
328
|
+
|
|
329
|
+
@return: GeodesicLineSolve items (C{str}).
|
|
330
|
+
'''
|
|
331
|
+
return _SolveLineBase._toStr(self, azi1=self.azi1, geodesic=self._solve,
|
|
332
|
+
GeodSolve=self.GeodSolve, **prec_sep)
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
__all__ += _ALL_DOCS(_GeodesicSolveBase)
|
|
336
|
+
|
|
337
|
+
if __name__ == '__main__':
|
|
338
|
+
|
|
339
|
+
from sys import argv
|
|
340
|
+
|
|
341
|
+
gS = GeodesicSolve(name='Test')
|
|
342
|
+
gS.verbose = '--verbose' in argv # or '-v' in argv
|
|
343
|
+
|
|
344
|
+
if gS.GeodSolve in (_PYGEODESY_GEODSOLVE_, None): # not set
|
|
345
|
+
gS.GeodSolve = '/opt/local/bin/GeodSolve' # '/opt/local/Cellar/geographiclib/1.51/bin/GeodSolve' # HomeBrew
|
|
346
|
+
printf('version: %s', gS.version)
|
|
347
|
+
|
|
348
|
+
r = gS.Direct(40.6, -73.8, 51, 5.5e6)
|
|
349
|
+
printf('Direct: %r', r, nl=1)
|
|
350
|
+
printf('Direct3: %r', gS.Direct3(40.6, -73.8, 51, 5.5e6))
|
|
351
|
+
|
|
352
|
+
printf('Inverse: %r', gS.Inverse( 40.6, -73.8, 51.6, -0.5), nl=1)
|
|
353
|
+
printf('Inverse1: %r', gS.Inverse1(40.6, -73.8, 51.6, -0.5))
|
|
354
|
+
printf('Inverse3: %r', gS.Inverse3(40.6, -73.8, 51.6, -0.5))
|
|
355
|
+
|
|
356
|
+
glS = GeodesicLineSolve(gS, 40.6, -73.8, 51, name='LineTest')
|
|
357
|
+
p = glS.Position(5.5e6)
|
|
358
|
+
printf('Position: %s %r', p == r, p, nl=1)
|
|
359
|
+
p = glS.ArcPosition(49.475527)
|
|
360
|
+
printf('ArcPosition: %s %r', p == r, p)
|
|
361
|
+
|
|
362
|
+
# % python3 -m pygeodesy.geodsolve
|
|
363
|
+
|
|
364
|
+
# version: /opt/local/bin/GeodSolve: GeographicLib version 1.51
|
|
365
|
+
|
|
366
|
+
# version: /opt/local/bin/GeodSolve: GeographicLib version 1.51
|
|
367
|
+
|
|
368
|
+
# Direct: GDict(M12=0.650911, M21=0.651229, S12=39735075134877.09375, a12=49.475527, azi1=51.0, azi2=107.189397, lat1=40.6, lat2=51.884565, lon1=-73.8, lon2=-1.141173, m12=4844148.703101, s12=5500000.0)
|
|
369
|
+
# Direct3: Destination3Tuple(lat=51.884565, lon=-1.141173, final=107.189397)
|
|
370
|
+
|
|
371
|
+
# Inverse: GDict(M12=0.64473, M21=0.645046, S12=40041368848742.53125, a12=49.94131, azi1=51.198883, azi2=107.821777, lat1=40.6, lat2=51.6, lon1=-73.8, lon2=-0.5, m12=4877684.602706, s12=5551759.400319)
|
|
372
|
+
# Inverse1: 49.94131021789904
|
|
373
|
+
# Inverse3: Distance3Tuple(distance=5551759.400319, initial=51.198883, final=107.821777)
|
|
374
|
+
|
|
375
|
+
# Position: True GDict(M12=0.650911, M21=0.651229, S12=39735075134877.09375, a12=49.475527, azi1=51.0, azi2=107.189397, lat1=40.6, lat2=51.884565, lon1=-73.8, lon2=-1.141173, m12=4844148.703101, s12=5500000.0)
|
|
376
|
+
# ArcPosition: False GDict(M12=0.650911, M21=0.651229, S12=39735074737272.734375, a12=49.475527, azi1=51.0, azi2=107.189397, lat1=40.6, lat2=51.884565, lon1=-73.8, lon2=-1.141174, m12=4844148.669561, s12=5499999.948497)
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
# % python3 -m pygeodesy.geodsolve --verbose
|
|
380
|
+
|
|
381
|
+
# GeodesicSolve 'Test' 1: /opt/local/bin/GeodSolve --version (invoke)
|
|
382
|
+
# GeodesicSolve 'Test' 1: /opt/local/bin/GeodSolve: GeographicLib version 1.51 (0)
|
|
383
|
+
# version: /opt/local/bin/GeodSolve: GeographicLib version 1.51
|
|
384
|
+
# GeodesicSolve 'Test' 2: /opt/local/bin/GeodSolve -E -p 10 -f \ 40.600000000000001 -73.799999999999997 51.0 5500000.0 (Direct)
|
|
385
|
+
# GeodesicSolve 'Test' 2: lat1=40.600000000000001, lon1=-73.799999999999997, azi1=51.0, lat2=51.884564505606761, lon2=-1.141172861200829, azi2=107.189397162605886, s12=5500000.0, a12=49.475527463251467, m12=4844148.703101486, M12=0.65091056699808603, M21=0.65122865892196558, S12=39735075134877.094 (0)
|
|
386
|
+
|
|
387
|
+
# Direct: GDict(M12=0.650911, M21=0.651229, S12=39735075134877.09375, a12=49.475527, azi1=51.0, azi2=107.189397, lat1=40.6, lat2=51.884565, lon1=-73.8, lon2=-1.141173, m12=4844148.703101, s12=5500000.0)
|
|
388
|
+
# GeodesicSolve 'Test' 3: /opt/local/bin/GeodSolve -E -p 10 -f \ 40.600000000000001 -73.799999999999997 51.0 5500000.0 (Direct3)
|
|
389
|
+
# GeodesicSolve 'Test' 3: lat1=40.600000000000001, lon1=-73.799999999999997, azi1=51.0, lat2=51.884564505606761, lon2=-1.141172861200829, azi2=107.189397162605886, s12=5500000.0, a12=49.475527463251467, m12=4844148.703101486, M12=0.65091056699808603, M21=0.65122865892196558, S12=39735075134877.094 (0)
|
|
390
|
+
# Direct3: Destination3Tuple(lat=51.884565, lon=-1.141173, final=107.189397)
|
|
391
|
+
# GeodesicSolve 'Test' 4: /opt/local/bin/GeodSolve -E -p 10 -f -i \ 40.600000000000001 -73.799999999999997 51.600000000000001 -0.5 (Inverse)
|
|
392
|
+
# GeodesicSolve 'Test' 4: lat1=40.600000000000001, lon1=-73.799999999999997, azi1=51.198882845579824, lat2=51.600000000000001, lon2=-0.5, azi2=107.821776735514248, s12=5551759.4003186841, a12=49.941310217899037, m12=4877684.6027061976, M12=0.64472969205948238, M21=0.64504567852134398, S12=40041368848742.531 (0)
|
|
393
|
+
|
|
394
|
+
# Inverse: GDict(M12=0.64473, M21=0.645046, S12=40041368848742.53125, a12=49.94131, azi1=51.198883, azi2=107.821777, lat1=40.6, lat2=51.6, lon1=-73.8, lon2=-0.5, m12=4877684.602706, s12=5551759.400319)
|
|
395
|
+
# GeodesicSolve 'Test' 5: /opt/local/bin/GeodSolve -E -p 10 -f -i \ 40.600000000000001 -73.799999999999997 51.600000000000001 -0.5 (Inverse1)
|
|
396
|
+
# GeodesicSolve 'Test' 5: lat1=40.600000000000001, lon1=-73.799999999999997, azi1=51.198882845579824, lat2=51.600000000000001, lon2=-0.5, azi2=107.821776735514248, s12=5551759.4003186841, a12=49.941310217899037, m12=4877684.6027061976, M12=0.64472969205948238, M21=0.64504567852134398, S12=40041368848742.531 (0)
|
|
397
|
+
# Inverse1: 49.94131021789904
|
|
398
|
+
# GeodesicSolve 'Test' 6: /opt/local/bin/GeodSolve -E -p 10 -f -i \ 40.600000000000001 -73.799999999999997 51.600000000000001 -0.5 (Inverse3)
|
|
399
|
+
# GeodesicSolve 'Test' 6: lat1=40.600000000000001, lon1=-73.799999999999997, azi1=51.198882845579824, lat2=51.600000000000001, lon2=-0.5, azi2=107.821776735514248, s12=5551759.4003186841, a12=49.941310217899037, m12=4877684.6027061976, M12=0.64472969205948238, M21=0.64504567852134398, S12=40041368848742.531 (0)
|
|
400
|
+
# Inverse3: Distance3Tuple(distance=5551759.400319, initial=51.198883, final=107.821777)
|
|
401
|
+
|
|
402
|
+
# Position: True GDict(M12=0.650911, M21=0.651229, S12=39735075134877.09375, a12=49.475527, azi1=51.0, azi2=107.189397, lat1=40.6, lat2=51.884565, lon1=-73.8, lon2=-1.141173, m12=4844148.703101, s12=5500000.0)
|
|
403
|
+
# ArcPosition: False GDict(M12=0.650911, M21=0.651229, S12=39735074737272.734375, a12=49.475527, azi1=51.0, azi2=107.189397, lat1=40.6, lat2=51.884565, lon1=-73.8, lon2=-1.141174, m12=4844148.669561, s12=5499999.948497)
|
|
404
|
+
|
|
405
|
+
|
|
406
|
+
# **) MIT License
|
|
407
|
+
#
|
|
408
|
+
# Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
|
|
409
|
+
#
|
|
410
|
+
# Permission is hereby granted, free of charge, to any person obtaining a
|
|
411
|
+
# copy of this software and associated documentation files (the "Software"),
|
|
412
|
+
# to deal in the Software without restriction, including without limitation
|
|
413
|
+
# the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
414
|
+
# and/or sell copies of the Software, and to permit persons to whom the
|
|
415
|
+
# Software is furnished to do so, subject to the following conditions:
|
|
416
|
+
#
|
|
417
|
+
# The above copyright notice and this permission notice shall be included
|
|
418
|
+
# in all copies or substantial portions of the Software.
|
|
419
|
+
#
|
|
420
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
421
|
+
# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
422
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
423
|
+
# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
|
424
|
+
# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
|
425
|
+
# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
|
426
|
+
# OTHER DEALINGS IN THE SOFTWARE.
|