h3 3.4.0 → 3.4.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|