h3 3.6.2 → 3.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|
}
|