/src/h3/src/h3lib/include/coordijk.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright 2016-2018, 2020-2022, 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 coordijk.h |
17 | | * @brief Header-only implementation of CoordIJK functions including |
18 | | * conversion from lat/lng. |
19 | | * |
20 | | * References two Vec2d cartesian coordinate systems: |
21 | | * |
22 | | * 1. gnomonic: face-centered polyhedral gnomonic projection space with |
23 | | * traditional scaling and x-axes aligned with the face Class II |
24 | | * i-axes. |
25 | | * |
26 | | * 2. hex2d: local face-centered coordinate system scaled a specific H3 grid |
27 | | * resolution unit length and with x-axes aligned with the local |
28 | | * i-axes |
29 | | */ |
30 | | |
31 | | #ifndef COORDIJK_H |
32 | | #define COORDIJK_H |
33 | | |
34 | | #include <math.h> |
35 | | #include <stdlib.h> |
36 | | |
37 | | #include "constants.h" |
38 | | #include "h3Assert.h" |
39 | | #include "h3api.h" |
40 | | #include "mathExtensions.h" |
41 | | #include "vec2d.h" |
42 | | |
43 | | /** @struct CoordIJK |
44 | | * @brief IJK hexagon coordinates |
45 | | * |
46 | | * Each axis is spaced 120 degrees apart. |
47 | | */ |
48 | | typedef struct { |
49 | | int i; ///< i component |
50 | | int j; ///< j component |
51 | | int k; ///< k component |
52 | | } CoordIJK; |
53 | | |
54 | | /** @brief CoordIJK unit vectors corresponding to the 7 H3 digits. |
55 | | */ |
56 | | static const CoordIJK UNIT_VECS[] = { |
57 | | {0, 0, 0}, // direction 0 |
58 | | {0, 0, 1}, // direction 1 |
59 | | {0, 1, 0}, // direction 2 |
60 | | {0, 1, 1}, // direction 3 |
61 | | {1, 0, 0}, // direction 4 |
62 | | {1, 0, 1}, // direction 5 |
63 | | {1, 1, 0} // direction 6 |
64 | | }; |
65 | | |
66 | | /** @brief H3 digit representing ijk+ axes direction. |
67 | | * Values will be within the lowest 3 bits of an integer. |
68 | | */ |
69 | | typedef enum { |
70 | | /** H3 digit in center */ |
71 | | CENTER_DIGIT = 0, |
72 | | /** H3 digit in k-axes direction */ |
73 | | K_AXES_DIGIT = 1, |
74 | | /** H3 digit in j-axes direction */ |
75 | | J_AXES_DIGIT = 2, |
76 | | /** H3 digit in j == k direction */ |
77 | | JK_AXES_DIGIT = J_AXES_DIGIT | K_AXES_DIGIT, /* 3 */ |
78 | | /** H3 digit in i-axes direction */ |
79 | | I_AXES_DIGIT = 4, |
80 | | /** H3 digit in i == k direction */ |
81 | | IK_AXES_DIGIT = I_AXES_DIGIT | K_AXES_DIGIT, /* 5 */ |
82 | | /** H3 digit in i == j direction */ |
83 | | IJ_AXES_DIGIT = I_AXES_DIGIT | J_AXES_DIGIT, /* 6 */ |
84 | | /** H3 digit in the invalid direction */ |
85 | | INVALID_DIGIT = 7, |
86 | | /** Valid digits will be less than this value. Same value as INVALID_DIGIT. |
87 | | */ |
88 | | NUM_DIGITS = INVALID_DIGIT, |
89 | | /** Child digit which is skipped for pentagons */ |
90 | | PENTAGON_SKIPPED_DIGIT = K_AXES_DIGIT /* 1 */ |
91 | | } Direction; |
92 | | |
93 | | #define INT32_MAX_3 (INT32_MAX / 3) |
94 | | |
95 | | /** |
96 | | * Sets an IJK coordinate to the specified component values. |
97 | | * |
98 | | * @param ijk The IJK coordinate to set. |
99 | | * @param i The desired i component value. |
100 | | * @param j The desired j component value. |
101 | | * @param k The desired k component value. |
102 | | */ |
103 | 106 | static inline void _setIJK(CoordIJK *ijk, int i, int j, int k) { |
104 | 106 | ijk->i = i; |
105 | 106 | ijk->j = j; |
106 | 106 | ijk->k = k; |
107 | 106 | } Unexecuted instantiation: fuzzerDirectedEdge.c:_setIJK Unexecuted instantiation: directedEdge.c:_setIJK Line | Count | Source | 103 | 106 | static inline void _setIJK(CoordIJK *ijk, int i, int j, int k) { | 104 | 106 | ijk->i = i; | 105 | 106 | ijk->j = j; | 106 | 106 | ijk->k = k; | 107 | 106 | } |
Unexecuted instantiation: algos.c:_setIJK Unexecuted instantiation: bbox.c:_setIJK Unexecuted instantiation: h3Index.c:_setIJK Unexecuted instantiation: vertex.c:_setIJK Unexecuted instantiation: iterators.c:_setIJK Unexecuted instantiation: baseCells.c:_setIJK Unexecuted instantiation: cellsToMultiPoly.c:_setIJK |
108 | | |
109 | | /** |
110 | | * Returns whether or not two ijk coordinates contain exactly the same |
111 | | * component values. |
112 | | * |
113 | | * @param c1 The first set of ijk coordinates. |
114 | | * @param c2 The second set of ijk coordinates. |
115 | | * @return 1 if the two addresses match, 0 if they do not. |
116 | | */ |
117 | 0 | static inline int _ijkMatches(const CoordIJK *c1, const CoordIJK *c2) { |
118 | 0 | return (c1->i == c2->i && c1->j == c2->j && c1->k == c2->k); |
119 | 0 | } Unexecuted instantiation: fuzzerDirectedEdge.c:_ijkMatches Unexecuted instantiation: directedEdge.c:_ijkMatches Unexecuted instantiation: faceijk.c:_ijkMatches Unexecuted instantiation: algos.c:_ijkMatches Unexecuted instantiation: bbox.c:_ijkMatches Unexecuted instantiation: h3Index.c:_ijkMatches Unexecuted instantiation: vertex.c:_ijkMatches Unexecuted instantiation: iterators.c:_ijkMatches Unexecuted instantiation: baseCells.c:_ijkMatches Unexecuted instantiation: cellsToMultiPoly.c:_ijkMatches |
120 | | |
121 | | /** |
122 | | * Add two ijk coordinates. |
123 | | * |
124 | | * @param h1 The first set of ijk coordinates. |
125 | | * @param h2 The second set of ijk coordinates. |
126 | | * @param sum The sum of the two sets of ijk coordinates. |
127 | | */ |
128 | | static inline void _ijkAdd(const CoordIJK *h1, const CoordIJK *h2, |
129 | 34.2k | CoordIJK *sum) { |
130 | 34.2k | sum->i = h1->i + h2->i; |
131 | 34.2k | sum->j = h1->j + h2->j; |
132 | 34.2k | sum->k = h1->k + h2->k; |
133 | 34.2k | } Unexecuted instantiation: fuzzerDirectedEdge.c:_ijkAdd Unexecuted instantiation: directedEdge.c:_ijkAdd Line | Count | Source | 129 | 11.5k | CoordIJK *sum) { | 130 | 11.5k | sum->i = h1->i + h2->i; | 131 | 11.5k | sum->j = h1->j + h2->j; | 132 | 11.5k | sum->k = h1->k + h2->k; | 133 | 11.5k | } |
Unexecuted instantiation: algos.c:_ijkAdd Unexecuted instantiation: bbox.c:_ijkAdd Line | Count | Source | 129 | 22.6k | CoordIJK *sum) { | 130 | 22.6k | sum->i = h1->i + h2->i; | 131 | 22.6k | sum->j = h1->j + h2->j; | 132 | 22.6k | sum->k = h1->k + h2->k; | 133 | 22.6k | } |
Unexecuted instantiation: vertex.c:_ijkAdd Unexecuted instantiation: iterators.c:_ijkAdd Unexecuted instantiation: baseCells.c:_ijkAdd Unexecuted instantiation: cellsToMultiPoly.c:_ijkAdd |
134 | | |
135 | | /** |
136 | | * Subtract two ijk coordinates. |
137 | | * |
138 | | * @param h1 The first set of ijk coordinates. |
139 | | * @param h2 The second set of ijk coordinates. |
140 | | * @param diff The difference of the two sets of ijk coordinates (h1 - h2). |
141 | | */ |
142 | | static inline void _ijkSub(const CoordIJK *h1, const CoordIJK *h2, |
143 | 106 | CoordIJK *diff) { |
144 | 106 | diff->i = h1->i - h2->i; |
145 | 106 | diff->j = h1->j - h2->j; |
146 | 106 | diff->k = h1->k - h2->k; |
147 | 106 | } Unexecuted instantiation: fuzzerDirectedEdge.c:_ijkSub Unexecuted instantiation: directedEdge.c:_ijkSub Line | Count | Source | 143 | 106 | CoordIJK *diff) { | 144 | 106 | diff->i = h1->i - h2->i; | 145 | 106 | diff->j = h1->j - h2->j; | 146 | 106 | diff->k = h1->k - h2->k; | 147 | 106 | } |
Unexecuted instantiation: algos.c:_ijkSub Unexecuted instantiation: bbox.c:_ijkSub Unexecuted instantiation: h3Index.c:_ijkSub Unexecuted instantiation: vertex.c:_ijkSub Unexecuted instantiation: iterators.c:_ijkSub Unexecuted instantiation: baseCells.c:_ijkSub Unexecuted instantiation: cellsToMultiPoly.c:_ijkSub |
148 | | |
149 | | /** |
150 | | * Uniformly scale ijk coordinates by a scalar. Works in place. |
151 | | * |
152 | | * @param c The ijk coordinates to scale. |
153 | | * @param factor The scaling factor. |
154 | | */ |
155 | 39.4k | static inline void _ijkScale(CoordIJK *c, int factor) { |
156 | 39.4k | c->i *= factor; |
157 | 39.4k | c->j *= factor; |
158 | 39.4k | c->k *= factor; |
159 | 39.4k | } Unexecuted instantiation: fuzzerDirectedEdge.c:_ijkScale Unexecuted instantiation: directedEdge.c:_ijkScale Line | Count | Source | 155 | 13.2k | static inline void _ijkScale(CoordIJK *c, int factor) { | 156 | 13.2k | c->i *= factor; | 157 | 13.2k | c->j *= factor; | 158 | 13.2k | c->k *= factor; | 159 | 13.2k | } |
Unexecuted instantiation: algos.c:_ijkScale Unexecuted instantiation: bbox.c:_ijkScale Line | Count | Source | 155 | 26.2k | static inline void _ijkScale(CoordIJK *c, int factor) { | 156 | 26.2k | c->i *= factor; | 157 | 26.2k | c->j *= factor; | 158 | 26.2k | c->k *= factor; | 159 | 26.2k | } |
Unexecuted instantiation: vertex.c:_ijkScale Unexecuted instantiation: iterators.c:_ijkScale Unexecuted instantiation: baseCells.c:_ijkScale Unexecuted instantiation: cellsToMultiPoly.c:_ijkScale |
160 | | |
161 | | /** |
162 | | * Returns true if _ijkNormalize with the given input could have a signed |
163 | | * integer overflow. Assumes k is set to 0. |
164 | | */ |
165 | 0 | static inline bool _ijkNormalizeCouldOverflow(const CoordIJK *ijk) { |
166 | 0 | // Check for the possibility of overflow |
167 | 0 | int max, min; |
168 | 0 | if (ijk->i > ijk->j) { |
169 | 0 | max = ijk->i; |
170 | 0 | min = ijk->j; |
171 | 0 | } else { |
172 | 0 | max = ijk->j; |
173 | 0 | min = ijk->i; |
174 | 0 | } |
175 | 0 | if (min < 0) { |
176 | 0 | // Only if the min is less than 0 will the resulting number be larger |
177 | 0 | // than max. If min is positive, then max is also positive, and a |
178 | 0 | // positive signed integer minus another positive signed integer will |
179 | 0 | // not overflow. |
180 | 0 | if (ADD_INT32S_OVERFLOWS(max, min)) { |
181 | 0 | // max + min would overflow |
182 | 0 | return true; |
183 | 0 | } |
184 | 0 | if (SUB_INT32S_OVERFLOWS(0, min)) { |
185 | 0 | // 0 - INT32_MIN would overflow |
186 | 0 | return true; |
187 | 0 | } |
188 | 0 | if (SUB_INT32S_OVERFLOWS(max, min)) { |
189 | 0 | // max - min would overflow |
190 | 0 | return true; |
191 | 0 | } |
192 | 0 | } |
193 | 0 | return false; |
194 | 0 | } Unexecuted instantiation: fuzzerDirectedEdge.c:_ijkNormalizeCouldOverflow Unexecuted instantiation: directedEdge.c:_ijkNormalizeCouldOverflow Unexecuted instantiation: faceijk.c:_ijkNormalizeCouldOverflow Unexecuted instantiation: algos.c:_ijkNormalizeCouldOverflow Unexecuted instantiation: bbox.c:_ijkNormalizeCouldOverflow Unexecuted instantiation: h3Index.c:_ijkNormalizeCouldOverflow Unexecuted instantiation: vertex.c:_ijkNormalizeCouldOverflow Unexecuted instantiation: iterators.c:_ijkNormalizeCouldOverflow Unexecuted instantiation: baseCells.c:_ijkNormalizeCouldOverflow Unexecuted instantiation: cellsToMultiPoly.c:_ijkNormalizeCouldOverflow |
195 | | |
196 | | /** |
197 | | * Normalizes ijk coordinates by setting the components to the smallest possible |
198 | | * values. Works in place. |
199 | | * |
200 | | * This function does not protect against signed integer overflow. The caller |
201 | | * must ensure that none of (i - j), (i - k), (j - i), (j - k), (k - i), (k - |
202 | | * j) will overflow. This function may be changed in the future to make that |
203 | | * check itself and return an error code. |
204 | | * |
205 | | * @param c The ijk coordinates to normalize. |
206 | | */ |
207 | 21.7k | static inline void _ijkNormalize(CoordIJK *c) { |
208 | | // remove any negative values |
209 | 21.7k | if (c->i < 0) { |
210 | 180 | c->j -= c->i; |
211 | 180 | c->k -= c->i; |
212 | 180 | c->i = 0; |
213 | 180 | } |
214 | | |
215 | 21.7k | if (c->j < 0) { |
216 | 120 | c->i -= c->j; |
217 | 120 | c->k -= c->j; |
218 | 120 | c->j = 0; |
219 | 120 | } |
220 | | |
221 | 21.7k | if (c->k < 0) { |
222 | 0 | c->i -= c->k; |
223 | 0 | c->j -= c->k; |
224 | 0 | c->k = 0; |
225 | 0 | } |
226 | | |
227 | | // remove the min value if needed |
228 | 21.7k | int min = c->i; |
229 | 21.7k | if (c->j < min) min = c->j; |
230 | 21.7k | if (c->k < min) min = c->k; |
231 | 21.7k | if (min > 0) { |
232 | 16.3k | c->i -= min; |
233 | 16.3k | c->j -= min; |
234 | 16.3k | c->k -= min; |
235 | 16.3k | } |
236 | 21.7k | } Unexecuted instantiation: fuzzerDirectedEdge.c:_ijkNormalize Unexecuted instantiation: directedEdge.c:_ijkNormalize Line | Count | Source | 207 | 7.30k | static inline void _ijkNormalize(CoordIJK *c) { | 208 | | // remove any negative values | 209 | 7.30k | if (c->i < 0) { | 210 | 0 | c->j -= c->i; | 211 | 0 | c->k -= c->i; | 212 | 0 | c->i = 0; | 213 | 0 | } | 214 | | | 215 | 7.30k | if (c->j < 0) { | 216 | 0 | c->i -= c->j; | 217 | 0 | c->k -= c->j; | 218 | 0 | c->j = 0; | 219 | 0 | } | 220 | | | 221 | 7.30k | if (c->k < 0) { | 222 | 0 | c->i -= c->k; | 223 | 0 | c->j -= c->k; | 224 | 0 | c->k = 0; | 225 | 0 | } | 226 | | | 227 | | // remove the min value if needed | 228 | 7.30k | int min = c->i; | 229 | 7.30k | if (c->j < min) min = c->j; | 230 | 7.30k | if (c->k < min) min = c->k; | 231 | 7.30k | if (min > 0) { | 232 | 6.39k | c->i -= min; | 233 | 6.39k | c->j -= min; | 234 | 6.39k | c->k -= min; | 235 | 6.39k | } | 236 | 7.30k | } |
Unexecuted instantiation: algos.c:_ijkNormalize Unexecuted instantiation: bbox.c:_ijkNormalize Line | Count | Source | 207 | 14.4k | static inline void _ijkNormalize(CoordIJK *c) { | 208 | | // remove any negative values | 209 | 14.4k | if (c->i < 0) { | 210 | 180 | c->j -= c->i; | 211 | 180 | c->k -= c->i; | 212 | 180 | c->i = 0; | 213 | 180 | } | 214 | | | 215 | 14.4k | if (c->j < 0) { | 216 | 120 | c->i -= c->j; | 217 | 120 | c->k -= c->j; | 218 | 120 | c->j = 0; | 219 | 120 | } | 220 | | | 221 | 14.4k | if (c->k < 0) { | 222 | 0 | c->i -= c->k; | 223 | 0 | c->j -= c->k; | 224 | 0 | c->k = 0; | 225 | 0 | } | 226 | | | 227 | | // remove the min value if needed | 228 | 14.4k | int min = c->i; | 229 | 14.4k | if (c->j < min) min = c->j; | 230 | 14.4k | if (c->k < min) min = c->k; | 231 | 14.4k | if (min > 0) { | 232 | 9.94k | c->i -= min; | 233 | 9.94k | c->j -= min; | 234 | 9.94k | c->k -= min; | 235 | 9.94k | } | 236 | 14.4k | } |
Unexecuted instantiation: vertex.c:_ijkNormalize Unexecuted instantiation: iterators.c:_ijkNormalize Unexecuted instantiation: baseCells.c:_ijkNormalize Unexecuted instantiation: cellsToMultiPoly.c:_ijkNormalize |
237 | | |
238 | | /** |
239 | | * Find the center point in 2D cartesian coordinates of a hex. |
240 | | * |
241 | | * @param h The ijk coordinates of the hex. |
242 | | * @param v The 2D cartesian coordinates of the hex center point. |
243 | | */ |
244 | 824 | static inline void _ijkToHex2d(const CoordIJK *h, Vec2d *v) { |
245 | 824 | int i = h->i - h->k; |
246 | 824 | int j = h->j - h->k; |
247 | | |
248 | 824 | v->x = i - 0.5 * j; |
249 | 824 | v->y = j * M_SQRT3_2; |
250 | 824 | } Unexecuted instantiation: fuzzerDirectedEdge.c:_ijkToHex2d Unexecuted instantiation: directedEdge.c:_ijkToHex2d Line | Count | Source | 244 | 824 | static inline void _ijkToHex2d(const CoordIJK *h, Vec2d *v) { | 245 | 824 | int i = h->i - h->k; | 246 | 824 | int j = h->j - h->k; | 247 | | | 248 | 824 | v->x = i - 0.5 * j; | 249 | 824 | v->y = j * M_SQRT3_2; | 250 | 824 | } |
Unexecuted instantiation: algos.c:_ijkToHex2d Unexecuted instantiation: bbox.c:_ijkToHex2d Unexecuted instantiation: h3Index.c:_ijkToHex2d Unexecuted instantiation: vertex.c:_ijkToHex2d Unexecuted instantiation: iterators.c:_ijkToHex2d Unexecuted instantiation: baseCells.c:_ijkToHex2d Unexecuted instantiation: cellsToMultiPoly.c:_ijkToHex2d |
251 | | |
252 | | /** |
253 | | * Determine the containing hex in ijk+ coordinates for a 2D cartesian |
254 | | * coordinate vector (from DGGRID). |
255 | | * |
256 | | * @param v The 2D cartesian coordinate vector. |
257 | | * @param h The ijk+ coordinates of the containing hex. |
258 | | */ |
259 | 0 | static inline void _hex2dToCoordIJK(const Vec2d *v, CoordIJK *h) { |
260 | 0 | double a1, a2; |
261 | 0 | double x1, x2; |
262 | 0 | int m1, m2; |
263 | 0 | double r1, r2; |
264 | | |
265 | | // quantize into the ij system and then normalize |
266 | 0 | h->k = 0; |
267 | |
|
268 | 0 | a1 = fabsl(v->x); |
269 | 0 | a2 = fabsl(v->y); |
270 | | |
271 | | // first do a reverse conversion |
272 | 0 | x2 = a2 * M_RSIN60; |
273 | 0 | x1 = a1 + x2 / 2.0; |
274 | | |
275 | | // check if we have the center of a hex |
276 | 0 | m1 = (int)x1; |
277 | 0 | m2 = (int)x2; |
278 | | |
279 | | // otherwise round correctly |
280 | 0 | r1 = x1 - m1; |
281 | 0 | r2 = x2 - m2; |
282 | |
|
283 | 0 | if (r1 < 0.5) { |
284 | 0 | if (r1 < 1.0 / 3.0) { |
285 | 0 | if (r2 < (1.0 + r1) / 2.0) { |
286 | 0 | h->i = m1; |
287 | 0 | h->j = m2; |
288 | 0 | } else { |
289 | 0 | h->i = m1; |
290 | 0 | h->j = m2 + 1; |
291 | 0 | } |
292 | 0 | } else { |
293 | 0 | if (r2 < (1.0 - r1)) { |
294 | 0 | h->j = m2; |
295 | 0 | } else { |
296 | 0 | h->j = m2 + 1; |
297 | 0 | } |
298 | |
|
299 | 0 | if ((1.0 - r1) <= r2 && r2 < (2.0 * r1)) { |
300 | 0 | h->i = m1 + 1; |
301 | 0 | } else { |
302 | 0 | h->i = m1; |
303 | 0 | } |
304 | 0 | } |
305 | 0 | } else { |
306 | 0 | if (r1 < 2.0 / 3.0) { |
307 | 0 | if (r2 < (1.0 - r1)) { |
308 | 0 | h->j = m2; |
309 | 0 | } else { |
310 | 0 | h->j = m2 + 1; |
311 | 0 | } |
312 | |
|
313 | 0 | if ((2.0 * r1 - 1.0) < r2 && r2 < (1.0 - r1)) { |
314 | 0 | h->i = m1; |
315 | 0 | } else { |
316 | 0 | h->i = m1 + 1; |
317 | 0 | } |
318 | 0 | } else { |
319 | 0 | if (r2 < (r1 / 2.0)) { |
320 | 0 | h->i = m1 + 1; |
321 | 0 | h->j = m2; |
322 | 0 | } else { |
323 | 0 | h->i = m1 + 1; |
324 | 0 | h->j = m2 + 1; |
325 | 0 | } |
326 | 0 | } |
327 | 0 | } |
328 | | |
329 | | // now fold across the axes if necessary |
330 | |
|
331 | 0 | if (v->x < 0.0) { |
332 | 0 | if ((h->j % 2) == 0) // even |
333 | 0 | { |
334 | 0 | long long int axisi = h->j / 2; |
335 | 0 | long long int diff = h->i - axisi; |
336 | 0 | h->i = (int)(h->i - 2.0 * diff); |
337 | 0 | } else { |
338 | 0 | long long int axisi = (h->j + 1) / 2; |
339 | 0 | long long int diff = h->i - axisi; |
340 | 0 | h->i = (int)(h->i - (2.0 * diff + 1)); |
341 | 0 | } |
342 | 0 | } |
343 | |
|
344 | 0 | if (v->y < 0.0) { |
345 | 0 | h->i = h->i - (2 * h->j + 1) / 2; |
346 | 0 | h->j = -1 * h->j; |
347 | 0 | } |
348 | |
|
349 | 0 | _ijkNormalize(h); |
350 | 0 | } Unexecuted instantiation: fuzzerDirectedEdge.c:_hex2dToCoordIJK Unexecuted instantiation: directedEdge.c:_hex2dToCoordIJK Unexecuted instantiation: faceijk.c:_hex2dToCoordIJK Unexecuted instantiation: algos.c:_hex2dToCoordIJK Unexecuted instantiation: bbox.c:_hex2dToCoordIJK Unexecuted instantiation: h3Index.c:_hex2dToCoordIJK Unexecuted instantiation: vertex.c:_hex2dToCoordIJK Unexecuted instantiation: iterators.c:_hex2dToCoordIJK Unexecuted instantiation: baseCells.c:_hex2dToCoordIJK Unexecuted instantiation: cellsToMultiPoly.c:_hex2dToCoordIJK |
351 | | |
352 | | /** |
353 | | * Determines the H3 digit corresponding to a unit vector or the zero vector |
354 | | * in ijk coordinates. |
355 | | * |
356 | | * @param ijk The ijk coordinates; must be a unit vector or zero vector. |
357 | | * @return The H3 digit (0-6) corresponding to the ijk unit vector, zero |
358 | | * vector, or INVALID_DIGIT (7) on failure. |
359 | | */ |
360 | 0 | static inline Direction _unitIjkToDigit(const CoordIJK *ijk) { |
361 | 0 | CoordIJK c = *ijk; |
362 | 0 | _ijkNormalize(&c); |
363 | |
|
364 | 0 | Direction digit = INVALID_DIGIT; |
365 | 0 | for (Direction i = CENTER_DIGIT; i < NUM_DIGITS; i++) { |
366 | 0 | if (_ijkMatches(&c, &UNIT_VECS[i])) { |
367 | 0 | digit = i; |
368 | 0 | break; |
369 | 0 | } |
370 | 0 | } |
371 | |
|
372 | 0 | return digit; |
373 | 0 | } Unexecuted instantiation: fuzzerDirectedEdge.c:_unitIjkToDigit Unexecuted instantiation: directedEdge.c:_unitIjkToDigit Unexecuted instantiation: faceijk.c:_unitIjkToDigit Unexecuted instantiation: algos.c:_unitIjkToDigit Unexecuted instantiation: bbox.c:_unitIjkToDigit Unexecuted instantiation: h3Index.c:_unitIjkToDigit Unexecuted instantiation: vertex.c:_unitIjkToDigit Unexecuted instantiation: iterators.c:_unitIjkToDigit Unexecuted instantiation: baseCells.c:_unitIjkToDigit Unexecuted instantiation: cellsToMultiPoly.c:_unitIjkToDigit |
374 | | |
375 | | /** |
376 | | * Returns non-zero if _upAp7 with the given input could have a signed integer |
377 | | * overflow. |
378 | | * |
379 | | * Assumes ijk is IJK+ coordinates (no negative numbers). |
380 | | */ |
381 | 0 | static inline H3Error _upAp7Checked(CoordIJK *ijk) { |
382 | 0 | // Doesn't need to be checked because i, j, and k must all be non-negative |
383 | 0 | int i = ijk->i - ijk->k; |
384 | 0 | int j = ijk->j - ijk->k; |
385 | 0 |
|
386 | 0 | // <0 is checked because the input must all be non-negative, but some |
387 | 0 | // negative inputs are used in unit tests to exercise the below. |
388 | 0 | if (i >= INT32_MAX_3 || j >= INT32_MAX_3 || i < 0 || j < 0) { |
389 | 0 | if (ADD_INT32S_OVERFLOWS(i, i)) { |
390 | 0 | return E_FAILED; |
391 | 0 | } |
392 | 0 | int i2 = i + i; |
393 | 0 | if (ADD_INT32S_OVERFLOWS(i2, i)) { |
394 | 0 | return E_FAILED; |
395 | 0 | } |
396 | 0 | int i3 = i2 + i; |
397 | 0 | if (ADD_INT32S_OVERFLOWS(j, j)) { |
398 | 0 | return E_FAILED; |
399 | 0 | } |
400 | 0 | int j2 = j + j; |
401 | 0 |
|
402 | 0 | if (SUB_INT32S_OVERFLOWS(i3, j)) { |
403 | 0 | return E_FAILED; |
404 | 0 | } |
405 | 0 | if (ADD_INT32S_OVERFLOWS(i, j2)) { |
406 | 0 | return E_FAILED; |
407 | 0 | } |
408 | 0 | } |
409 | 0 |
|
410 | 0 | ijk->i = (int)lround(((i * 3) - j) * M_ONESEVENTH); |
411 | 0 | ijk->j = (int)lround((i + (j * 2)) * M_ONESEVENTH); |
412 | 0 | ijk->k = 0; |
413 | 0 |
|
414 | 0 | // Expected not to be reachable, because max + min or max - min would need |
415 | 0 | // to overflow. |
416 | 0 | if (NEVER(_ijkNormalizeCouldOverflow(ijk))) { |
417 | 0 | return E_FAILED; |
418 | 0 | } |
419 | 0 | _ijkNormalize(ijk); |
420 | 0 | return E_SUCCESS; |
421 | 0 | } Unexecuted instantiation: fuzzerDirectedEdge.c:_upAp7Checked Unexecuted instantiation: directedEdge.c:_upAp7Checked Unexecuted instantiation: faceijk.c:_upAp7Checked Unexecuted instantiation: algos.c:_upAp7Checked Unexecuted instantiation: bbox.c:_upAp7Checked Unexecuted instantiation: h3Index.c:_upAp7Checked Unexecuted instantiation: vertex.c:_upAp7Checked Unexecuted instantiation: iterators.c:_upAp7Checked Unexecuted instantiation: baseCells.c:_upAp7Checked Unexecuted instantiation: cellsToMultiPoly.c:_upAp7Checked |
422 | | |
423 | | /** |
424 | | * Returns non-zero if _upAp7r with the given input could have a signed integer |
425 | | * overflow. |
426 | | * |
427 | | * Assumes ijk is IJK+ coordinates (no negative numbers). |
428 | | */ |
429 | 0 | static inline H3Error _upAp7rChecked(CoordIJK *ijk) { |
430 | 0 | // Doesn't need to be checked because i, j, and k must all be non-negative |
431 | 0 | int i = ijk->i - ijk->k; |
432 | 0 | int j = ijk->j - ijk->k; |
433 | 0 |
|
434 | 0 | // <0 is checked because the input must all be non-negative, but some |
435 | 0 | // negative inputs are used in unit tests to exercise the below. |
436 | 0 | if (i >= INT32_MAX_3 || j >= INT32_MAX_3 || i < 0 || j < 0) { |
437 | 0 | if (ADD_INT32S_OVERFLOWS(i, i)) { |
438 | 0 | return E_FAILED; |
439 | 0 | } |
440 | 0 | int i2 = i + i; |
441 | 0 | if (ADD_INT32S_OVERFLOWS(j, j)) { |
442 | 0 | return E_FAILED; |
443 | 0 | } |
444 | 0 | int j2 = j + j; |
445 | 0 | if (ADD_INT32S_OVERFLOWS(j2, j)) { |
446 | 0 | return E_FAILED; |
447 | 0 | } |
448 | 0 | int j3 = j2 + j; |
449 | 0 |
|
450 | 0 | if (ADD_INT32S_OVERFLOWS(i2, j)) { |
451 | 0 | return E_FAILED; |
452 | 0 | } |
453 | 0 | if (SUB_INT32S_OVERFLOWS(j3, i)) { |
454 | 0 | return E_FAILED; |
455 | 0 | } |
456 | 0 | } |
457 | 0 |
|
458 | 0 | ijk->i = (int)lround(((i * 2) + j) * M_ONESEVENTH); |
459 | 0 | ijk->j = (int)lround(((j * 3) - i) * M_ONESEVENTH); |
460 | 0 | ijk->k = 0; |
461 | 0 |
|
462 | 0 | // Expected not to be reachable, because max + min or max - min would need |
463 | 0 | // to overflow. |
464 | 0 | if (NEVER(_ijkNormalizeCouldOverflow(ijk))) { |
465 | 0 | return E_FAILED; |
466 | 0 | } |
467 | 0 | _ijkNormalize(ijk); |
468 | 0 | return E_SUCCESS; |
469 | 0 | } Unexecuted instantiation: fuzzerDirectedEdge.c:_upAp7rChecked Unexecuted instantiation: directedEdge.c:_upAp7rChecked Unexecuted instantiation: faceijk.c:_upAp7rChecked Unexecuted instantiation: algos.c:_upAp7rChecked Unexecuted instantiation: bbox.c:_upAp7rChecked Unexecuted instantiation: h3Index.c:_upAp7rChecked Unexecuted instantiation: vertex.c:_upAp7rChecked Unexecuted instantiation: iterators.c:_upAp7rChecked Unexecuted instantiation: baseCells.c:_upAp7rChecked Unexecuted instantiation: cellsToMultiPoly.c:_upAp7rChecked |
470 | | |
471 | | /** |
472 | | * Find the normalized ijk coordinates of the indexing parent of a cell in a |
473 | | * counter-clockwise aperture 7 grid. Works in place. |
474 | | * |
475 | | * @param ijk The ijk coordinates. |
476 | | */ |
477 | 0 | static inline void _upAp7(CoordIJK *ijk) { |
478 | | // convert to CoordIJ |
479 | 0 | int i = ijk->i - ijk->k; |
480 | 0 | int j = ijk->j - ijk->k; |
481 | |
|
482 | 0 | ijk->i = (int)lround((3 * i - j) * M_ONESEVENTH); |
483 | 0 | ijk->j = (int)lround((i + 2 * j) * M_ONESEVENTH); |
484 | 0 | ijk->k = 0; |
485 | 0 | _ijkNormalize(ijk); |
486 | 0 | } Unexecuted instantiation: fuzzerDirectedEdge.c:_upAp7 Unexecuted instantiation: directedEdge.c:_upAp7 Unexecuted instantiation: faceijk.c:_upAp7 Unexecuted instantiation: algos.c:_upAp7 Unexecuted instantiation: bbox.c:_upAp7 Unexecuted instantiation: h3Index.c:_upAp7 Unexecuted instantiation: vertex.c:_upAp7 Unexecuted instantiation: iterators.c:_upAp7 Unexecuted instantiation: baseCells.c:_upAp7 Unexecuted instantiation: cellsToMultiPoly.c:_upAp7 |
487 | | |
488 | | /** |
489 | | * Find the normalized ijk coordinates of the indexing parent of a cell in a |
490 | | * clockwise aperture 7 grid. Works in place. |
491 | | * |
492 | | * @param ijk The ijk coordinates. |
493 | | */ |
494 | 488 | static inline void _upAp7r(CoordIJK *ijk) { |
495 | | // convert to CoordIJ |
496 | 488 | int i = ijk->i - ijk->k; |
497 | 488 | int j = ijk->j - ijk->k; |
498 | | |
499 | 488 | ijk->i = (int)lround((2 * i + j) * M_ONESEVENTH); |
500 | 488 | ijk->j = (int)lround((3 * j - i) * M_ONESEVENTH); |
501 | 488 | ijk->k = 0; |
502 | 488 | _ijkNormalize(ijk); |
503 | 488 | } Unexecuted instantiation: fuzzerDirectedEdge.c:_upAp7r Unexecuted instantiation: directedEdge.c:_upAp7r Unexecuted instantiation: faceijk.c:_upAp7r Unexecuted instantiation: algos.c:_upAp7r Unexecuted instantiation: bbox.c:_upAp7r Line | Count | Source | 494 | 488 | static inline void _upAp7r(CoordIJK *ijk) { | 495 | | // convert to CoordIJ | 496 | 488 | int i = ijk->i - ijk->k; | 497 | 488 | int j = ijk->j - ijk->k; | 498 | | | 499 | 488 | ijk->i = (int)lround((2 * i + j) * M_ONESEVENTH); | 500 | 488 | ijk->j = (int)lround((3 * j - i) * M_ONESEVENTH); | 501 | 488 | ijk->k = 0; | 502 | 488 | _ijkNormalize(ijk); | 503 | 488 | } |
Unexecuted instantiation: vertex.c:_upAp7r Unexecuted instantiation: iterators.c:_upAp7r Unexecuted instantiation: baseCells.c:_upAp7r Unexecuted instantiation: cellsToMultiPoly.c:_upAp7r |
504 | | |
505 | | /** |
506 | | * Find the normalized ijk coordinates of the hex centered on the indicated |
507 | | * hex at the next finer aperture 7 counter-clockwise resolution. Works in |
508 | | * place. |
509 | | * |
510 | | * @param ijk The ijk coordinates. |
511 | | */ |
512 | 4.37k | static inline void _downAp7(CoordIJK *ijk) { |
513 | | // res r unit vectors in res r+1 |
514 | 4.37k | CoordIJK iVec = {3, 0, 1}; |
515 | 4.37k | CoordIJK jVec = {1, 3, 0}; |
516 | 4.37k | CoordIJK kVec = {0, 1, 3}; |
517 | | |
518 | 4.37k | _ijkScale(&iVec, ijk->i); |
519 | 4.37k | _ijkScale(&jVec, ijk->j); |
520 | 4.37k | _ijkScale(&kVec, ijk->k); |
521 | | |
522 | 4.37k | _ijkAdd(&iVec, &jVec, ijk); |
523 | 4.37k | _ijkAdd(ijk, &kVec, ijk); |
524 | | |
525 | 4.37k | _ijkNormalize(ijk); |
526 | 4.37k | } Unexecuted instantiation: fuzzerDirectedEdge.c:_downAp7 Unexecuted instantiation: directedEdge.c:_downAp7 Unexecuted instantiation: faceijk.c:_downAp7 Unexecuted instantiation: algos.c:_downAp7 Unexecuted instantiation: bbox.c:_downAp7 Line | Count | Source | 512 | 4.37k | static inline void _downAp7(CoordIJK *ijk) { | 513 | | // res r unit vectors in res r+1 | 514 | 4.37k | CoordIJK iVec = {3, 0, 1}; | 515 | 4.37k | CoordIJK jVec = {1, 3, 0}; | 516 | 4.37k | CoordIJK kVec = {0, 1, 3}; | 517 | | | 518 | 4.37k | _ijkScale(&iVec, ijk->i); | 519 | 4.37k | _ijkScale(&jVec, ijk->j); | 520 | 4.37k | _ijkScale(&kVec, ijk->k); | 521 | | | 522 | 4.37k | _ijkAdd(&iVec, &jVec, ijk); | 523 | 4.37k | _ijkAdd(ijk, &kVec, ijk); | 524 | | | 525 | 4.37k | _ijkNormalize(ijk); | 526 | 4.37k | } |
Unexecuted instantiation: vertex.c:_downAp7 Unexecuted instantiation: iterators.c:_downAp7 Unexecuted instantiation: baseCells.c:_downAp7 Unexecuted instantiation: cellsToMultiPoly.c:_downAp7 |
527 | | |
528 | | /** |
529 | | * Find the normalized ijk coordinates of the hex centered on the indicated |
530 | | * hex at the next finer aperture 7 clockwise resolution. Works in place. |
531 | | * |
532 | | * @param ijk The ijk coordinates. |
533 | | */ |
534 | 4.68k | static inline void _downAp7r(CoordIJK *ijk) { |
535 | | // res r unit vectors in res r+1 |
536 | 4.68k | CoordIJK iVec = {3, 1, 0}; |
537 | 4.68k | CoordIJK jVec = {0, 3, 1}; |
538 | 4.68k | CoordIJK kVec = {1, 0, 3}; |
539 | | |
540 | 4.68k | _ijkScale(&iVec, ijk->i); |
541 | 4.68k | _ijkScale(&jVec, ijk->j); |
542 | 4.68k | _ijkScale(&kVec, ijk->k); |
543 | | |
544 | 4.68k | _ijkAdd(&iVec, &jVec, ijk); |
545 | 4.68k | _ijkAdd(ijk, &kVec, ijk); |
546 | | |
547 | 4.68k | _ijkNormalize(ijk); |
548 | 4.68k | } Unexecuted instantiation: fuzzerDirectedEdge.c:_downAp7r Unexecuted instantiation: directedEdge.c:_downAp7r Line | Count | Source | 534 | 321 | static inline void _downAp7r(CoordIJK *ijk) { | 535 | | // res r unit vectors in res r+1 | 536 | 321 | CoordIJK iVec = {3, 1, 0}; | 537 | 321 | CoordIJK jVec = {0, 3, 1}; | 538 | 321 | CoordIJK kVec = {1, 0, 3}; | 539 | | | 540 | 321 | _ijkScale(&iVec, ijk->i); | 541 | 321 | _ijkScale(&jVec, ijk->j); | 542 | 321 | _ijkScale(&kVec, ijk->k); | 543 | | | 544 | 321 | _ijkAdd(&iVec, &jVec, ijk); | 545 | 321 | _ijkAdd(ijk, &kVec, ijk); | 546 | | | 547 | 321 | _ijkNormalize(ijk); | 548 | 321 | } |
Unexecuted instantiation: algos.c:_downAp7r Unexecuted instantiation: bbox.c:_downAp7r Line | Count | Source | 534 | 4.36k | static inline void _downAp7r(CoordIJK *ijk) { | 535 | | // res r unit vectors in res r+1 | 536 | 4.36k | CoordIJK iVec = {3, 1, 0}; | 537 | 4.36k | CoordIJK jVec = {0, 3, 1}; | 538 | 4.36k | CoordIJK kVec = {1, 0, 3}; | 539 | | | 540 | 4.36k | _ijkScale(&iVec, ijk->i); | 541 | 4.36k | _ijkScale(&jVec, ijk->j); | 542 | 4.36k | _ijkScale(&kVec, ijk->k); | 543 | | | 544 | 4.36k | _ijkAdd(&iVec, &jVec, ijk); | 545 | 4.36k | _ijkAdd(ijk, &kVec, ijk); | 546 | | | 547 | 4.36k | _ijkNormalize(ijk); | 548 | 4.36k | } |
Unexecuted instantiation: vertex.c:_downAp7r Unexecuted instantiation: iterators.c:_downAp7r Unexecuted instantiation: baseCells.c:_downAp7r Unexecuted instantiation: cellsToMultiPoly.c:_downAp7r |
549 | | |
550 | | /** |
551 | | * Find the normalized ijk coordinates of the hex centered on the indicated |
552 | | * hex at the next finer aperture 3 counter-clockwise resolution. Works in |
553 | | * place. |
554 | | * |
555 | | * @param ijk The ijk coordinates. |
556 | | */ |
557 | 383 | static inline void _downAp3(CoordIJK *ijk) { |
558 | | // res r unit vectors in res r+1 |
559 | 383 | CoordIJK iVec = {2, 0, 1}; |
560 | 383 | CoordIJK jVec = {1, 2, 0}; |
561 | 383 | CoordIJK kVec = {0, 1, 2}; |
562 | | |
563 | 383 | _ijkScale(&iVec, ijk->i); |
564 | 383 | _ijkScale(&jVec, ijk->j); |
565 | 383 | _ijkScale(&kVec, ijk->k); |
566 | | |
567 | 383 | _ijkAdd(&iVec, &jVec, ijk); |
568 | 383 | _ijkAdd(ijk, &kVec, ijk); |
569 | | |
570 | 383 | _ijkNormalize(ijk); |
571 | 383 | } Unexecuted instantiation: fuzzerDirectedEdge.c:_downAp3 Unexecuted instantiation: directedEdge.c:_downAp3 Line | Count | Source | 557 | 383 | static inline void _downAp3(CoordIJK *ijk) { | 558 | | // res r unit vectors in res r+1 | 559 | 383 | CoordIJK iVec = {2, 0, 1}; | 560 | 383 | CoordIJK jVec = {1, 2, 0}; | 561 | 383 | CoordIJK kVec = {0, 1, 2}; | 562 | | | 563 | 383 | _ijkScale(&iVec, ijk->i); | 564 | 383 | _ijkScale(&jVec, ijk->j); | 565 | 383 | _ijkScale(&kVec, ijk->k); | 566 | | | 567 | 383 | _ijkAdd(&iVec, &jVec, ijk); | 568 | 383 | _ijkAdd(ijk, &kVec, ijk); | 569 | | | 570 | 383 | _ijkNormalize(ijk); | 571 | 383 | } |
Unexecuted instantiation: algos.c:_downAp3 Unexecuted instantiation: bbox.c:_downAp3 Unexecuted instantiation: h3Index.c:_downAp3 Unexecuted instantiation: vertex.c:_downAp3 Unexecuted instantiation: iterators.c:_downAp3 Unexecuted instantiation: baseCells.c:_downAp3 Unexecuted instantiation: cellsToMultiPoly.c:_downAp3 |
572 | | |
573 | | /** |
574 | | * Find the normalized ijk coordinates of the hex centered on the indicated |
575 | | * hex at the next finer aperture 3 clockwise resolution. Works in place. |
576 | | * |
577 | | * @param ijk The ijk coordinates. |
578 | | */ |
579 | 383 | static inline void _downAp3r(CoordIJK *ijk) { |
580 | | // res r unit vectors in res r+1 |
581 | 383 | CoordIJK iVec = {2, 1, 0}; |
582 | 383 | CoordIJK jVec = {0, 2, 1}; |
583 | 383 | CoordIJK kVec = {1, 0, 2}; |
584 | | |
585 | 383 | _ijkScale(&iVec, ijk->i); |
586 | 383 | _ijkScale(&jVec, ijk->j); |
587 | 383 | _ijkScale(&kVec, ijk->k); |
588 | | |
589 | 383 | _ijkAdd(&iVec, &jVec, ijk); |
590 | 383 | _ijkAdd(ijk, &kVec, ijk); |
591 | | |
592 | 383 | _ijkNormalize(ijk); |
593 | 383 | } Unexecuted instantiation: fuzzerDirectedEdge.c:_downAp3r Unexecuted instantiation: directedEdge.c:_downAp3r Line | Count | Source | 579 | 383 | static inline void _downAp3r(CoordIJK *ijk) { | 580 | | // res r unit vectors in res r+1 | 581 | 383 | CoordIJK iVec = {2, 1, 0}; | 582 | 383 | CoordIJK jVec = {0, 2, 1}; | 583 | 383 | CoordIJK kVec = {1, 0, 2}; | 584 | | | 585 | 383 | _ijkScale(&iVec, ijk->i); | 586 | 383 | _ijkScale(&jVec, ijk->j); | 587 | 383 | _ijkScale(&kVec, ijk->k); | 588 | | | 589 | 383 | _ijkAdd(&iVec, &jVec, ijk); | 590 | 383 | _ijkAdd(ijk, &kVec, ijk); | 591 | | | 592 | 383 | _ijkNormalize(ijk); | 593 | 383 | } |
Unexecuted instantiation: algos.c:_downAp3r Unexecuted instantiation: bbox.c:_downAp3r Unexecuted instantiation: h3Index.c:_downAp3r Unexecuted instantiation: vertex.c:_downAp3r Unexecuted instantiation: iterators.c:_downAp3r Unexecuted instantiation: baseCells.c:_downAp3r Unexecuted instantiation: cellsToMultiPoly.c:_downAp3r |
594 | | |
595 | | /** |
596 | | * Find the normalized ijk coordinates of the hex in the specified digit |
597 | | * direction from the specified ijk coordinates. Works in place. |
598 | | * |
599 | | * @param ijk The ijk coordinates. |
600 | | * @param digit The digit direction from the original ijk coordinates. |
601 | | */ |
602 | 8.11k | static inline void _neighbor(CoordIJK *ijk, Direction digit) { |
603 | 8.11k | if (digit > CENTER_DIGIT && digit < NUM_DIGITS) { |
604 | 5.22k | _ijkAdd(ijk, &UNIT_VECS[digit], ijk); |
605 | 5.22k | _ijkNormalize(ijk); |
606 | 5.22k | } |
607 | 8.11k | } Unexecuted instantiation: fuzzerDirectedEdge.c:_neighbor Unexecuted instantiation: directedEdge.c:_neighbor Unexecuted instantiation: faceijk.c:_neighbor Unexecuted instantiation: algos.c:_neighbor Unexecuted instantiation: bbox.c:_neighbor Line | Count | Source | 602 | 8.11k | static inline void _neighbor(CoordIJK *ijk, Direction digit) { | 603 | 8.11k | if (digit > CENTER_DIGIT && digit < NUM_DIGITS) { | 604 | 5.22k | _ijkAdd(ijk, &UNIT_VECS[digit], ijk); | 605 | 5.22k | _ijkNormalize(ijk); | 606 | 5.22k | } | 607 | 8.11k | } |
Unexecuted instantiation: vertex.c:_neighbor Unexecuted instantiation: iterators.c:_neighbor Unexecuted instantiation: baseCells.c:_neighbor Unexecuted instantiation: cellsToMultiPoly.c:_neighbor |
608 | | |
609 | | /** |
610 | | * Rotates ijk coordinates 60 degrees counter-clockwise. Works in place. |
611 | | * |
612 | | * @param ijk The ijk coordinates. |
613 | | */ |
614 | 2.91k | static inline void _ijkRotate60ccw(CoordIJK *ijk) { |
615 | | // unit vector rotations |
616 | 2.91k | CoordIJK iVec = {1, 1, 0}; |
617 | 2.91k | CoordIJK jVec = {0, 1, 1}; |
618 | 2.91k | CoordIJK kVec = {1, 0, 1}; |
619 | | |
620 | 2.91k | _ijkScale(&iVec, ijk->i); |
621 | 2.91k | _ijkScale(&jVec, ijk->j); |
622 | 2.91k | _ijkScale(&kVec, ijk->k); |
623 | | |
624 | 2.91k | _ijkAdd(&iVec, &jVec, ijk); |
625 | 2.91k | _ijkAdd(ijk, &kVec, ijk); |
626 | | |
627 | 2.91k | _ijkNormalize(ijk); |
628 | 2.91k | } Unexecuted instantiation: fuzzerDirectedEdge.c:_ijkRotate60ccw Unexecuted instantiation: directedEdge.c:_ijkRotate60ccw faceijk.c:_ijkRotate60ccw Line | Count | Source | 614 | 2.91k | static inline void _ijkRotate60ccw(CoordIJK *ijk) { | 615 | | // unit vector rotations | 616 | 2.91k | CoordIJK iVec = {1, 1, 0}; | 617 | 2.91k | CoordIJK jVec = {0, 1, 1}; | 618 | 2.91k | CoordIJK kVec = {1, 0, 1}; | 619 | | | 620 | 2.91k | _ijkScale(&iVec, ijk->i); | 621 | 2.91k | _ijkScale(&jVec, ijk->j); | 622 | 2.91k | _ijkScale(&kVec, ijk->k); | 623 | | | 624 | 2.91k | _ijkAdd(&iVec, &jVec, ijk); | 625 | 2.91k | _ijkAdd(ijk, &kVec, ijk); | 626 | | | 627 | 2.91k | _ijkNormalize(ijk); | 628 | 2.91k | } |
Unexecuted instantiation: algos.c:_ijkRotate60ccw Unexecuted instantiation: bbox.c:_ijkRotate60ccw Unexecuted instantiation: h3Index.c:_ijkRotate60ccw Unexecuted instantiation: vertex.c:_ijkRotate60ccw Unexecuted instantiation: iterators.c:_ijkRotate60ccw Unexecuted instantiation: baseCells.c:_ijkRotate60ccw Unexecuted instantiation: cellsToMultiPoly.c:_ijkRotate60ccw |
629 | | |
630 | | /** |
631 | | * Rotates ijk coordinates 60 degrees clockwise. Works in place. |
632 | | * |
633 | | * @param ijk The ijk coordinates. |
634 | | */ |
635 | 106 | static inline void _ijkRotate60cw(CoordIJK *ijk) { |
636 | | // unit vector rotations |
637 | 106 | CoordIJK iVec = {1, 0, 1}; |
638 | 106 | CoordIJK jVec = {1, 1, 0}; |
639 | 106 | CoordIJK kVec = {0, 1, 1}; |
640 | | |
641 | 106 | _ijkScale(&iVec, ijk->i); |
642 | 106 | _ijkScale(&jVec, ijk->j); |
643 | 106 | _ijkScale(&kVec, ijk->k); |
644 | | |
645 | 106 | _ijkAdd(&iVec, &jVec, ijk); |
646 | 106 | _ijkAdd(ijk, &kVec, ijk); |
647 | | |
648 | 106 | _ijkNormalize(ijk); |
649 | 106 | } Unexecuted instantiation: fuzzerDirectedEdge.c:_ijkRotate60cw Unexecuted instantiation: directedEdge.c:_ijkRotate60cw Line | Count | Source | 635 | 106 | static inline void _ijkRotate60cw(CoordIJK *ijk) { | 636 | | // unit vector rotations | 637 | 106 | CoordIJK iVec = {1, 0, 1}; | 638 | 106 | CoordIJK jVec = {1, 1, 0}; | 639 | 106 | CoordIJK kVec = {0, 1, 1}; | 640 | | | 641 | 106 | _ijkScale(&iVec, ijk->i); | 642 | 106 | _ijkScale(&jVec, ijk->j); | 643 | 106 | _ijkScale(&kVec, ijk->k); | 644 | | | 645 | 106 | _ijkAdd(&iVec, &jVec, ijk); | 646 | 106 | _ijkAdd(ijk, &kVec, ijk); | 647 | | | 648 | 106 | _ijkNormalize(ijk); | 649 | 106 | } |
Unexecuted instantiation: algos.c:_ijkRotate60cw Unexecuted instantiation: bbox.c:_ijkRotate60cw Unexecuted instantiation: h3Index.c:_ijkRotate60cw Unexecuted instantiation: vertex.c:_ijkRotate60cw Unexecuted instantiation: iterators.c:_ijkRotate60cw Unexecuted instantiation: baseCells.c:_ijkRotate60cw Unexecuted instantiation: cellsToMultiPoly.c:_ijkRotate60cw |
650 | | |
651 | | /** |
652 | | * Rotates indexing digit 60 degrees counter-clockwise. Returns result. |
653 | | * |
654 | | * @param digit Indexing digit (between 1 and 6 inclusive) |
655 | | */ |
656 | 16.0k | static inline Direction _rotate60ccw(Direction digit) { |
657 | 16.0k | switch (digit) { |
658 | 2.61k | case K_AXES_DIGIT: |
659 | 2.61k | return IK_AXES_DIGIT; |
660 | 2.10k | case IK_AXES_DIGIT: |
661 | 2.10k | return I_AXES_DIGIT; |
662 | 2.25k | case I_AXES_DIGIT: |
663 | 2.25k | return IJ_AXES_DIGIT; |
664 | 2.90k | case IJ_AXES_DIGIT: |
665 | 2.90k | return J_AXES_DIGIT; |
666 | 3.00k | case J_AXES_DIGIT: |
667 | 3.00k | return JK_AXES_DIGIT; |
668 | 2.89k | case JK_AXES_DIGIT: |
669 | 2.89k | return K_AXES_DIGIT; |
670 | 333 | default: |
671 | 333 | return digit; |
672 | 16.0k | } |
673 | 16.0k | } Unexecuted instantiation: fuzzerDirectedEdge.c:_rotate60ccw Unexecuted instantiation: directedEdge.c:_rotate60ccw Unexecuted instantiation: faceijk.c:_rotate60ccw Line | Count | Source | 656 | 207 | static inline Direction _rotate60ccw(Direction digit) { | 657 | 207 | switch (digit) { | 658 | 31 | case K_AXES_DIGIT: | 659 | 31 | return IK_AXES_DIGIT; | 660 | 37 | case IK_AXES_DIGIT: | 661 | 37 | return I_AXES_DIGIT; | 662 | 36 | case I_AXES_DIGIT: | 663 | 36 | return IJ_AXES_DIGIT; | 664 | 37 | case IJ_AXES_DIGIT: | 665 | 37 | return J_AXES_DIGIT; | 666 | 35 | case J_AXES_DIGIT: | 667 | 35 | return JK_AXES_DIGIT; | 668 | 31 | case JK_AXES_DIGIT: | 669 | 31 | return K_AXES_DIGIT; | 670 | 0 | default: | 671 | 0 | return digit; | 672 | 207 | } | 673 | 207 | } |
Unexecuted instantiation: bbox.c:_rotate60ccw Line | Count | Source | 656 | 15.8k | static inline Direction _rotate60ccw(Direction digit) { | 657 | 15.8k | switch (digit) { | 658 | 2.58k | case K_AXES_DIGIT: | 659 | 2.58k | return IK_AXES_DIGIT; | 660 | 2.06k | case IK_AXES_DIGIT: | 661 | 2.06k | return I_AXES_DIGIT; | 662 | 2.21k | case I_AXES_DIGIT: | 663 | 2.21k | return IJ_AXES_DIGIT; | 664 | 2.86k | case IJ_AXES_DIGIT: | 665 | 2.86k | return J_AXES_DIGIT; | 666 | 2.96k | case J_AXES_DIGIT: | 667 | 2.96k | return JK_AXES_DIGIT; | 668 | 2.85k | case JK_AXES_DIGIT: | 669 | 2.85k | return K_AXES_DIGIT; | 670 | 333 | default: | 671 | 333 | return digit; | 672 | 15.8k | } | 673 | 15.8k | } |
Unexecuted instantiation: vertex.c:_rotate60ccw Unexecuted instantiation: iterators.c:_rotate60ccw Unexecuted instantiation: baseCells.c:_rotate60ccw Unexecuted instantiation: cellsToMultiPoly.c:_rotate60ccw |
674 | | |
675 | | /** |
676 | | * Rotates indexing digit 60 degrees clockwise. Returns result. |
677 | | * |
678 | | * @param digit Indexing digit (between 1 and 6 inclusive) |
679 | | */ |
680 | 1.43k | static inline Direction _rotate60cw(Direction digit) { |
681 | 1.43k | switch (digit) { |
682 | 256 | case K_AXES_DIGIT: |
683 | 256 | return JK_AXES_DIGIT; |
684 | 147 | case JK_AXES_DIGIT: |
685 | 147 | return J_AXES_DIGIT; |
686 | 107 | case J_AXES_DIGIT: |
687 | 107 | return IJ_AXES_DIGIT; |
688 | 137 | case IJ_AXES_DIGIT: |
689 | 137 | return I_AXES_DIGIT; |
690 | 195 | case I_AXES_DIGIT: |
691 | 195 | return IK_AXES_DIGIT; |
692 | 261 | case IK_AXES_DIGIT: |
693 | 261 | return K_AXES_DIGIT; |
694 | 335 | default: |
695 | 335 | return digit; |
696 | 1.43k | } |
697 | 1.43k | } Unexecuted instantiation: fuzzerDirectedEdge.c:_rotate60cw Unexecuted instantiation: directedEdge.c:_rotate60cw Unexecuted instantiation: faceijk.c:_rotate60cw Unexecuted instantiation: algos.c:_rotate60cw Unexecuted instantiation: bbox.c:_rotate60cw Line | Count | Source | 680 | 1.43k | static inline Direction _rotate60cw(Direction digit) { | 681 | 1.43k | switch (digit) { | 682 | 256 | case K_AXES_DIGIT: | 683 | 256 | return JK_AXES_DIGIT; | 684 | 147 | case JK_AXES_DIGIT: | 685 | 147 | return J_AXES_DIGIT; | 686 | 107 | case J_AXES_DIGIT: | 687 | 107 | return IJ_AXES_DIGIT; | 688 | 137 | case IJ_AXES_DIGIT: | 689 | 137 | return I_AXES_DIGIT; | 690 | 195 | case I_AXES_DIGIT: | 691 | 195 | return IK_AXES_DIGIT; | 692 | 261 | case IK_AXES_DIGIT: | 693 | 261 | return K_AXES_DIGIT; | 694 | 335 | default: | 695 | 335 | return digit; | 696 | 1.43k | } | 697 | 1.43k | } |
Unexecuted instantiation: vertex.c:_rotate60cw Unexecuted instantiation: iterators.c:_rotate60cw Unexecuted instantiation: baseCells.c:_rotate60cw Unexecuted instantiation: cellsToMultiPoly.c:_rotate60cw |
698 | | |
699 | | /** |
700 | | * Finds the distance between the two coordinates. Returns result. |
701 | | * |
702 | | * @param c1 The first set of ijk coordinates. |
703 | | * @param c2 The second set of ijk coordinates. |
704 | | */ |
705 | 0 | static inline int ijkDistance(const CoordIJK *c1, const CoordIJK *c2) { |
706 | 0 | CoordIJK diff; |
707 | 0 | _ijkSub(c1, c2, &diff); |
708 | 0 | _ijkNormalize(&diff); |
709 | 0 | CoordIJK absDiff = {abs(diff.i), abs(diff.j), abs(diff.k)}; |
710 | 0 | return MAX(absDiff.i, MAX(absDiff.j, absDiff.k)); |
711 | 0 | } Unexecuted instantiation: fuzzerDirectedEdge.c:ijkDistance Unexecuted instantiation: directedEdge.c:ijkDistance Unexecuted instantiation: faceijk.c:ijkDistance Unexecuted instantiation: algos.c:ijkDistance Unexecuted instantiation: bbox.c:ijkDistance Unexecuted instantiation: h3Index.c:ijkDistance Unexecuted instantiation: vertex.c:ijkDistance Unexecuted instantiation: iterators.c:ijkDistance Unexecuted instantiation: baseCells.c:ijkDistance Unexecuted instantiation: cellsToMultiPoly.c:ijkDistance |
712 | | |
713 | | /** |
714 | | * Transforms coordinates from the IJK+ coordinate system to the IJ coordinate |
715 | | * system. |
716 | | * |
717 | | * @param ijk The input IJK+ coordinates |
718 | | * @param ij The output IJ coordinates |
719 | | */ |
720 | 0 | static inline void ijkToIj(const CoordIJK *ijk, CoordIJ *ij) { |
721 | 0 | ij->i = ijk->i - ijk->k; |
722 | 0 | ij->j = ijk->j - ijk->k; |
723 | 0 | } Unexecuted instantiation: fuzzerDirectedEdge.c:ijkToIj Unexecuted instantiation: directedEdge.c:ijkToIj Unexecuted instantiation: faceijk.c:ijkToIj Unexecuted instantiation: algos.c:ijkToIj Unexecuted instantiation: bbox.c:ijkToIj Unexecuted instantiation: h3Index.c:ijkToIj Unexecuted instantiation: vertex.c:ijkToIj Unexecuted instantiation: iterators.c:ijkToIj Unexecuted instantiation: baseCells.c:ijkToIj Unexecuted instantiation: cellsToMultiPoly.c:ijkToIj |
724 | | |
725 | | /** |
726 | | * Transforms coordinates from the IJ coordinate system to the IJK+ coordinate |
727 | | * system. |
728 | | * |
729 | | * @param ij The input IJ coordinates |
730 | | * @param ijk The output IJK+ coordinates |
731 | | * @returns E_SUCCESS on success, E_FAILED if signed integer overflow would have |
732 | | * occurred. |
733 | | */ |
734 | 0 | static inline H3Error ijToIjk(const CoordIJ *ij, CoordIJK *ijk) { |
735 | 0 | ijk->i = ij->i; |
736 | 0 | ijk->j = ij->j; |
737 | 0 | ijk->k = 0; |
738 | 0 |
|
739 | 0 | if (_ijkNormalizeCouldOverflow(ijk)) { |
740 | 0 | return E_FAILED; |
741 | 0 | } |
742 | 0 |
|
743 | 0 | _ijkNormalize(ijk); |
744 | 0 | return E_SUCCESS; |
745 | 0 | } Unexecuted instantiation: fuzzerDirectedEdge.c:ijToIjk Unexecuted instantiation: directedEdge.c:ijToIjk Unexecuted instantiation: faceijk.c:ijToIjk Unexecuted instantiation: algos.c:ijToIjk Unexecuted instantiation: bbox.c:ijToIjk Unexecuted instantiation: h3Index.c:ijToIjk Unexecuted instantiation: vertex.c:ijToIjk Unexecuted instantiation: iterators.c:ijToIjk Unexecuted instantiation: baseCells.c:ijToIjk Unexecuted instantiation: cellsToMultiPoly.c:ijToIjk |
746 | | |
747 | | /** |
748 | | * Convert IJK coordinates to cube coordinates, in place |
749 | | * @param ijk Coordinate to convert |
750 | | */ |
751 | 0 | static inline void ijkToCube(CoordIJK *ijk) { |
752 | 0 | ijk->i = -ijk->i + ijk->k; |
753 | 0 | ijk->j = ijk->j - ijk->k; |
754 | 0 | ijk->k = -ijk->i - ijk->j; |
755 | 0 | } Unexecuted instantiation: fuzzerDirectedEdge.c:ijkToCube Unexecuted instantiation: directedEdge.c:ijkToCube Unexecuted instantiation: faceijk.c:ijkToCube Unexecuted instantiation: algos.c:ijkToCube Unexecuted instantiation: bbox.c:ijkToCube Unexecuted instantiation: h3Index.c:ijkToCube Unexecuted instantiation: vertex.c:ijkToCube Unexecuted instantiation: iterators.c:ijkToCube Unexecuted instantiation: baseCells.c:ijkToCube Unexecuted instantiation: cellsToMultiPoly.c:ijkToCube |
756 | | |
757 | | /** |
758 | | * Convert cube coordinates to IJK coordinates, in place |
759 | | * @param ijk Coordinate to convert |
760 | | */ |
761 | 0 | static inline void cubeToIjk(CoordIJK *ijk) { |
762 | 0 | ijk->i = -ijk->i; |
763 | 0 | ijk->k = 0; |
764 | 0 | _ijkNormalize(ijk); |
765 | 0 | } Unexecuted instantiation: fuzzerDirectedEdge.c:cubeToIjk Unexecuted instantiation: directedEdge.c:cubeToIjk Unexecuted instantiation: faceijk.c:cubeToIjk Unexecuted instantiation: algos.c:cubeToIjk Unexecuted instantiation: bbox.c:cubeToIjk Unexecuted instantiation: h3Index.c:cubeToIjk Unexecuted instantiation: vertex.c:cubeToIjk Unexecuted instantiation: iterators.c:cubeToIjk Unexecuted instantiation: baseCells.c:cubeToIjk Unexecuted instantiation: cellsToMultiPoly.c:cubeToIjk |
766 | | |
767 | | #undef INT32_MAX_3 |
768 | | |
769 | | #endif |