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/gars.py ADDED
@@ -0,0 +1,358 @@
1
+
2
+ # -*- coding: utf-8 -*-
3
+
4
+ u'''I{Global Area Reference System} (GARS) en-/decoding.
5
+
6
+ Classes L{Garef} and L{GARSError} and several functions to encode,
7
+ decode and inspect I{Global Area Reference System} (GARS) references.
8
+
9
+ Transcoded from C++ class U{GARS
10
+ <https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1GARS.html>}
11
+ by I{Charles Karney}. See also U{Global Area Reference System
12
+ <https://WikiPedia.org/wiki/Global_Area_Reference_System>} and U{NGA (GARS)
13
+ <https://Earth-Info.NGA.mil/GandG/coordsys/grids/gars.html>}.
14
+ '''
15
+
16
+ # from pygeodesy.basics import isstr # from .dms
17
+ from pygeodesy.constants import _off90, _1_over, _0_5, \
18
+ _1_0 # PYCHOK used!
19
+ from pygeodesy.dms import parse3llh, Fmt, isstr # parseDMS2
20
+ from pygeodesy.errors import _ValueError, _xkwds
21
+ from pygeodesy.interns import NN, _0to9_, _AtoZnoIO_, _COMMA_
22
+ from pygeodesy.lazily import _ALL_LAZY, _ALL_OTHER
23
+ from pygeodesy.named import nameof, Property_RO
24
+ from pygeodesy.namedTuples import LatLon2Tuple, LatLonPrec3Tuple
25
+ # from pygeodesy.props import Property_RO # from .named
26
+ # from pygeodesy.streprs import Fmt # from .dms
27
+ from pygeodesy.units import Int_, Lat, Lon, Precision_, Scalar_, \
28
+ Str, _xStrError
29
+
30
+ from math import floor
31
+
32
+ __all__ = _ALL_LAZY.gars
33
+ __version__ = '23.10.07'
34
+
35
+ _Digits = _0to9_
36
+ _LatLen = 2
37
+ _LatOrig = -90
38
+ _Letters = _AtoZnoIO_
39
+ _LonLen = 3
40
+ _LonOrig = -180
41
+ _MaxPrec = 2
42
+
43
+ _MinLen = _LonLen + _LatLen
44
+ _MaxLen = _MinLen + _MaxPrec
45
+
46
+ _M1 = _M2 = 2
47
+ _M3 = 3
48
+ _M4 = _M1 * _M2 * _M3
49
+
50
+ _LatOrig_M4 = _LatOrig * _M4
51
+ _LatOrig_M1 = _LatOrig * _M1
52
+ _LonOrig_M4 = _LonOrig * _M4
53
+ _LonOrig_M1_1 = _LonOrig * _M1 - 1
54
+
55
+ _Resolutions = _1_over(_M1), _1_over(_M1 * _M2), _1_over(_M4)
56
+
57
+
58
+ def _2divmod2(ll, _Orig_M4):
59
+ x = int(floor(ll * _M4)) - _Orig_M4
60
+ i = (x * _M1) // _M4
61
+ x -= i * _M4 // _M1
62
+ return i, x
63
+
64
+
65
+ def _2fll(lat, lon, *unused):
66
+ '''(INTERNAL) Convert lat, lon.
67
+ '''
68
+ # lat, lon = parseDMS2(lat, lon)
69
+ return (Lat(lat, Error=GARSError),
70
+ Lon(lon, Error=GARSError))
71
+
72
+
73
+ # def _2Garef(garef):
74
+ # '''(INTERNAL) Check or create a L{Garef} instance.
75
+ # '''
76
+ # if not isinstance(garef, Garef):
77
+ # try:
78
+ # garef = Garef(garef)
79
+ # except (TypeError, ValueError):
80
+ # raise _xStrError(Garef, Str, garef=garef)
81
+ # return garef
82
+
83
+
84
+ def _2garstr2(garef):
85
+ '''(INTERNAL) Check a garef string.
86
+ '''
87
+ try:
88
+ n, garstr = len(garef), garef.upper()
89
+ if n < _MinLen or n > _MaxLen \
90
+ or garstr[:3] == 'INV' \
91
+ or not garstr.isalnum():
92
+ raise ValueError
93
+ return garstr, _2Precision(n - _MinLen)
94
+
95
+ except (AttributeError, TypeError, ValueError) as x:
96
+ raise GARSError(Garef.__name__, garef, cause=x)
97
+
98
+
99
+ def _2Precision(precision):
100
+ '''(INTERNAL) Return a L{Precision_} instance.
101
+ '''
102
+ return Precision_(precision, Error=GARSError, low=0, high=_MaxPrec)
103
+
104
+
105
+ class GARSError(_ValueError):
106
+ '''Global Area Reference System (GARS) encode, decode or other L{Garef} issue.
107
+ '''
108
+ pass
109
+
110
+
111
+ class Garef(Str):
112
+ '''Garef class, a named C{str}.
113
+ '''
114
+ # no str.__init__ in Python 3
115
+ def __new__(cls, cll, precision=1, name=NN):
116
+ '''New L{Garef} from an other L{Garef} instance or garef
117
+ C{str} or from a C{LatLon} instance or lat-/longitude C{str}.
118
+
119
+ @arg cll: Cell or location (L{Garef} or C{str}, C{LatLon}
120
+ or C{str}).
121
+ @kwarg precision: Optional, the desired garef resolution
122
+ and length (C{int} 0..2), see function
123
+ L{gars.encode} for more details.
124
+ @kwarg name: Optional name (C{str}).
125
+
126
+ @return: New L{Garef}.
127
+
128
+ @raise RangeError: Invalid B{C{cll}} lat- or longitude.
129
+
130
+ @raise TypeError: Invalid B{C{cll}}.
131
+
132
+ @raise GARSError: INValid or non-alphanumeric B{C{cll}}.
133
+ '''
134
+ ll = p = None
135
+
136
+ if isinstance(cll, Garef):
137
+ g, p = _2garstr2(str(cll))
138
+
139
+ elif isstr(cll):
140
+ if _COMMA_ in cll:
141
+ ll = _2fll(*parse3llh(cll))
142
+ g = encode(*ll, precision=precision) # PYCHOK false
143
+ else:
144
+ g = cll.upper()
145
+
146
+ else: # assume LatLon
147
+ try:
148
+ ll = _2fll(cll.lat, cll.lon)
149
+ g = encode(*ll, precision=precision) # PYCHOK false
150
+ except AttributeError:
151
+ raise _xStrError(Garef, cll=cll) # Error=GARSError
152
+
153
+ self = Str.__new__(cls, g, name=name or nameof(cll))
154
+ self._latlon = ll
155
+ self._precision = p
156
+ return self
157
+
158
+ @Property_RO
159
+ def decoded3(self):
160
+ '''Get this garef's attributes (L{LatLonPrec3Tuple}).
161
+ '''
162
+ lat, lon = self.latlon
163
+ return LatLonPrec3Tuple(lat, lon, self.precision, name=self.name)
164
+
165
+ @Property_RO
166
+ def _decoded3(self):
167
+ '''(INTERNAL) Initial L{LatLonPrec3Tuple}.
168
+ '''
169
+ return decode3(self)
170
+
171
+ @Property_RO
172
+ def latlon(self):
173
+ '''Get this garef's (center) lat- and longitude (L{LatLon2Tuple}).
174
+ '''
175
+ lat, lon = self._latlon or self._decoded3[:2]
176
+ return LatLon2Tuple(lat, lon, name=self.name)
177
+
178
+ @Property_RO
179
+ def precision(self):
180
+ '''Get this garef's precision (C{int}).
181
+ '''
182
+ p = self._precision
183
+ return self._decoded3.precision if p is None else p
184
+
185
+ def toLatLon(self, LatLon=None, **LatLon_kwds):
186
+ '''Return (the center of) this garef cell as an instance
187
+ of the supplied C{LatLon} class.
188
+
189
+ @kwarg LatLon: Class to use (C{LatLon} or C{None}).
190
+ @kwarg LatLon_kwds: Optional, additional B{C{LatLon}}
191
+ keyword arguments.
192
+
193
+ @return: This garef location as B{C{LatLon}} or if
194
+ C{B{LatLon} is None} as L{LatLonPrec3Tuple}.
195
+ '''
196
+ return self.decoded3 if LatLon is None else LatLon(
197
+ *self.latlon, **_xkwds(LatLon_kwds, name=self.name))
198
+
199
+
200
+ def decode3(garef, center=True):
201
+ '''Decode a C{garef} to lat-, longitude and precision.
202
+
203
+ @arg garef: To be decoded (L{Garef} or C{str}).
204
+ @kwarg center: If C{True} the center, otherwise the south-west,
205
+ lower-left corner (C{bool}).
206
+
207
+ @return: A L{LatLonPrec3Tuple}C{(lat, lon, precision)}.
208
+
209
+ @raise GARSError: Invalid B{C{garef}}, INValid, non-alphanumeric
210
+ or bad length B{C{garef}}.
211
+ '''
212
+ def _Error(i):
213
+ return GARSError(garef=Fmt.SQUARE(repr(garef), i))
214
+
215
+ def _ll(chars, g, i, j, lo, hi):
216
+ ll, b = 0, len(chars)
217
+ for i in range(i, j):
218
+ d = chars.find(g[i])
219
+ if d < 0:
220
+ raise _Error(i)
221
+ ll = ll * b + d
222
+ if ll < lo or ll > hi:
223
+ raise _Error(j)
224
+ return ll
225
+
226
+ def _ll2(lon, lat, g, i, m):
227
+ d = _Digits.find(g[i])
228
+ if d < 1 or d > m * m:
229
+ raise _Error(i)
230
+ d, r = divmod(d - 1, m)
231
+ lon = lon * m + r
232
+ lat = lat * m + (m - 1 - d)
233
+ return lon, lat
234
+
235
+ g, precision = _2garstr2(garef)
236
+
237
+ lon = _ll(_Digits, g, 0, _LonLen, 1, 720) + _LonOrig_M1_1
238
+ lat = _ll(_Letters, g, _LonLen, _MinLen, 0, 359) + _LatOrig_M1
239
+ if precision > 0:
240
+ lon, lat = _ll2(lon, lat, g, _MinLen, _M2)
241
+ if precision > 1:
242
+ lon, lat = _ll2(lon, lat, g, _MinLen + 1, _M3)
243
+
244
+ if center: # ll = (ll * 2 + 1) / 2
245
+ lon += _0_5
246
+ lat += _0_5
247
+
248
+ r = _Resolutions[precision] # == 1.0 / unit
249
+ return LatLonPrec3Tuple(Lat(lat * r, Error=GARSError),
250
+ Lon(lon * r, Error=GARSError),
251
+ precision, name=nameof(garef))
252
+
253
+
254
+ def encode(lat, lon, precision=1): # MCCABE 14
255
+ '''Encode a lat-/longitude as a C{garef} of the given precision.
256
+
257
+ @arg lat: Latitude (C{degrees}).
258
+ @arg lon: Longitude (C{degrees}).
259
+ @kwarg precision: Optional, the desired C{garef} resolution
260
+ and length (C{int} 0..2).
261
+
262
+ @return: The C{garef} (C{str}).
263
+
264
+ @raise RangeError: Invalid B{C{lat}} or B{C{lon}}.
265
+
266
+ @raise GARSError: Invalid B{C{precision}}.
267
+
268
+ @note: The C{garef} length is M{precision + 5} and the C{garef}
269
+ resolution is B{30′} for B{C{precision}} 0, B{15′} for 1
270
+ and B{5′} for 2, respectively.
271
+ '''
272
+ def _digit(x, y, m):
273
+ return _Digits[m * (m - y - 1) + x + 1],
274
+
275
+ def _str(chars, x, n):
276
+ s, b = [], len(chars)
277
+ for i in range(n):
278
+ x, i = divmod(x, b)
279
+ s.append(chars[i])
280
+ return tuple(reversed(s))
281
+
282
+ p = _2Precision(precision)
283
+
284
+ lat, lon = _2fll(lat, lon)
285
+ lat = _off90(lat)
286
+
287
+ ix, x = _2divmod2(lon, _LonOrig_M4)
288
+ iy, y = _2divmod2(lat, _LatOrig_M4)
289
+
290
+ g = _str(_Digits, ix + 1, _LonLen) + _str(_Letters, iy, _LatLen)
291
+ if p > 0:
292
+ ix, x = divmod(x, _M3)
293
+ iy, y = divmod(y, _M3)
294
+ g += _digit(ix, iy, _M2)
295
+ if p > 1:
296
+ g += _digit(x, y, _M3)
297
+
298
+ return NN.join(g)
299
+
300
+
301
+ def precision(res):
302
+ '''Determine the L{Garef} precision to meet a required (geographic)
303
+ resolution.
304
+
305
+ @arg res: The required resolution (C{degrees}).
306
+
307
+ @return: The L{Garef} precision (C{int} 0..2).
308
+
309
+ @raise ValueError: Invalid B{C{res}}.
310
+
311
+ @see: Function L{gars.encode} for more C{precision} details.
312
+ '''
313
+ r = Scalar_(res=res)
314
+ for p in range(_MaxPrec):
315
+ if resolution(p) <= r:
316
+ return p
317
+ return _MaxPrec
318
+
319
+
320
+ def resolution(prec):
321
+ '''Determine the (geographic) resolution of a given L{Garef} precision.
322
+
323
+ @arg prec: The given precision (C{int}).
324
+
325
+ @return: The (geographic) resolution (C{degrees}).
326
+
327
+ @raise GARSError: Invalid B{C{prec}}.
328
+
329
+ @see: Function L{gars.encode} for more C{precision} details.
330
+ '''
331
+ p = Int_(prec=prec, Error=GARSError, low=-1, high=_MaxPrec + 1)
332
+ return _Resolutions[max(0, min(p, _MaxPrec))]
333
+
334
+
335
+ __all__ += _ALL_OTHER(decode3, # functions
336
+ encode, precision, resolution)
337
+
338
+ # **) MIT License
339
+ #
340
+ # Copyright (C) 2016-2024 -- mrJean1 at Gmail -- All Rights Reserved.
341
+ #
342
+ # Permission is hereby granted, free of charge, to any person obtaining a
343
+ # copy of this software and associated documentation files (the "Software"),
344
+ # to deal in the Software without restriction, including without limitation
345
+ # the rights to use, copy, modify, merge, publish, distribute, sublicense,
346
+ # and/or sell copies of the Software, and to permit persons to whom the
347
+ # Software is furnished to do so, subject to the following conditions:
348
+ #
349
+ # The above copyright notice and this permission notice shall be included
350
+ # in all copies or substantial portions of the Software.
351
+ #
352
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
353
+ # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
354
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
355
+ # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
356
+ # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
357
+ # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
358
+ # OTHER DEALINGS IN THE SOFTWARE.