Coverage Report

Created: 2023-09-25 06:53

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