h3 3.6.0 → 3.7.2
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 +4 -4
- data/.github/workflows/ruby_ci.yml +30 -0
- data/.rubocop.yml +1 -1
- data/.ruby-version +1 -0
- data/CHANGELOG.md +39 -0
- data/Gemfile.lock +6 -24
- data/LICENSE.md +1 -1
- data/README.md +2 -3
- 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 +20 -42
- data/ext/h3/src/CHANGELOG.md +57 -0
- data/ext/h3/src/CMakeLists.txt +135 -33
- data/ext/h3/src/CONTRIBUTING.md +1 -1
- data/ext/h3/src/README.md +61 -11
- 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 +10 -0
- 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 +109 -2
- data/ext/h3/src/src/apps/testapps/testCoordIj.c +1 -0
- data/ext/h3/src/src/apps/testapps/testGeoCoord.c +47 -8
- 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 +12 -6
- 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 +19 -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 +27 -1
- 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 +304 -76
- data/ext/h3/src/src/h3lib/lib/baseCells.c +26 -4
- data/ext/h3/src/src/h3lib/lib/bbox.c +56 -27
- 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 +83 -42
- 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/h3.gemspec +2 -2
- data/lib/h3/bindings/base.rb +14 -4
- data/lib/h3/bindings/private.rb +12 -9
- data/lib/h3/hierarchy.rb +0 -18
- data/lib/h3/indexing.rb +0 -18
- data/lib/h3/inspection.rb +3 -59
- data/lib/h3/miscellaneous.rb +119 -14
- data/lib/h3/regions.rb +3 -0
- data/lib/h3/traversal.rb +0 -18
- data/lib/h3/unidirectional_edges.rb +5 -60
- data/lib/h3/version.rb +1 -1
- data/spec/geo_json_spec.rb +8 -0
- data/spec/miscellaneous_spec.rb +117 -0
- data/spec/{region_spec.rb → regions_spec.rb} +1 -1
- data/spec/spec_helper.rb +2 -2
- metadata +44 -36
- data/.travis.yml +0 -11
- data/ext/h3/src/.ycm_extra_conf.py +0 -92
- data/ext/h3/src/appveyor.yml +0 -50
- 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
|
}
|
|
@@ -266,17 +279,27 @@ H3Index H3_EXPORT(h3ToCenterChild)(H3Index h, int childRes) {
|
|
|
266
279
|
*/
|
|
267
280
|
int H3_EXPORT(compact)(const H3Index* h3Set, H3Index* compactedSet,
|
|
268
281
|
const int numHexes) {
|
|
282
|
+
if (numHexes == 0) {
|
|
283
|
+
return COMPACT_SUCCESS;
|
|
284
|
+
}
|
|
269
285
|
int res = H3_GET_RESOLUTION(h3Set[0]);
|
|
270
286
|
if (res == 0) {
|
|
271
287
|
// No compaction possible, just copy the set to output
|
|
272
288
|
for (int i = 0; i < numHexes; i++) {
|
|
273
289
|
compactedSet[i] = h3Set[i];
|
|
274
290
|
}
|
|
275
|
-
return
|
|
291
|
+
return COMPACT_SUCCESS;
|
|
292
|
+
}
|
|
293
|
+
H3Index* remainingHexes = H3_MEMORY(malloc)(numHexes * sizeof(H3Index));
|
|
294
|
+
if (!remainingHexes) {
|
|
295
|
+
return COMPACT_ALLOC_FAILED;
|
|
276
296
|
}
|
|
277
|
-
H3Index* remainingHexes = malloc(numHexes * sizeof(H3Index));
|
|
278
297
|
memcpy(remainingHexes, h3Set, numHexes * sizeof(H3Index));
|
|
279
|
-
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
|
+
}
|
|
280
303
|
H3Index* compactedSetOffset = compactedSet;
|
|
281
304
|
int numRemainingHexes = numHexes;
|
|
282
305
|
while (numRemainingHexes) {
|
|
@@ -298,23 +321,31 @@ int H3_EXPORT(compact)(const H3Index* h3Set, H3Index* compactedSet,
|
|
|
298
321
|
// This case should not be possible because at most one
|
|
299
322
|
// index is placed into hashSetArray per
|
|
300
323
|
// numRemainingHexes.
|
|
301
|
-
free(remainingHexes);
|
|
302
|
-
free(hashSetArray);
|
|
303
|
-
return
|
|
324
|
+
H3_MEMORY(free)(remainingHexes);
|
|
325
|
+
H3_MEMORY(free)(hashSetArray);
|
|
326
|
+
return COMPACT_LOOP_EXCEEDED;
|
|
304
327
|
// LCOV_EXCL_STOP
|
|
305
328
|
}
|
|
306
329
|
H3Index tempIndex =
|
|
307
330
|
hashSetArray[loc] & H3_RESERVED_MASK_NEGATIVE;
|
|
308
331
|
if (tempIndex == parent) {
|
|
309
332
|
int count = H3_GET_RESERVED_BITS(hashSetArray[loc]) + 1;
|
|
310
|
-
|
|
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) {
|
|
311
342
|
// Only possible on duplicate input
|
|
312
|
-
free(remainingHexes);
|
|
313
|
-
free(hashSetArray);
|
|
314
|
-
return
|
|
343
|
+
H3_MEMORY(free)(remainingHexes);
|
|
344
|
+
H3_MEMORY(free)(hashSetArray);
|
|
345
|
+
return COMPACT_DUPLICATE;
|
|
315
346
|
}
|
|
316
347
|
H3_SET_RESERVED_BITS(parent, count);
|
|
317
|
-
hashSetArray[loc] =
|
|
348
|
+
hashSetArray[loc] = H3_NULL;
|
|
318
349
|
} else {
|
|
319
350
|
loc = (loc + 1) % numRemainingHexes;
|
|
320
351
|
}
|
|
@@ -334,7 +365,12 @@ int H3_EXPORT(compact)(const H3Index* h3Set, H3Index* compactedSet,
|
|
|
334
365
|
break;
|
|
335
366
|
}
|
|
336
367
|
H3Index* compactableHexes =
|
|
337
|
-
|
|
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
|
+
}
|
|
338
374
|
for (int i = 0; i < numRemainingHexes; i++) {
|
|
339
375
|
if (hashSetArray[i] == 0) continue;
|
|
340
376
|
int count = H3_GET_RESERVED_BITS(hashSetArray[i]) + 1;
|
|
@@ -360,7 +396,7 @@ int H3_EXPORT(compact)(const H3Index* h3Set, H3Index* compactedSet,
|
|
|
360
396
|
int uncompactableCount = 0;
|
|
361
397
|
for (int i = 0; i < numRemainingHexes; i++) {
|
|
362
398
|
H3Index currIndex = remainingHexes[i];
|
|
363
|
-
if (currIndex !=
|
|
399
|
+
if (currIndex != H3_NULL) {
|
|
364
400
|
H3Index parent = H3_EXPORT(h3ToParent)(currIndex, parentRes);
|
|
365
401
|
// Modulus hash the parent into the temp array
|
|
366
402
|
// to determine if this index was included in
|
|
@@ -373,10 +409,10 @@ int H3_EXPORT(compact)(const H3Index* h3Set, H3Index* compactedSet,
|
|
|
373
409
|
// LCOV_EXCL_START
|
|
374
410
|
// This case should not be possible because at most one
|
|
375
411
|
// index is placed into hashSetArray per input hexagon.
|
|
376
|
-
free(compactableHexes);
|
|
377
|
-
free(remainingHexes);
|
|
378
|
-
free(hashSetArray);
|
|
379
|
-
return
|
|
412
|
+
H3_MEMORY(free)(compactableHexes);
|
|
413
|
+
H3_MEMORY(free)(remainingHexes);
|
|
414
|
+
H3_MEMORY(free)(hashSetArray);
|
|
415
|
+
return COMPACT_LOOP_EXCEEDED;
|
|
380
416
|
// LCOV_EXCL_STOP
|
|
381
417
|
}
|
|
382
418
|
H3Index tempIndex =
|
|
@@ -404,11 +440,11 @@ int H3_EXPORT(compact)(const H3Index* h3Set, H3Index* compactedSet,
|
|
|
404
440
|
memcpy(remainingHexes, compactableHexes,
|
|
405
441
|
compactableCount * sizeof(H3Index));
|
|
406
442
|
numRemainingHexes = compactableCount;
|
|
407
|
-
free(compactableHexes);
|
|
443
|
+
H3_MEMORY(free)(compactableHexes);
|
|
408
444
|
}
|
|
409
|
-
free(remainingHexes);
|
|
410
|
-
free(hashSetArray);
|
|
411
|
-
return
|
|
445
|
+
H3_MEMORY(free)(remainingHexes);
|
|
446
|
+
H3_MEMORY(free)(hashSetArray);
|
|
447
|
+
return COMPACT_SUCCESS;
|
|
412
448
|
}
|
|
413
449
|
|
|
414
450
|
/**
|
|
@@ -600,7 +636,7 @@ H3Index _h3Rotate60cw(H3Index h) {
|
|
|
600
636
|
* Convert an FaceIJK address to the corresponding H3Index.
|
|
601
637
|
* @param fijk The FaceIJK address.
|
|
602
638
|
* @param res The cell resolution.
|
|
603
|
-
* @return The encoded H3Index (or
|
|
639
|
+
* @return The encoded H3Index (or H3_NULL on failure).
|
|
604
640
|
*/
|
|
605
641
|
H3Index _faceIjkToH3(const FaceIJK* fijk, int res) {
|
|
606
642
|
// initialize the index
|
|
@@ -613,7 +649,7 @@ H3Index _faceIjkToH3(const FaceIJK* fijk, int res) {
|
|
|
613
649
|
if (fijk->coord.i > MAX_FACE_COORD || fijk->coord.j > MAX_FACE_COORD ||
|
|
614
650
|
fijk->coord.k > MAX_FACE_COORD) {
|
|
615
651
|
// out of range input
|
|
616
|
-
return
|
|
652
|
+
return H3_NULL;
|
|
617
653
|
}
|
|
618
654
|
|
|
619
655
|
H3_SET_BASE_CELL(h, _faceIjkToBaseCell(fijk));
|
|
@@ -657,7 +693,7 @@ H3Index _faceIjkToH3(const FaceIJK* fijk, int res) {
|
|
|
657
693
|
if (fijkBC.coord.i > MAX_FACE_COORD || fijkBC.coord.j > MAX_FACE_COORD ||
|
|
658
694
|
fijkBC.coord.k > MAX_FACE_COORD) {
|
|
659
695
|
// out of range input
|
|
660
|
-
return
|
|
696
|
+
return H3_NULL;
|
|
661
697
|
}
|
|
662
698
|
|
|
663
699
|
// lookup the correct base cell
|
|
@@ -696,14 +732,14 @@ H3Index _faceIjkToH3(const FaceIJK* fijk, int res) {
|
|
|
696
732
|
*
|
|
697
733
|
* @param g The spherical coordinates to encode.
|
|
698
734
|
* @param res The desired H3 resolution for the encoding.
|
|
699
|
-
* @return The encoded H3Index (or
|
|
735
|
+
* @return The encoded H3Index (or H3_NULL on failure).
|
|
700
736
|
*/
|
|
701
737
|
H3Index H3_EXPORT(geoToH3)(const GeoCoord* g, int res) {
|
|
702
738
|
if (res < 0 || res > MAX_H3_RES) {
|
|
703
|
-
return
|
|
739
|
+
return H3_NULL;
|
|
704
740
|
}
|
|
705
741
|
if (!isfinite(g->lat) || !isfinite(g->lon)) {
|
|
706
|
-
return
|
|
742
|
+
return H3_NULL;
|
|
707
743
|
}
|
|
708
744
|
|
|
709
745
|
FaceIJK fijk;
|
|
@@ -813,8 +849,13 @@ void H3_EXPORT(h3ToGeo)(H3Index h3, GeoCoord* g) {
|
|
|
813
849
|
void H3_EXPORT(h3ToGeoBoundary)(H3Index h3, GeoBoundary* gb) {
|
|
814
850
|
FaceIJK fijk;
|
|
815
851
|
_h3ToFaceIjk(h3, &fijk);
|
|
816
|
-
|
|
817
|
-
|
|
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
|
+
}
|
|
818
859
|
}
|
|
819
860
|
|
|
820
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
|
}
|