h3 3.4.0 → 3.4.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -1
  3. data/ext/h3/src/.travis.yml +5 -0
  4. data/ext/h3/src/CHANGELOG.md +25 -0
  5. data/ext/h3/src/CMakeLists.txt +5 -8
  6. data/ext/h3/src/CONTRIBUTING.md +2 -0
  7. data/ext/h3/src/README.md +6 -2
  8. data/ext/h3/src/VERSION +1 -1
  9. data/ext/h3/src/appveyor.yml +6 -1
  10. data/ext/h3/src/docs/api/misc.md +16 -0
  11. data/ext/h3/src/docs/community/bindings.md +9 -0
  12. data/ext/h3/src/docs/community/tutorials.md +4 -0
  13. data/ext/h3/src/scripts/binding_functions.ps1 +1 -2
  14. data/ext/h3/src/scripts/binding_functions.sh +3 -2
  15. data/ext/h3/src/scripts/coverage.sh.in +3 -3
  16. data/ext/h3/src/src/apps/applib/include/utility.h +60 -0
  17. data/ext/h3/src/src/apps/applib/lib/utility.c +196 -2
  18. data/ext/h3/src/src/apps/benchmarks/benchmarkPolyfill.c +7 -4
  19. data/ext/h3/src/src/apps/filters/geoToH3.c +73 -27
  20. data/ext/h3/src/src/apps/filters/h3ToGeo.c +63 -47
  21. data/ext/h3/src/src/apps/filters/h3ToGeoBoundary.c +64 -48
  22. data/ext/h3/src/src/apps/filters/h3ToLocalIj.c +4 -5
  23. data/ext/h3/src/src/apps/filters/hexRange.c +0 -1
  24. data/ext/h3/src/src/apps/filters/kRing.c +60 -28
  25. data/ext/h3/src/src/apps/filters/localIjToH3.c +75 -0
  26. data/ext/h3/src/src/apps/miscapps/generateBaseCellNeighbors.c +2 -2
  27. data/ext/h3/src/src/apps/testapps/testBBox.c +18 -0
  28. data/ext/h3/src/src/apps/testapps/testCompact.c +41 -0
  29. data/ext/h3/src/src/apps/testapps/testCoordIj.c +0 -1
  30. data/ext/h3/src/src/apps/testapps/testCoordIjk.c +53 -0
  31. data/ext/h3/src/src/apps/testapps/testH3Api.c +20 -0
  32. data/ext/h3/src/src/apps/testapps/testH3Distance.c +5 -3
  33. data/ext/h3/src/src/apps/testapps/testH3Line.c +18 -6
  34. data/ext/h3/src/src/apps/testapps/testH3ToLocalIj.c +75 -3
  35. data/ext/h3/src/src/apps/testapps/testH3UniEdge.c +17 -11
  36. data/ext/h3/src/src/apps/testapps/testHexRanges.c +10 -0
  37. data/ext/h3/src/src/apps/testapps/testKRing.c +11 -7
  38. data/ext/h3/src/src/h3lib/lib/algos.c +2 -1
  39. data/ext/h3/src/src/h3lib/lib/geoCoord.c +10 -10
  40. data/ext/h3/src/src/h3lib/lib/h3Index.c +1 -2
  41. data/ext/h3/src/src/h3lib/lib/localij.c +32 -36
  42. data/lib/h3/version.rb +1 -1
  43. metadata +4 -7
  44. data/ext/h3/src/cmake/CheckAlloca.cmake +0 -33
  45. data/ext/h3/src/cmake/CheckVLA.cmake +0 -33
  46. data/ext/h3/src/cmake/alloca_test.c +0 -29
  47. data/ext/h3/src/cmake/vla_test.c +0 -26
  48. 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
- STACK_ARRAY_CALLOC(H3Index, line, sz);
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 - 3]),
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* line = {0};
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
- STACK_ARRAY_CALLOC(H3Index, neighbors, sz);
135
- STACK_ARRAY_CALLOC(int, distances, sz);
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
- STACK_ARRAY_CALLOC(H3Index, ring, H3_EXPORT(maxKringSize)(1));
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
- STACK_ARRAY_CALLOC(H3Index, largerRing, H3_EXPORT(maxKringSize)(2));
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
- STACK_ARRAY_CALLOC(H3Index, ring, H3_EXPORT(maxKringSize)(1));
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
- STACK_ARRAY_CALLOC(H3Index, largerRing, H3_EXPORT(maxKringSize)(2));
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
- STACK_ARRAY_CALLOC(H3Index, ring, H3_EXPORT(maxKringSize)(1));
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
- STACK_ARRAY_CALLOC(H3Index, edges, 6);
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
- STACK_ARRAY_CALLOC(H3Index, edges, 6);
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
- STACK_ARRAY_CALLOC(H3Index, edges, 6);
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
- STACK_ARRAY_CALLOC(H3Index, edges, 6);
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
- STACK_ARRAY_CALLOC(H3Index, edges, 6);
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
- STACK_ARRAY_CALLOC(H3Index, neighbors, kSz);
35
- STACK_ARRAY_CALLOC(int, distances, kSz);
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
- STACK_ARRAY_CALLOC(H3Index, internalNeighbors, kSz);
40
- STACK_ARRAY_CALLOC(int, internalDistances, kSz);
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.0L;
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.0L;
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.0L) sinlat = 1.0L;
236
- if (sinlat < -1.0L) sinlat = -1.0L;
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.0L;
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.0L;
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.0L) sinlon = 1.0L;
251
- if (sinlon < -1.0L) sinlon = -1.0L;
252
- if (coslon > 1.0L) sinlon = 1.0L;
253
- if (coslon < -1.0L) sinlon = -1.0L;
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
- // Simply prohibit many pentagon distortion cases rather than handling them.
91
- const bool FAILED_DIRECTIONS_II[7][7] = {
92
- {false, false, false, false, false, false, false}, // 0
93
- {false, false, false, false, false, false, false}, // 1
94
- {false, false, false, false, true, false, false}, // 2
95
- {false, false, false, false, false, false, true}, // 3
96
- {false, false, false, true, false, false, false}, // 4
97
- {false, false, true, false, false, false, false}, // 5
98
- {false, false, false, false, false, true, false}, // 6
99
- };
100
- const bool FAILED_DIRECTIONS_III[7][7] = {
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, false, true, false}, // 2
104
- {false, false, false, false, true, false, false}, // 3
105
- {false, false, true, false, false, false, false}, // 4
106
- {false, false, false, false, false, false, true}, // 5
107
- {false, false, false, true, false, false, false}, // 6
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
- // TODO: This previously included the Class III-based checks
187
- // as in the index-on-pentagon case below, but these were
188
- // removed due to some failure cases. It is possible that we
189
- // could restrict this error to a narrower set of cases.
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 ((isResClassIII(res) &&
204
- FAILED_DIRECTIONS_III[indexLeadingDigit][revDir]) ||
205
- (!isResClassIII(res) &&
206
- FAILED_DIRECTIONS_II[indexLeadingDigit][revDir])) {
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 (FAILED_DIRECTIONS_III[originLeadingDigit][indexLeadingDigit] ||
252
- FAILED_DIRECTIONS_II[originLeadingDigit][indexLeadingDigit]) {
253
- // TODO this part of the pentagon might not be unfolded
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