rustmap3d 0.2.3__cp314-cp314-win_amd64.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.
- rustmap3d/__init__.py +5 -0
- rustmap3d/__init__.pyi +855 -0
- rustmap3d/py.typed +0 -0
- rustmap3d/rustmap3d.cp314-win_amd64.pyd +0 -0
- rustmap3d-0.2.3.dist-info/METADATA +102 -0
- rustmap3d-0.2.3.dist-info/RECORD +8 -0
- rustmap3d-0.2.3.dist-info/WHEEL +4 -0
- rustmap3d-0.2.3.dist-info/licenses/LICENSE +21 -0
rustmap3d/__init__.py
ADDED
rustmap3d/__init__.pyi
ADDED
|
@@ -0,0 +1,855 @@
|
|
|
1
|
+
# This file is automatically generated by pyo3_stub_gen
|
|
2
|
+
# ruff: noqa: E501, F401
|
|
3
|
+
|
|
4
|
+
import builtins
|
|
5
|
+
|
|
6
|
+
def aer2ecef(
|
|
7
|
+
a_d: builtins.float,
|
|
8
|
+
e_d: builtins.float,
|
|
9
|
+
r_m: builtins.float,
|
|
10
|
+
lat_ref_d: builtins.float,
|
|
11
|
+
lon_ref_d: builtins.float,
|
|
12
|
+
) -> tuple[builtins.float, builtins.float, builtins.float]:
|
|
13
|
+
r"""
|
|
14
|
+
Converts AER from a given lat/lon to a new ECEF location
|
|
15
|
+
|
|
16
|
+
# Arguments
|
|
17
|
+
|
|
18
|
+
* `a_d` - Azimuth in degrees [float]
|
|
19
|
+
* `e_d` - Elevation in degrees [float]
|
|
20
|
+
* `r_m` - Range in meters [float]
|
|
21
|
+
* `lat_ref_d` - Reference WGS84 Lat in degrees [float]
|
|
22
|
+
* `lon_ref_d` - Reference WGS84 Lon in degrees [float]
|
|
23
|
+
|
|
24
|
+
# Returns
|
|
25
|
+
|
|
26
|
+
* `ecef` - Absolute ECEF position in meters
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
def aer2ecef_uvw(
|
|
30
|
+
a_d: builtins.float,
|
|
31
|
+
e_d: builtins.float,
|
|
32
|
+
r_m: builtins.float,
|
|
33
|
+
lat_ref_d: builtins.float,
|
|
34
|
+
lon_ref_d: builtins.float,
|
|
35
|
+
) -> tuple[builtins.float, builtins.float, builtins.float]:
|
|
36
|
+
r"""
|
|
37
|
+
Converts a vector direction and distance given in AER to ECEF uvw
|
|
38
|
+
|
|
39
|
+
# Arguments
|
|
40
|
+
|
|
41
|
+
* `a_d` - Azimuth in degrees [float]
|
|
42
|
+
* `e_d` - Elevation in degrees [float]
|
|
43
|
+
* `r_m` - Range in meters [float]
|
|
44
|
+
* `lat_ref_d` - Reference WGS84 Lat in degrees [float]
|
|
45
|
+
* `lon_ref_d` - Reference WGS84 Lon in degrees [float]
|
|
46
|
+
|
|
47
|
+
# Returns
|
|
48
|
+
|
|
49
|
+
* `ecef_uvw` - Vector represented in ECEF frame. Not an absolute position [[meters]].
|
|
50
|
+
"""
|
|
51
|
+
|
|
52
|
+
def aer2enu(
|
|
53
|
+
a_d: builtins.float, e_d: builtins.float, r_m: builtins.float
|
|
54
|
+
) -> tuple[builtins.float, builtins.float, builtins.float]:
|
|
55
|
+
r"""
|
|
56
|
+
Converts AER vector direction and magnitude to ENU.
|
|
57
|
+
|
|
58
|
+
# Arguments
|
|
59
|
+
|
|
60
|
+
* `a_d` - Azimuth in degrees [float]
|
|
61
|
+
* `e_d` - Elevation in degrees [float]
|
|
62
|
+
* `r_m` - Range in meters [float]
|
|
63
|
+
|
|
64
|
+
# Returns
|
|
65
|
+
|
|
66
|
+
* `enu` - Vector represented in ENU coordinates [meters].
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
def aer2ned(
|
|
70
|
+
a_d: builtins.float, e_d: builtins.float, r_m: builtins.float
|
|
71
|
+
) -> tuple[builtins.float, builtins.float, builtins.float]:
|
|
72
|
+
r"""
|
|
73
|
+
Converts AER vector direction and magnitude to NED.
|
|
74
|
+
|
|
75
|
+
# Arguments
|
|
76
|
+
|
|
77
|
+
* `a_d` - Azimuth in degrees [float]
|
|
78
|
+
* `e_d` - Elevation in degrees [float]
|
|
79
|
+
* `r_m` - Range in meters [float]
|
|
80
|
+
|
|
81
|
+
# Returns
|
|
82
|
+
|
|
83
|
+
* `ned` - Vector represented in NED coordinates [meters].
|
|
84
|
+
"""
|
|
85
|
+
|
|
86
|
+
def angle_between(
|
|
87
|
+
ax: builtins.float,
|
|
88
|
+
ay: builtins.float,
|
|
89
|
+
az: builtins.float,
|
|
90
|
+
bx: builtins.float,
|
|
91
|
+
by: builtins.float,
|
|
92
|
+
bz: builtins.float,
|
|
93
|
+
) -> builtins.float:
|
|
94
|
+
r"""
|
|
95
|
+
Computes the angle between two vectors in radians. Dot product is clamped to [-1, 1] so this always outputs a number
|
|
96
|
+
|
|
97
|
+
# Arguments
|
|
98
|
+
|
|
99
|
+
* `ax` - a vector x [float]
|
|
100
|
+
* `ay` - a vector y [float]
|
|
101
|
+
* `az` - a vector z [float]
|
|
102
|
+
* `bx` - b vector x [float]
|
|
103
|
+
* `by` - b vector y [float]
|
|
104
|
+
* `bz` - b vector z [float]
|
|
105
|
+
|
|
106
|
+
# Returns
|
|
107
|
+
|
|
108
|
+
* `angle` - angle between the two vectors in radians
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
def dd2dms(dd: builtins.float, is_lat: builtins.bool) -> builtins.str:
|
|
112
|
+
r"""
|
|
113
|
+
Converts decimal degrees (DD) to degrees-minutes-seconds (DMS).
|
|
114
|
+
|
|
115
|
+
# Arguments
|
|
116
|
+
|
|
117
|
+
* `dd` - Decimal degrees [degrees].
|
|
118
|
+
* `is_lat` - Flag to denote if this decimal value describes a latitude [bool]
|
|
119
|
+
|
|
120
|
+
# Returns
|
|
121
|
+
|
|
122
|
+
* `dms` - Format "{Degrees}:{Minutes}:{Seconds}.{DecSeconds}{Direction}" where Direction is one of N, E, S, or W.
|
|
123
|
+
|
|
124
|
+
# Examples
|
|
125
|
+
```
|
|
126
|
+
dms = map3d.dd2dms(25.37909389, true) #> "25:22:44.738N"
|
|
127
|
+
```
|
|
128
|
+
"""
|
|
129
|
+
|
|
130
|
+
def dms2dd(dms: builtins.str) -> builtins.float:
|
|
131
|
+
r"""
|
|
132
|
+
Converts degrees-minutes-seconds (DMS) to decimal degrees (DD).
|
|
133
|
+
|
|
134
|
+
# Arguments
|
|
135
|
+
|
|
136
|
+
* `dms` - Format "{Degrees}:{Minutes}:{Seconds}.{DecSeconds}{Direction}" where Direction is one of N, E, S, or W.
|
|
137
|
+
|
|
138
|
+
# Returns
|
|
139
|
+
|
|
140
|
+
* `dd` - Decimal degrees [degrees].
|
|
141
|
+
|
|
142
|
+
# Examples
|
|
143
|
+
```
|
|
144
|
+
dd = map3d.dms2dd("25:22:44.738N") #> 25.37909389
|
|
145
|
+
```
|
|
146
|
+
"""
|
|
147
|
+
|
|
148
|
+
def ecef2aer(
|
|
149
|
+
x_m: builtins.float,
|
|
150
|
+
y_m: builtins.float,
|
|
151
|
+
z_m: builtins.float,
|
|
152
|
+
lat_ref_d: builtins.float,
|
|
153
|
+
lon_ref_d: builtins.float,
|
|
154
|
+
) -> tuple[builtins.float, builtins.float, builtins.float]:
|
|
155
|
+
r"""
|
|
156
|
+
Converts an absolute ECEF to AER (az el range).
|
|
157
|
+
|
|
158
|
+
# Arguments
|
|
159
|
+
|
|
160
|
+
* `x_m` - ECEF x in meters [float]
|
|
161
|
+
* `y_m` - ECEF y in meters [float]
|
|
162
|
+
* `z_m` - ECEF z in meters [float]
|
|
163
|
+
* `lat_ref_d` - Reference WGS84 Lat in degrees [float]
|
|
164
|
+
* `lon_ref_d` - Reference WGS84 Lon in degrees [float]
|
|
165
|
+
|
|
166
|
+
# Returns
|
|
167
|
+
|
|
168
|
+
* `aer` - Vector represented in AER coordinates [degrees-degrees-meters].
|
|
169
|
+
"""
|
|
170
|
+
|
|
171
|
+
def ecef2enu(
|
|
172
|
+
x_m: builtins.float,
|
|
173
|
+
y_m: builtins.float,
|
|
174
|
+
z_m: builtins.float,
|
|
175
|
+
lat_ref_d: builtins.float,
|
|
176
|
+
lon_ref_d: builtins.float,
|
|
177
|
+
) -> tuple[builtins.float, builtins.float, builtins.float]:
|
|
178
|
+
r"""
|
|
179
|
+
Converts an ECEF position to ENU.
|
|
180
|
+
|
|
181
|
+
# Arguments
|
|
182
|
+
|
|
183
|
+
* `x_m` - ECEF x in meters [float]
|
|
184
|
+
* `y_m` - ECEF y in meters [float]
|
|
185
|
+
* `z_m` - ECEF z in meters [float]
|
|
186
|
+
* `lat_ref_d` - Reference WGS84 Lat in degrees [float]
|
|
187
|
+
* `lon_ref_d` - Reference WGS84 Lon in degrees [float]
|
|
188
|
+
|
|
189
|
+
# Returns
|
|
190
|
+
|
|
191
|
+
* `enu` - Vector represented in ENU coordinates [meters].
|
|
192
|
+
"""
|
|
193
|
+
|
|
194
|
+
def ecef2enu_dcm(
|
|
195
|
+
lat_d: builtins.float, lon_d: builtins.float
|
|
196
|
+
) -> tuple[
|
|
197
|
+
builtins.float,
|
|
198
|
+
builtins.float,
|
|
199
|
+
builtins.float,
|
|
200
|
+
builtins.float,
|
|
201
|
+
builtins.float,
|
|
202
|
+
builtins.float,
|
|
203
|
+
builtins.float,
|
|
204
|
+
builtins.float,
|
|
205
|
+
builtins.float,
|
|
206
|
+
]:
|
|
207
|
+
r"""
|
|
208
|
+
Calculates the direction cosine matrix that yields an ECEF to ENU transformation at this LLA.
|
|
209
|
+
|
|
210
|
+
# Arguments
|
|
211
|
+
|
|
212
|
+
* `lat_d` - Latitude reference in degrees [float].
|
|
213
|
+
* `lon_d` - Longitude reference in degrees [float].
|
|
214
|
+
|
|
215
|
+
# Returns
|
|
216
|
+
|
|
217
|
+
* `dcm` - ECEF to ENU direction cosine matrix [[xx, xy, xz], [yx, yy, yz], [zx, zy, zz]]
|
|
218
|
+
"""
|
|
219
|
+
|
|
220
|
+
def ecef2enu_quat(
|
|
221
|
+
lat_d: builtins.float, lon_d: builtins.float
|
|
222
|
+
) -> tuple[builtins.float, builtins.float, builtins.float, builtins.float]:
|
|
223
|
+
r"""
|
|
224
|
+
Calculates the quaternion that yields an ECEF to ENU transformation at this LLA.
|
|
225
|
+
|
|
226
|
+
# Arguments
|
|
227
|
+
|
|
228
|
+
* `lat_d` - Latitude reference in degrees [float].
|
|
229
|
+
* `lon_d` - Longitude reference in degrees [float].
|
|
230
|
+
|
|
231
|
+
# Returns
|
|
232
|
+
|
|
233
|
+
* `quat` - Normalized ECEF to ENU quaternion.
|
|
234
|
+
"""
|
|
235
|
+
|
|
236
|
+
def ecef2lla(
|
|
237
|
+
x_m: builtins.float, y_m: builtins.float, z_m: builtins.float
|
|
238
|
+
) -> tuple[builtins.float, builtins.float, builtins.float]:
|
|
239
|
+
r"""
|
|
240
|
+
Converts ECEF to WGS84 LLA
|
|
241
|
+
|
|
242
|
+
# Arguments
|
|
243
|
+
|
|
244
|
+
* `x_m` - ECEF x in meters [float]
|
|
245
|
+
* `y_m` - ECEF y in meters [float]
|
|
246
|
+
* `z_m` - ECEF z in meters [float]
|
|
247
|
+
|
|
248
|
+
# Returns
|
|
249
|
+
|
|
250
|
+
* `lla` - Vector represented in WGS84 LLA [degrees-degrees-meters].
|
|
251
|
+
"""
|
|
252
|
+
|
|
253
|
+
def ecef2ned(
|
|
254
|
+
x_m: builtins.float,
|
|
255
|
+
y_m: builtins.float,
|
|
256
|
+
z_m: builtins.float,
|
|
257
|
+
lat_ref_d: builtins.float,
|
|
258
|
+
lon_ref_d: builtins.float,
|
|
259
|
+
) -> tuple[builtins.float, builtins.float, builtins.float]:
|
|
260
|
+
r"""
|
|
261
|
+
Converts an absolute ECEF location to NED.
|
|
262
|
+
|
|
263
|
+
# Arguments
|
|
264
|
+
|
|
265
|
+
* `x_m` - ECEF x in meters [float]
|
|
266
|
+
* `y_m` - ECEF y in meters [float]
|
|
267
|
+
* `z_m` - ECEF z in meters [float]
|
|
268
|
+
* `lat_ref_d` - Reference WGS84 Lat in degrees [float]
|
|
269
|
+
* `lon_ref_d` - Reference WGS84 Lon in degrees [float]
|
|
270
|
+
|
|
271
|
+
# Returns
|
|
272
|
+
|
|
273
|
+
* `ned` - Vector represented in NED coordinates [meters].
|
|
274
|
+
"""
|
|
275
|
+
|
|
276
|
+
def ecef2ned_dcm(
|
|
277
|
+
lat_d: builtins.float, lon_d: builtins.float
|
|
278
|
+
) -> tuple[
|
|
279
|
+
builtins.float,
|
|
280
|
+
builtins.float,
|
|
281
|
+
builtins.float,
|
|
282
|
+
builtins.float,
|
|
283
|
+
builtins.float,
|
|
284
|
+
builtins.float,
|
|
285
|
+
builtins.float,
|
|
286
|
+
builtins.float,
|
|
287
|
+
builtins.float,
|
|
288
|
+
]:
|
|
289
|
+
r"""
|
|
290
|
+
Calculates the direction cosine matrix that yields an ECEF to NED transformation at this LLA.
|
|
291
|
+
|
|
292
|
+
# Arguments
|
|
293
|
+
|
|
294
|
+
* `lat_d` - Latitude reference in degrees [float].
|
|
295
|
+
* `lon_d` - Longitude reference in degrees [float].
|
|
296
|
+
|
|
297
|
+
# Returns
|
|
298
|
+
|
|
299
|
+
* `dcm` - ECEF to NED direction cosine matrix [[xx, xy, xz], [yx, yy, yz], [zx, zy, zz]]
|
|
300
|
+
"""
|
|
301
|
+
|
|
302
|
+
def ecef2ned_quat(
|
|
303
|
+
lat_d: builtins.float, lon_d: builtins.float
|
|
304
|
+
) -> tuple[builtins.float, builtins.float, builtins.float, builtins.float]:
|
|
305
|
+
r"""
|
|
306
|
+
Calculates the quaternion that yields an ECEF to NED transformation at this LLA.
|
|
307
|
+
|
|
308
|
+
# Arguments
|
|
309
|
+
|
|
310
|
+
* `lat_d` - Latitude reference in degrees [float].
|
|
311
|
+
* `lon_d` - Longitude reference in degrees [float].
|
|
312
|
+
|
|
313
|
+
# Returns
|
|
314
|
+
|
|
315
|
+
* `quat` - Normalized ECEF to NED quaternion (w, x, y, z).
|
|
316
|
+
"""
|
|
317
|
+
|
|
318
|
+
def ecef_quat2heading(
|
|
319
|
+
w: builtins.float,
|
|
320
|
+
x: builtins.float,
|
|
321
|
+
y: builtins.float,
|
|
322
|
+
z: builtins.float,
|
|
323
|
+
lat_ref_d: builtins.float,
|
|
324
|
+
lon_ref_d: builtins.float,
|
|
325
|
+
) -> builtins.float:
|
|
326
|
+
r"""
|
|
327
|
+
Computes the clockwise angle from North of a local body-frame's x-axis
|
|
328
|
+
|
|
329
|
+
# Arguments
|
|
330
|
+
|
|
331
|
+
* `w` - Scalar part of quaternion [float]
|
|
332
|
+
* `x` - x part of quaternion [float]
|
|
333
|
+
* `y` - y part of quaternion [float]
|
|
334
|
+
* `z` - z part of quaternion [float]
|
|
335
|
+
* `lat_ref_d` - Reference WGS84 Lat in degrees [float]
|
|
336
|
+
* `lon_ref_d` - Reference WGS84 Lon in degrees [float]
|
|
337
|
+
|
|
338
|
+
# Returns
|
|
339
|
+
|
|
340
|
+
* `heading` - Clockwise angle off true north [[degrees]] of the body's x axis
|
|
341
|
+
"""
|
|
342
|
+
|
|
343
|
+
def ecef_uvw2aer(
|
|
344
|
+
u_m: builtins.float,
|
|
345
|
+
v_m: builtins.float,
|
|
346
|
+
w_m: builtins.float,
|
|
347
|
+
lat_ref_d: builtins.float,
|
|
348
|
+
lon_ref_d: builtins.float,
|
|
349
|
+
) -> tuple[builtins.float, builtins.float, builtins.float]:
|
|
350
|
+
r"""
|
|
351
|
+
Converts ECEF uvw to AER (az el range).
|
|
352
|
+
|
|
353
|
+
# Arguments
|
|
354
|
+
|
|
355
|
+
* `u_m` - ECEF u in meters [float]
|
|
356
|
+
* `v_m` - ECEF v in meters [float]
|
|
357
|
+
* `w_m` - ECEF w in meters [float]
|
|
358
|
+
* `lat_ref_d` - Reference WGS84 Lat in degrees [float]
|
|
359
|
+
* `lon_ref_d` - Reference WGS84 Lon in degrees [float]
|
|
360
|
+
|
|
361
|
+
# Returns
|
|
362
|
+
|
|
363
|
+
* `aer` - Vector represented in AER coordinates [degrees-degrees-meters].
|
|
364
|
+
"""
|
|
365
|
+
|
|
366
|
+
def ecef_uvw2enu(
|
|
367
|
+
u_m: builtins.float,
|
|
368
|
+
v_m: builtins.float,
|
|
369
|
+
w_m: builtins.float,
|
|
370
|
+
lat_ref_d: builtins.float,
|
|
371
|
+
lon_ref_d: builtins.float,
|
|
372
|
+
) -> tuple[builtins.float, builtins.float, builtins.float]:
|
|
373
|
+
r"""
|
|
374
|
+
Converts an ECEF uvw vector to ENU.
|
|
375
|
+
|
|
376
|
+
# Arguments
|
|
377
|
+
|
|
378
|
+
* `u_m` - ECEF u in meters [float]
|
|
379
|
+
* `v_m` - ECEF v in meters [float]
|
|
380
|
+
* `w_m` - ECEF w in meters [float]
|
|
381
|
+
* `lat_ref_d` - Reference WGS84 Lat in degrees [float]
|
|
382
|
+
* `lon_ref_d` - Reference WGS84 Lon in degrees [float]
|
|
383
|
+
|
|
384
|
+
# Returns
|
|
385
|
+
|
|
386
|
+
* `enu` - Vector represented in ENU coordinates [meters].
|
|
387
|
+
"""
|
|
388
|
+
|
|
389
|
+
def ecef_uvw2ned(
|
|
390
|
+
u_m: builtins.float,
|
|
391
|
+
v_m: builtins.float,
|
|
392
|
+
w_m: builtins.float,
|
|
393
|
+
lat_ref_d: builtins.float,
|
|
394
|
+
lon_ref_d: builtins.float,
|
|
395
|
+
) -> tuple[builtins.float, builtins.float, builtins.float]:
|
|
396
|
+
r"""
|
|
397
|
+
Converts ECEF UVW Vector to NED.
|
|
398
|
+
|
|
399
|
+
# Arguments
|
|
400
|
+
|
|
401
|
+
* `u_m` - ECEF u in meters [float]
|
|
402
|
+
* `v_m` - ECEF v in meters [float]
|
|
403
|
+
* `w_m` - ECEF w in meters [float]
|
|
404
|
+
* `lat_ref_d` - Reference WGS84 Lat in degrees [float]
|
|
405
|
+
* `lon_ref_d` - Reference WGS84 Lon in degrees [float]
|
|
406
|
+
|
|
407
|
+
# Returns
|
|
408
|
+
|
|
409
|
+
* `ned` - Vector represented in NED coordinates [meters].
|
|
410
|
+
"""
|
|
411
|
+
|
|
412
|
+
def enu2aer(
|
|
413
|
+
e_m: builtins.float, n_m: builtins.float, u_m: builtins.float
|
|
414
|
+
) -> tuple[builtins.float, builtins.float, builtins.float]:
|
|
415
|
+
r"""
|
|
416
|
+
Converts ENU to AER.
|
|
417
|
+
|
|
418
|
+
# Arguments
|
|
419
|
+
|
|
420
|
+
* `e_m` - East in meters [float]
|
|
421
|
+
* `n_m` - North in meters [float]
|
|
422
|
+
* `u_m` - Up in meters [float]
|
|
423
|
+
|
|
424
|
+
# Returns
|
|
425
|
+
|
|
426
|
+
* `aer` - Vector represented in AER coordinates [degrees-degrees-meters].
|
|
427
|
+
"""
|
|
428
|
+
|
|
429
|
+
def enu2ecef(
|
|
430
|
+
e_m: builtins.float,
|
|
431
|
+
n_m: builtins.float,
|
|
432
|
+
u_m: builtins.float,
|
|
433
|
+
lat_ref_d: builtins.float,
|
|
434
|
+
lon_ref_d: builtins.float,
|
|
435
|
+
) -> tuple[builtins.float, builtins.float, builtins.float]:
|
|
436
|
+
r"""
|
|
437
|
+
Converts ENU to an ECEF position
|
|
438
|
+
|
|
439
|
+
# Arguments
|
|
440
|
+
|
|
441
|
+
* `e_m` - East in meters [float]
|
|
442
|
+
* `n_m` - North in meters [float]
|
|
443
|
+
* `u_m` - Up in meters [float]
|
|
444
|
+
* `lat_ref_d` - Reference WGS84 Lat in degrees [float]
|
|
445
|
+
* `lon_ref_d` - Reference WGS84 Lon in degrees [float]
|
|
446
|
+
|
|
447
|
+
# Returns
|
|
448
|
+
|
|
449
|
+
* `ecef` - Absolute ECEF position in meters
|
|
450
|
+
"""
|
|
451
|
+
|
|
452
|
+
def enu2ecef_dcm(
|
|
453
|
+
lat_d: builtins.float, lon_d: builtins.float
|
|
454
|
+
) -> tuple[
|
|
455
|
+
builtins.float,
|
|
456
|
+
builtins.float,
|
|
457
|
+
builtins.float,
|
|
458
|
+
builtins.float,
|
|
459
|
+
builtins.float,
|
|
460
|
+
builtins.float,
|
|
461
|
+
builtins.float,
|
|
462
|
+
builtins.float,
|
|
463
|
+
builtins.float,
|
|
464
|
+
]:
|
|
465
|
+
r"""
|
|
466
|
+
Calculates the direction cosine matrix that yields an ENU to ECEF transformation at this LLA.
|
|
467
|
+
|
|
468
|
+
# Arguments
|
|
469
|
+
|
|
470
|
+
* `lat_d` - Latitude reference in degrees [float].
|
|
471
|
+
* `lon_d` - Longitude reference in degrees [float].
|
|
472
|
+
|
|
473
|
+
# Returns
|
|
474
|
+
|
|
475
|
+
* `dcm` - ENU to ECEF direction cosine matrix [[xx, xy, xz], [yx, yy, yz], [zx, zy, zz]]
|
|
476
|
+
"""
|
|
477
|
+
|
|
478
|
+
def enu2ecef_quat(
|
|
479
|
+
lat_d: builtins.float, lon_d: builtins.float
|
|
480
|
+
) -> tuple[builtins.float, builtins.float, builtins.float, builtins.float]:
|
|
481
|
+
r"""
|
|
482
|
+
Calculates the quaternion that yields an ENU to ECEF transformation at this LLA.
|
|
483
|
+
|
|
484
|
+
# Arguments
|
|
485
|
+
|
|
486
|
+
* `lat_d` - Latitude reference in degrees [float].
|
|
487
|
+
* `lon_d` - Longitude reference in degrees [float].
|
|
488
|
+
|
|
489
|
+
# Returns
|
|
490
|
+
|
|
491
|
+
* `quat` - Normalized ENU to ECEF quaternion (w, x, y, z).
|
|
492
|
+
"""
|
|
493
|
+
|
|
494
|
+
def enu2ecef_uvw(
|
|
495
|
+
e_m: builtins.float,
|
|
496
|
+
n_m: builtins.float,
|
|
497
|
+
u_m: builtins.float,
|
|
498
|
+
lat_ref_d: builtins.float,
|
|
499
|
+
lon_ref_d: builtins.float,
|
|
500
|
+
) -> tuple[builtins.float, builtins.float, builtins.float]:
|
|
501
|
+
r"""
|
|
502
|
+
Converts ENU to ECEF uvw vector
|
|
503
|
+
|
|
504
|
+
# Arguments
|
|
505
|
+
|
|
506
|
+
* `e_m` - East in meters [float]
|
|
507
|
+
* `n_m` - North in meters [float]
|
|
508
|
+
* `u_m` - Up in meters [float]
|
|
509
|
+
* `lat_ref_d` - Reference WGS84 Lat in degrees [float]
|
|
510
|
+
* `lon_ref_d` - Reference WGS84 Lon in degrees [float]
|
|
511
|
+
|
|
512
|
+
# Returns
|
|
513
|
+
|
|
514
|
+
* `ecef_uvw` - Vector represented in ECEF frame. Not an absolute position [[meters]].
|
|
515
|
+
"""
|
|
516
|
+
|
|
517
|
+
def enu2heading(
|
|
518
|
+
e_m: builtins.float, n_m: builtins.float, u_m: builtins.float
|
|
519
|
+
) -> builtins.float:
|
|
520
|
+
r"""
|
|
521
|
+
Calculates heading angle from ENU.
|
|
522
|
+
|
|
523
|
+
# Arguments
|
|
524
|
+
|
|
525
|
+
* `e_m` - East in meters [float]
|
|
526
|
+
* `n_m` - North in meters [float]
|
|
527
|
+
* `u_m` - Up in meters [float]
|
|
528
|
+
|
|
529
|
+
# Returns
|
|
530
|
+
|
|
531
|
+
* `heading_deg` - Heading angle relative to true north [degrees].
|
|
532
|
+
"""
|
|
533
|
+
|
|
534
|
+
def enu2lla(
|
|
535
|
+
e_m: builtins.float,
|
|
536
|
+
n_m: builtins.float,
|
|
537
|
+
u_m: builtins.float,
|
|
538
|
+
lat_ref_d: builtins.float,
|
|
539
|
+
lon_ref_d: builtins.float,
|
|
540
|
+
) -> tuple[builtins.float, builtins.float, builtins.float]:
|
|
541
|
+
r"""
|
|
542
|
+
Converts ENU to an absolute LLA position
|
|
543
|
+
|
|
544
|
+
# Arguments
|
|
545
|
+
|
|
546
|
+
* `e_m` - East in meters [float]
|
|
547
|
+
* `n_m` - North in meters [float]
|
|
548
|
+
* `u_m` - Up in meters [float]
|
|
549
|
+
* `lat_ref_d` - Reference WGS84 Lat in degrees [float]
|
|
550
|
+
* `lon_ref_d` - Reference WGS84 Lon in degrees [float]
|
|
551
|
+
|
|
552
|
+
# Returns
|
|
553
|
+
|
|
554
|
+
* `lla` - Absolute LLA position [deg-deg-m]
|
|
555
|
+
"""
|
|
556
|
+
|
|
557
|
+
def ll2dms(
|
|
558
|
+
lat_d: builtins.float, lon_d: builtins.float
|
|
559
|
+
) -> tuple[builtins.str, builtins.str]:
|
|
560
|
+
r"""
|
|
561
|
+
Convenience function to convert lat/lon to a tuple of (lat dms, lon dms)
|
|
562
|
+
|
|
563
|
+
# Arguments
|
|
564
|
+
|
|
565
|
+
* `lat` - Latitude in decimal degrees
|
|
566
|
+
* `lon` - Longitude in decimal degrees
|
|
567
|
+
|
|
568
|
+
# Returns
|
|
569
|
+
|
|
570
|
+
* `(lat dms, lon dms)` - Tuple of lat/lon as degrees:minutes:seconds [Tuple[String, String]]
|
|
571
|
+
```
|
|
572
|
+
"""
|
|
573
|
+
|
|
574
|
+
def lla2ecef(
|
|
575
|
+
lat_d: builtins.float, lon_d: builtins.float, alt_m: builtins.float
|
|
576
|
+
) -> tuple[builtins.float, builtins.float, builtins.float]:
|
|
577
|
+
r"""
|
|
578
|
+
Converts WGS84 LLA to ECEF.
|
|
579
|
+
|
|
580
|
+
# Arguments
|
|
581
|
+
|
|
582
|
+
* `lat_d` - WGS84 Lat in degrees [float]
|
|
583
|
+
* `lon_d` - WGS84 Lon in degrees [float]
|
|
584
|
+
* `alt_m` - WGS84 MSL alt in meters [float]
|
|
585
|
+
|
|
586
|
+
# Returns
|
|
587
|
+
|
|
588
|
+
* `ecef` - Vector represented in ECEF coordinates [meters].
|
|
589
|
+
"""
|
|
590
|
+
|
|
591
|
+
def lla2enu(
|
|
592
|
+
lat_d: builtins.float,
|
|
593
|
+
lon_d: builtins.float,
|
|
594
|
+
alt_m: builtins.float,
|
|
595
|
+
lat_ref_d: builtins.float,
|
|
596
|
+
lon_ref_d: builtins.float,
|
|
597
|
+
) -> tuple[builtins.float, builtins.float, builtins.float]:
|
|
598
|
+
r"""
|
|
599
|
+
Converts an absolute LLA position to an ENU vector relative to a lla reference
|
|
600
|
+
|
|
601
|
+
# Arguments
|
|
602
|
+
|
|
603
|
+
* `lat_d` - WGS84 Lat in degrees [float]
|
|
604
|
+
* `lon_d` - WGS84 Lon in degrees [float]
|
|
605
|
+
* `alt_m` - WGS84 MSL alt in meters [float]
|
|
606
|
+
* `lat_ref_d` - Reference WGS84 Lat in degrees [float]
|
|
607
|
+
* `lon_ref_d` - Reference WGS84 Lon in degrees [float]
|
|
608
|
+
|
|
609
|
+
# Returns
|
|
610
|
+
|
|
611
|
+
* `enu` - Vector represented in ENU coordinates [meters].
|
|
612
|
+
"""
|
|
613
|
+
|
|
614
|
+
def lla2ned(
|
|
615
|
+
lat_d: builtins.float,
|
|
616
|
+
lon_d: builtins.float,
|
|
617
|
+
alt_m: builtins.float,
|
|
618
|
+
lat_ref_d: builtins.float,
|
|
619
|
+
lon_ref_d: builtins.float,
|
|
620
|
+
) -> tuple[builtins.float, builtins.float, builtins.float]:
|
|
621
|
+
r"""
|
|
622
|
+
Converts an absolute LLA location to a NED vector relative to a lla reference point
|
|
623
|
+
|
|
624
|
+
# Arguments
|
|
625
|
+
|
|
626
|
+
* `lat_d` - WGS84 Lat in degrees [float]
|
|
627
|
+
* `lon_d` - WGS84 Lon in degrees [float]
|
|
628
|
+
* `alt_m` - WGS84 MSL alt in meters [float]
|
|
629
|
+
* `lat_ref_d` - Reference WGS84 Lat in degrees [float]
|
|
630
|
+
* `lon_ref_d` - Reference WGS84 Lon in degrees [float]
|
|
631
|
+
|
|
632
|
+
# Returns
|
|
633
|
+
|
|
634
|
+
* `ned` - Vector represented in NED coordinates [meters].
|
|
635
|
+
"""
|
|
636
|
+
|
|
637
|
+
def ned2aer(
|
|
638
|
+
n_m: builtins.float, e_m: builtins.float, d_m: builtins.float
|
|
639
|
+
) -> tuple[builtins.float, builtins.float, builtins.float]:
|
|
640
|
+
r"""
|
|
641
|
+
Converts NED to AER.
|
|
642
|
+
|
|
643
|
+
# Arguments
|
|
644
|
+
|
|
645
|
+
* `n_m` - North in meters [float]
|
|
646
|
+
* `e_m` - East in meters [float]
|
|
647
|
+
* `d_m` - Down in meters [float]
|
|
648
|
+
|
|
649
|
+
# Returns
|
|
650
|
+
|
|
651
|
+
* `aer` - Vector represented in AER coordinates [degrees-degrees-meters].
|
|
652
|
+
"""
|
|
653
|
+
|
|
654
|
+
def ned2ecef(
|
|
655
|
+
n_m: builtins.float,
|
|
656
|
+
e_m: builtins.float,
|
|
657
|
+
d_m: builtins.float,
|
|
658
|
+
lat_ref_d: builtins.float,
|
|
659
|
+
lon_ref_d: builtins.float,
|
|
660
|
+
) -> tuple[builtins.float, builtins.float, builtins.float]:
|
|
661
|
+
r"""
|
|
662
|
+
Converts NED to an absolute ECEF location
|
|
663
|
+
|
|
664
|
+
# Arguments
|
|
665
|
+
|
|
666
|
+
* `n_m` - North in meters [float]
|
|
667
|
+
* `e_m` - East in meters [float]
|
|
668
|
+
* `d_m` - Down in meters [float]
|
|
669
|
+
* `lat_ref_d` - Reference WGS84 Lat in degrees [float]
|
|
670
|
+
* `lon_ref_d` - Reference WGS84 Lon in degrees [float]
|
|
671
|
+
|
|
672
|
+
# Returns
|
|
673
|
+
|
|
674
|
+
* `ecef` - Absolute ECEF position in meters
|
|
675
|
+
"""
|
|
676
|
+
|
|
677
|
+
def ned2ecef_dcm(
|
|
678
|
+
lat_d: builtins.float, lon_d: builtins.float
|
|
679
|
+
) -> tuple[
|
|
680
|
+
builtins.float,
|
|
681
|
+
builtins.float,
|
|
682
|
+
builtins.float,
|
|
683
|
+
builtins.float,
|
|
684
|
+
builtins.float,
|
|
685
|
+
builtins.float,
|
|
686
|
+
builtins.float,
|
|
687
|
+
builtins.float,
|
|
688
|
+
builtins.float,
|
|
689
|
+
]:
|
|
690
|
+
r"""
|
|
691
|
+
Calculates the direction cosine matrix that yields an NED to ECEF transformation at this LLA.
|
|
692
|
+
|
|
693
|
+
# Arguments
|
|
694
|
+
|
|
695
|
+
* `lat_d` - Latitude reference in degrees [float].
|
|
696
|
+
* `lon_d` - Longitude reference in degrees [float].
|
|
697
|
+
|
|
698
|
+
# Returns
|
|
699
|
+
|
|
700
|
+
* `dcm` - NED to ECEF direction cosine matrix [[xx, xy, xz], [yx, yy, yz], [zx, zy, zz]]
|
|
701
|
+
"""
|
|
702
|
+
|
|
703
|
+
def ned2ecef_quat(
|
|
704
|
+
lat_d: builtins.float, lon_d: builtins.float
|
|
705
|
+
) -> tuple[builtins.float, builtins.float, builtins.float, builtins.float]:
|
|
706
|
+
r"""
|
|
707
|
+
Calculates the quaternion that yields an NED to ECEF transformation at this LLA.
|
|
708
|
+
|
|
709
|
+
# Arguments
|
|
710
|
+
|
|
711
|
+
* `lat_d` - Latitude reference in degrees [float].
|
|
712
|
+
* `lon_d` - Longitude reference in degrees [float].
|
|
713
|
+
|
|
714
|
+
# Returns
|
|
715
|
+
|
|
716
|
+
* `quat` - Normalized NED to ECEF quaternion (w, x, y, z).
|
|
717
|
+
"""
|
|
718
|
+
|
|
719
|
+
def ned2ecef_uvw(
|
|
720
|
+
n_m: builtins.float,
|
|
721
|
+
e_m: builtins.float,
|
|
722
|
+
d_m: builtins.float,
|
|
723
|
+
lat_ref_d: builtins.float,
|
|
724
|
+
lon_ref_d: builtins.float,
|
|
725
|
+
) -> tuple[builtins.float, builtins.float, builtins.float]:
|
|
726
|
+
r"""
|
|
727
|
+
Converts NED to ECEF uvw
|
|
728
|
+
|
|
729
|
+
# Arguments
|
|
730
|
+
|
|
731
|
+
* `n_m` - North in meters [float]
|
|
732
|
+
* `e_m` - East in meters [float]
|
|
733
|
+
* `d_m` - Down in meters [float]
|
|
734
|
+
* `lat_ref_d` - Reference WGS84 Lat in degrees [float]
|
|
735
|
+
* `lon_ref_d` - Reference WGS84 Lon in degrees [float]
|
|
736
|
+
|
|
737
|
+
# Returns
|
|
738
|
+
|
|
739
|
+
* `ecef_uvw` - Vector represented in ECEF frame. Not an absolute position [[meters]].
|
|
740
|
+
"""
|
|
741
|
+
|
|
742
|
+
def ned2lla(
|
|
743
|
+
n_m: builtins.float,
|
|
744
|
+
e_m: builtins.float,
|
|
745
|
+
d_m: builtins.float,
|
|
746
|
+
lat_ref_d: builtins.float,
|
|
747
|
+
lon_ref_d: builtins.float,
|
|
748
|
+
) -> tuple[builtins.float, builtins.float, builtins.float]:
|
|
749
|
+
r"""
|
|
750
|
+
Converts a NED vector to an absolute lat lon alt
|
|
751
|
+
|
|
752
|
+
# Arguments
|
|
753
|
+
|
|
754
|
+
* `n_m` - North in meters [float]
|
|
755
|
+
* `e_m` - East in meters [float]
|
|
756
|
+
* `d_m` - Down in meters [float]
|
|
757
|
+
* `lat_ref_d` - Reference WGS84 Lat in degrees [float]
|
|
758
|
+
* `lon_ref_d` - Reference WGS84 Lon in degrees [float]
|
|
759
|
+
|
|
760
|
+
# Returns
|
|
761
|
+
|
|
762
|
+
* `lla` - Absolute lat lon alt [deg-deg-m]
|
|
763
|
+
"""
|
|
764
|
+
|
|
765
|
+
def rand_ecef() -> tuple[builtins.float, builtins.float, builtins.float]:
|
|
766
|
+
r"""
|
|
767
|
+
Generates a uniform random ECEF point on the surface of a spherical Earth.
|
|
768
|
+
|
|
769
|
+
# Returns
|
|
770
|
+
|
|
771
|
+
* `ecef` - Random ECEF location [meters].
|
|
772
|
+
"""
|
|
773
|
+
|
|
774
|
+
def rand_lla() -> tuple[builtins.float, builtins.float, builtins.float]:
|
|
775
|
+
r"""
|
|
776
|
+
Generates a uniform random LLA point. Altitude is generated in the domain [0.0, 10000.0].
|
|
777
|
+
|
|
778
|
+
# Returns
|
|
779
|
+
|
|
780
|
+
* `lla` - Random LLA location [degrees-degrees-meters].
|
|
781
|
+
"""
|
|
782
|
+
|
|
783
|
+
def rand_orientation() -> tuple[
|
|
784
|
+
builtins.float, builtins.float, builtins.float, builtins.float
|
|
785
|
+
]:
|
|
786
|
+
r"""
|
|
787
|
+
Generates a random normalized quaternion.
|
|
788
|
+
|
|
789
|
+
# Returns
|
|
790
|
+
|
|
791
|
+
* `quat` - Random normalized quaternion (w, x, y, z).
|
|
792
|
+
"""
|
|
793
|
+
|
|
794
|
+
def vincenty_direct(
|
|
795
|
+
lat_d: builtins.float,
|
|
796
|
+
lon_d: builtins.float,
|
|
797
|
+
range_m: builtins.float,
|
|
798
|
+
bearing_d: builtins.float,
|
|
799
|
+
atol: builtins.float = ...,
|
|
800
|
+
max_iters: builtins.int = ...,
|
|
801
|
+
) -> tuple[builtins.float, builtins.float]:
|
|
802
|
+
r"""
|
|
803
|
+
Calculates the LLA location that is a fixed range and bearing from a reference LLA. This function uses an iterative
|
|
804
|
+
solution to determine outputs using the WGS84 ellipsoidal Earth model.
|
|
805
|
+
|
|
806
|
+
See reference:
|
|
807
|
+
https://en.wikipedia.org/wiki/Vincenty%27s_formulae.
|
|
808
|
+
|
|
809
|
+
# Arguments
|
|
810
|
+
|
|
811
|
+
* `lat_d` - Latitude reference in degrees [float].
|
|
812
|
+
* `lon_d` - Longitude reference in degrees [float].
|
|
813
|
+
* `range_m` - Range (i.e., distance) from point A to point B [meters].
|
|
814
|
+
* `bearing_d` - Bearing (i.e., azimuth) from point A to point B relative to true north [degrees].
|
|
815
|
+
* `abs_tol` - Absolute tolerance used for convergence.
|
|
816
|
+
* `max_iters` - Maximum possible number of iterations before early termination.
|
|
817
|
+
|
|
818
|
+
# Returns
|
|
819
|
+
|
|
820
|
+
A tuple `(lat_deg, lon_deg)` where:
|
|
821
|
+
* `lat_deg` - Latitude location [degrees].
|
|
822
|
+
* `lon_deg` - Longitude location [degrees].
|
|
823
|
+
"""
|
|
824
|
+
|
|
825
|
+
def vincenty_inverse(
|
|
826
|
+
lat_a_deg: builtins.float,
|
|
827
|
+
lon_a_deg: builtins.float,
|
|
828
|
+
lat_b_deg: builtins.float,
|
|
829
|
+
lon_b_deg: builtins.float,
|
|
830
|
+
atol: builtins.float = ...,
|
|
831
|
+
max_iters: builtins.int = ...,
|
|
832
|
+
) -> tuple[builtins.float, builtins.float, builtins.float]:
|
|
833
|
+
r"""
|
|
834
|
+
Calculates range and bearings between two latitude-longitude points. This function uses an iterative solution to
|
|
835
|
+
determine outputs using the WGS84 ellipsoidal Earth model.
|
|
836
|
+
|
|
837
|
+
See reference:
|
|
838
|
+
https://en.wikipedia.org/wiki/Vincenty%27s_formulae.
|
|
839
|
+
|
|
840
|
+
# Arguments
|
|
841
|
+
|
|
842
|
+
* `lat_a_deg` - Latitude point A [degrees].
|
|
843
|
+
* `lon_a_deg` - Longitude point A [degrees].
|
|
844
|
+
* `lat_b_deg` - Latitude point A [degrees].
|
|
845
|
+
* `lon_b_deg` - Longitude point A [degrees].
|
|
846
|
+
* `atol` - Absolute tolerance used for convergence.
|
|
847
|
+
* `max_iters` - Maximum possible number of iterations before early termination.
|
|
848
|
+
|
|
849
|
+
# Returns
|
|
850
|
+
|
|
851
|
+
A tuple `(range_m, bearing_ab_deg, bearing_ba_deg)` where:
|
|
852
|
+
* `range_m` - Range (i.e., distance) from point A to point B [meters].
|
|
853
|
+
* `bearing_ab_deg` - Bearing (i.e., azimuth) from point A to point B relative to true north [degrees].
|
|
854
|
+
* `bearing_ba_deg` - Bearing (i.e., azimuth) from point B to point A relative to true north [degrees].
|
|
855
|
+
"""
|
rustmap3d/py.typed
ADDED
|
File without changes
|
|
Binary file
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rustmap3d
|
|
3
|
+
Version: 0.2.3
|
|
4
|
+
Classifier: Programming Language :: Rust
|
|
5
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
6
|
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Summary: Python geodetic coordinate conversions written in rust
|
|
10
|
+
Author-email: weiler <lucas.l.weiler@leidos.com>, molnar <andrew.b.molnar@leidos.com>
|
|
11
|
+
Requires-Python: >=3.8
|
|
12
|
+
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
|
|
13
|
+
Project-URL: Homepage, https://github.com/lskyweiler/rustmap3d
|
|
14
|
+
|
|
15
|
+
# rustmap3d
|
|
16
|
+
|
|
17
|
+
[](https://github.com/lskyweiler/rustmap3d#license)
|
|
18
|
+

|
|
19
|
+
[](https://pypi.org/project/rustmap3d/)
|
|
20
|
+
[](https://github.com/astral-sh/ruff)
|
|
21
|
+
|
|
22
|
+
<p align="center"><img src="docs/rustmap3d.logo.svg" width="300px" height="300px"/></p>
|
|
23
|
+
|
|
24
|
+
**Simple, fast, and ergonomic geodetic coordinate conversions**
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
### Installation
|
|
28
|
+
```bash
|
|
29
|
+
# add to an existing project
|
|
30
|
+
uv add rustmap3d
|
|
31
|
+
# pip install it directly
|
|
32
|
+
uv pip install rustmap3d
|
|
33
|
+
|
|
34
|
+
# pip install without uv
|
|
35
|
+
pip install rustmap3d
|
|
36
|
+
```
|
|
37
|
+
---
|
|
38
|
+
### Examples
|
|
39
|
+
```python
|
|
40
|
+
import rustmap3d
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
# wgs84 geodetic conversions
|
|
44
|
+
lla = rustmap3d.ecef2lla(x, y, z)
|
|
45
|
+
ecef = rustmap3d.lla2ecef(lat, lon, alt)
|
|
46
|
+
...
|
|
47
|
+
|
|
48
|
+
# local conversions
|
|
49
|
+
ecef_uvw = rustmap3d.enu2ecef_uvw(e, n, u, lat_ref, lon_ref)
|
|
50
|
+
ecef = rustmap3d.enu2ecef(e, n, u, lat_ref, lon_ref)
|
|
51
|
+
ecef_uvw = rustmap3d.ned2ecef_uvw(n, e, d, lat_ref, lon_ref)
|
|
52
|
+
ecef = rustmap3d.ned2ecef(n, e, d, lat_ref, lon_ref)
|
|
53
|
+
# enu, ned, aer
|
|
54
|
+
...
|
|
55
|
+
|
|
56
|
+
# local rotations
|
|
57
|
+
enu_quat = rustmap3d.enu2ecef_quat(lat, lon)
|
|
58
|
+
enu_dcm = rustmap3d.enu2ecef_dcm(lat, lon)
|
|
59
|
+
# enu, ned
|
|
60
|
+
|
|
61
|
+
# Conversions
|
|
62
|
+
dd = rustmap3d.dms2dd("25:22:44.738N") #> 25.37909389
|
|
63
|
+
dms = rustmap3d.dd2dms(25.37909389, is_lat=true) #> "25:22:44.738N"
|
|
64
|
+
lat, lon = rustmap3d.ll2dms(25.37909389, -138.7895679) #> "25:22:44.738N", "138:47:22.444W"
|
|
65
|
+
...
|
|
66
|
+
|
|
67
|
+
# distance functions
|
|
68
|
+
lat, lon = rustmap3d.vincenty_direct(lat_deg, lon_deg, range_m, bearing_deg)
|
|
69
|
+
range_m, bearing_ab, bearing_ba = rustmap3d.vincenty_inverse(lat_a, lon_a, lat_b, lon_b)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Comparison with similar packages
|
|
73
|
+
|
|
74
|
+
- 🚀🚀 Blazingly fast - written in rust (see [benchmarks](#benchmarks))
|
|
75
|
+
- Zero dependencies
|
|
76
|
+
- Dead simple api modeled after [pymap3d](https://github.com/geospace-code/pymap3d) and [matlab](https://www.mathworks.com/matlabcentral/fileexchange/15285-geodetic-toolbox)
|
|
77
|
+
- Exposes rotations (both quaternions and 3x3 matrices)
|
|
78
|
+
|
|
79
|
+
## Benchmarks
|
|
80
|
+
|
|
81
|
+
Compared to [pymap3d](https://github.com/geospace-code/pymap3d)
|
|
82
|
+
> Note: This is comparing single calls of python floats, not vectorized numpy performance. Vectorized batched conversions will be implemented in the future
|
|
83
|
+
|
|
84
|
+
- *~50x* faster for lla2ecef
|
|
85
|
+
- *~400x* faster for ecef2lla
|
|
86
|
+
|
|
87
|
+
<p align="center"><img src="docs/benchmarks.svg"></p>
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
# Run benchmarks
|
|
91
|
+
uv run pytest --benchmark-histogram="./docs/benchmarks" bench/
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Build From Source
|
|
95
|
+
|
|
96
|
+
Uses standard [maturin](https://github.com/PyO3/maturin) build process
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
uv run maturin build -r # build a whl
|
|
100
|
+
uv run maturin dev -r # build a dev package similar to -e
|
|
101
|
+
```
|
|
102
|
+
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
rustmap3d/__init__.py,sha256=3KvRU840onBHW4lM0rI1gngSINaQf2XjWebzsEnLULo,119
|
|
2
|
+
rustmap3d/__init__.pyi,sha256=4VKlAGbeyYr2EYv0sVZBQk-wBYEDR0dUdNkBbZIPqZQ,22918
|
|
3
|
+
rustmap3d/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
rustmap3d/rustmap3d.cp314-win_amd64.pyd,sha256=G6FY4VEBR1KRFsmWJ02uN8ILirOfx5BpDybm713j1og,1792000
|
|
5
|
+
rustmap3d-0.2.3.dist-info/METADATA,sha256=tjFxvGNw7IA3zd2gFDcFQviGMhiRjTCu9U7Skg0BtgY,3429
|
|
6
|
+
rustmap3d-0.2.3.dist-info/WHEEL,sha256=TASrtxyeL-Pi7odwPBMCgR1YebCHdBFZvgqiADG_4b0,97
|
|
7
|
+
rustmap3d-0.2.3.dist-info/licenses/LICENSE,sha256=nPus_5ylrEEVZWLoXU2-Sz5VWnp4BPaNUt0bP2FY52o,1070
|
|
8
|
+
rustmap3d-0.2.3.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) [2025] [rustmap3d]
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|