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
|
@@ -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.
|