pygeodesy 24.11.11__py2.py3-none-any.whl → 25.1.5__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.11.11.dist-info → PyGeodesy-25.1.5.dist-info}/METADATA +34 -35
- PyGeodesy-25.1.5.dist-info/RECORD +118 -0
- {PyGeodesy-24.11.11.dist-info → PyGeodesy-25.1.5.dist-info}/WHEEL +1 -1
- pygeodesy/__init__.py +19 -19
- pygeodesy/__main__.py +1 -1
- pygeodesy/albers.py +5 -5
- pygeodesy/auxilats/_CX_4.py +1 -1
- pygeodesy/auxilats/_CX_6.py +1 -1
- pygeodesy/auxilats/_CX_8.py +1 -1
- pygeodesy/auxilats/_CX_Rs.py +1 -1
- pygeodesy/auxilats/__init__.py +1 -1
- pygeodesy/auxilats/__main__.py +1 -1
- pygeodesy/auxilats/auxAngle.py +5 -5
- pygeodesy/auxilats/auxDLat.py +6 -6
- pygeodesy/auxilats/auxDST.py +2 -2
- pygeodesy/auxilats/auxLat.py +5 -5
- pygeodesy/auxilats/auxily.py +2 -2
- pygeodesy/azimuthal.py +5 -5
- pygeodesy/basics.py +60 -8
- pygeodesy/booleans.py +1 -1
- pygeodesy/cartesianBase.py +22 -61
- pygeodesy/clipy.py +1 -1
- pygeodesy/constants.py +5 -5
- pygeodesy/css.py +1 -1
- pygeodesy/datums.py +1 -1
- pygeodesy/deprecated/__init__.py +2 -2
- pygeodesy/deprecated/bases.py +1 -1
- pygeodesy/deprecated/classes.py +86 -2
- pygeodesy/deprecated/consterns.py +1 -1
- pygeodesy/deprecated/datum.py +5 -5
- pygeodesy/deprecated/functions.py +42 -8
- pygeodesy/deprecated/nvector.py +1 -1
- pygeodesy/deprecated/rhumbBase.py +1 -1
- pygeodesy/deprecated/rhumbaux.py +1 -1
- pygeodesy/deprecated/rhumbsolve.py +1 -1
- pygeodesy/deprecated/rhumbx.py +1 -1
- pygeodesy/dms.py +1 -1
- pygeodesy/ecef.py +53 -56
- pygeodesy/elevations.py +1 -1
- pygeodesy/ellipsoidalBase.py +3 -3
- pygeodesy/ellipsoidalBaseDI.py +1 -1
- pygeodesy/ellipsoidalExact.py +1 -1
- pygeodesy/ellipsoidalGeodSolve.py +1 -1
- pygeodesy/ellipsoidalKarney.py +1 -1
- pygeodesy/ellipsoidalNvector.py +1 -1
- pygeodesy/ellipsoidalVincenty.py +6 -5
- pygeodesy/ellipsoids.py +4 -5
- pygeodesy/elliptic.py +6 -6
- pygeodesy/epsg.py +1 -1
- pygeodesy/errors.py +1 -1
- pygeodesy/etm.py +5 -5
- pygeodesy/fmath.py +18 -17
- pygeodesy/formy.py +409 -555
- pygeodesy/frechet.py +29 -86
- pygeodesy/fstats.py +1 -1
- pygeodesy/fsums.py +32 -33
- pygeodesy/gars.py +1 -1
- pygeodesy/geodesici.py +7 -7
- pygeodesy/geodesicw.py +1 -1
- pygeodesy/geodesicx/_C4_24.py +2 -2
- pygeodesy/geodesicx/_C4_27.py +2 -2
- pygeodesy/geodesicx/_C4_30.py +2 -2
- pygeodesy/geodesicx/__init__.py +2 -2
- pygeodesy/geodesicx/__main__.py +4 -5
- pygeodesy/geodesicx/gx.py +6 -5
- pygeodesy/geodesicx/gxarea.py +2 -2
- pygeodesy/geodesicx/gxbases.py +2 -2
- pygeodesy/geodesicx/gxline.py +16 -12
- pygeodesy/geodsolve.py +1 -1
- pygeodesy/geohash.py +1 -1
- pygeodesy/geoids.py +277 -203
- pygeodesy/hausdorff.py +23 -81
- pygeodesy/heights.py +115 -150
- pygeodesy/internals.py +1 -1
- pygeodesy/interns.py +2 -3
- pygeodesy/iters.py +1 -1
- pygeodesy/karney.py +3 -3
- pygeodesy/ktm.py +16 -15
- pygeodesy/latlonBase.py +323 -409
- pygeodesy/lazily.py +53 -44
- pygeodesy/lcc.py +1 -1
- pygeodesy/ltp.py +46 -50
- pygeodesy/ltpTuples.py +147 -130
- pygeodesy/mgrs.py +1 -1
- pygeodesy/named.py +149 -3
- pygeodesy/namedTuples.py +58 -7
- pygeodesy/nvectorBase.py +122 -105
- pygeodesy/osgr.py +1 -1
- pygeodesy/points.py +1 -1
- pygeodesy/props.py +1 -1
- pygeodesy/resections.py +18 -17
- pygeodesy/rhumb/__init__.py +1 -1
- pygeodesy/rhumb/aux_.py +2 -2
- pygeodesy/rhumb/bases.py +2 -2
- pygeodesy/rhumb/ekx.py +4 -4
- pygeodesy/rhumb/solve.py +1 -1
- pygeodesy/simplify.py +289 -401
- pygeodesy/solveBase.py +1 -1
- pygeodesy/sphericalBase.py +1 -1
- pygeodesy/sphericalNvector.py +5 -5
- pygeodesy/sphericalTrigonometry.py +7 -6
- pygeodesy/streprs.py +10 -5
- pygeodesy/trf.py +1 -1
- pygeodesy/triaxials.py +23 -16
- pygeodesy/units.py +16 -16
- pygeodesy/unitsBase.py +1 -1
- pygeodesy/ups.py +4 -4
- pygeodesy/utily.py +341 -211
- pygeodesy/utm.py +5 -5
- pygeodesy/utmups.py +1 -1
- pygeodesy/utmupsBase.py +1 -1
- pygeodesy/vector2d.py +5 -5
- pygeodesy/vector3d.py +14 -3
- pygeodesy/vector3dBase.py +5 -5
- pygeodesy/webmercator.py +1 -1
- pygeodesy/wgrs.py +1 -1
- PyGeodesy-24.11.11.dist-info/RECORD +0 -118
- {PyGeodesy-24.11.11.dist-info → PyGeodesy-25.1.5.dist-info}/top_level.txt +0 -0
pygeodesy/utily.py
CHANGED
|
@@ -3,45 +3,52 @@
|
|
|
3
3
|
|
|
4
4
|
u'''Various utility functions.
|
|
5
5
|
|
|
6
|
-
After I{
|
|
7
|
-
U{Latitude/Longitude<https://www.Movable-Type.co.UK/scripts/latlong.html>}
|
|
8
|
-
U{Vector-based geodesy<https://www.Movable-Type.co.UK/scripts/latlong-vectors.html>}
|
|
6
|
+
After I{Karney}'s C++ U{Math<https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1Math.html>}
|
|
7
|
+
class and I{Veness}' U{Latitude/Longitude<https://www.Movable-Type.co.UK/scripts/latlong.html>}
|
|
8
|
+
and U{Vector-based geodesy<https://www.Movable-Type.co.UK/scripts/latlong-vectors.html>}
|
|
9
|
+
and published under the same MIT Licence**.
|
|
9
10
|
'''
|
|
10
11
|
# make sure int/int division yields float quotient, see .basics
|
|
11
12
|
from __future__ import division as _; del _ # PYCHOK semicolon
|
|
12
13
|
|
|
13
|
-
from pygeodesy.basics import _copysign, isinstanceof, isint, isstr
|
|
14
|
+
from pygeodesy.basics import _copysign, isinstanceof, isint, isstr
|
|
14
15
|
from pygeodesy.constants import EPS, EPS0, INF, NAN, PI, PI2, PI_2, R_M, \
|
|
15
|
-
_M_KM, _M_NM, _M_SM, _0_0, _1__90, _0_5,
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
_float as _F, _isfinite, isnan, isnear0, \
|
|
16
|
+
_M_KM, _M_NM, _M_SM, _0_0, _1__90, _0_5, _2__PI, \
|
|
17
|
+
_1_0, _N_1_0, _10_0, _90_0, _180_0, _360_0, \
|
|
18
|
+
_copysign_0_0, _float, _isfinite, isnan, isnear0, \
|
|
19
19
|
_over, _umod_360, _umod_PI2
|
|
20
|
-
from pygeodesy.errors import _ValueError, _xkwds,
|
|
21
|
-
from pygeodesy.internals import _passargs
|
|
20
|
+
from pygeodesy.errors import _ValueError, _xkwds, _ALL_LAZY, _MODS
|
|
21
|
+
from pygeodesy.internals import _passargs
|
|
22
22
|
from pygeodesy.interns import _edge_, _radians_, _semi_circular_, _SPACE_
|
|
23
23
|
# from pygeodesy.lazily import _ALL_LAZY, _ALL_MODS as _MODS # from .errors
|
|
24
24
|
from pygeodesy.units import Degrees, Degrees_, Feet, Float, Lam, Lamd, \
|
|
25
|
-
Meter, Meter2, Radians
|
|
25
|
+
Meter, Meter2, Radians # Radians_
|
|
26
26
|
|
|
27
|
-
from math import acos, asin, atan2, cos, degrees, fabs, radians,
|
|
27
|
+
from math import acos, asin, atan2 as _atan2, cos, degrees, fabs, radians, \
|
|
28
|
+
sin, tan as _tan # pow
|
|
28
29
|
|
|
29
30
|
__all__ = _ALL_LAZY.utily
|
|
30
|
-
__version__ = '
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
31
|
+
__version__ = '25.01.05'
|
|
32
|
+
|
|
33
|
+
_G_DEG = _float( 400.0 / _360_0) # grades per degree
|
|
34
|
+
_G_RAD = _float( 400.0 / PI2) # grades per radian
|
|
35
|
+
_M_ACRE = _float( 4046.8564224) # square meter per acre, chain2m(1) * furlong2m(1)
|
|
36
|
+
_M_CHAIN = _float( 20.1168) # meter per yard2m(1) * 22
|
|
37
|
+
_M_FATHOM = _float( 1.8288) # meter per yard2m(1) * 2 or _M_NM * 1e-3
|
|
38
|
+
_M_FOOT = _float( 0.3048) # meter per Int'l foot, 1 / 3.280_839_895_0131 = 10_000 / (254 * 12)
|
|
39
|
+
_M_FOOT_GE = _float( 0.31608) # meter per German Fuss, 1 / 3.163_756_011_1364
|
|
40
|
+
_M_FOOT_FR = _float( 0.3248406) # meter per French Pied-du-Roi or pied, 1 / 3.078_432_929_8739
|
|
41
|
+
_M_FOOT_US = _float( 0.3048006096012192) # meter per US Survey foot, 1_200 / 3_937
|
|
42
|
+
_M_FURLONG = _float( 201.168) # meter per furlong, 220 * yard2m(1) = 10 * m2chain(1)
|
|
43
|
+
_M_HA = _float(10000.0) # square meter per hectare, 100 * 100
|
|
44
|
+
# _M_KM = _float( 1000.0) # meter per kilo meter
|
|
45
|
+
# _M_NM = _float( 1852.0) # meter per nautical mile
|
|
46
|
+
# _M_SM = _float( 1609.344) # meter per statute mile
|
|
47
|
+
_M_TOISE = _float( 1.9490436) # meter per French toise, 6 pieds = 6 / 3.078_432_929_8739
|
|
48
|
+
_M_YARD_UK = _float( 0.9144) # meter per yard, 254 * 12 * 3 / 10_000 = 3 * _M_FOOT
|
|
49
|
+
# sqrt(3) <https://WikiPedia.org/wiki/Square_root_of_3>
|
|
50
|
+
_COS_30, _SIN_30 = 0.86602540378443864676, _0_5 # sqrt(3) / 2
|
|
51
|
+
_COS_45 = _SIN_45 = 0.70710678118654752440 # sqrt(2) / 2
|
|
45
52
|
|
|
46
53
|
|
|
47
54
|
def _abs1nan(x):
|
|
@@ -65,8 +72,7 @@ def acre2ha(acres):
|
|
|
65
72
|
|
|
66
73
|
@raise ValueError: Invalid B{C{acres}}.
|
|
67
74
|
'''
|
|
68
|
-
|
|
69
|
-
return Float(ha=Float(acres) * 0.40468564224)
|
|
75
|
+
return m2ha(acre2m2(acres))
|
|
70
76
|
|
|
71
77
|
|
|
72
78
|
def acre2m2(acres):
|
|
@@ -78,8 +84,7 @@ def acre2m2(acres):
|
|
|
78
84
|
|
|
79
85
|
@raise ValueError: Invalid B{C{acres}}.
|
|
80
86
|
'''
|
|
81
|
-
|
|
82
|
-
return Meter2(Float(acres) * 4046.8564224)
|
|
87
|
+
return Meter2(Float(acres=acres) * _M_ACRE)
|
|
83
88
|
|
|
84
89
|
|
|
85
90
|
def asin1(x):
|
|
@@ -92,7 +97,7 @@ def atan1(y, x=_1_0):
|
|
|
92
97
|
'''Return C{atan(B{y} / B{x})} angle in C{radians} M{[-PI/2..+PI/2]}
|
|
93
98
|
using C{atan2} for consistency and to avoid C{ZeroDivisionError}.
|
|
94
99
|
'''
|
|
95
|
-
return
|
|
100
|
+
return _atan1u(y, x, atan2)
|
|
96
101
|
|
|
97
102
|
|
|
98
103
|
def atan1d(y, x=_1_0):
|
|
@@ -101,18 +106,35 @@ def atan1d(y, x=_1_0):
|
|
|
101
106
|
|
|
102
107
|
@see: Function L{pygeodesy.atan2d}.
|
|
103
108
|
'''
|
|
104
|
-
return
|
|
109
|
+
return _atan1u(y, x, atan2d)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _atan1u(y, x, _2u):
|
|
113
|
+
'''(INTERNAL) Helper for functions C{atan1} and C{atan1d}.
|
|
114
|
+
'''
|
|
115
|
+
if x < 0:
|
|
116
|
+
x = -x
|
|
117
|
+
y = -y
|
|
118
|
+
return _2u(y, x or _0_0)
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
atan2 = _atan2
|
|
122
|
+
'''Return C{atan2(B{y}, B{x})} in radians M{[-PI..+PI]}.
|
|
123
|
+
|
|
124
|
+
@see: I{Karney}'s C++ function U{Math.atan2d
|
|
125
|
+
<https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1Math.html>}.
|
|
126
|
+
'''
|
|
105
127
|
|
|
106
128
|
|
|
107
129
|
def atan2b(y, x):
|
|
108
|
-
'''Return C{atan2(B{y}, B{x})} in degrees M{[0..+360]}.
|
|
130
|
+
'''Return C{atan2(B{y}, B{x})} in degrees M{[0..+360], counter-clockwise}.
|
|
109
131
|
|
|
110
132
|
@see: Function L{pygeodesy.atan2d}.
|
|
111
133
|
'''
|
|
112
134
|
b = atan2d(y, x)
|
|
113
135
|
if b < 0:
|
|
114
136
|
b += _360_0
|
|
115
|
-
return b
|
|
137
|
+
return b or _0_0 # unsigned-0
|
|
116
138
|
|
|
117
139
|
|
|
118
140
|
def atan2d(y, x, reverse=False):
|
|
@@ -122,29 +144,14 @@ def atan2d(y, x, reverse=False):
|
|
|
122
144
|
@see: I{Karney}'s C++ function U{Math.atan2d
|
|
123
145
|
<https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1Math.html>}.
|
|
124
146
|
'''
|
|
125
|
-
|
|
126
|
-
if y < 0: # q = 3
|
|
127
|
-
d = degrees(atan2(x, -y)) - _90_0
|
|
128
|
-
else: # q = 2
|
|
129
|
-
d = _90_0 - degrees(atan2(x, y))
|
|
130
|
-
elif isnan(x) or isnan(y):
|
|
131
|
-
return NAN
|
|
132
|
-
elif y:
|
|
133
|
-
if x > 0: # q = 0
|
|
134
|
-
d = degrees(atan2(y, x))
|
|
135
|
-
elif x < 0: # q = 1
|
|
136
|
-
d = _copysign(_180_0, y) - degrees(atan2(y, -x))
|
|
137
|
-
else: # x == 0
|
|
138
|
-
d = _copysign(_90_0, y)
|
|
139
|
-
else:
|
|
140
|
-
d = _180_0 if x < 0 else _0_0
|
|
147
|
+
d = degrees(_atan2(y, x)) # preserves signed-0
|
|
141
148
|
return _azireversed(d) if reverse else d
|
|
142
149
|
|
|
143
150
|
|
|
144
|
-
def _azireversed(
|
|
145
|
-
'''(INTERNAL) Return the I{reverse} B{C{
|
|
151
|
+
def _azireversed(azi): # in .rhumbBase
|
|
152
|
+
'''(INTERNAL) Return the I{reverse} B{C{azi}} in degrees M{[-180..+180]}.
|
|
146
153
|
'''
|
|
147
|
-
return
|
|
154
|
+
return azi - _copysign(_180_0, azi)
|
|
148
155
|
|
|
149
156
|
|
|
150
157
|
def chain2m(chains):
|
|
@@ -162,13 +169,11 @@ def chain2m(chains):
|
|
|
162
169
|
def circle4(earth, lat):
|
|
163
170
|
'''Get the equatorial or a parallel I{circle of latitude}.
|
|
164
171
|
|
|
165
|
-
@arg earth: The earth radius, ellipsoid or datum
|
|
166
|
-
(
|
|
167
|
-
L{Datum} or L{a_f2Tuple}).
|
|
172
|
+
@arg earth: The earth radius (C{meter}), ellipsoid or datum
|
|
173
|
+
(L{Ellipsoid}, L{Ellipsoid2}, L{Datum} or L{a_f2Tuple}).
|
|
168
174
|
@arg lat: Geodetic latitude (C{degrees90}, C{str}).
|
|
169
175
|
|
|
170
|
-
@return: A L{Circle4Tuple}C{(radius, height, lat, beta)}
|
|
171
|
-
instance.
|
|
176
|
+
@return: A L{Circle4Tuple}C{(radius, height, lat, beta)}.
|
|
172
177
|
|
|
173
178
|
@raise RangeError: Latitude B{C{lat}} outside valid range and
|
|
174
179
|
L{rangerrors<pygeodesy.rangerrors>} is C{True}.
|
|
@@ -181,76 +186,78 @@ def circle4(earth, lat):
|
|
|
181
186
|
return E.circle4(lat)
|
|
182
187
|
|
|
183
188
|
|
|
184
|
-
def cot(rad, **
|
|
189
|
+
def cot(rad, **raiser_kwds):
|
|
185
190
|
'''Return the C{cotangent} of an angle in C{radians}.
|
|
186
191
|
|
|
187
192
|
@arg rad: Angle (C{radians}).
|
|
188
|
-
@kwarg
|
|
193
|
+
@kwarg raiser_kwds: Use C{B{raiser}=False} to avoid
|
|
194
|
+
ValueErrors or optionally, additional
|
|
195
|
+
ValueError keyword argments.
|
|
189
196
|
|
|
190
197
|
@return: C{cot(B{rad})}.
|
|
191
198
|
|
|
192
|
-
@raise
|
|
199
|
+
@raise Error: If L{pygeodesy.isnear0}C{(sin(B{rad})}.
|
|
193
200
|
'''
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
c = c / s # /= chokes PyChecker
|
|
199
|
-
return c
|
|
201
|
+
try:
|
|
202
|
+
return _cotu(*sincos2(rad), **raiser_kwds)
|
|
203
|
+
except ZeroDivisionError:
|
|
204
|
+
raise _valueError(cot, rad, **raiser_kwds)
|
|
200
205
|
|
|
201
206
|
|
|
202
|
-
def cot_(*rads, **
|
|
203
|
-
'''
|
|
207
|
+
def cot_(*rads, **raiser_kwds):
|
|
208
|
+
'''Yield the C{cotangent} of angle(s) in C{radians}.
|
|
204
209
|
|
|
205
|
-
@arg rads: One or more angles (C{radians}).
|
|
206
|
-
@kwarg error_kwds: Error to raise (C{ValueError}).
|
|
210
|
+
@arg rads: One or more angles (each in C{radians}).
|
|
207
211
|
|
|
208
|
-
@return: Yield
|
|
212
|
+
@return: Yield C{cot(B{rad})} for each angle.
|
|
209
213
|
|
|
210
|
-
@
|
|
214
|
+
@see: Function L{pygeodesy.cot} for further details.
|
|
211
215
|
'''
|
|
212
216
|
try:
|
|
213
217
|
for r in rads:
|
|
214
|
-
yield
|
|
215
|
-
except
|
|
216
|
-
raise _valueError(cot_, r, **
|
|
218
|
+
yield _cotu(*sincos2(r), **raiser_kwds)
|
|
219
|
+
except ZeroDivisionError:
|
|
220
|
+
raise _valueError(cot_, r, **raiser_kwds)
|
|
217
221
|
|
|
218
222
|
|
|
219
|
-
def cotd(deg, **
|
|
223
|
+
def cotd(deg, **raiser_kwds):
|
|
220
224
|
'''Return the C{cotangent} of an angle in C{degrees}.
|
|
221
225
|
|
|
222
226
|
@arg deg: Angle (C{degrees}).
|
|
223
|
-
@kwarg
|
|
227
|
+
@kwarg raiser_kwds: Use C{B{raiser}=False} to avoid
|
|
228
|
+
ValueErrors or optionally, additional
|
|
229
|
+
ValueError keyword argments.
|
|
224
230
|
|
|
225
231
|
@return: C{cot(B{deg})}.
|
|
226
232
|
|
|
227
|
-
@raise
|
|
233
|
+
@raise Error: If L{pygeodesy.isnear0}C{(sin(B{deg})}.
|
|
228
234
|
'''
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
c = c / s # /= chokes PyChecker
|
|
234
|
-
elif s < 0:
|
|
235
|
-
c = -c # negate-0
|
|
236
|
-
return c
|
|
235
|
+
try:
|
|
236
|
+
return _cotu(*sincos2d(deg), **raiser_kwds)
|
|
237
|
+
except ZeroDivisionError:
|
|
238
|
+
raise _valueError(cotd, deg, **raiser_kwds)
|
|
237
239
|
|
|
238
240
|
|
|
239
|
-
def cotd_(*degs, **
|
|
240
|
-
'''
|
|
241
|
+
def cotd_(*degs, **raiser_kwds):
|
|
242
|
+
'''Yield the C{cotangent} of angle(s) in C{degrees}.
|
|
241
243
|
|
|
242
|
-
@arg degs: One or more angles (C{degrees}).
|
|
243
|
-
@kwarg error_kwds: Error to raise (C{ValueError}).
|
|
244
|
+
@arg degs: One or more angles (each in C{degrees}).
|
|
244
245
|
|
|
245
|
-
@return: Yield
|
|
246
|
+
@return: Yield C{cotd(B{deg})} for each angle.
|
|
246
247
|
|
|
247
|
-
@
|
|
248
|
+
@see: Function L{pygeodesy.cotd} for further details.
|
|
248
249
|
'''
|
|
249
250
|
try:
|
|
250
251
|
for d in degs:
|
|
251
|
-
yield
|
|
252
|
-
except
|
|
253
|
-
raise _valueError(cotd_, d, **
|
|
252
|
+
yield _cotu(*sincos2d(d), **raiser_kwds)
|
|
253
|
+
except ZeroDivisionError:
|
|
254
|
+
raise _valueError(cotd_, d, **raiser_kwds)
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
def _cotu(s, c, **raiser_kwds):
|
|
258
|
+
'''(INTERNAL) Helper for functions C{cot}, C{cotd}, C{cot_} and C{cotd_}.
|
|
259
|
+
'''
|
|
260
|
+
return _tanu(c, s, **raiser_kwds)
|
|
254
261
|
|
|
255
262
|
|
|
256
263
|
def degrees90(rad):
|
|
@@ -290,30 +297,27 @@ def degrees2grades(deg):
|
|
|
290
297
|
|
|
291
298
|
@return: Angle (C{grades}).
|
|
292
299
|
'''
|
|
293
|
-
return Degrees(deg) *
|
|
300
|
+
return Float(grades=Degrees(deg) * _G_DEG)
|
|
294
301
|
|
|
295
302
|
|
|
296
303
|
def degrees2m(deg, radius=R_M, lat=0):
|
|
297
|
-
'''Convert an angle to a distance along the equator or
|
|
298
|
-
|
|
304
|
+
'''Convert an angle to a distance along the equator or along a parallel
|
|
305
|
+
at (geodetic) latitude.
|
|
299
306
|
|
|
300
307
|
@arg deg: The angle (C{degrees}).
|
|
301
|
-
@kwarg radius: Mean earth radius, ellipsoid or datum
|
|
302
|
-
(
|
|
303
|
-
L{Datum} or L{a_f2Tuple}).
|
|
308
|
+
@kwarg radius: Mean earth radius (C{meter}), an ellipsoid or datum
|
|
309
|
+
(L{Ellipsoid}, L{Ellipsoid2}, L{Datum} or L{a_f2Tuple}).
|
|
304
310
|
@kwarg lat: Parallel latitude (C{degrees90}, C{str}).
|
|
305
311
|
|
|
306
|
-
@return: Distance (C{meter}, same units as B{C{radius}}
|
|
307
|
-
|
|
308
|
-
near-polar B{C{lat}}.
|
|
312
|
+
@return: Distance (C{meter}, same units as B{C{radius}} or polar and
|
|
313
|
+
equatorial radii) or C{0.0} for near-polar B{C{lat}}.
|
|
309
314
|
|
|
310
315
|
@raise RangeError: Latitude B{C{lat}} outside valid range and
|
|
311
316
|
L{rangerrors<pygeodesy.rangerrors>} is C{True}.
|
|
312
317
|
|
|
313
318
|
@raise TypeError: Invalid B{C{radius}}.
|
|
314
319
|
|
|
315
|
-
@raise ValueError: Invalid B{C{deg}}, B{C{radius}} or
|
|
316
|
-
B{C{lat}}.
|
|
320
|
+
@raise ValueError: Invalid B{C{deg}}, B{C{radius}} or B{C{lat}}.
|
|
317
321
|
|
|
318
322
|
@see: Function L{radians2m} and L{m2degrees}.
|
|
319
323
|
'''
|
|
@@ -349,9 +353,9 @@ def ft2m(feet, usurvey=False, pied=False, fuss=False):
|
|
|
349
353
|
|
|
350
354
|
@raise ValueError: Invalid B{C{feet}}.
|
|
351
355
|
'''
|
|
352
|
-
return Meter(Feet(feet) * (
|
|
353
|
-
(_M_FOOT_FR
|
|
354
|
-
(_M_FOOT_GE
|
|
356
|
+
return Meter(Feet(feet) * (_M_FOOT_US if usurvey else
|
|
357
|
+
(_M_FOOT_FR if pied else
|
|
358
|
+
(_M_FOOT_GE if fuss else _M_FOOT))))
|
|
355
359
|
|
|
356
360
|
|
|
357
361
|
def furlong2m(furlongs):
|
|
@@ -373,7 +377,7 @@ def grades(rad):
|
|
|
373
377
|
|
|
374
378
|
@return: Angle (C{grades}).
|
|
375
379
|
'''
|
|
376
|
-
return Float(grades=
|
|
380
|
+
return Float(grades=Radians(rad) * _G_RAD)
|
|
377
381
|
|
|
378
382
|
|
|
379
383
|
def grades400(rad):
|
|
@@ -383,7 +387,7 @@ def grades400(rad):
|
|
|
383
387
|
|
|
384
388
|
@return: Angle, wrapped (C{grades}).
|
|
385
389
|
'''
|
|
386
|
-
return Float(grades400=(
|
|
390
|
+
return Float(grades400=wrapPI2(rad) * _G_RAD)
|
|
387
391
|
|
|
388
392
|
|
|
389
393
|
def grades2degrees(gon):
|
|
@@ -393,7 +397,7 @@ def grades2degrees(gon):
|
|
|
393
397
|
|
|
394
398
|
@return: Angle (C{degrees}).
|
|
395
399
|
'''
|
|
396
|
-
return Degrees(Float(gon=gon)
|
|
400
|
+
return Degrees(Float(gon=gon) / _G_DEG)
|
|
397
401
|
|
|
398
402
|
|
|
399
403
|
def grades2radians(gon):
|
|
@@ -403,7 +407,41 @@ def grades2radians(gon):
|
|
|
403
407
|
|
|
404
408
|
@return: Angle (C{radians}).
|
|
405
409
|
'''
|
|
406
|
-
return Radians(Float(gon=gon)
|
|
410
|
+
return Radians(Float(gon=gon) / _G_RAD)
|
|
411
|
+
|
|
412
|
+
|
|
413
|
+
def ha2acre(ha):
|
|
414
|
+
'''Convert hectare to acre.
|
|
415
|
+
|
|
416
|
+
@arg ha: Value in hectare (C{scalar}).
|
|
417
|
+
|
|
418
|
+
@return: Value in acres (C{float}).
|
|
419
|
+
|
|
420
|
+
@raise ValueError: Invalid B{C{ha}}.
|
|
421
|
+
'''
|
|
422
|
+
return m2acre(ha2m2(ha))
|
|
423
|
+
|
|
424
|
+
|
|
425
|
+
def ha2m2(ha):
|
|
426
|
+
'''Convert hectare to I{square} meter.
|
|
427
|
+
|
|
428
|
+
@arg ha: Value in hectare (C{scalar}).
|
|
429
|
+
|
|
430
|
+
@return: Value in C{meter^2} (C{float}).
|
|
431
|
+
|
|
432
|
+
@raise ValueError: Invalid B{C{ha}}.
|
|
433
|
+
'''
|
|
434
|
+
return Meter2(Float(ha=ha) * _M_HA)
|
|
435
|
+
|
|
436
|
+
|
|
437
|
+
def hav(rad):
|
|
438
|
+
'''Return the U{haversine<https://WikiPedia.org/wiki/Haversine_formula>} of an angle.
|
|
439
|
+
|
|
440
|
+
@arg rad: Angle (C{radians}).
|
|
441
|
+
|
|
442
|
+
@return: C{sin(B{rad} / 2)**2}.
|
|
443
|
+
'''
|
|
444
|
+
return sin(rad * _0_5)**2
|
|
407
445
|
|
|
408
446
|
|
|
409
447
|
def km2m(km):
|
|
@@ -424,6 +462,18 @@ def _loneg(lon):
|
|
|
424
462
|
return _180_0 - lon
|
|
425
463
|
|
|
426
464
|
|
|
465
|
+
def m2acre(meter2):
|
|
466
|
+
'''Convert I{square} meter to acres.
|
|
467
|
+
|
|
468
|
+
@arg meter2: Value in C{meter^2} (C{scalar}).
|
|
469
|
+
|
|
470
|
+
@return: Value in acres (C{float}).
|
|
471
|
+
|
|
472
|
+
@raise ValueError: Invalid B{C{meter2}}.
|
|
473
|
+
'''
|
|
474
|
+
return Float(acre=Meter2(meter2) / _M_ACRE)
|
|
475
|
+
|
|
476
|
+
|
|
427
477
|
def m2chain(meter):
|
|
428
478
|
'''Convert meter to I{UK} chains.
|
|
429
479
|
|
|
@@ -433,17 +483,16 @@ def m2chain(meter):
|
|
|
433
483
|
|
|
434
484
|
@raise ValueError: Invalid B{C{meter}}.
|
|
435
485
|
'''
|
|
436
|
-
return Float(chain=Meter(meter) / _M_CHAIN) # * 0.
|
|
486
|
+
return Float(chain=Meter(meter) / _M_CHAIN) # * 0.049_709_695_378_986_715
|
|
437
487
|
|
|
438
488
|
|
|
439
489
|
def m2degrees(distance, radius=R_M, lat=0):
|
|
440
|
-
'''Convert a distance to an angle along the equator or
|
|
441
|
-
|
|
490
|
+
'''Convert a distance to an angle along the equator or along a parallel
|
|
491
|
+
at (geodetic) latitude.
|
|
442
492
|
|
|
443
493
|
@arg distance: Distance (C{meter}, same units as B{C{radius}}).
|
|
444
|
-
@kwarg radius: Mean earth radius, ellipsoid or datum
|
|
445
|
-
|
|
446
|
-
L{a_f2Tuple}).
|
|
494
|
+
@kwarg radius: Mean earth radius (C{meter}), an ellipsoid or datum
|
|
495
|
+
(L{Ellipsoid}, L{Ellipsoid2}, L{Datum} or L{a_f2Tuple}).
|
|
447
496
|
@kwarg lat: Parallel latitude (C{degrees90}, C{str}).
|
|
448
497
|
|
|
449
498
|
@return: Angle (C{degrees}) or C{INF} for near-polar B{C{lat}}.
|
|
@@ -453,8 +502,7 @@ def m2degrees(distance, radius=R_M, lat=0):
|
|
|
453
502
|
|
|
454
503
|
@raise TypeError: Invalid B{C{radius}}.
|
|
455
504
|
|
|
456
|
-
@raise ValueError: Invalid B{C{distance}}, B{C{radius}}
|
|
457
|
-
or B{C{lat}}.
|
|
505
|
+
@raise ValueError: Invalid B{C{distance}}, B{C{radius}} or B{C{lat}}.
|
|
458
506
|
|
|
459
507
|
@see: Function L{m2radians} and L{degrees2m}.
|
|
460
508
|
'''
|
|
@@ -473,7 +521,7 @@ def m2fathom(meter):
|
|
|
473
521
|
@see: Function L{m2toise}, U{Fathom<https://WikiPedia.org/wiki/Fathom>}
|
|
474
522
|
and U{Klafter<https://WikiPedia.org/wiki/Klafter>}.
|
|
475
523
|
'''
|
|
476
|
-
return Float(fathom=Meter(meter) / _M_FATHOM) # * 0.
|
|
524
|
+
return Float(fathom=Meter(meter) / _M_FATHOM) # * 0.546_806_649
|
|
477
525
|
|
|
478
526
|
|
|
479
527
|
def m2ft(meter, usurvey=False, pied=False, fuss=False):
|
|
@@ -490,11 +538,11 @@ def m2ft(meter, usurvey=False, pied=False, fuss=False):
|
|
|
490
538
|
|
|
491
539
|
@raise ValueError: Invalid B{C{meter}}.
|
|
492
540
|
'''
|
|
493
|
-
# * 3.
|
|
494
|
-
# * 3.
|
|
495
|
-
return Float(feet=Meter(meter) / (
|
|
496
|
-
(_M_FOOT_FR
|
|
497
|
-
(_M_FOOT_GE
|
|
541
|
+
# * 3.280_833_333_333_3333, US Survey 3_937 / 1_200
|
|
542
|
+
# * 3.280_839_895_013_1235, Int'l 10_000 / (254 * 12)
|
|
543
|
+
return Float(feet=Meter(meter) / (_M_FOOT_US if usurvey else
|
|
544
|
+
(_M_FOOT_FR if pied else
|
|
545
|
+
(_M_FOOT_GE if fuss else _M_FOOT))))
|
|
498
546
|
|
|
499
547
|
|
|
500
548
|
def m2furlong(meter):
|
|
@@ -506,7 +554,19 @@ def m2furlong(meter):
|
|
|
506
554
|
|
|
507
555
|
@raise ValueError: Invalid B{C{meter}}.
|
|
508
556
|
'''
|
|
509
|
-
return Float(furlong=Meter(meter) / _M_FURLONG) # * 0.
|
|
557
|
+
return Float(furlong=Meter(meter) / _M_FURLONG) # * 0.004_970_969_54
|
|
558
|
+
|
|
559
|
+
|
|
560
|
+
def m2ha(meter2):
|
|
561
|
+
'''Convert I{square} meter to hectare.
|
|
562
|
+
|
|
563
|
+
@arg meter2: Value in C{meter^2} (C{scalar}).
|
|
564
|
+
|
|
565
|
+
@return: Value in hectare (C{float}).
|
|
566
|
+
|
|
567
|
+
@raise ValueError: Invalid B{C{meter2}}.
|
|
568
|
+
'''
|
|
569
|
+
return Float(ha=Meter2(meter2) / _M_HA)
|
|
510
570
|
|
|
511
571
|
|
|
512
572
|
def m2km(meter):
|
|
@@ -530,17 +590,16 @@ def m2NM(meter):
|
|
|
530
590
|
|
|
531
591
|
@raise ValueError: Invalid B{C{meter}}.
|
|
532
592
|
'''
|
|
533
|
-
return Float(NM=Meter(meter) / _M_NM) # * 5.
|
|
593
|
+
return Float(NM=Meter(meter) / _M_NM) # * 5.399_568_04e-4
|
|
534
594
|
|
|
535
595
|
|
|
536
596
|
def m2radians(distance, radius=R_M, lat=0):
|
|
537
|
-
'''Convert a distance to an angle along the equator or along
|
|
538
|
-
|
|
597
|
+
'''Convert a distance to an angle along the equator or along a parallel
|
|
598
|
+
at (geodetic) latitude.
|
|
539
599
|
|
|
540
600
|
@arg distance: Distance (C{meter}, same units as B{C{radius}}).
|
|
541
|
-
@kwarg radius: Mean earth radius, ellipsoid or datum
|
|
542
|
-
|
|
543
|
-
L{a_f2Tuple}).
|
|
601
|
+
@kwarg radius: Mean earth radius (C{meter}, an ellipsoid or datum
|
|
602
|
+
(L{Ellipsoid}, L{Ellipsoid2}, L{Datum} or L{a_f2Tuple}).
|
|
544
603
|
@kwarg lat: Parallel latitude (C{degrees90}, C{str}).
|
|
545
604
|
|
|
546
605
|
@return: Angle (C{radians}) or C{INF} for near-polar B{C{lat}}.
|
|
@@ -550,8 +609,7 @@ def m2radians(distance, radius=R_M, lat=0):
|
|
|
550
609
|
|
|
551
610
|
@raise TypeError: Invalid B{C{radius}}.
|
|
552
611
|
|
|
553
|
-
@raise ValueError: Invalid B{C{distance}}, B{C{radius}}
|
|
554
|
-
or B{C{lat}}.
|
|
612
|
+
@raise ValueError: Invalid B{C{distance}}, B{C{radius}} or B{C{lat}}.
|
|
555
613
|
|
|
556
614
|
@see: Function L{m2degrees} and L{radians2m}.
|
|
557
615
|
'''
|
|
@@ -568,7 +626,7 @@ def m2SM(meter):
|
|
|
568
626
|
|
|
569
627
|
@raise ValueError: Invalid B{C{meter}}.
|
|
570
628
|
'''
|
|
571
|
-
return Float(SM=Meter(meter) / _M_SM) # * 6.
|
|
629
|
+
return Float(SM=Meter(meter) / _M_SM) # * 6.213_699_49e-4 == 1 / 1_609.344
|
|
572
630
|
|
|
573
631
|
|
|
574
632
|
def m2toise(meter):
|
|
@@ -582,7 +640,7 @@ def m2toise(meter):
|
|
|
582
640
|
|
|
583
641
|
@see: Function L{m2fathom}.
|
|
584
642
|
'''
|
|
585
|
-
return Float(toise=Meter(meter) / _M_TOISE) # * 0.
|
|
643
|
+
return Float(toise=Meter(meter) / _M_TOISE) # * 0.513_083_632_632_119
|
|
586
644
|
|
|
587
645
|
|
|
588
646
|
def m2yard(meter):
|
|
@@ -594,7 +652,7 @@ def m2yard(meter):
|
|
|
594
652
|
|
|
595
653
|
@raise ValueError: Invalid B{C{meter}}.
|
|
596
654
|
'''
|
|
597
|
-
return Float(yard=Meter(meter) / _M_YARD_UK) # * 1.
|
|
655
|
+
return Float(yard=Meter(meter) / _M_YARD_UK) # * 1.093_613_298_337_707_8
|
|
598
656
|
|
|
599
657
|
|
|
600
658
|
def NM2m(nm):
|
|
@@ -610,26 +668,23 @@ def NM2m(nm):
|
|
|
610
668
|
|
|
611
669
|
|
|
612
670
|
def radians2m(rad, radius=R_M, lat=0):
|
|
613
|
-
'''Convert an angle to a distance along the equator or
|
|
614
|
-
|
|
671
|
+
'''Convert an angle to a distance along the equator or along a parallel
|
|
672
|
+
at (geodetic) latitude.
|
|
615
673
|
|
|
616
674
|
@arg rad: The angle (C{radians}).
|
|
617
|
-
@kwarg radius: Mean earth radius
|
|
618
|
-
(
|
|
619
|
-
L{Datum} or L{a_f2Tuple}).
|
|
675
|
+
@kwarg radius: Mean earth radius (C{meter}) or an ellipsoid or datum
|
|
676
|
+
(L{Ellipsoid}, L{Ellipsoid2}, L{Datum} or L{a_f2Tuple}).
|
|
620
677
|
@kwarg lat: Parallel latitude (C{degrees90}, C{str}).
|
|
621
678
|
|
|
622
|
-
@return: Distance (C{meter}, same units as B{C{radius}}
|
|
623
|
-
|
|
624
|
-
near-polar B{C{lat}}.
|
|
679
|
+
@return: Distance (C{meter}, same units as B{C{radius}} or polar and
|
|
680
|
+
equatorial radii) or C{0.0} for near-polar B{C{lat}}.
|
|
625
681
|
|
|
626
682
|
@raise RangeError: Latitude B{C{lat}} outside valid range and
|
|
627
683
|
L{rangerrors<pygeodesy.rangerrors>} is C{True}.
|
|
628
684
|
|
|
629
685
|
@raise TypeError: Invalid B{C{radius}}.
|
|
630
686
|
|
|
631
|
-
@raise ValueError: Invalid B{C{rad}}, B{C{radius}} or
|
|
632
|
-
B{C{lat}}.
|
|
687
|
+
@raise ValueError: Invalid B{C{rad}}, B{C{radius}} or B{C{lat}}.
|
|
633
688
|
|
|
634
689
|
@see: Function L{degrees2m} and L{m2radians}.
|
|
635
690
|
'''
|
|
@@ -673,20 +728,25 @@ def radiansPI_2(deg):
|
|
|
673
728
|
return wrapPI_2(radians(deg))
|
|
674
729
|
|
|
675
730
|
|
|
676
|
-
def _sin0cos2(q, r, sign):
|
|
677
|
-
'''(INTERNAL) 2-tuple (C{sin(r), cos(r)}) in quadrant C{0 <= B{q} <= 3}
|
|
678
|
-
|
|
731
|
+
def _sin0cos2(q, r, sign, a, Q): # Quarter turn
|
|
732
|
+
'''(INTERNAL) 2-tuple (C{sin(r), cos(r)}) in quadrant C{0 <= B{q} <= 3} and
|
|
733
|
+
C{sin} zero I{signed} with B{C{sign}}, like Karney's U{Math.sind and .cosd
|
|
734
|
+
<https://GeographicLib.SourceForge.io/C++/doc/classGeographicLib_1_1Math.html>}
|
|
679
735
|
'''
|
|
680
736
|
if r < PI_2:
|
|
681
|
-
s
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
737
|
+
s = sin(r)
|
|
738
|
+
if (a * 2) == Q:
|
|
739
|
+
s, c = _copysign(_SIN_45, s), _COS_45
|
|
740
|
+
elif (a * 3) == Q:
|
|
741
|
+
s, c = _copysign(_SIN_30, s), _COS_30
|
|
742
|
+
else:
|
|
743
|
+
c = cos(r)
|
|
744
|
+
else:
|
|
745
|
+
s, c = _1_0, _0_0
|
|
746
|
+
t = s, c, -s, -c, s
|
|
687
747
|
# q &= 3
|
|
688
|
-
s
|
|
689
|
-
c
|
|
748
|
+
s = t[q] or _copysign_0_0(sign)
|
|
749
|
+
c = t[q + 1] or _0_0
|
|
690
750
|
return s, c
|
|
691
751
|
|
|
692
752
|
|
|
@@ -698,8 +758,8 @@ def SinCos2(x):
|
|
|
698
758
|
@return: 2-Tuple (C{sin(B{x})}, C{cos(B{x})}).
|
|
699
759
|
'''
|
|
700
760
|
return sincos2d(x) if isinstanceof(x, Degrees, Degrees_) else (
|
|
701
|
-
|
|
702
|
-
sincos2(
|
|
761
|
+
# sincos2(x) if isinstanceof(x, Radians, Radians_) else
|
|
762
|
+
sincos2(Radians(x))) # assume C{radians}
|
|
703
763
|
|
|
704
764
|
|
|
705
765
|
def sincos2(rad):
|
|
@@ -720,20 +780,21 @@ def sincos2(rad):
|
|
|
720
780
|
q = int(rad * _2__PI) # int(math.floor)
|
|
721
781
|
if q < 0:
|
|
722
782
|
q -= 1
|
|
723
|
-
|
|
783
|
+
r = rad - q * PI_2
|
|
784
|
+
t = _sin0cos2(q & 3, r, rad, fabs(r), PI_2)
|
|
724
785
|
else:
|
|
725
786
|
t = NAN, NAN
|
|
726
787
|
return t
|
|
727
788
|
|
|
728
789
|
|
|
729
790
|
def sincos2_(*rads):
|
|
730
|
-
'''
|
|
791
|
+
'''Yield the C{sine} and C{cosine} of angle(s) in C{radians}.
|
|
731
792
|
|
|
732
793
|
@arg rads: One or more angles (C{radians}).
|
|
733
794
|
|
|
734
|
-
@return: Yield
|
|
795
|
+
@return: Yield C{sin(B{rad})} and C{cos(B{rad})} for each angle.
|
|
735
796
|
|
|
736
|
-
@see:
|
|
797
|
+
@see: Function L{sincos2}.
|
|
737
798
|
'''
|
|
738
799
|
for r in rads:
|
|
739
800
|
s, c = sincos2(r)
|
|
@@ -741,7 +802,7 @@ def sincos2_(*rads):
|
|
|
741
802
|
yield c
|
|
742
803
|
|
|
743
804
|
|
|
744
|
-
def sincos2d(deg,
|
|
805
|
+
def sincos2d(deg, adeg=_0_0):
|
|
745
806
|
'''Return the C{sine} and C{cosine} of an angle in C{degrees}.
|
|
746
807
|
|
|
747
808
|
@arg deg: Angle (C{degrees}).
|
|
@@ -763,20 +824,19 @@ def sincos2d(deg, **adeg):
|
|
|
763
824
|
q -= 1
|
|
764
825
|
d = deg - q * _90_0
|
|
765
826
|
if adeg:
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
t = _sin0cos2(q & 3, radians(d), deg)
|
|
827
|
+
d = _MODS.karney._around(d + adeg)
|
|
828
|
+
t = _sin0cos2(q & 3, radians(d), deg, fabs(d), _90_0)
|
|
769
829
|
else:
|
|
770
830
|
t = NAN, NAN
|
|
771
831
|
return t
|
|
772
832
|
|
|
773
833
|
|
|
774
834
|
def sincos2d_(*degs):
|
|
775
|
-
'''
|
|
835
|
+
'''Yield the C{sine} and C{cosine} of angle(s) in C{degrees}.
|
|
776
836
|
|
|
777
837
|
@arg degs: One or more angles (C{degrees}).
|
|
778
838
|
|
|
779
|
-
@return: Yield
|
|
839
|
+
@return: Yield C{sind(B{deg})} and C{cosd(B{deg})} for each angle.
|
|
780
840
|
|
|
781
841
|
@see: Function L{sincos2d}.
|
|
782
842
|
'''
|
|
@@ -795,9 +855,25 @@ def sincostan3(rad):
|
|
|
795
855
|
|
|
796
856
|
@see: Function L{sincos2}.
|
|
797
857
|
'''
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
858
|
+
return _sincostan3(*sincos2(float(rad)))
|
|
859
|
+
|
|
860
|
+
|
|
861
|
+
def _sincostan3(s, c):
|
|
862
|
+
'''(INTERNAL) Helper for C{sincostan3} and C{sincostan3d}.
|
|
863
|
+
'''
|
|
864
|
+
return s, c, _tanu(s, c, raiser=False)
|
|
865
|
+
|
|
866
|
+
|
|
867
|
+
def sincostan3d(deg):
|
|
868
|
+
'''Return the C{sine}, C{cosine} and C{tangent} of an angle in C{degrees}.
|
|
869
|
+
|
|
870
|
+
@arg deg: Angle (C{degrees}).
|
|
871
|
+
|
|
872
|
+
@return: 3-Tuple (C{sind(B{deg})}, C{cosd(B{deg})}, C{tand(B{deg})}).
|
|
873
|
+
|
|
874
|
+
@see: Function L{sincos2d}.
|
|
875
|
+
'''
|
|
876
|
+
return _sincostan3(*sincos2d(float(deg)))
|
|
801
877
|
|
|
802
878
|
|
|
803
879
|
def SM2m(sm):
|
|
@@ -832,41 +908,75 @@ def tan_2(rad, **semi): # edge=1
|
|
|
832
908
|
_SPACE_(_MODS.streprs.Fmt.SQUARE(**semi), _edge_)
|
|
833
909
|
raise _ValueError(n, rad, txt=_semi_circular_)
|
|
834
910
|
|
|
835
|
-
return
|
|
911
|
+
return _tan(rad * _0_5) if _isfinite(rad) else NAN
|
|
912
|
+
|
|
913
|
+
|
|
914
|
+
def tan(rad, **raiser_kwds):
|
|
915
|
+
'''Return the C{tangent} of an angle in C{radians}.
|
|
916
|
+
|
|
917
|
+
@arg rad: Angle (C{radians}).
|
|
918
|
+
@kwarg raiser_kwds: Use C{B{raiser}=False} to avoid
|
|
919
|
+
ValueErrors or optionally, additional
|
|
920
|
+
ValueError keyword argments.
|
|
921
|
+
|
|
922
|
+
@return: C{tan(B{rad})}.
|
|
923
|
+
|
|
924
|
+
@raise Error: If L{pygeodesy.isnear0}C{(cos(B{rad})}.
|
|
925
|
+
'''
|
|
926
|
+
try:
|
|
927
|
+
return _tanu(*sincos2(rad), **raiser_kwds)
|
|
928
|
+
except ZeroDivisionError:
|
|
929
|
+
raise _valueError(tan, rad, **raiser_kwds)
|
|
930
|
+
|
|
931
|
+
|
|
932
|
+
def tan_(*rads, **raiser_kwds):
|
|
933
|
+
'''Yield the C{tangent} of angle(s) in C{radians}.
|
|
836
934
|
|
|
935
|
+
@arg rads: One or more angles (each in C{radians}).
|
|
837
936
|
|
|
838
|
-
|
|
937
|
+
@return: Yield C{tan(B{rad})} for each angle.
|
|
938
|
+
|
|
939
|
+
@see: Function L{pygeodesy.tan} for futher details.
|
|
940
|
+
'''
|
|
941
|
+
try:
|
|
942
|
+
for r in rads:
|
|
943
|
+
yield _tanu(*sincos2(r), **raiser_kwds)
|
|
944
|
+
except ZeroDivisionError:
|
|
945
|
+
raise _valueError(tan_, r, **raiser_kwds)
|
|
946
|
+
|
|
947
|
+
|
|
948
|
+
def tand(deg, **raiser_kwds):
|
|
839
949
|
'''Return the C{tangent} of an angle in C{degrees}.
|
|
840
950
|
|
|
841
951
|
@arg deg: Angle (C{degrees}).
|
|
842
|
-
@kwarg
|
|
952
|
+
@kwarg raiser_kwds: Use C{B{raiser}=False} to avoid
|
|
953
|
+
ValueErrors or optionally, additional
|
|
954
|
+
ValueError keyword argments.
|
|
843
955
|
|
|
844
956
|
@return: C{tan(B{deg})}.
|
|
845
957
|
|
|
846
|
-
@raise
|
|
958
|
+
@raise Error: If L{pygeodesy.isnear0}C{(cos(B{deg})}.
|
|
847
959
|
'''
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
s = s / c # /= chokes PyChecker
|
|
853
|
-
elif c < 0:
|
|
854
|
-
s = -s # negate-0
|
|
855
|
-
return s
|
|
960
|
+
try:
|
|
961
|
+
return _tanu(*sincos2d(deg), **raiser_kwds)
|
|
962
|
+
except ZeroDivisionError:
|
|
963
|
+
raise _valueError(tand, deg, **raiser_kwds)
|
|
856
964
|
|
|
857
965
|
|
|
858
|
-
def tand_(*degs, **
|
|
859
|
-
'''
|
|
966
|
+
def tand_(*degs, **raiser_kwds):
|
|
967
|
+
'''Yield the C{tangent} of angle(s) in C{degrees}.
|
|
860
968
|
|
|
861
|
-
@arg degs: One or more angles (C{degrees}).
|
|
862
|
-
@kwarg error_kwds: Error to raise (C{ValueError}).
|
|
969
|
+
@arg degs: One or more angles (each in C{degrees}).
|
|
863
970
|
|
|
864
|
-
@return: Yield
|
|
971
|
+
@return: Yield C{tand(B{deg})} for each angle.
|
|
865
972
|
|
|
866
|
-
@
|
|
973
|
+
@see: Function L{pygeodesy.tand} for futher details.
|
|
867
974
|
'''
|
|
868
|
-
|
|
869
|
-
|
|
975
|
+
try:
|
|
976
|
+
for d in degs:
|
|
977
|
+
yield _tanu(*sincos2d(d), **raiser_kwds)
|
|
978
|
+
except ZeroDivisionError:
|
|
979
|
+
raise _valueError(tand_, d, **raiser_kwds)
|
|
870
980
|
|
|
871
981
|
|
|
872
982
|
def tanPI_2_2(rad):
|
|
@@ -876,8 +986,24 @@ def tanPI_2_2(rad):
|
|
|
876
986
|
|
|
877
987
|
@return: M{tan((rad + PI/2) / 2)} (C{float}).
|
|
878
988
|
'''
|
|
879
|
-
return
|
|
880
|
-
|
|
989
|
+
return _tan((rad + PI_2) * _0_5) if _isfinite(rad) else (
|
|
990
|
+
NAN if isnan(rad) else _copysign(_90_0, rad))
|
|
991
|
+
|
|
992
|
+
|
|
993
|
+
def _tanu(s, c, raiser=True, **unused):
|
|
994
|
+
'''(INTERNAL) Helper for functions C{_cotu}, C{sincostan3},
|
|
995
|
+
C{sincostan3d}, C{tan}, C{tan_}, C{tand} and C{tand_}.
|
|
996
|
+
'''
|
|
997
|
+
if s is NAN or isnan(s):
|
|
998
|
+
s = NAN
|
|
999
|
+
elif s:
|
|
1000
|
+
if raiser and isnear0(c):
|
|
1001
|
+
raise ZeroDivisionError()
|
|
1002
|
+
s = _over(s, c) if fabs(s) != fabs(c) else \
|
|
1003
|
+
_copysign(_1_0, (-s) if c < 0 else s)
|
|
1004
|
+
elif c < 0:
|
|
1005
|
+
s = -s # negate-0
|
|
1006
|
+
return s
|
|
881
1007
|
|
|
882
1008
|
|
|
883
1009
|
def toise2m(toises):
|
|
@@ -980,11 +1106,11 @@ def unrollPI(rad1, rad2, wrap=True):
|
|
|
980
1106
|
return r, rad2
|
|
981
1107
|
|
|
982
1108
|
|
|
983
|
-
def _valueError(where, x, **kwds):
|
|
984
|
-
'''(INTERNAL) Return a C{_ValueError}.
|
|
1109
|
+
def _valueError(where, x, raiser=True, **kwds):
|
|
1110
|
+
'''(INTERNAL) Return a C{_ValueError} or C{None}.
|
|
985
1111
|
'''
|
|
986
1112
|
t = _MODS.streprs.Fmt.PAREN(where.__name__, x)
|
|
987
|
-
return _ValueError(t, **kwds)
|
|
1113
|
+
return _ValueError(t, **kwds) if raiser else None
|
|
988
1114
|
|
|
989
1115
|
|
|
990
1116
|
class _Wrap(object):
|
|
@@ -1065,7 +1191,7 @@ class _Wrap(object):
|
|
|
1065
1191
|
'''
|
|
1066
1192
|
if wrap and self._normal is not None:
|
|
1067
1193
|
lat, lon = ll.latlon
|
|
1068
|
-
if fabs(lon) >
|
|
1194
|
+
if fabs(lon) > _180_0 or fabs(lat) > _90_0:
|
|
1069
1195
|
_n = self.latlon
|
|
1070
1196
|
ll = ll.copy(name=_n.__name__)
|
|
1071
1197
|
ll.latlon = _n(lat, lon)
|
|
@@ -1100,8 +1226,7 @@ def wrap90(deg):
|
|
|
1100
1226
|
|
|
1101
1227
|
@return: Degrees, wrapped (C{degrees90}).
|
|
1102
1228
|
'''
|
|
1103
|
-
|
|
1104
|
-
return (w - _180_0) if w > 90 else ((w + _180_0) if w < -90 else w)
|
|
1229
|
+
return _wrapu(wrap180(deg), _180_0, _90_0)
|
|
1105
1230
|
|
|
1106
1231
|
|
|
1107
1232
|
def wrap180(deg):
|
|
@@ -1113,9 +1238,9 @@ def wrap180(deg):
|
|
|
1113
1238
|
'''
|
|
1114
1239
|
d = float(deg)
|
|
1115
1240
|
w = _umod_360(d)
|
|
1116
|
-
if w >
|
|
1241
|
+
if w > _180_0:
|
|
1117
1242
|
w -= _360_0
|
|
1118
|
-
elif d < 0 and w ==
|
|
1243
|
+
elif d < 0 and w == _180_0:
|
|
1119
1244
|
w = -w
|
|
1120
1245
|
return w
|
|
1121
1246
|
|
|
@@ -1163,8 +1288,7 @@ def wrapPI_2(rad):
|
|
|
1163
1288
|
|
|
1164
1289
|
@return: Radians, wrapped (C{radiansPI_2}).
|
|
1165
1290
|
'''
|
|
1166
|
-
|
|
1167
|
-
return (w - PI) if w > PI_2 else ((w + PI) if w < (-PI_2) else w)
|
|
1291
|
+
return _wrapu(wrapPI(rad), PI, PI_2)
|
|
1168
1292
|
|
|
1169
1293
|
|
|
1170
1294
|
# def wraplatlon(lat, lon):
|
|
@@ -1183,7 +1307,7 @@ def wrap_normal(*normal):
|
|
|
1183
1307
|
lat- and longitude individually by L{wrap90} or
|
|
1184
1308
|
L{wrapPI_2} respectively L{wrap180}, L{wrapPI} or
|
|
1185
1309
|
if C{None}, leave lat- and longitude I{unchanged}.
|
|
1186
|
-
|
|
1310
|
+
To get the current setting, do not specify.
|
|
1187
1311
|
|
|
1188
1312
|
@return: The previous L{wrap_normal} setting (C{bool} or C{None}).
|
|
1189
1313
|
'''
|
|
@@ -1199,6 +1323,12 @@ def wrap_normal(*normal):
|
|
|
1199
1323
|
# return wrapPI_2(phi), wrapPI(lam)
|
|
1200
1324
|
|
|
1201
1325
|
|
|
1326
|
+
def _wrapu(w, H, Q):
|
|
1327
|
+
'''(INTERNAL) Helper for functions C{wrap180} and C{wrapPI}.
|
|
1328
|
+
'''
|
|
1329
|
+
return (w - H) if w > Q else ((w + H) if w < (-Q) else w)
|
|
1330
|
+
|
|
1331
|
+
|
|
1202
1332
|
def yard2m(yards):
|
|
1203
1333
|
'''Convert I{UK} yards to meter.
|
|
1204
1334
|
|
|
@@ -1212,7 +1342,7 @@ def yard2m(yards):
|
|
|
1212
1342
|
|
|
1213
1343
|
# **) MIT License
|
|
1214
1344
|
#
|
|
1215
|
-
# Copyright (C) 2016-
|
|
1345
|
+
# Copyright (C) 2016-2025 -- mrJean1 at Gmail -- All Rights Reserved.
|
|
1216
1346
|
#
|
|
1217
1347
|
# Permission is hereby granted, free of charge, to any person obtaining a
|
|
1218
1348
|
# copy of this software and associated documentation files (the "Software"),
|