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.
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