h3 3.6.2 → 3.7.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +23 -0
- data/Gemfile.lock +6 -6
- data/README.md +1 -1
- data/ext/h3/src/.github/workflows/test-linux.yml +118 -0
- data/ext/h3/src/.github/workflows/test-macos.yml +42 -0
- data/ext/h3/src/.github/workflows/test-website.yml +32 -0
- data/ext/h3/src/.github/workflows/test-windows.yml +44 -0
- data/ext/h3/src/.gitignore +5 -0
- data/ext/h3/src/.travis.yml +16 -46
- data/ext/h3/src/CHANGELOG.md +43 -0
- data/ext/h3/src/CMakeLists.txt +133 -33
- data/ext/h3/src/CONTRIBUTING.md +1 -1
- data/ext/h3/src/README.md +60 -10
- data/ext/h3/src/RELEASE.md +3 -1
- data/ext/h3/src/VERSION +1 -1
- data/ext/h3/src/dev-docs/RFCs/rfc-template.md +21 -0
- data/ext/h3/src/dev-docs/RFCs/v4.0.0/error-handling-rfc.md +21 -0
- data/ext/h3/src/dev-docs/RFCs/v4.0.0/names_for_concepts_types_functions.md +276 -0
- data/ext/h3/src/dev-docs/RFCs/v4.0.0/overrideable-allocators-rfc.md +141 -0
- data/ext/h3/src/dev-docs/RFCs/v4.0.0/polyfill-modes-rfc.md +21 -0
- data/ext/h3/src/dev-docs/RFCs/v4.0.0/vertex-mode-rfc.md +50 -0
- data/ext/h3/src/dev-docs/build_windows.md +6 -1
- data/ext/h3/src/dev-docs/creating_bindings.md +3 -3
- data/ext/h3/src/dev-docs/custom_alloc.md +27 -0
- data/ext/h3/src/docs/{overview/mainpage.md → README.md} +2 -3
- data/ext/h3/src/docs/api/misc.md +76 -0
- data/ext/h3/src/docs/community/applications.md +1 -0
- data/ext/h3/src/docs/community/bindings.md +7 -1
- data/ext/h3/src/docs/community/tutorials.md +8 -3
- data/ext/h3/src/docs/core-library/coordsystems.md +5 -4
- data/ext/h3/src/docs/core-library/filters.md +8 -9
- data/ext/h3/src/docs/core-library/geoToH3desc.md +2 -3
- data/ext/h3/src/docs/core-library/h3ToGeoBoundaryDesc.md +4 -5
- data/ext/h3/src/docs/core-library/h3ToGeoDesc.md +3 -4
- data/ext/h3/src/docs/core-library/h3indexing.md +26 -17
- data/ext/h3/src/docs/core-library/overview.md +2 -3
- data/ext/h3/src/docs/core-library/restable.md +1 -2
- data/ext/h3/src/docs/core-library/usage.md +1 -2
- data/ext/h3/src/docs/table-of-contents.json +47 -0
- data/ext/h3/src/docs/{overview/usecases.md → usecases.md} +6 -11
- data/ext/h3/src/scripts/binding_functions.sh +1 -1
- data/ext/h3/src/scripts/coverage.sh.in +1 -1
- data/ext/h3/src/scripts/update_version.sh +2 -2
- data/ext/h3/src/src/apps/applib/include/args.h +1 -0
- data/ext/h3/src/src/apps/applib/include/test.h +1 -0
- data/ext/h3/src/src/apps/applib/include/utility.h +7 -1
- data/ext/h3/src/src/apps/applib/lib/args.c +2 -0
- data/ext/h3/src/src/apps/applib/lib/kml.c +2 -0
- data/ext/h3/src/src/apps/applib/lib/test.c +1 -0
- data/ext/h3/src/src/apps/applib/lib/utility.c +133 -2
- data/ext/h3/src/src/apps/benchmarks/benchmarkH3Api.c +1 -1
- data/ext/h3/src/{website/html.config.js → src/apps/benchmarks/benchmarkH3UniEdge.c} +15 -12
- data/ext/h3/src/src/apps/filters/h3ToComponents.c +1 -0
- data/ext/h3/src/src/apps/filters/h3ToGeo.c +1 -0
- data/ext/h3/src/src/apps/filters/h3ToGeoBoundary.c +1 -0
- data/ext/h3/src/src/apps/filters/h3ToLocalIj.c +1 -0
- data/ext/h3/src/src/apps/filters/hexRange.c +1 -0
- data/ext/h3/src/src/apps/filters/kRing.c +1 -0
- data/ext/h3/src/src/apps/filters/localIjToH3.c +1 -0
- data/ext/h3/src/src/apps/miscapps/generateFaceCenterPoint.c +1 -0
- data/ext/h3/src/src/apps/miscapps/generateNumHexagons.c +1 -0
- data/ext/h3/src/src/apps/miscapps/generatePentagonDirectionFaces.c +67 -0
- data/ext/h3/src/src/apps/miscapps/h3ToGeoBoundaryHier.c +1 -0
- data/ext/h3/src/src/apps/miscapps/h3ToGeoHier.c +1 -0
- data/ext/h3/src/src/apps/miscapps/h3ToHier.c +1 -0
- data/ext/h3/src/src/apps/testapps/mkRandGeo.c +1 -0
- data/ext/h3/src/src/apps/testapps/mkRandGeoBoundary.c +1 -0
- data/ext/h3/src/src/apps/testapps/testBBox.c +1 -0
- data/ext/h3/src/src/apps/testapps/testBaseCells.c +15 -1
- data/ext/h3/src/src/apps/testapps/testCompact.c +75 -0
- data/ext/h3/src/src/apps/testapps/testCoordIj.c +1 -0
- data/ext/h3/src/src/apps/testapps/testGeoCoord.c +40 -13
- data/ext/h3/src/src/apps/testapps/testGeoToH3.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3Api.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3CellArea.c +47 -0
- data/ext/h3/src/src/apps/testapps/testH3CellAreaExhaustive.c +180 -0
- data/ext/h3/src/src/apps/testapps/testH3Distance.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3DistanceExhaustive.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3GetFaces.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3Index.c +33 -3
- data/ext/h3/src/src/apps/testapps/testH3Line.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3LineExhaustive.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3Memory.c +175 -0
- data/ext/h3/src/src/apps/testapps/testH3NeighborRotations.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3SetToLinkedGeo.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3SetToVertexGraph.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3ToCenterChild.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3ToChildren.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3ToGeo.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3ToGeoBoundary.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3ToLocalIj.c +9 -5
- data/ext/h3/src/src/apps/testapps/testH3ToLocalIjExhaustive.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3ToParent.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3UniEdge.c +45 -16
- data/ext/h3/src/src/apps/testapps/testH3UniEdgeExhaustive.c +111 -0
- data/ext/h3/src/src/apps/testapps/testHexRanges.c +1 -0
- data/ext/h3/src/src/apps/testapps/testHexRing.c +1 -0
- data/ext/h3/src/src/apps/testapps/testKRing.c +1 -0
- data/ext/h3/src/src/apps/testapps/testLinkedGeo.c +1 -0
- data/ext/h3/src/src/apps/testapps/testMaxH3ToChildrenSize.c +1 -0
- data/ext/h3/src/src/apps/testapps/testPentagonIndexes.c +1 -0
- data/ext/h3/src/src/apps/testapps/testPolyfill.c +72 -9
- data/ext/h3/src/src/apps/testapps/testPolyfillReported.c +157 -0
- data/ext/h3/src/src/apps/testapps/testPolygon.c +1 -0
- data/ext/h3/src/src/apps/testapps/testVec2d.c +1 -0
- data/ext/h3/src/src/apps/testapps/testVec3d.c +1 -0
- data/ext/h3/src/src/apps/testapps/testVertex.c +66 -0
- data/ext/h3/src/src/apps/testapps/testVertexGraph.c +1 -0
- data/ext/h3/src/src/h3lib/include/algos.h +8 -0
- data/ext/h3/src/src/h3lib/include/alloc.h +40 -0
- data/ext/h3/src/src/h3lib/include/baseCells.h +4 -0
- data/ext/h3/src/src/h3lib/include/bbox.h +4 -1
- data/ext/h3/src/src/h3lib/include/faceijk.h +3 -2
- data/ext/h3/src/src/h3lib/include/geoCoord.h +2 -3
- data/ext/h3/src/src/h3lib/include/h3Index.h +37 -4
- data/ext/h3/src/src/h3lib/include/h3api.h.in +65 -17
- data/ext/h3/src/src/h3lib/include/linkedGeo.h +1 -0
- data/ext/h3/src/src/h3lib/include/polygon.h +1 -0
- data/ext/h3/src/src/h3lib/include/polygonAlgos.h +1 -0
- data/ext/h3/src/src/h3lib/include/vertex.h +44 -0
- data/ext/h3/src/src/h3lib/include/vertexGraph.h +1 -0
- data/ext/h3/src/src/h3lib/lib/algos.c +300 -75
- data/ext/h3/src/src/h3lib/lib/baseCells.c +26 -4
- data/ext/h3/src/src/h3lib/lib/bbox.c +56 -31
- data/ext/h3/src/src/h3lib/lib/coordijk.c +2 -0
- data/ext/h3/src/src/h3lib/lib/faceijk.c +32 -21
- data/ext/h3/src/src/h3lib/lib/geoCoord.c +162 -44
- data/ext/h3/src/src/h3lib/lib/h3Index.c +81 -43
- data/ext/h3/src/src/h3lib/lib/h3UniEdge.c +42 -57
- data/ext/h3/src/src/h3lib/lib/linkedGeo.c +20 -15
- data/ext/h3/src/src/h3lib/lib/localij.c +1 -1
- data/ext/h3/src/src/h3lib/lib/polygon.c +2 -0
- data/ext/h3/src/src/h3lib/lib/vec2d.c +1 -0
- data/ext/h3/src/src/h3lib/lib/vec3d.c +1 -0
- data/ext/h3/src/src/h3lib/lib/vertex.c +134 -0
- data/ext/h3/src/src/h3lib/lib/vertexGraph.c +8 -5
- data/ext/h3/src/website/.eslintignore +2 -0
- data/ext/h3/src/website/.gitignore +57 -0
- data/ext/h3/src/website/.nvmrc +1 -0
- data/ext/h3/src/website/README.md +8 -6
- data/ext/h3/src/website/gatsby-config.js +83 -0
- data/ext/h3/src/website/package.json +20 -12
- data/ext/h3/src/website/scripts/build-to-gh-pages.sh +7 -5
- data/ext/h3/src/website/src/.gitkeep +0 -0
- data/ext/h3/src/website/templates/documentation.jsx +129 -0
- data/ext/h3/src/website/yarn.lock +13723 -0
- data/lib/h3/bindings/private.rb +3 -0
- data/lib/h3/miscellaneous.rb +123 -0
- data/lib/h3/version.rb +1 -1
- data/spec/miscellaneous_spec.rb +117 -0
- data/spec/regions_spec.rb +1 -1
- metadata +35 -14
- data/ext/h3/src/.ycm_extra_conf.py +0 -92
- data/ext/h3/src/appveyor.yml +0 -50
- data/ext/h3/src/src/apps/testapps/testPolyfill_GH136.c +0 -58
- data/ext/h3/src/website/src/config.js +0 -46
- data/ext/h3/src/website/src/mdRoutes.js +0 -151
- data/ext/h3/src/website/src/styles/_variables.scss +0 -16
- data/ext/h3/src/website/src/styles/index.scss +0 -3
- data/ext/h3/src/website/static/index.html +0 -15
@@ -18,11 +18,14 @@
|
|
18
18
|
* (see h3api.h for the main library entry functions)
|
19
19
|
*/
|
20
20
|
#include "h3Index.h"
|
21
|
+
|
21
22
|
#include <faceijk.h>
|
22
23
|
#include <inttypes.h>
|
23
24
|
#include <math.h>
|
24
25
|
#include <stdlib.h>
|
25
26
|
#include <string.h>
|
27
|
+
|
28
|
+
#include "alloc.h"
|
26
29
|
#include "baseCells.h"
|
27
30
|
#include "faceijk.h"
|
28
31
|
#include "mathExtensions.h"
|
@@ -35,20 +38,25 @@
|
|
35
38
|
int H3_EXPORT(h3GetResolution)(H3Index h) { return H3_GET_RESOLUTION(h); }
|
36
39
|
|
37
40
|
/**
|
38
|
-
* Returns the H3 base cell number of an H3
|
39
|
-
*
|
40
|
-
*
|
41
|
+
* Returns the H3 base cell "number" of an H3 cell (hexagon or pentagon).
|
42
|
+
*
|
43
|
+
* Note: Technically works on H3 edges, but will return base cell of the
|
44
|
+
* origin cell.
|
45
|
+
*
|
46
|
+
* @param h The H3 cell.
|
47
|
+
* @return The base cell "number" of the H3 cell argument.
|
41
48
|
*/
|
42
49
|
int H3_EXPORT(h3GetBaseCell)(H3Index h) { return H3_GET_BASE_CELL(h); }
|
43
50
|
|
44
51
|
/**
|
45
52
|
* Converts a string representation of an H3 index into an H3 index.
|
46
53
|
* @param str The string representation of an H3 index.
|
47
|
-
* @return The H3 index corresponding to the string argument, or
|
54
|
+
* @return The H3 index corresponding to the string argument, or H3_NULL if
|
55
|
+
* invalid.
|
48
56
|
*/
|
49
57
|
H3Index H3_EXPORT(stringToH3)(const char* str) {
|
50
|
-
H3Index h =
|
51
|
-
// If failed, h will be unmodified and we should return
|
58
|
+
H3Index h = H3_NULL;
|
59
|
+
// If failed, h will be unmodified and we should return H3_NULL anyways.
|
52
60
|
sscanf(str, "%" PRIx64, &h);
|
53
61
|
return h;
|
54
62
|
}
|
@@ -70,13 +78,17 @@ void H3_EXPORT(h3ToString)(H3Index h, char* str, size_t sz) {
|
|
70
78
|
}
|
71
79
|
|
72
80
|
/**
|
73
|
-
* Returns whether or not an H3 index is valid.
|
81
|
+
* Returns whether or not an H3 index is a valid cell (hexagon or pentagon).
|
74
82
|
* @param h The H3 index to validate.
|
75
83
|
* @return 1 if the H3 index if valid, and 0 if it is not.
|
76
84
|
*/
|
77
85
|
int H3_EXPORT(h3IsValid)(H3Index h) {
|
86
|
+
if (H3_GET_HIGH_BIT(h) != 0) return 0;
|
87
|
+
|
78
88
|
if (H3_GET_MODE(h) != H3_HEXAGON_MODE) return 0;
|
79
89
|
|
90
|
+
if (H3_GET_RESERVED_BITS(h) != 0) return 0;
|
91
|
+
|
80
92
|
int baseCell = H3_GET_BASE_CELL(h);
|
81
93
|
if (baseCell < 0 || baseCell >= NUM_BASE_CELLS) return 0;
|
82
94
|
|
@@ -127,16 +139,16 @@ void setH3Index(H3Index* hp, int res, int baseCell, Direction initDigit) {
|
|
127
139
|
* @param h H3Index to find parent of
|
128
140
|
* @param parentRes The resolution to switch to (parent, grandparent, etc)
|
129
141
|
*
|
130
|
-
* @return H3Index of the parent, or
|
142
|
+
* @return H3Index of the parent, or H3_NULL if you actually asked for a child
|
131
143
|
*/
|
132
144
|
H3Index H3_EXPORT(h3ToParent)(H3Index h, int parentRes) {
|
133
145
|
int childRes = H3_GET_RESOLUTION(h);
|
134
146
|
if (parentRes > childRes) {
|
135
|
-
return
|
147
|
+
return H3_NULL;
|
136
148
|
} else if (parentRes == childRes) {
|
137
149
|
return h;
|
138
150
|
} else if (parentRes < 0 || parentRes > MAX_H3_RES) {
|
139
|
-
return
|
151
|
+
return H3_NULL;
|
140
152
|
}
|
141
153
|
H3Index parentH = H3_SET_RESOLUTION(h, parentRes);
|
142
154
|
for (int i = parentRes + 1; i <= childRes; i++) {
|
@@ -220,7 +232,7 @@ void H3_EXPORT(h3ToChildren)(H3Index h, int childRes, H3Index* children) {
|
|
220
232
|
if (isAPentagon && i == K_AXES_DIGIT) {
|
221
233
|
H3Index* nextChild = children + bufferChildStep;
|
222
234
|
while (children < nextChild) {
|
223
|
-
*children =
|
235
|
+
*children = H3_NULL;
|
224
236
|
children++;
|
225
237
|
}
|
226
238
|
} else {
|
@@ -237,12 +249,13 @@ void H3_EXPORT(h3ToChildren)(H3Index h, int childRes, H3Index* children) {
|
|
237
249
|
* @param h H3Index to find center child of
|
238
250
|
* @param childRes The resolution to switch to
|
239
251
|
*
|
240
|
-
* @return H3Index of the center child, or
|
252
|
+
* @return H3Index of the center child, or H3_NULL if you actually asked for a
|
253
|
+
* parent
|
241
254
|
*/
|
242
255
|
H3Index H3_EXPORT(h3ToCenterChild)(H3Index h, int childRes) {
|
243
256
|
int parentRes = H3_GET_RESOLUTION(h);
|
244
257
|
if (!_isValidChildRes(parentRes, childRes)) {
|
245
|
-
return
|
258
|
+
return H3_NULL;
|
246
259
|
} else if (childRes == parentRes) {
|
247
260
|
return h;
|
248
261
|
}
|
@@ -267,7 +280,7 @@ H3Index H3_EXPORT(h3ToCenterChild)(H3Index h, int childRes) {
|
|
267
280
|
int H3_EXPORT(compact)(const H3Index* h3Set, H3Index* compactedSet,
|
268
281
|
const int numHexes) {
|
269
282
|
if (numHexes == 0) {
|
270
|
-
return
|
283
|
+
return COMPACT_SUCCESS;
|
271
284
|
}
|
272
285
|
int res = H3_GET_RESOLUTION(h3Set[0]);
|
273
286
|
if (res == 0) {
|
@@ -275,11 +288,18 @@ int H3_EXPORT(compact)(const H3Index* h3Set, H3Index* compactedSet,
|
|
275
288
|
for (int i = 0; i < numHexes; i++) {
|
276
289
|
compactedSet[i] = h3Set[i];
|
277
290
|
}
|
278
|
-
return
|
291
|
+
return COMPACT_SUCCESS;
|
292
|
+
}
|
293
|
+
H3Index* remainingHexes = H3_MEMORY(malloc)(numHexes * sizeof(H3Index));
|
294
|
+
if (!remainingHexes) {
|
295
|
+
return COMPACT_ALLOC_FAILED;
|
279
296
|
}
|
280
|
-
H3Index* remainingHexes = malloc(numHexes * sizeof(H3Index));
|
281
297
|
memcpy(remainingHexes, h3Set, numHexes * sizeof(H3Index));
|
282
|
-
H3Index* hashSetArray = calloc(numHexes, sizeof(H3Index));
|
298
|
+
H3Index* hashSetArray = H3_MEMORY(calloc)(numHexes, sizeof(H3Index));
|
299
|
+
if (!hashSetArray) {
|
300
|
+
H3_MEMORY(free)(remainingHexes);
|
301
|
+
return COMPACT_ALLOC_FAILED;
|
302
|
+
}
|
283
303
|
H3Index* compactedSetOffset = compactedSet;
|
284
304
|
int numRemainingHexes = numHexes;
|
285
305
|
while (numRemainingHexes) {
|
@@ -301,23 +321,31 @@ int H3_EXPORT(compact)(const H3Index* h3Set, H3Index* compactedSet,
|
|
301
321
|
// This case should not be possible because at most one
|
302
322
|
// index is placed into hashSetArray per
|
303
323
|
// numRemainingHexes.
|
304
|
-
free(remainingHexes);
|
305
|
-
free(hashSetArray);
|
306
|
-
return
|
324
|
+
H3_MEMORY(free)(remainingHexes);
|
325
|
+
H3_MEMORY(free)(hashSetArray);
|
326
|
+
return COMPACT_LOOP_EXCEEDED;
|
307
327
|
// LCOV_EXCL_STOP
|
308
328
|
}
|
309
329
|
H3Index tempIndex =
|
310
330
|
hashSetArray[loc] & H3_RESERVED_MASK_NEGATIVE;
|
311
331
|
if (tempIndex == parent) {
|
312
332
|
int count = H3_GET_RESERVED_BITS(hashSetArray[loc]) + 1;
|
313
|
-
|
333
|
+
int limitCount = 7;
|
334
|
+
if (H3_EXPORT(h3IsPentagon)(
|
335
|
+
tempIndex & H3_RESERVED_MASK_NEGATIVE)) {
|
336
|
+
limitCount--;
|
337
|
+
}
|
338
|
+
// One is added to count for this check to match one
|
339
|
+
// being added to count later in this function when
|
340
|
+
// checking for all children being present.
|
341
|
+
if (count + 1 > limitCount) {
|
314
342
|
// Only possible on duplicate input
|
315
|
-
free(remainingHexes);
|
316
|
-
free(hashSetArray);
|
317
|
-
return
|
343
|
+
H3_MEMORY(free)(remainingHexes);
|
344
|
+
H3_MEMORY(free)(hashSetArray);
|
345
|
+
return COMPACT_DUPLICATE;
|
318
346
|
}
|
319
347
|
H3_SET_RESERVED_BITS(parent, count);
|
320
|
-
hashSetArray[loc] =
|
348
|
+
hashSetArray[loc] = H3_NULL;
|
321
349
|
} else {
|
322
350
|
loc = (loc + 1) % numRemainingHexes;
|
323
351
|
}
|
@@ -337,7 +365,12 @@ int H3_EXPORT(compact)(const H3Index* h3Set, H3Index* compactedSet,
|
|
337
365
|
break;
|
338
366
|
}
|
339
367
|
H3Index* compactableHexes =
|
340
|
-
|
368
|
+
H3_MEMORY(calloc)(maxCompactableCount, sizeof(H3Index));
|
369
|
+
if (!compactableHexes) {
|
370
|
+
H3_MEMORY(free)(remainingHexes);
|
371
|
+
H3_MEMORY(free)(hashSetArray);
|
372
|
+
return COMPACT_ALLOC_FAILED;
|
373
|
+
}
|
341
374
|
for (int i = 0; i < numRemainingHexes; i++) {
|
342
375
|
if (hashSetArray[i] == 0) continue;
|
343
376
|
int count = H3_GET_RESERVED_BITS(hashSetArray[i]) + 1;
|
@@ -363,7 +396,7 @@ int H3_EXPORT(compact)(const H3Index* h3Set, H3Index* compactedSet,
|
|
363
396
|
int uncompactableCount = 0;
|
364
397
|
for (int i = 0; i < numRemainingHexes; i++) {
|
365
398
|
H3Index currIndex = remainingHexes[i];
|
366
|
-
if (currIndex !=
|
399
|
+
if (currIndex != H3_NULL) {
|
367
400
|
H3Index parent = H3_EXPORT(h3ToParent)(currIndex, parentRes);
|
368
401
|
// Modulus hash the parent into the temp array
|
369
402
|
// to determine if this index was included in
|
@@ -376,10 +409,10 @@ int H3_EXPORT(compact)(const H3Index* h3Set, H3Index* compactedSet,
|
|
376
409
|
// LCOV_EXCL_START
|
377
410
|
// This case should not be possible because at most one
|
378
411
|
// index is placed into hashSetArray per input hexagon.
|
379
|
-
free(compactableHexes);
|
380
|
-
free(remainingHexes);
|
381
|
-
free(hashSetArray);
|
382
|
-
return
|
412
|
+
H3_MEMORY(free)(compactableHexes);
|
413
|
+
H3_MEMORY(free)(remainingHexes);
|
414
|
+
H3_MEMORY(free)(hashSetArray);
|
415
|
+
return COMPACT_LOOP_EXCEEDED;
|
383
416
|
// LCOV_EXCL_STOP
|
384
417
|
}
|
385
418
|
H3Index tempIndex =
|
@@ -407,11 +440,11 @@ int H3_EXPORT(compact)(const H3Index* h3Set, H3Index* compactedSet,
|
|
407
440
|
memcpy(remainingHexes, compactableHexes,
|
408
441
|
compactableCount * sizeof(H3Index));
|
409
442
|
numRemainingHexes = compactableCount;
|
410
|
-
free(compactableHexes);
|
443
|
+
H3_MEMORY(free)(compactableHexes);
|
411
444
|
}
|
412
|
-
free(remainingHexes);
|
413
|
-
free(hashSetArray);
|
414
|
-
return
|
445
|
+
H3_MEMORY(free)(remainingHexes);
|
446
|
+
H3_MEMORY(free)(hashSetArray);
|
447
|
+
return COMPACT_SUCCESS;
|
415
448
|
}
|
416
449
|
|
417
450
|
/**
|
@@ -603,7 +636,7 @@ H3Index _h3Rotate60cw(H3Index h) {
|
|
603
636
|
* Convert an FaceIJK address to the corresponding H3Index.
|
604
637
|
* @param fijk The FaceIJK address.
|
605
638
|
* @param res The cell resolution.
|
606
|
-
* @return The encoded H3Index (or
|
639
|
+
* @return The encoded H3Index (or H3_NULL on failure).
|
607
640
|
*/
|
608
641
|
H3Index _faceIjkToH3(const FaceIJK* fijk, int res) {
|
609
642
|
// initialize the index
|
@@ -616,7 +649,7 @@ H3Index _faceIjkToH3(const FaceIJK* fijk, int res) {
|
|
616
649
|
if (fijk->coord.i > MAX_FACE_COORD || fijk->coord.j > MAX_FACE_COORD ||
|
617
650
|
fijk->coord.k > MAX_FACE_COORD) {
|
618
651
|
// out of range input
|
619
|
-
return
|
652
|
+
return H3_NULL;
|
620
653
|
}
|
621
654
|
|
622
655
|
H3_SET_BASE_CELL(h, _faceIjkToBaseCell(fijk));
|
@@ -660,7 +693,7 @@ H3Index _faceIjkToH3(const FaceIJK* fijk, int res) {
|
|
660
693
|
if (fijkBC.coord.i > MAX_FACE_COORD || fijkBC.coord.j > MAX_FACE_COORD ||
|
661
694
|
fijkBC.coord.k > MAX_FACE_COORD) {
|
662
695
|
// out of range input
|
663
|
-
return
|
696
|
+
return H3_NULL;
|
664
697
|
}
|
665
698
|
|
666
699
|
// lookup the correct base cell
|
@@ -699,14 +732,14 @@ H3Index _faceIjkToH3(const FaceIJK* fijk, int res) {
|
|
699
732
|
*
|
700
733
|
* @param g The spherical coordinates to encode.
|
701
734
|
* @param res The desired H3 resolution for the encoding.
|
702
|
-
* @return The encoded H3Index (or
|
735
|
+
* @return The encoded H3Index (or H3_NULL on failure).
|
703
736
|
*/
|
704
737
|
H3Index H3_EXPORT(geoToH3)(const GeoCoord* g, int res) {
|
705
738
|
if (res < 0 || res > MAX_H3_RES) {
|
706
|
-
return
|
739
|
+
return H3_NULL;
|
707
740
|
}
|
708
741
|
if (!isfinite(g->lat) || !isfinite(g->lon)) {
|
709
|
-
return
|
742
|
+
return H3_NULL;
|
710
743
|
}
|
711
744
|
|
712
745
|
FaceIJK fijk;
|
@@ -816,8 +849,13 @@ void H3_EXPORT(h3ToGeo)(H3Index h3, GeoCoord* g) {
|
|
816
849
|
void H3_EXPORT(h3ToGeoBoundary)(H3Index h3, GeoBoundary* gb) {
|
817
850
|
FaceIJK fijk;
|
818
851
|
_h3ToFaceIjk(h3, &fijk);
|
819
|
-
|
820
|
-
|
852
|
+
if (H3_EXPORT(h3IsPentagon)(h3)) {
|
853
|
+
_faceIjkPentToGeoBoundary(&fijk, H3_GET_RESOLUTION(h3), 0,
|
854
|
+
NUM_PENT_VERTS, gb);
|
855
|
+
} else {
|
856
|
+
_faceIjkToGeoBoundary(&fijk, H3_GET_RESOLUTION(h3), 0, NUM_HEX_VERTS,
|
857
|
+
gb);
|
858
|
+
}
|
821
859
|
}
|
822
860
|
|
823
861
|
/**
|
@@ -19,11 +19,13 @@
|
|
19
19
|
|
20
20
|
#include <inttypes.h>
|
21
21
|
#include <stdbool.h>
|
22
|
+
|
22
23
|
#include "algos.h"
|
23
24
|
#include "constants.h"
|
24
25
|
#include "coordijk.h"
|
25
26
|
#include "geoCoord.h"
|
26
27
|
#include "h3Index.h"
|
28
|
+
#include "vertex.h"
|
27
29
|
|
28
30
|
/**
|
29
31
|
* Returns whether or not the provided H3Indexes are neighbors.
|
@@ -96,25 +98,30 @@ int H3_EXPORT(h3IndexesAreNeighbors)(H3Index origin, H3Index destination) {
|
|
96
98
|
* destination
|
97
99
|
* @param origin The origin H3 hexagon index
|
98
100
|
* @param destination The destination H3 hexagon index
|
99
|
-
* @return The unidirectional edge H3Index, or
|
101
|
+
* @return The unidirectional edge H3Index, or H3_NULL on failure.
|
100
102
|
*/
|
101
103
|
H3Index H3_EXPORT(getH3UnidirectionalEdge)(H3Index origin,
|
102
104
|
H3Index destination) {
|
103
105
|
// Short-circuit and return an invalid index value if they are not neighbors
|
104
106
|
if (H3_EXPORT(h3IndexesAreNeighbors)(origin, destination) == 0) {
|
105
|
-
return
|
107
|
+
return H3_NULL;
|
106
108
|
}
|
107
109
|
|
108
110
|
// Otherwise, determine the IJK direction from the origin to the destination
|
109
111
|
H3Index output = origin;
|
110
112
|
H3_SET_MODE(output, H3_UNIEDGE_MODE);
|
111
113
|
|
114
|
+
bool isPentagon = H3_EXPORT(h3IsPentagon)(origin);
|
115
|
+
|
112
116
|
// Checks each neighbor, in order, to determine which direction the
|
113
117
|
// destination neighbor is located. Skips CENTER_DIGIT since that
|
114
118
|
// would be this index.
|
115
119
|
H3Index neighbor;
|
116
|
-
|
117
|
-
|
120
|
+
// Excluding from branch coverage as we never hit the end condition
|
121
|
+
// LCOV_EXCL_BR_START
|
122
|
+
for (Direction direction = isPentagon ? J_AXES_DIGIT : K_AXES_DIGIT;
|
123
|
+
direction < NUM_DIGITS; direction++) {
|
124
|
+
// LCOV_EXCL_BR_STOP
|
118
125
|
int rotations = 0;
|
119
126
|
neighbor = h3NeighborRotations(origin, direction, &rotations);
|
120
127
|
if (neighbor == destination) {
|
@@ -123,18 +130,18 @@ H3Index H3_EXPORT(getH3UnidirectionalEdge)(H3Index origin,
|
|
123
130
|
}
|
124
131
|
}
|
125
132
|
|
126
|
-
// This should be impossible, return
|
127
|
-
return
|
133
|
+
// This should be impossible, return H3_NULL in this case;
|
134
|
+
return H3_NULL; // LCOV_EXCL_LINE
|
128
135
|
}
|
129
136
|
|
130
137
|
/**
|
131
138
|
* Returns the origin hexagon from the unidirectional edge H3Index
|
132
139
|
* @param edge The edge H3 index
|
133
|
-
* @return The origin H3 hexagon index
|
140
|
+
* @return The origin H3 hexagon index, or H3_NULL on failure
|
134
141
|
*/
|
135
142
|
H3Index H3_EXPORT(getOriginH3IndexFromUnidirectionalEdge)(H3Index edge) {
|
136
143
|
if (H3_GET_MODE(edge) != H3_UNIEDGE_MODE) {
|
137
|
-
return
|
144
|
+
return H3_NULL;
|
138
145
|
}
|
139
146
|
H3Index origin = edge;
|
140
147
|
H3_SET_MODE(origin, H3_HEXAGON_MODE);
|
@@ -145,11 +152,11 @@ H3Index H3_EXPORT(getOriginH3IndexFromUnidirectionalEdge)(H3Index edge) {
|
|
145
152
|
/**
|
146
153
|
* Returns the destination hexagon from the unidirectional edge H3Index
|
147
154
|
* @param edge The edge H3 index
|
148
|
-
* @return The destination H3 hexagon index
|
155
|
+
* @return The destination H3 hexagon index, or H3_NULL on failure
|
149
156
|
*/
|
150
157
|
H3Index H3_EXPORT(getDestinationH3IndexFromUnidirectionalEdge)(H3Index edge) {
|
151
158
|
if (H3_GET_MODE(edge) != H3_UNIEDGE_MODE) {
|
152
|
-
return
|
159
|
+
return H3_NULL;
|
153
160
|
}
|
154
161
|
Direction direction = H3_GET_RESERVED_BITS(edge);
|
155
162
|
int rotations = 0;
|
@@ -211,7 +218,7 @@ void H3_EXPORT(getH3UnidirectionalEdgesFromHexagon)(H3Index origin,
|
|
211
218
|
// which is zeroed.
|
212
219
|
for (int i = 0; i < 6; i++) {
|
213
220
|
if (isPentagon && i == 0) {
|
214
|
-
edges[i] =
|
221
|
+
edges[i] = H3_NULL;
|
215
222
|
} else {
|
216
223
|
edges[i] = origin;
|
217
224
|
H3_SET_MODE(edges[i], H3_UNIEDGE_MODE);
|
@@ -220,59 +227,37 @@ void H3_EXPORT(getH3UnidirectionalEdgesFromHexagon)(H3Index origin,
|
|
220
227
|
}
|
221
228
|
}
|
222
229
|
|
223
|
-
/**
|
224
|
-
* Whether the given coordinate has a matching vertex in the given geo boundary.
|
225
|
-
* @param vertex Coordinate to check
|
226
|
-
* @param boundary Geo boundary to look in
|
227
|
-
* @return Whether a match was found
|
228
|
-
*/
|
229
|
-
static bool _hasMatchingVertex(const GeoCoord* vertex,
|
230
|
-
const GeoBoundary* boundary) {
|
231
|
-
for (int i = 0; i < boundary->numVerts; i++) {
|
232
|
-
if (geoAlmostEqualThreshold(vertex, &boundary->verts[i], 0.000001)) {
|
233
|
-
return true;
|
234
|
-
}
|
235
|
-
}
|
236
|
-
return false;
|
237
|
-
}
|
238
|
-
|
239
230
|
/**
|
240
231
|
* Provides the coordinates defining the unidirectional edge.
|
241
232
|
* @param edge The unidirectional edge H3Index
|
242
233
|
* @param gb The geoboundary object to store the edge coordinates.
|
243
234
|
*/
|
244
235
|
void H3_EXPORT(getH3UnidirectionalEdgeBoundary)(H3Index edge, GeoBoundary* gb) {
|
245
|
-
//
|
246
|
-
|
247
|
-
|
248
|
-
GeoCoord postponedVertex = {0};
|
249
|
-
bool hasPostponedVertex = false;
|
250
|
-
|
251
|
-
H3_EXPORT(h3ToGeoBoundary)
|
252
|
-
(H3_EXPORT(getOriginH3IndexFromUnidirectionalEdge)(edge), &origin);
|
253
|
-
H3_EXPORT(h3ToGeoBoundary)
|
254
|
-
(H3_EXPORT(getDestinationH3IndexFromUnidirectionalEdge)(edge),
|
255
|
-
&destination);
|
236
|
+
// Get the origin and neighbor direction from the edge
|
237
|
+
Direction direction = H3_GET_RESERVED_BITS(edge);
|
238
|
+
H3Index origin = H3_EXPORT(getOriginH3IndexFromUnidirectionalEdge)(edge);
|
256
239
|
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
postponedVertex = origin.verts[i];
|
265
|
-
hasPostponedVertex = true;
|
266
|
-
} else {
|
267
|
-
gb->verts[k] = origin.verts[i];
|
268
|
-
k++;
|
269
|
-
}
|
270
|
-
}
|
240
|
+
// Get the start vertex for the edge
|
241
|
+
int startVertex = vertexNumForDirection(origin, direction);
|
242
|
+
if (startVertex == INVALID_VERTEX_NUM) {
|
243
|
+
// This is not actually an edge (i.e. no valid direction),
|
244
|
+
// so return no vertices.
|
245
|
+
gb->numVerts = 0;
|
246
|
+
return;
|
271
247
|
}
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
248
|
+
|
249
|
+
// Get the geo boundary for the appropriate vertexes of the origin. Note
|
250
|
+
// that while there are always 2 topological vertexes per edge, the
|
251
|
+
// resulting edge boundary may have an additional distortion vertex if it
|
252
|
+
// crosses an edge of the icosahedron.
|
253
|
+
FaceIJK fijk;
|
254
|
+
_h3ToFaceIjk(origin, &fijk);
|
255
|
+
int res = H3_GET_RESOLUTION(origin);
|
256
|
+
int isPentagon = H3_EXPORT(h3IsPentagon)(origin);
|
257
|
+
|
258
|
+
if (isPentagon) {
|
259
|
+
_faceIjkPentToGeoBoundary(&fijk, res, startVertex, 2, gb);
|
260
|
+
} else {
|
261
|
+
_faceIjkToGeoBoundary(&fijk, res, startVertex, 2, gb);
|
276
262
|
}
|
277
|
-
gb->numVerts = k;
|
278
263
|
}
|