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.
Files changed (115) hide show
  1. PyGeodesy-24.3.24.dist-info/METADATA +272 -0
  2. PyGeodesy-24.3.24.dist-info/RECORD +115 -0
  3. PyGeodesy-24.3.24.dist-info/WHEEL +6 -0
  4. PyGeodesy-24.3.24.dist-info/top_level.txt +1 -0
  5. pygeodesy/LICENSE +21 -0
  6. pygeodesy/__init__.py +615 -0
  7. pygeodesy/__main__.py +103 -0
  8. pygeodesy/albers.py +867 -0
  9. pygeodesy/auxilats/_CX_4.py +218 -0
  10. pygeodesy/auxilats/_CX_6.py +314 -0
  11. pygeodesy/auxilats/_CX_8.py +475 -0
  12. pygeodesy/auxilats/__init__.py +54 -0
  13. pygeodesy/auxilats/__main__.py +86 -0
  14. pygeodesy/auxilats/auxAngle.py +548 -0
  15. pygeodesy/auxilats/auxDLat.py +302 -0
  16. pygeodesy/auxilats/auxDST.py +296 -0
  17. pygeodesy/auxilats/auxLat.py +848 -0
  18. pygeodesy/auxilats/auxily.py +272 -0
  19. pygeodesy/azimuthal.py +1150 -0
  20. pygeodesy/basics.py +892 -0
  21. pygeodesy/booleans.py +2031 -0
  22. pygeodesy/cartesianBase.py +1062 -0
  23. pygeodesy/clipy.py +704 -0
  24. pygeodesy/constants.py +516 -0
  25. pygeodesy/css.py +660 -0
  26. pygeodesy/datums.py +752 -0
  27. pygeodesy/deprecated/__init__.py +61 -0
  28. pygeodesy/deprecated/bases.py +40 -0
  29. pygeodesy/deprecated/classes.py +262 -0
  30. pygeodesy/deprecated/consterns.py +54 -0
  31. pygeodesy/deprecated/datum.py +40 -0
  32. pygeodesy/deprecated/functions.py +375 -0
  33. pygeodesy/deprecated/nvector.py +48 -0
  34. pygeodesy/deprecated/rhumbBase.py +32 -0
  35. pygeodesy/deprecated/rhumbaux.py +33 -0
  36. pygeodesy/deprecated/rhumbsolve.py +33 -0
  37. pygeodesy/deprecated/rhumbx.py +33 -0
  38. pygeodesy/dms.py +986 -0
  39. pygeodesy/ecef.py +1348 -0
  40. pygeodesy/elevations.py +279 -0
  41. pygeodesy/ellipsoidalBase.py +1224 -0
  42. pygeodesy/ellipsoidalBaseDI.py +913 -0
  43. pygeodesy/ellipsoidalExact.py +343 -0
  44. pygeodesy/ellipsoidalGeodSolve.py +343 -0
  45. pygeodesy/ellipsoidalKarney.py +403 -0
  46. pygeodesy/ellipsoidalNvector.py +685 -0
  47. pygeodesy/ellipsoidalVincenty.py +590 -0
  48. pygeodesy/ellipsoids.py +2476 -0
  49. pygeodesy/elliptic.py +1198 -0
  50. pygeodesy/epsg.py +243 -0
  51. pygeodesy/errors.py +804 -0
  52. pygeodesy/etm.py +1190 -0
  53. pygeodesy/fmath.py +1013 -0
  54. pygeodesy/formy.py +1818 -0
  55. pygeodesy/frechet.py +865 -0
  56. pygeodesy/fstats.py +760 -0
  57. pygeodesy/fsums.py +1898 -0
  58. pygeodesy/gars.py +358 -0
  59. pygeodesy/geodesicw.py +581 -0
  60. pygeodesy/geodesicx/_C4_24.py +1699 -0
  61. pygeodesy/geodesicx/_C4_27.py +2395 -0
  62. pygeodesy/geodesicx/_C4_30.py +3301 -0
  63. pygeodesy/geodesicx/__init__.py +48 -0
  64. pygeodesy/geodesicx/__main__.py +91 -0
  65. pygeodesy/geodesicx/gx.py +1382 -0
  66. pygeodesy/geodesicx/gxarea.py +535 -0
  67. pygeodesy/geodesicx/gxbases.py +154 -0
  68. pygeodesy/geodesicx/gxline.py +669 -0
  69. pygeodesy/geodsolve.py +426 -0
  70. pygeodesy/geohash.py +914 -0
  71. pygeodesy/geoids.py +1884 -0
  72. pygeodesy/hausdorff.py +892 -0
  73. pygeodesy/heights.py +1155 -0
  74. pygeodesy/interns.py +687 -0
  75. pygeodesy/iters.py +545 -0
  76. pygeodesy/karney.py +919 -0
  77. pygeodesy/ktm.py +633 -0
  78. pygeodesy/latlonBase.py +1766 -0
  79. pygeodesy/lazily.py +960 -0
  80. pygeodesy/lcc.py +684 -0
  81. pygeodesy/ltp.py +1107 -0
  82. pygeodesy/ltpTuples.py +1563 -0
  83. pygeodesy/mgrs.py +721 -0
  84. pygeodesy/named.py +1324 -0
  85. pygeodesy/namedTuples.py +683 -0
  86. pygeodesy/nvectorBase.py +695 -0
  87. pygeodesy/osgr.py +781 -0
  88. pygeodesy/points.py +1686 -0
  89. pygeodesy/props.py +628 -0
  90. pygeodesy/resections.py +1048 -0
  91. pygeodesy/rhumb/__init__.py +46 -0
  92. pygeodesy/rhumb/aux_.py +397 -0
  93. pygeodesy/rhumb/bases.py +1148 -0
  94. pygeodesy/rhumb/ekx.py +563 -0
  95. pygeodesy/rhumb/solve.py +572 -0
  96. pygeodesy/simplify.py +647 -0
  97. pygeodesy/solveBase.py +472 -0
  98. pygeodesy/sphericalBase.py +724 -0
  99. pygeodesy/sphericalNvector.py +1264 -0
  100. pygeodesy/sphericalTrigonometry.py +1447 -0
  101. pygeodesy/streprs.py +627 -0
  102. pygeodesy/trf.py +2079 -0
  103. pygeodesy/triaxials.py +1484 -0
  104. pygeodesy/units.py +969 -0
  105. pygeodesy/unitsBase.py +349 -0
  106. pygeodesy/ups.py +538 -0
  107. pygeodesy/utily.py +1231 -0
  108. pygeodesy/utm.py +762 -0
  109. pygeodesy/utmups.py +318 -0
  110. pygeodesy/utmupsBase.py +517 -0
  111. pygeodesy/vector2d.py +785 -0
  112. pygeodesy/vector3d.py +968 -0
  113. pygeodesy/vector3dBase.py +1049 -0
  114. pygeodesy/webmercator.py +383 -0
  115. 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.