h3 3.4.0 → 3.4.4
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -1
- data/ext/h3/src/.travis.yml +5 -0
- data/ext/h3/src/CHANGELOG.md +25 -0
- data/ext/h3/src/CMakeLists.txt +5 -8
- data/ext/h3/src/CONTRIBUTING.md +2 -0
- data/ext/h3/src/README.md +6 -2
- data/ext/h3/src/VERSION +1 -1
- data/ext/h3/src/appveyor.yml +6 -1
- data/ext/h3/src/docs/api/misc.md +16 -0
- data/ext/h3/src/docs/community/bindings.md +9 -0
- data/ext/h3/src/docs/community/tutorials.md +4 -0
- data/ext/h3/src/scripts/binding_functions.ps1 +1 -2
- data/ext/h3/src/scripts/binding_functions.sh +3 -2
- data/ext/h3/src/scripts/coverage.sh.in +3 -3
- data/ext/h3/src/src/apps/applib/include/utility.h +60 -0
- data/ext/h3/src/src/apps/applib/lib/utility.c +196 -2
- data/ext/h3/src/src/apps/benchmarks/benchmarkPolyfill.c +7 -4
- data/ext/h3/src/src/apps/filters/geoToH3.c +73 -27
- data/ext/h3/src/src/apps/filters/h3ToGeo.c +63 -47
- data/ext/h3/src/src/apps/filters/h3ToGeoBoundary.c +64 -48
- data/ext/h3/src/src/apps/filters/h3ToLocalIj.c +4 -5
- data/ext/h3/src/src/apps/filters/hexRange.c +0 -1
- data/ext/h3/src/src/apps/filters/kRing.c +60 -28
- data/ext/h3/src/src/apps/filters/localIjToH3.c +75 -0
- data/ext/h3/src/src/apps/miscapps/generateBaseCellNeighbors.c +2 -2
- data/ext/h3/src/src/apps/testapps/testBBox.c +18 -0
- data/ext/h3/src/src/apps/testapps/testCompact.c +41 -0
- data/ext/h3/src/src/apps/testapps/testCoordIj.c +0 -1
- data/ext/h3/src/src/apps/testapps/testCoordIjk.c +53 -0
- data/ext/h3/src/src/apps/testapps/testH3Api.c +20 -0
- data/ext/h3/src/src/apps/testapps/testH3Distance.c +5 -3
- data/ext/h3/src/src/apps/testapps/testH3Line.c +18 -6
- data/ext/h3/src/src/apps/testapps/testH3ToLocalIj.c +75 -3
- data/ext/h3/src/src/apps/testapps/testH3UniEdge.c +17 -11
- data/ext/h3/src/src/apps/testapps/testHexRanges.c +10 -0
- data/ext/h3/src/src/apps/testapps/testKRing.c +11 -7
- data/ext/h3/src/src/h3lib/lib/algos.c +2 -1
- data/ext/h3/src/src/h3lib/lib/geoCoord.c +10 -10
- data/ext/h3/src/src/h3lib/lib/h3Index.c +1 -2
- data/ext/h3/src/src/h3lib/lib/localij.c +32 -36
- data/lib/h3/version.rb +1 -1
- metadata +4 -7
- data/ext/h3/src/cmake/CheckAlloca.cmake +0 -33
- data/ext/h3/src/cmake/CheckVLA.cmake +0 -33
- data/ext/h3/src/cmake/alloca_test.c +0 -29
- data/ext/h3/src/cmake/vla_test.c +0 -26
- data/ext/h3/src/src/h3lib/include/stackAlloc.h +0 -64
@@ -25,7 +25,6 @@
|
|
25
25
|
#include "h3Index.h"
|
26
26
|
#include "h3api.h"
|
27
27
|
#include "localij.h"
|
28
|
-
#include "stackAlloc.h"
|
29
28
|
#include "test.h"
|
30
29
|
#include "utility.h"
|
31
30
|
|
@@ -37,7 +36,7 @@ static const int MAX_DISTANCES[] = {1, 2, 5, 12, 19, 26};
|
|
37
36
|
static void h3Line_assertions(H3Index start, H3Index end) {
|
38
37
|
int sz = H3_EXPORT(h3LineSize)(start, end);
|
39
38
|
t_assert(sz > 0, "got valid size");
|
40
|
-
|
39
|
+
H3Index *line = calloc(sz, sizeof(H3Index));
|
41
40
|
|
42
41
|
int err = H3_EXPORT(h3Line)(start, end, line);
|
43
42
|
|
@@ -51,10 +50,12 @@ static void h3Line_assertions(H3Index start, H3Index end) {
|
|
51
50
|
"index is a neighbor of the previous index");
|
52
51
|
if (i > 1) {
|
53
52
|
t_assert(
|
54
|
-
!H3_EXPORT(h3IndexesAreNeighbors)(line[i], line[i -
|
53
|
+
!H3_EXPORT(h3IndexesAreNeighbors)(line[i], line[i - 2]),
|
55
54
|
"index is not a neighbor of the index before the previous");
|
56
55
|
}
|
57
56
|
}
|
57
|
+
|
58
|
+
free(line);
|
58
59
|
}
|
59
60
|
|
60
61
|
/**
|
@@ -64,7 +65,7 @@ static void h3Line_invalid_assertions(H3Index start, H3Index end) {
|
|
64
65
|
int sz = H3_EXPORT(h3LineSize)(start, end);
|
65
66
|
t_assert(sz < 0, "line size marked as invalid");
|
66
67
|
|
67
|
-
H3Index*
|
68
|
+
H3Index *line = {0};
|
68
69
|
int err = H3_EXPORT(h3Line)(start, end, line);
|
69
70
|
t_assert(err != 0, "line marked as invalid");
|
70
71
|
}
|
@@ -78,13 +79,14 @@ static void h3Line_kRing_assertions(H3Index h3) {
|
|
78
79
|
int maxK = MAX_DISTANCES[r];
|
79
80
|
|
80
81
|
int sz = H3_EXPORT(maxKringSize)(maxK);
|
81
|
-
STACK_ARRAY_CALLOC(H3Index, neighbors, sz);
|
82
|
-
H3_EXPORT(kRing)(h3, maxK, neighbors);
|
83
82
|
|
84
83
|
if (H3_EXPORT(h3IsPentagon)(h3)) {
|
85
84
|
return;
|
86
85
|
}
|
87
86
|
|
87
|
+
H3Index *neighbors = calloc(sz, sizeof(H3Index));
|
88
|
+
H3_EXPORT(kRing)(h3, maxK, neighbors);
|
89
|
+
|
88
90
|
for (int i = 0; i < sz; i++) {
|
89
91
|
if (neighbors[i] == 0) {
|
90
92
|
continue;
|
@@ -96,6 +98,8 @@ static void h3Line_kRing_assertions(H3Index h3) {
|
|
96
98
|
h3Line_invalid_assertions(h3, neighbors[i]);
|
97
99
|
}
|
98
100
|
}
|
101
|
+
|
102
|
+
free(neighbors);
|
99
103
|
}
|
100
104
|
|
101
105
|
SUITE(h3Line) {
|
@@ -107,4 +111,12 @@ SUITE(h3Line) {
|
|
107
111
|
iterateAllIndexesAtResPartial(3, h3Line_kRing_assertions, 6);
|
108
112
|
// Further resolutions aren't tested to save time.
|
109
113
|
}
|
114
|
+
|
115
|
+
TEST(h3Line_acrossMultipleFaces) {
|
116
|
+
H3Index start = 0x85285aa7fffffff;
|
117
|
+
H3Index end = 0x851d9b1bfffffff;
|
118
|
+
|
119
|
+
int lineSz = H3_EXPORT(h3LineSize)(start, end);
|
120
|
+
t_assert(lineSz < 0, "Line not computable across multiple icosa faces");
|
121
|
+
}
|
110
122
|
}
|
@@ -29,7 +29,6 @@
|
|
29
29
|
#include "h3Index.h"
|
30
30
|
#include "h3api.h"
|
31
31
|
#include "localij.h"
|
32
|
-
#include "stackAlloc.h"
|
33
32
|
#include "test.h"
|
34
33
|
#include "utility.h"
|
35
34
|
|
@@ -131,8 +130,8 @@ void localIjToH3_kRing_assertions(H3Index h3) {
|
|
131
130
|
int maxK = MAX_DISTANCES[r];
|
132
131
|
|
133
132
|
int sz = H3_EXPORT(maxKringSize)(maxK);
|
134
|
-
|
135
|
-
|
133
|
+
H3Index *neighbors = calloc(sz, sizeof(H3Index));
|
134
|
+
int *distances = calloc(sz, sizeof(int));
|
136
135
|
|
137
136
|
H3_EXPORT(kRingDistances)(h3, maxK, neighbors, distances);
|
138
137
|
|
@@ -152,6 +151,9 @@ void localIjToH3_kRing_assertions(H3Index h3) {
|
|
152
151
|
"round trip neighboring index matches expected");
|
153
152
|
}
|
154
153
|
}
|
154
|
+
|
155
|
+
free(distances);
|
156
|
+
free(neighbors);
|
155
157
|
}
|
156
158
|
|
157
159
|
void localIjToH3_traverse_assertions(H3Index h3) {
|
@@ -339,4 +341,74 @@ SUITE(h3ToLocalIj) {
|
|
339
341
|
t_assert(H3_EXPORT(experimentalH3ToLocalIj)(pent1, bc3, &ij) != 0,
|
340
342
|
"found IJ (5)");
|
341
343
|
}
|
344
|
+
|
345
|
+
/**
|
346
|
+
* Test that coming from the same direction outside the pentagon is handled
|
347
|
+
* the same as coming from the same direction inside the pentagon.
|
348
|
+
*/
|
349
|
+
TEST(onOffPentagonSame) {
|
350
|
+
for (int bc = 0; bc < NUM_BASE_CELLS; bc++) {
|
351
|
+
for (int res = 1; res <= MAX_H3_RES; res++) {
|
352
|
+
// K_AXES_DIGIT is the first internal direction, and it's also
|
353
|
+
// invalid for pentagons, so skip to next.
|
354
|
+
Direction startDir = K_AXES_DIGIT;
|
355
|
+
if (_isBaseCellPentagon(bc)) {
|
356
|
+
startDir++;
|
357
|
+
}
|
358
|
+
|
359
|
+
for (Direction dir = startDir; dir < NUM_DIGITS; dir++) {
|
360
|
+
H3Index internalOrigin;
|
361
|
+
setH3Index(&internalOrigin, res, bc, dir);
|
362
|
+
|
363
|
+
H3Index externalOrigin;
|
364
|
+
setH3Index(&externalOrigin, res,
|
365
|
+
_getBaseCellNeighbor(bc, dir), CENTER_DIGIT);
|
366
|
+
|
367
|
+
for (Direction testDir = startDir; testDir < NUM_DIGITS;
|
368
|
+
testDir++) {
|
369
|
+
H3Index testIndex;
|
370
|
+
setH3Index(&testIndex, res, bc, testDir);
|
371
|
+
|
372
|
+
CoordIJ internalIj;
|
373
|
+
int internalIjFailed =
|
374
|
+
H3_EXPORT(experimentalH3ToLocalIj)(
|
375
|
+
internalOrigin, testIndex, &internalIj);
|
376
|
+
CoordIJ externalIj;
|
377
|
+
int externalIjFailed =
|
378
|
+
H3_EXPORT(experimentalH3ToLocalIj)(
|
379
|
+
externalOrigin, testIndex, &externalIj);
|
380
|
+
|
381
|
+
t_assert(
|
382
|
+
(bool)internalIjFailed == (bool)externalIjFailed,
|
383
|
+
"internal/external failed matches when getting IJ");
|
384
|
+
|
385
|
+
if (internalIjFailed) {
|
386
|
+
continue;
|
387
|
+
}
|
388
|
+
|
389
|
+
H3Index internalIndex;
|
390
|
+
int internalIjFailed2 =
|
391
|
+
H3_EXPORT(experimentalLocalIjToH3)(
|
392
|
+
internalOrigin, &internalIj, &internalIndex);
|
393
|
+
H3Index externalIndex;
|
394
|
+
int externalIjFailed2 =
|
395
|
+
H3_EXPORT(experimentalLocalIjToH3)(
|
396
|
+
externalOrigin, &externalIj, &externalIndex);
|
397
|
+
|
398
|
+
t_assert(
|
399
|
+
(bool)internalIjFailed2 == (bool)externalIjFailed2,
|
400
|
+
"internal/external failed matches when getting "
|
401
|
+
"index");
|
402
|
+
|
403
|
+
if (internalIjFailed2) {
|
404
|
+
continue;
|
405
|
+
}
|
406
|
+
|
407
|
+
t_assert(internalIndex == externalIndex,
|
408
|
+
"internal/external index matches");
|
409
|
+
}
|
410
|
+
}
|
411
|
+
}
|
412
|
+
}
|
413
|
+
}
|
342
414
|
}
|
@@ -23,7 +23,6 @@
|
|
23
23
|
#include "constants.h"
|
24
24
|
#include "geoCoord.h"
|
25
25
|
#include "h3Index.h"
|
26
|
-
#include "stackAlloc.h"
|
27
26
|
#include "test.h"
|
28
27
|
|
29
28
|
// Fixtures
|
@@ -32,7 +31,7 @@ static GeoCoord sfGeo = {0.659966917655, -2.1364398519396};
|
|
32
31
|
SUITE(h3UniEdge) {
|
33
32
|
TEST(h3IndexesAreNeighbors) {
|
34
33
|
H3Index sf = H3_EXPORT(geoToH3)(&sfGeo, 9);
|
35
|
-
|
34
|
+
H3Index ring[7] = {0};
|
36
35
|
H3_EXPORT(hexRing)(sf, 1, ring);
|
37
36
|
|
38
37
|
t_assert(H3_EXPORT(h3IndexesAreNeighbors)(sf, sf) == 0,
|
@@ -47,7 +46,7 @@ SUITE(h3UniEdge) {
|
|
47
46
|
t_assert(neighbors == 6,
|
48
47
|
"got the expected number of neighbors from a k-ring of 1");
|
49
48
|
|
50
|
-
|
49
|
+
H3Index largerRing[19] = {0};
|
51
50
|
H3_EXPORT(hexRing)(sf, 2, largerRing);
|
52
51
|
|
53
52
|
neighbors = 0;
|
@@ -64,6 +63,8 @@ SUITE(h3UniEdge) {
|
|
64
63
|
H3_SET_MODE(sfBroken, H3_UNIEDGE_MODE);
|
65
64
|
t_assert(H3_EXPORT(h3IndexesAreNeighbors)(sf, sfBroken) == 0,
|
66
65
|
"broken H3Indexes can't be neighbors");
|
66
|
+
t_assert(H3_EXPORT(h3IndexesAreNeighbors)(sfBroken, sf) == 0,
|
67
|
+
"broken H3Indexes can't be neighbors (reversed)");
|
67
68
|
|
68
69
|
H3Index sfBigger = H3_EXPORT(geoToH3)(&sfGeo, 7);
|
69
70
|
t_assert(H3_EXPORT(h3IndexesAreNeighbors)(sf, sfBigger) == 0,
|
@@ -75,7 +76,7 @@ SUITE(h3UniEdge) {
|
|
75
76
|
|
76
77
|
TEST(getH3UnidirectionalEdgeAndFriends) {
|
77
78
|
H3Index sf = H3_EXPORT(geoToH3)(&sfGeo, 9);
|
78
|
-
|
79
|
+
H3Index ring[7] = {0};
|
79
80
|
H3_EXPORT(hexRing)(sf, 1, ring);
|
80
81
|
H3Index sf2 = ring[0];
|
81
82
|
|
@@ -93,7 +94,7 @@ SUITE(h3UniEdge) {
|
|
93
94
|
t_assert(originDestination[1] == sf2,
|
94
95
|
"got the destination last in the pair request");
|
95
96
|
|
96
|
-
|
97
|
+
H3Index largerRing[19] = {0};
|
97
98
|
H3_EXPORT(hexRing)(sf, 2, largerRing);
|
98
99
|
H3Index sf3 = largerRing[0];
|
99
100
|
|
@@ -133,7 +134,7 @@ SUITE(h3UniEdge) {
|
|
133
134
|
|
134
135
|
TEST(h3UnidirectionalEdgeIsValid) {
|
135
136
|
H3Index sf = H3_EXPORT(geoToH3)(&sfGeo, 9);
|
136
|
-
|
137
|
+
H3Index ring[7] = {0};
|
137
138
|
H3_EXPORT(hexRing)(sf, 1, ring);
|
138
139
|
H3Index sf2 = ring[0];
|
139
140
|
|
@@ -147,6 +148,11 @@ SUITE(h3UniEdge) {
|
|
147
148
|
H3_SET_MODE(fakeEdge, H3_UNIEDGE_MODE);
|
148
149
|
t_assert(H3_EXPORT(h3UnidirectionalEdgeIsValid)(fakeEdge) == 0,
|
149
150
|
"edges without an edge specified don't work");
|
151
|
+
H3Index invalidEdge = sf;
|
152
|
+
H3_SET_MODE(invalidEdge, H3_UNIEDGE_MODE);
|
153
|
+
H3_SET_RESERVED_BITS(invalidEdge, INVALID_DIGIT);
|
154
|
+
t_assert(H3_EXPORT(h3UnidirectionalEdgeIsValid)(invalidEdge) == 0,
|
155
|
+
"edges with an invalid edge specified don't work");
|
150
156
|
|
151
157
|
H3Index pentagon = 0x821c07fffffffff;
|
152
158
|
H3Index goodPentagonalEdge = pentagon;
|
@@ -164,7 +170,7 @@ SUITE(h3UniEdge) {
|
|
164
170
|
|
165
171
|
TEST(getH3UnidirectionalEdgesFromHexagon) {
|
166
172
|
H3Index sf = H3_EXPORT(geoToH3)(&sfGeo, 9);
|
167
|
-
|
173
|
+
H3Index edges[6] = {0};
|
168
174
|
H3_EXPORT(getH3UnidirectionalEdgesFromHexagon)(sf, edges);
|
169
175
|
|
170
176
|
for (int i = 0; i < 6; i++) {
|
@@ -182,7 +188,7 @@ SUITE(h3UniEdge) {
|
|
182
188
|
|
183
189
|
TEST(getH3UnidirectionalEdgesFromPentagon) {
|
184
190
|
H3Index pentagon = 0x821c07fffffffff;
|
185
|
-
|
191
|
+
H3Index edges[6] = {0};
|
186
192
|
H3_EXPORT(getH3UnidirectionalEdgesFromHexagon)(pentagon, edges);
|
187
193
|
|
188
194
|
int missingEdgeCount = 0;
|
@@ -211,7 +217,7 @@ SUITE(h3UniEdge) {
|
|
211
217
|
H3Index sf;
|
212
218
|
GeoBoundary boundary;
|
213
219
|
GeoBoundary edgeBoundary;
|
214
|
-
|
220
|
+
H3Index edges[6] = {0};
|
215
221
|
|
216
222
|
const int expectedVertices[][2] = {{3, 4}, {1, 2}, {2, 3},
|
217
223
|
{5, 0}, {4, 5}, {0, 1}};
|
@@ -242,7 +248,7 @@ SUITE(h3UniEdge) {
|
|
242
248
|
H3Index pentagon;
|
243
249
|
GeoBoundary boundary;
|
244
250
|
GeoBoundary edgeBoundary;
|
245
|
-
|
251
|
+
H3Index edges[6] = {0};
|
246
252
|
|
247
253
|
const int expectedVertices[][3] = {{-1, -1, -1}, {2, 3, 4}, {4, 5, 6},
|
248
254
|
{8, 9, 0}, {6, 7, 8}, {0, 1, 2}};
|
@@ -282,7 +288,7 @@ SUITE(h3UniEdge) {
|
|
282
288
|
H3Index pentagon;
|
283
289
|
GeoBoundary boundary;
|
284
290
|
GeoBoundary edgeBoundary;
|
285
|
-
|
291
|
+
H3Index edges[6] = {0};
|
286
292
|
|
287
293
|
const int expectedVertices[][3] = {{-1, -1}, {1, 2}, {2, 3},
|
288
294
|
{4, 0}, {3, 4}, {0, 1}};
|
@@ -25,6 +25,7 @@ SUITE(hexRanges) {
|
|
25
25
|
|
26
26
|
H3Index k1[] = {0x89283080ddbffff, 0x89283080c37ffff, 0x89283080c27ffff,
|
27
27
|
0x89283080d53ffff, 0x89283080dcfffff, 0x89283080dc3ffff};
|
28
|
+
H3Index withPentagon[] = {0x8029fffffffffff, 0x801dfffffffffff};
|
28
29
|
|
29
30
|
TEST(identityKRing) {
|
30
31
|
int err;
|
@@ -74,4 +75,13 @@ SUITE(hexRanges) {
|
|
74
75
|
}
|
75
76
|
free(allKrings2);
|
76
77
|
}
|
78
|
+
|
79
|
+
TEST(failed) {
|
80
|
+
int err;
|
81
|
+
H3Index* allKrings = calloc(2 * (1 + 6), sizeof(H3Index));
|
82
|
+
err = H3_EXPORT(hexRanges)(withPentagon, 2, 1, allKrings);
|
83
|
+
|
84
|
+
t_assert(err != 0, "Expected error on hexRanges");
|
85
|
+
free(allKrings);
|
86
|
+
}
|
77
87
|
}
|
@@ -19,7 +19,6 @@
|
|
19
19
|
* usage: `testKRing`
|
20
20
|
*/
|
21
21
|
|
22
|
-
#include <stackAlloc.h>
|
23
22
|
#include <stdlib.h>
|
24
23
|
#include "algos.h"
|
25
24
|
#include "baseCells.h"
|
@@ -31,13 +30,12 @@ static void kRing_equals_kRingInternal_assertions(H3Index h3) {
|
|
31
30
|
for (int k = 0; k < 3; k++) {
|
32
31
|
int kSz = H3_EXPORT(maxKringSize)(k);
|
33
32
|
|
34
|
-
|
35
|
-
|
36
|
-
H3_EXPORT(kRingDistances)
|
37
|
-
(h3, k, neighbors, distances);
|
33
|
+
H3Index *neighbors = calloc(kSz, sizeof(H3Index));
|
34
|
+
int *distances = calloc(kSz, sizeof(int));
|
35
|
+
H3_EXPORT(kRingDistances)(h3, k, neighbors, distances);
|
38
36
|
|
39
|
-
|
40
|
-
|
37
|
+
H3Index *internalNeighbors = calloc(kSz, sizeof(H3Index));
|
38
|
+
int *internalDistances = calloc(kSz, sizeof(int));
|
41
39
|
_kRingInternal(h3, k, internalNeighbors, internalDistances, kSz, 0);
|
42
40
|
|
43
41
|
int found = 0;
|
@@ -64,6 +62,12 @@ static void kRing_equals_kRingInternal_assertions(H3Index h3) {
|
|
64
62
|
"produce same output");
|
65
63
|
}
|
66
64
|
}
|
65
|
+
|
66
|
+
free(internalDistances);
|
67
|
+
free(internalNeighbors);
|
68
|
+
|
69
|
+
free(distances);
|
70
|
+
free(neighbors);
|
67
71
|
}
|
68
72
|
}
|
69
73
|
|
@@ -18,10 +18,12 @@
|
|
18
18
|
*/
|
19
19
|
|
20
20
|
#include "algos.h"
|
21
|
+
#include <assert.h>
|
21
22
|
#include <float.h>
|
22
23
|
#include <math.h>
|
23
24
|
#include <stdbool.h>
|
24
25
|
#include <stdlib.h>
|
26
|
+
#include <string.h>
|
25
27
|
#include "baseCells.h"
|
26
28
|
#include "bbox.h"
|
27
29
|
#include "faceijk.h"
|
@@ -30,7 +32,6 @@
|
|
30
32
|
#include "h3api.h"
|
31
33
|
#include "linkedGeo.h"
|
32
34
|
#include "polygon.h"
|
33
|
-
#include "stackAlloc.h"
|
34
35
|
#include "vertexGraph.h"
|
35
36
|
|
36
37
|
/*
|
@@ -221,36 +221,36 @@ void _geoAzDistanceRads(const GeoCoord* p1, double az, double distance,
|
|
221
221
|
if (fabs(p2->lat - M_PI_2) < EPSILON) // north pole
|
222
222
|
{
|
223
223
|
p2->lat = M_PI_2;
|
224
|
-
p2->lon = 0.
|
224
|
+
p2->lon = 0.0;
|
225
225
|
} else if (fabs(p2->lat + M_PI_2) < EPSILON) // south pole
|
226
226
|
{
|
227
227
|
p2->lat = -M_PI_2;
|
228
|
-
p2->lon = 0.
|
228
|
+
p2->lon = 0.0;
|
229
229
|
} else
|
230
230
|
p2->lon = constrainLng(p1->lon);
|
231
231
|
} else // not due north or south
|
232
232
|
{
|
233
233
|
sinlat = sin(p1->lat) * cos(distance) +
|
234
234
|
cos(p1->lat) * sin(distance) * cos(az);
|
235
|
-
if (sinlat > 1.
|
236
|
-
if (sinlat < -1.
|
235
|
+
if (sinlat > 1.0) sinlat = 1.0;
|
236
|
+
if (sinlat < -1.0) sinlat = -1.0;
|
237
237
|
p2->lat = asin(sinlat);
|
238
238
|
if (fabs(p2->lat - M_PI_2) < EPSILON) // north pole
|
239
239
|
{
|
240
240
|
p2->lat = M_PI_2;
|
241
|
-
p2->lon = 0.
|
241
|
+
p2->lon = 0.0;
|
242
242
|
} else if (fabs(p2->lat + M_PI_2) < EPSILON) // south pole
|
243
243
|
{
|
244
244
|
p2->lat = -M_PI_2;
|
245
|
-
p2->lon = 0.
|
245
|
+
p2->lon = 0.0;
|
246
246
|
} else {
|
247
247
|
sinlon = sin(az) * sin(distance) / cos(p2->lat);
|
248
248
|
coslon = (cos(distance) - sin(p1->lat) * sin(p2->lat)) /
|
249
249
|
cos(p1->lat) / cos(p2->lat);
|
250
|
-
if (sinlon > 1.
|
251
|
-
if (sinlon < -1.
|
252
|
-
if (coslon > 1.
|
253
|
-
if (coslon < -1.
|
250
|
+
if (sinlon > 1.0) sinlon = 1.0;
|
251
|
+
if (sinlon < -1.0) sinlon = -1.0;
|
252
|
+
if (coslon > 1.0) coslon = 1.0;
|
253
|
+
if (coslon < -1.0) coslon = -1.0;
|
254
254
|
p2->lon = constrainLng(p1->lon + atan2(sinlon, coslon));
|
255
255
|
}
|
256
256
|
}
|
@@ -26,7 +26,6 @@
|
|
26
26
|
#include "baseCells.h"
|
27
27
|
#include "faceijk.h"
|
28
28
|
#include "mathExtensions.h"
|
29
|
-
#include "stackAlloc.h"
|
30
29
|
|
31
30
|
/**
|
32
31
|
* Returns the H3 resolution of an H3 index.
|
@@ -388,11 +387,11 @@ int H3_EXPORT(uncompact)(const H3Index* compactedSet, const int numHexes,
|
|
388
387
|
H3Index* h3Set, const int maxHexes, const int res) {
|
389
388
|
int outOffset = 0;
|
390
389
|
for (int i = 0; i < numHexes; i++) {
|
390
|
+
if (compactedSet[i] == 0) continue;
|
391
391
|
if (outOffset >= maxHexes) {
|
392
392
|
// We went too far, abort!
|
393
393
|
return -1;
|
394
394
|
}
|
395
|
-
if (compactedSet[i] == 0) continue;
|
396
395
|
int currentRes = H3_GET_RESOLUTION(compactedSet[i]);
|
397
396
|
if (currentRes > res) {
|
398
397
|
// Nonsensical. Abort.
|
@@ -19,6 +19,7 @@
|
|
19
19
|
* These functions try to provide a useful coordinate space in the vicinity of
|
20
20
|
* an origin index.
|
21
21
|
*/
|
22
|
+
#include <assert.h>
|
22
23
|
#include <faceijk.h>
|
23
24
|
#include <inttypes.h>
|
24
25
|
#include <math.h>
|
@@ -28,7 +29,6 @@
|
|
28
29
|
#include "faceijk.h"
|
29
30
|
#include "h3Index.h"
|
30
31
|
#include "mathExtensions.h"
|
31
|
-
#include "stackAlloc.h"
|
32
32
|
|
33
33
|
/**
|
34
34
|
* Origin leading digit -> index leading digit -> rotations 60 cw
|
@@ -87,24 +87,28 @@ const int PENTAGON_ROTATIONS_REVERSE_POLAR[7][7] = {
|
|
87
87
|
{0, 1, 1, 0, 1, 1, 1}, // 6
|
88
88
|
};
|
89
89
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
90
|
+
/**
|
91
|
+
* Prohibited directions when unfolding a pentagon.
|
92
|
+
*
|
93
|
+
* Indexes by two directions, both relative to the pentagon base cell. The first
|
94
|
+
* is the direction of the origin index and the second is the direction of the
|
95
|
+
* index to unfold. Direction refers to the direction from base cell to base
|
96
|
+
* cell if the indexes are on different base cells, or the leading digit if
|
97
|
+
* within the pentagon base cell.
|
98
|
+
*
|
99
|
+
* This previously included a Class II/Class III check but these were removed
|
100
|
+
* due to failure cases. It's possible this could be restricted to a narrower
|
101
|
+
* set of a failure cases. Currently, the logic is any unfolding across more
|
102
|
+
* than one icosahedron face is not permitted.
|
103
|
+
*/
|
104
|
+
const bool FAILED_DIRECTIONS[7][7] = {
|
101
105
|
{false, false, false, false, false, false, false}, // 0
|
102
106
|
{false, false, false, false, false, false, false}, // 1
|
103
|
-
{false, false, false, false,
|
104
|
-
{false, false, false, false, true, false,
|
105
|
-
{false, false, true,
|
106
|
-
{false, false,
|
107
|
-
{false, false, false, true, false,
|
107
|
+
{false, false, false, false, true, true, false}, // 2
|
108
|
+
{false, false, false, false, true, false, true}, // 3
|
109
|
+
{false, false, true, true, false, false, false}, // 4
|
110
|
+
{false, false, true, false, false, false, true}, // 5
|
111
|
+
{false, false, false, true, false, true, false}, // 6
|
108
112
|
};
|
109
113
|
|
110
114
|
/**
|
@@ -183,15 +187,10 @@ int h3ToLocalIjk(H3Index origin, H3Index h3, CoordIJK* out) {
|
|
183
187
|
if (originOnPent) {
|
184
188
|
int originLeadingDigit = _h3LeadingNonZeroDigit(origin);
|
185
189
|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
// https://github.com/uber/h3/issues/163
|
191
|
-
if (FAILED_DIRECTIONS_III[originLeadingDigit][dir] ||
|
192
|
-
FAILED_DIRECTIONS_II[originLeadingDigit][dir]) {
|
193
|
-
// TODO this part of the pentagon might not be unfolded
|
194
|
-
// correctly.
|
190
|
+
if (FAILED_DIRECTIONS[originLeadingDigit][dir]) {
|
191
|
+
// TODO: We may be unfolding the pentagon incorrectly in this
|
192
|
+
// case; return an error code until this is guaranteed to be
|
193
|
+
// correct.
|
195
194
|
return 3;
|
196
195
|
}
|
197
196
|
|
@@ -200,12 +199,10 @@ int h3ToLocalIjk(H3Index origin, H3Index h3, CoordIJK* out) {
|
|
200
199
|
} else if (indexOnPent) {
|
201
200
|
int indexLeadingDigit = _h3LeadingNonZeroDigit(h3);
|
202
201
|
|
203
|
-
if (
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
// TODO this part of the pentagon might not be unfolded
|
208
|
-
// correctly.
|
202
|
+
if (FAILED_DIRECTIONS[indexLeadingDigit][revDir]) {
|
203
|
+
// TODO: We may be unfolding the pentagon incorrectly in this
|
204
|
+
// case; return an error code until this is guaranteed to be
|
205
|
+
// correct.
|
209
206
|
return 4;
|
210
207
|
}
|
211
208
|
|
@@ -248,10 +245,9 @@ int h3ToLocalIjk(H3Index origin, H3Index h3, CoordIJK* out) {
|
|
248
245
|
int originLeadingDigit = _h3LeadingNonZeroDigit(origin);
|
249
246
|
int indexLeadingDigit = _h3LeadingNonZeroDigit(h3);
|
250
247
|
|
251
|
-
if (
|
252
|
-
|
253
|
-
//
|
254
|
-
// correctly.
|
248
|
+
if (FAILED_DIRECTIONS[originLeadingDigit][indexLeadingDigit]) {
|
249
|
+
// TODO: We may be unfolding the pentagon incorrectly in this case;
|
250
|
+
// return an error code until this is guaranteed to be correct.
|
255
251
|
return 5;
|
256
252
|
}
|
257
253
|
|