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
@@ -0,0 +1,548 @@
1
+
2
+ # -*- coding: utf-8 -*-
3
+
4
+ u'''(INTERNAL) I{Auxiliary} latitudes' base classes, constants and functions.
5
+
6
+ Class L{AuxAngle} transcoded to Python from I{Karney}'s C++ class U{AuxAngle
7
+ <https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1AuxAngle.html>}
8
+ in I{GeographicLib version 2.2+}.
9
+
10
+ Copyright (C) U{Charles Karney<mailto:Karney@Alum.MIT.edu>} (2022-2023) and licensed
11
+ under the MIT/X11 License. For more information, see the U{GeographicLib
12
+ <https://GeographicLib.SourceForge.io>} documentation.
13
+ '''
14
+ # make sure int/int division yields float quotient, see .basics
15
+ from __future__ import division as _; del _ # PYCHOK semicolon
16
+
17
+ from pygeodesy.auxilats.auxily import Aux, _Aux2Greek, AuxError
18
+ from pygeodesy.basics import _xinstanceof, _xkwds_get
19
+ from pygeodesy.constants import EPS, _INF_NAN_NINF, MAX, NAN, _0_0, _0_5, _1_0, \
20
+ _copysign_1_0, _over, _pos_self, isfinite, isnan
21
+ # from pygeodesy.errors import AuxError, _xkwds_get # from .auxily, .basics
22
+ from pygeodesy.fmath import hypot, unstr
23
+ from pygeodesy.fsums import _add_op_, _isub_op_, _sub_op_, _iadd_op_, _Named, NN
24
+ # from pygeodesy.interns import NN, _iadd_op_ # from .fsums
25
+ # from pygeodesy.named import _Named # from .fsums
26
+ from pygeodesy.lazily import _ALL_DOCS, _ALL_MODS as _MODS
27
+ from pygeodesy.props import Property, Property_RO, property_RO, _update_all
28
+ # from pygeodesy.streprs import unstr # from .fmath
29
+ from pygeodesy.units import Degrees, Radians
30
+ from pygeodesy.utily import atan2d, sincos2, sincos2d
31
+
32
+ from math import asinh, atan2, copysign, degrees, fabs, radians, sinh
33
+
34
+ __all__ = ()
35
+ __version__ = '23.12.02'
36
+
37
+ _0_INF_NAN_NINF = (0, _0_0) + _INF_NAN_NINF
38
+ _MAX_2 = MAX * _0_5 # PYCHOK used!
39
+ # del _INF_NAN_NINF, MAX
40
+
41
+
42
+ class AuxAngle(_Named):
43
+ '''U{An accurate representation of angles
44
+ <https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1AuxAngle.html>}
45
+ '''
46
+ _AUX = None # overloaded/-ridden
47
+ _diff = NAN # default
48
+ _iter = None # like .Named._NamedBase
49
+ _y = _0_0
50
+ _x = _1_0
51
+
52
+ def __init__(self, y_angle=_0_0, x=_1_0, name=NN, **aux):
53
+ '''New L{AuxAngle}.
54
+
55
+ @kwarg y_angle: The Y component (C{scalar}, including C{INF}, C{NAN}
56
+ and C{NINF}) or a previous L{AuxAngle} instance.
57
+ @kwarg x: The X component, ignored if C{B{y_angle}} is non-C{scalar}.
58
+ @kwarg name: Optional name (C{str}).
59
+ @kwarg aux: I{Auxiliary} kind (C{Aux.KIND}), ignored if B{C{y_angle}}
60
+ is non-C{scalar}.
61
+
62
+ @raise AuxError: Invalid B{C{y_angle}}, B{C{x}} or B{C{aux}}.
63
+ '''
64
+ try:
65
+ yx = y_angle._yx
66
+ if self._AUX is None:
67
+ self._AUX = y_angle._AUX
68
+ if self._diff != y_angle._diff:
69
+ self._diff = y_angle._diff
70
+ except AttributeError:
71
+ yx = y_angle, x
72
+ if aux:
73
+ aux = _xkwds_get(aux, aux=self._AUX)
74
+ if self._AUX is not aux:
75
+ if aux not in _AUXClass:
76
+ raise AuxError(aux=aux)
77
+ self._AUX = aux
78
+ self._y, self._x = _yx2(yx)
79
+ if name:
80
+ self.name = name
81
+
82
+ def __abs__(self):
83
+ '''Return this angle's absolute value (L{AuxAngle}).
84
+ '''
85
+ a = self._copy_2(self.__abs__)
86
+ a._yx = map(fabs, self._yx)
87
+ return a
88
+
89
+ def __add__(self, other):
90
+ '''Return C{B{self} + B{other}} as an L{AuxAngle}.
91
+
92
+ @arg other: An L{AuxAngle}.
93
+
94
+ @return: The sum (L{AuxAngle}).
95
+
96
+ @raise TypeError: Invalid B{C{other}}.
97
+ '''
98
+ a = self._copy_2(self.__add__)
99
+ return a._iadd(other, _add_op_)
100
+
101
+ def __bool__(self): # PYCHOK not special in Python 2-
102
+ '''Return C{True} if this angle is non-zero.
103
+ '''
104
+ return bool(self.tan)
105
+
106
+ def __eq__(self, other):
107
+ '''Return C{B{self} == B{other}} as C{bool}.
108
+ '''
109
+ return not self.__ne__(other)
110
+
111
+ def __float__(self):
112
+ '''Return this angle's C{tan} (C{float}).
113
+ '''
114
+ return self.tan
115
+
116
+ def __iadd__(self, other):
117
+ '''Apply C{B{self} += B{other}} to this angle.
118
+
119
+ @arg other: An L{AuxAngle}.
120
+
121
+ @return: This angle, updated (L{AuxAngle}).
122
+
123
+ @raise TypeError: Invalid B{C{other}}.
124
+ '''
125
+ return self._iadd(other, _iadd_op_)
126
+
127
+ def __isub__(self, other):
128
+ '''Apply C{B{self} -= B{other}} to this angle.
129
+
130
+ @arg other: An L{AuxAngle}.
131
+
132
+ @return: This instance, updated (L{AuxAngle}).
133
+
134
+ @raise TypeError: Invalid B{C{other}} type.
135
+ '''
136
+ return self._iadd(-other, _isub_op_)
137
+
138
+ def __ne__(self, other):
139
+ '''Return C{B{self} != B{other}} as C{bool}.
140
+ '''
141
+ _xinstanceof(AuxAngle, other=other)
142
+ y, x, r = self._yxr_normalized()
143
+ s, c, t = other._yxr_normalized()
144
+ return fabs(y - s) > EPS or fabs(x - c) > EPS \
145
+ or fabs(r - t) > EPS
146
+
147
+ def __neg__(self):
148
+ '''Return I{a copy of} this angle, negated.
149
+ '''
150
+ a = self._copy_2(self.__neg__)
151
+ if a.y or not a.x:
152
+ a.y = -a.y
153
+ else:
154
+ a.x = -a.x
155
+ return a
156
+
157
+ def __pos__(self):
158
+ '''Return this angle I{as-is}, like C{float.__pos__()}.
159
+ '''
160
+ return self if _pos_self else self._copy_2(self.__pos__)
161
+
162
+ def __radd__(self, other):
163
+ '''Return C{B{other} + B{self}} as an L{AuxAngle}.
164
+
165
+ @see: Method L{AuxAngle.__add__}.
166
+ '''
167
+ a = self._copy_r2(other, self.__radd__)
168
+ return a._iadd(self, _add_op_)
169
+
170
+ def __rsub__(self, other):
171
+ '''Return C{B{other} - B{self}} as an L{AuxAngle}.
172
+
173
+ @see: Method L{AuxAngle.__sub__}.
174
+ '''
175
+ a = self._copy_r2(other, self.__rsub__)
176
+ return a._iadd(-self, _sub_op_)
177
+
178
+ def __str__(self):
179
+ n = _Aux2Greek.get(self._AUX, self.classname)
180
+ return unstr(n, y=self.y, x=self.x, tan=self.tan)
181
+
182
+ def __sub__(self, other):
183
+ '''Return C{B{self} - B{other}} as an L{AuxAngle}.
184
+
185
+ @arg other: An L{AuxAngle}.
186
+
187
+ @return: The difference (L{AuxAngle}).
188
+
189
+ @raise TypeError: Invalid B{C{other}} type.
190
+ '''
191
+ a = self._copy_2(self.__sub__)
192
+ return a._iadd(-other, _sub_op_)
193
+
194
+ def _iadd(self, other, *unused): # op
195
+ '''(INTERNAL) Apply C{B{self} += B{other}}.
196
+ '''
197
+ _xinstanceof(AuxAngle, other=other)
198
+ # ignore zero other to preserve signs of _y and _x
199
+ if other.tan:
200
+ s, c = other._yx
201
+ y, x = self._yx
202
+ self._yx = (y * c + x * s), \
203
+ (x * c - y * s)
204
+ return self
205
+
206
+ def _copy_2(self, which):
207
+ '''(INTERNAL) Copy for I{dyadic} operators.
208
+ '''
209
+ return _Named.copy(self, deep=False, name=which.__name__)
210
+
211
+ def _copy_r2(self, other, which):
212
+ '''(INTERNAL) Copy for I{reverse-dyadic} operators.
213
+ '''
214
+ _xinstanceof(AuxAngle, other=other)
215
+ return other._copy_2(which)
216
+
217
+ def copyquadrant(self, other):
218
+ '''Copy an B{C{other}} angle's quadrant into this angle (L{auxAngle}).
219
+ '''
220
+ _xinstanceof(AuxAngle, other=other)
221
+ self._yx = copysign(self.y, other.y), \
222
+ copysign(self.x, other.x)
223
+ return self
224
+
225
+ @Property_RO
226
+ def diff(self):
227
+ '''Get derivative C{dtan(Eta) / dtan(Phi)} (C{float} or C{NAN}).
228
+ '''
229
+ return self._diff
230
+
231
+ @staticmethod
232
+ def fromDegrees(deg, **name_aux):
233
+ '''Get an L{AuxAngle} from degrees.
234
+ '''
235
+ return _AuxClass(**name_aux)(*sincos2d(deg), **name_aux)
236
+
237
+ @staticmethod
238
+ def fromLambertianDegrees(psi, **name_aux):
239
+ '''Get an L{AuxAngle} from I{Lambertian} degrees.
240
+ '''
241
+ return _AuxClass(**name_aux)(sinh(radians(psi)), **name_aux)
242
+
243
+ @staticmethod
244
+ def fromLambertianRadians(psi, **name_aux):
245
+ '''Get an L{AuxAngle} from I{Lambertian} radians.
246
+ '''
247
+ return _AuxClass(**name_aux)(sinh(psi), **name_aux)
248
+
249
+ @staticmethod
250
+ def fromRadians(rad, **name_aux):
251
+ '''Get an L{AuxAngle} from radians.
252
+ '''
253
+ return _AuxClass(**name_aux)(*sincos2(rad), **name_aux)
254
+
255
+ @Property_RO
256
+ def iteration(self):
257
+ '''Get the iteration (C{int} or C{None}).
258
+ '''
259
+ return self._iter
260
+
261
+ def normal(self):
262
+ '''Normalize this angle I{in-place}.
263
+
264
+ @return: This angle, normalized (L{AuxAngle}).
265
+ '''
266
+ self._yx = self._yx_normalized
267
+ return self
268
+
269
+ @Property_RO
270
+ def normalized(self):
271
+ '''Get a normalized copy of this angle (L{AuxAngle}).
272
+ '''
273
+ y, x = self._yx_normalized
274
+ return self.classof(y, x, name=self.name, aux=self._AUX)
275
+
276
+ @property_RO
277
+ def _RhumbAux(self):
278
+ '''(INTERNAL) Import the L{RhumbAux} class, I{once}.
279
+ '''
280
+ AuxAngle._RhumbAux = R = _MODS.rhumb.aux_.RhumbAux # overwrite property_RO
281
+ return R
282
+
283
+ @Property_RO
284
+ def tan(self):
285
+ '''Get this angle's C{tan} (C{float}).
286
+ '''
287
+ y, x = self._yx
288
+ return _over(y, x) if isfinite(y) and y else y
289
+
290
+ def toBeta(self, rhumb):
291
+ '''Short for C{rhumb.auxDLat.convert(Aux.BETA, self, exact=rhumb.exact)}
292
+ '''
293
+ return self._toRhumbAux(rhumb, Aux.BETA)
294
+
295
+ def toChi(self, rhumb):
296
+ '''Short for C{rhumb.auxDLat.convert(Aux.CHI, self, exact=rhumb.exact)}
297
+ '''
298
+ return self._toRhumbAux(rhumb, Aux.CHI)
299
+
300
+ @Property_RO
301
+ def toDegrees(self):
302
+ '''Get this angle as L{Degrees}.
303
+ '''
304
+ return Degrees(atan2d(*self._yx), name=self.name)
305
+
306
+ @Property_RO
307
+ def toLambertianDegrees(self): # PYCHOK no cover
308
+ '''Get this angle's I{Lambertian} in L{Degrees}.
309
+ '''
310
+ r = self.toLambertianRadians
311
+ return Degrees(degrees(r), name=r.name)
312
+
313
+ @Property_RO
314
+ def toLambertianRadians(self):
315
+ '''Get this angle's I{Lambertian} in L{Radians}.
316
+ '''
317
+ return Radians(asinh(self.tan), name=self.name)
318
+
319
+ def toMu(self, rhumb):
320
+ '''Short for C{rhumb.auxDLat.convert(Aux.MU, self, exact=rhumb.exact)}
321
+ '''
322
+ return self._toRhumbAux(rhumb, Aux.MU)
323
+
324
+ def toPhi(self, rhumb):
325
+ '''Short for C{rhumb.auxDLat.convert(Aux.PHI, self, exact=rhumb.exact)}
326
+ '''
327
+ return self._toRhumbAux(rhumb, Aux.PHI)
328
+
329
+ @Property_RO
330
+ def toRadians(self):
331
+ '''Get this angle as L{Radians}.
332
+ '''
333
+ return Radians(atan2(*self._yx), name=self.name)
334
+
335
+ def _toRhumbAux(self, rhumb, aux):
336
+ '''(INTERNAL) Create an C{aux}-KIND angle from this angle.
337
+ '''
338
+ _xinstanceof(self._RhumbAux, rhumb=rhumb)
339
+ return rhumb._auxD.convert(aux, self, exact=rhumb.exact)
340
+
341
+ @Property
342
+ def x(self):
343
+ '''Get this angle's C{x} (C{float}).
344
+ '''
345
+ return self._x
346
+
347
+ @x.setter # PYCHOK setter!
348
+ def x(self, x): # PYCHOK no cover
349
+ '''Set this angle's C{x} (C{float}).
350
+ '''
351
+ x = float(x)
352
+ if self._x != x:
353
+ _update_all(self)
354
+ self._x = x
355
+
356
+ @property_RO
357
+ def _x_normalized(self):
358
+ '''(INTERNAL) Get the I{normalized} C{x}.
359
+ '''
360
+ _, x = self._yx_normalized
361
+ return x
362
+
363
+ @Property
364
+ def y(self):
365
+ '''Get this angle's C{y} (C{float}).
366
+ '''
367
+ return self._y
368
+
369
+ @y.setter # PYCHOK setter!
370
+ def y(self, y): # PYCHOK no cover
371
+ '''Set this angle's C{y} (C{float}).
372
+ '''
373
+ y = float(y)
374
+ if self.y != y:
375
+ _update_all(self)
376
+ self._y = y
377
+
378
+ @Property
379
+ def _yx(self):
380
+ '''(INTERNAL) Get this angle as 2-tuple C{(y, x)}.
381
+ '''
382
+ return self._y, self._x
383
+
384
+ @_yx.setter # PYCHOK setter!
385
+ def _yx(self, yx):
386
+ '''(INTERNAL) Set this angle's C{y} and C{x}.
387
+ '''
388
+ yx = _yx2(yx)
389
+ if self._yx != yx:
390
+ _update_all(self)
391
+ self._y, self._x = yx
392
+
393
+ @Property_RO
394
+ def _yx_normalized(self):
395
+ '''(INTERNAL) Get this angle as 2-tuple C{(y, x)}, I{normalized}.
396
+ '''
397
+ y, x = self._yx
398
+ if isfinite(y) and fabs(y) < _MAX_2 \
399
+ and fabs(x) < _MAX_2 \
400
+ and isfinite(self.tan):
401
+ h = hypot(y, x)
402
+ if h > 0 and y:
403
+ y = y / h # /= chokes PyChecker
404
+ x = x / h
405
+ if isnan(y): # PYCHOK no cover
406
+ y = _copysign_1_0(self.y)
407
+ if isnan(x): # PYCHOK no cover
408
+ x = _copysign_1_0(self.x)
409
+ else: # scalar 0
410
+ y, x = _0_0, _copysign_1_0(y * x)
411
+ else: # scalar NAN
412
+ y, x = NAN, _copysign_1_0(y * x)
413
+ return y, x
414
+
415
+ def _yxr_normalized(self, abs_y=False):
416
+ '''(INTERNAL) Get 3-tuple C{(y, x, r)}, I{normalized}
417
+ with C{y} or C{abs(y)} and C{r} as C{.toRadians}.
418
+ '''
419
+ y, x = self._yx_normalized
420
+ if abs_y:
421
+ y = fabs(y) # only y, not x
422
+ return y, x, atan2(y, x) # .toRadians
423
+
424
+
425
+ class AuxBeta(AuxAngle):
426
+ '''A I{Parametric, Auxiliary} latitude.
427
+ '''
428
+ _AUX = Aux.BETA
429
+
430
+ @staticmethod
431
+ def fromDegrees(deg, name=NN):
432
+ '''Get an L{AuxBeta} from degrees.
433
+ '''
434
+ return AuxBeta(*sincos2d(deg), name=name)
435
+
436
+ @staticmethod
437
+ def fromRadians(rad, name=NN):
438
+ '''Get an L{AuxBeta} from radians.
439
+ '''
440
+ return AuxBeta(*sincos2(rad), name=name)
441
+
442
+
443
+ class AuxChi(AuxAngle):
444
+ '''A I{Conformal, Auxiliary} latitude.
445
+ '''
446
+ _AUX = Aux.CHI
447
+
448
+ @staticmethod
449
+ def fromDegrees(deg, name=NN):
450
+ '''Get an L{AuxChi} from degrees.
451
+ '''
452
+ return AuxChi(*sincos2d(deg), name=name)
453
+
454
+
455
+ class AuxMu(AuxAngle):
456
+ '''A I{Rectifying, Auxiliary} latitude.
457
+ '''
458
+ _AUX = Aux.MU
459
+
460
+ @staticmethod
461
+ def fromDegrees(deg, name=NN):
462
+ '''Get an L{AuxMu} from degrees.
463
+ '''
464
+ return AuxMu(*sincos2d(deg), name=name)
465
+
466
+
467
+ class AuxPhi(AuxAngle):
468
+ '''A I{Geodetic or Geographic, Auxiliary} latitude.
469
+ '''
470
+ _AUX = Aux.PHI
471
+ _diff = _1_0 # see .auxLat._Newton
472
+
473
+ @staticmethod
474
+ def fromDegrees(deg, name=NN):
475
+ '''Get an L{AuxPhi} from degrees.
476
+ '''
477
+ return AuxPhi(*sincos2d(deg), name=name)
478
+
479
+
480
+ class AuxTheta(AuxAngle):
481
+ '''A I{Geocentric, Auxiliary} latitude.
482
+ '''
483
+ _AUX = Aux.THETA
484
+
485
+ @staticmethod
486
+ def fromDegrees(deg, name=NN):
487
+ '''Get an L{AuxTheta} from degrees.
488
+ '''
489
+ return AuxTheta(*sincos2d(deg), name=name)
490
+
491
+
492
+ class AuxXi(AuxAngle):
493
+ '''An I{Authalic, Auxiliary} latitude.
494
+ '''
495
+ _AUX = Aux.XI
496
+
497
+ @staticmethod
498
+ def fromDegrees(deg, name=NN):
499
+ '''Get an L{AuxXi} from degrees.
500
+ '''
501
+ return AuxXi(*sincos2d(deg), name=name)
502
+
503
+
504
+ _AUXClass = {Aux.BETA: AuxBeta,
505
+ Aux.CHI: AuxChi,
506
+ Aux.MU: AuxMu,
507
+ Aux.PHI: AuxPhi,
508
+ Aux.THETA: AuxTheta,
509
+ Aux.XI: AuxXi}
510
+
511
+ def _AuxClass(aux=None, **unused): # PYCHOK C{classof(aux)}
512
+ return _AUXClass.get(aux, AuxAngle)
513
+
514
+
515
+ def _yx2(yx):
516
+ try:
517
+ y, x = map(float, yx)
518
+ if y in _0_INF_NAN_NINF:
519
+ x = _copysign_1_0(x)
520
+ except (TypeError, ValueError) as e:
521
+ y, x = yx
522
+ raise AuxError(y=y, x=x, cause=e)
523
+ return y, x
524
+
525
+
526
+ __all__ += _ALL_DOCS(AuxAngle, AuxBeta, AuxChi, AuxMu, AuxPhi, AuxTheta, AuxXi)
527
+
528
+ # **) MIT License
529
+ #
530
+ # Copyright (C) 2023-2024 -- mrJean1 at Gmail -- All Rights Reserved.
531
+ #
532
+ # Permission is hereby granted, free of charge, to any person obtaining a
533
+ # copy of this software and associated documentation files (the "Software"),
534
+ # to deal in the Software without restriction, including without limitation
535
+ # the rights to use, copy, modify, merge, publish, distribute, sublicense,
536
+ # and/or sell copies of the Software, and to permit persons to whom the
537
+ # Software is furnished to do so, subject to the following conditions:
538
+ #
539
+ # The above copyright notice and this permission notice shall be included
540
+ # in all copies or substantial portions of the Software.
541
+ #
542
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
543
+ # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
544
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
545
+ # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
546
+ # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
547
+ # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
548
+ # OTHER DEALINGS IN THE SOFTWARE.