/src/h3/src/h3lib/include/vec3d.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright 2018, 2020-2021, 2026 Uber Technologies, Inc. |
3 | | * |
4 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | | * you may not use this file except in compliance with the License. |
6 | | * You may obtain a copy of the License at |
7 | | * |
8 | | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | | * |
10 | | * Unless required by applicable law or agreed to in writing, software |
11 | | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | * See the License for the specific language governing permissions and |
14 | | * limitations under the License. |
15 | | */ |
16 | | /** @file vec3d.h |
17 | | * @brief 3D floating point vector functions. |
18 | | * |
19 | | * Header-only (static inline) so callers in other translation units |
20 | | * can inline these without requiring LTO. |
21 | | */ |
22 | | |
23 | | #ifndef VEC3D_H |
24 | | #define VEC3D_H |
25 | | |
26 | | #include <math.h> |
27 | | |
28 | | #include "h3api.h" |
29 | | #include "latLng.h" |
30 | | |
31 | | /** @struct Vec3d |
32 | | * @brief 3D floating point structure |
33 | | * |
34 | | * For geodesic calculations represents a point on the surface of the Earth |
35 | | * as a unit vector in 3D Cartesian space (ECEF-like coordinates). |
36 | | */ |
37 | | typedef struct { |
38 | | double x; /// towards 0deg lat, 0deg lon |
39 | | double y; /// towards 0deg lat, 90deg lon |
40 | | double z; /// towards north pole |
41 | | } Vec3d; |
42 | | |
43 | | /** Convert latitude and longitude to a unit Vec3d on the sphere. */ |
44 | 0 | static inline Vec3d latLngToVec3(LatLng geo) { |
45 | 0 | double r = cos(geo.lat); |
46 | 0 | Vec3d out = { |
47 | 0 | .x = cos(geo.lng) * r, |
48 | 0 | .y = sin(geo.lng) * r, |
49 | 0 | .z = sin(geo.lat), |
50 | 0 | }; |
51 | 0 | return out; |
52 | 0 | } Unexecuted instantiation: algos.c:latLngToVec3 Unexecuted instantiation: bbox.c:latLngToVec3 Unexecuted instantiation: h3Index.c:latLngToVec3 Unexecuted instantiation: vertex.c:latLngToVec3 Unexecuted instantiation: directedEdge.c:latLngToVec3 Unexecuted instantiation: iterators.c:latLngToVec3 Unexecuted instantiation: faceijk.c:latLngToVec3 Unexecuted instantiation: baseCells.c:latLngToVec3 |
53 | | |
54 | 0 | static inline LatLng vec3ToLatLng(Vec3d v) { |
55 | 0 | LatLng out = { |
56 | 0 | .lat = asin(v.z), |
57 | 0 | .lng = atan2(v.y, v.x), |
58 | 0 | }; |
59 | 0 | return out; |
60 | 0 | } Unexecuted instantiation: algos.c:vec3ToLatLng Unexecuted instantiation: bbox.c:vec3ToLatLng Unexecuted instantiation: h3Index.c:vec3ToLatLng Unexecuted instantiation: vertex.c:vec3ToLatLng Unexecuted instantiation: directedEdge.c:vec3ToLatLng Unexecuted instantiation: iterators.c:vec3ToLatLng Unexecuted instantiation: faceijk.c:vec3ToLatLng Unexecuted instantiation: baseCells.c:vec3ToLatLng |
61 | | |
62 | 0 | static inline Vec3d vec3LinComb(double a, Vec3d v1, double b, Vec3d v2) { |
63 | 0 | Vec3d out = { |
64 | 0 | .x = a * v1.x + b * v2.x, |
65 | 0 | .y = a * v1.y + b * v2.y, |
66 | 0 | .z = a * v1.z + b * v2.z, |
67 | 0 | }; |
68 | 0 | return out; |
69 | 0 | } Unexecuted instantiation: algos.c:vec3LinComb Unexecuted instantiation: bbox.c:vec3LinComb Unexecuted instantiation: h3Index.c:vec3LinComb Unexecuted instantiation: vertex.c:vec3LinComb Unexecuted instantiation: directedEdge.c:vec3LinComb Unexecuted instantiation: iterators.c:vec3LinComb Unexecuted instantiation: faceijk.c:vec3LinComb Unexecuted instantiation: baseCells.c:vec3LinComb |
70 | | |
71 | 0 | static inline Vec3d vec3Cross(Vec3d v1, Vec3d v2) { |
72 | 0 | Vec3d out = { |
73 | 0 | .x = v1.y * v2.z - v1.z * v2.y, |
74 | 0 | .y = v1.z * v2.x - v1.x * v2.z, |
75 | 0 | .z = v1.x * v2.y - v1.y * v2.x, |
76 | 0 | }; |
77 | 0 | return out; |
78 | 0 | } Unexecuted instantiation: algos.c:vec3Cross Unexecuted instantiation: bbox.c:vec3Cross Unexecuted instantiation: h3Index.c:vec3Cross Unexecuted instantiation: vertex.c:vec3Cross Unexecuted instantiation: directedEdge.c:vec3Cross Unexecuted instantiation: iterators.c:vec3Cross Unexecuted instantiation: faceijk.c:vec3Cross Unexecuted instantiation: baseCells.c:vec3Cross |
79 | | |
80 | 0 | static inline double vec3Dot(Vec3d v1, Vec3d v2) { |
81 | 0 | return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; |
82 | 0 | } Unexecuted instantiation: algos.c:vec3Dot Unexecuted instantiation: bbox.c:vec3Dot Unexecuted instantiation: h3Index.c:vec3Dot Unexecuted instantiation: vertex.c:vec3Dot Unexecuted instantiation: directedEdge.c:vec3Dot Unexecuted instantiation: iterators.c:vec3Dot Unexecuted instantiation: faceijk.c:vec3Dot Unexecuted instantiation: baseCells.c:vec3Dot |
83 | | |
84 | 0 | static inline double vec3NormSq(Vec3d v) { return vec3Dot(v, v); }Unexecuted instantiation: algos.c:vec3NormSq Unexecuted instantiation: bbox.c:vec3NormSq Unexecuted instantiation: h3Index.c:vec3NormSq Unexecuted instantiation: vertex.c:vec3NormSq Unexecuted instantiation: directedEdge.c:vec3NormSq Unexecuted instantiation: iterators.c:vec3NormSq Unexecuted instantiation: faceijk.c:vec3NormSq Unexecuted instantiation: baseCells.c:vec3NormSq |
85 | | |
86 | 0 | static inline double vec3Norm(Vec3d v) { return sqrt(vec3NormSq(v)); }Unexecuted instantiation: algos.c:vec3Norm Unexecuted instantiation: bbox.c:vec3Norm Unexecuted instantiation: h3Index.c:vec3Norm Unexecuted instantiation: vertex.c:vec3Norm Unexecuted instantiation: directedEdge.c:vec3Norm Unexecuted instantiation: iterators.c:vec3Norm Unexecuted instantiation: faceijk.c:vec3Norm Unexecuted instantiation: baseCells.c:vec3Norm |
87 | | |
88 | 0 | static inline void vec3Normalize(Vec3d *v) { |
89 | 0 | double norm = vec3Norm(*v); |
90 | | |
91 | | // Norm can be zero either from true zero vector, or from squaring |
92 | | // underflowing to zero. |
93 | | // If the norm is nonzero, we normalize v using it. |
94 | | // If the norm is zero, we set the vector to be exactly zero. |
95 | 0 | double s = 0.0; |
96 | 0 | if (norm > 0.0) { |
97 | 0 | s = 1.0 / norm; |
98 | 0 | } |
99 | |
|
100 | 0 | v->x *= s; |
101 | 0 | v->y *= s; |
102 | 0 | v->z *= s; |
103 | 0 | } Unexecuted instantiation: algos.c:vec3Normalize Unexecuted instantiation: bbox.c:vec3Normalize Unexecuted instantiation: h3Index.c:vec3Normalize Unexecuted instantiation: vertex.c:vec3Normalize Unexecuted instantiation: directedEdge.c:vec3Normalize Unexecuted instantiation: iterators.c:vec3Normalize Unexecuted instantiation: faceijk.c:vec3Normalize Unexecuted instantiation: baseCells.c:vec3Normalize |
104 | | |
105 | 0 | static inline double vec3DistSq(Vec3d v1, Vec3d v2) { |
106 | 0 | Vec3d d = vec3LinComb(1.0, v1, -1.0, v2); |
107 | 0 | return vec3NormSq(d); |
108 | 0 | } Unexecuted instantiation: algos.c:vec3DistSq Unexecuted instantiation: bbox.c:vec3DistSq Unexecuted instantiation: h3Index.c:vec3DistSq Unexecuted instantiation: vertex.c:vec3DistSq Unexecuted instantiation: directedEdge.c:vec3DistSq Unexecuted instantiation: iterators.c:vec3DistSq Unexecuted instantiation: faceijk.c:vec3DistSq Unexecuted instantiation: baseCells.c:vec3DistSq |
109 | | |
110 | | #endif |