h3 3.4.4 → 3.5.0

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 +10 -0
  3. data/Gemfile.lock +1 -1
  4. data/README.md +2 -1
  5. data/ext/h3/Makefile +1 -1
  6. data/ext/h3/src/.gitignore +2 -1
  7. data/ext/h3/src/CHANGELOG.md +9 -0
  8. data/ext/h3/src/CMakeLists.txt +72 -45
  9. data/ext/h3/src/RELEASE.md +2 -1
  10. data/ext/h3/src/VERSION +1 -1
  11. data/ext/h3/src/docs/api/hierarchy.md +2 -0
  12. data/ext/h3/src/docs/api/indexing.md +3 -1
  13. data/ext/h3/src/docs/api/inspection.md +20 -0
  14. data/ext/h3/src/docs/api/misc.md +2 -0
  15. data/ext/h3/src/docs/api/regions.md +2 -0
  16. data/ext/h3/src/docs/api/traversal.md +2 -0
  17. data/ext/h3/src/docs/api/uniedge.md +2 -0
  18. data/ext/h3/src/docs/community/bindings.md +4 -0
  19. data/ext/h3/src/docs/community/tutorials.md +12 -0
  20. data/ext/h3/src/scripts/update_version.sh +50 -0
  21. data/ext/h3/src/src/apps/applib/include/args.h +122 -0
  22. data/ext/h3/src/src/apps/applib/include/utility.h +5 -62
  23. data/ext/h3/src/src/apps/applib/lib/args.c +216 -0
  24. data/ext/h3/src/src/apps/applib/lib/utility.c +40 -206
  25. data/ext/h3/src/src/apps/filters/geoToH3.c +7 -9
  26. data/ext/h3/src/src/apps/filters/h3ToComponents.c +50 -47
  27. data/ext/h3/src/src/apps/filters/h3ToGeo.c +7 -30
  28. data/ext/h3/src/src/apps/filters/h3ToGeoBoundary.c +7 -27
  29. data/ext/h3/src/src/apps/filters/h3ToLocalIj.c +42 -25
  30. data/ext/h3/src/src/apps/filters/hexRange.c +43 -24
  31. data/ext/h3/src/src/apps/filters/kRing.c +4 -4
  32. data/ext/h3/src/src/apps/filters/localIjToH3.c +63 -21
  33. data/ext/h3/src/src/apps/miscapps/h3ToGeoBoundaryHier.c +68 -44
  34. data/ext/h3/src/src/apps/miscapps/h3ToGeoHier.c +68 -43
  35. data/ext/h3/src/src/apps/miscapps/h3ToHier.c +48 -37
  36. data/ext/h3/src/src/apps/testapps/mkRandGeo.c +32 -27
  37. data/ext/h3/src/src/apps/testapps/mkRandGeoBoundary.c +33 -28
  38. data/ext/h3/src/src/apps/testapps/testH3GetFaces.c +136 -0
  39. data/ext/h3/src/src/h3lib/include/faceijk.h +19 -7
  40. data/ext/h3/src/src/h3lib/include/h3api.h.in +12 -1
  41. data/ext/h3/src/src/h3lib/lib/algos.c +7 -2
  42. data/ext/h3/src/src/h3lib/lib/faceijk.c +135 -103
  43. data/ext/h3/src/src/h3lib/lib/h3Index.c +86 -5
  44. data/lib/h3/bindings/private.rb +1 -0
  45. data/lib/h3/inspection.rb +34 -0
  46. data/lib/h3/version.rb +1 -1
  47. data/spec/inspection_spec.rb +33 -1
  48. metadata +6 -2
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2016-2017 Uber Technologies, Inc.
2
+ * Copyright 2016-2017, 2019 Uber Technologies, Inc.
3
3
  *
4
4
  * Licensed under the Apache License, Version 2.0 (the "License");
5
5
  * you may not use this file except in compliance with the License.
@@ -17,7 +17,7 @@
17
17
  * @brief takes an optional H3 index and generates all descendant cells at the
18
18
  * specified resolution.
19
19
  *
20
- * usage: `h3ToHier [resolution H3Index]`
20
+ * See `h3ToHier --help` for usage.
21
21
  *
22
22
  * The program generates all cells at the specified resolution, optionally
23
23
  * only the children of the given index.
@@ -25,30 +25,25 @@
25
25
  * `resolution` should be a positive integer. The default is 0 (i.e., only the
26
26
  * base cells).
27
27
  *
28
- * `H3Index` should be an H3Index. By default, all indices at the specified
28
+ * `parent` should be an H3Index. By default, all indices at the specified
29
29
  * resolution are generated.
30
30
  */
31
31
 
32
+ #include <inttypes.h>
32
33
  #include <stdio.h>
33
34
  #include <stdlib.h>
34
- #include <string.h>
35
+ #include "args.h"
35
36
  #include "baseCells.h"
36
- #include "coordijk.h"
37
- #include "geoCoord.h"
38
37
  #include "h3Index.h"
39
38
  #include "h3api.h"
40
39
  #include "kml.h"
41
40
  #include "utility.h"
42
- #include "vec2d.h"
43
-
44
- #include "algos.h"
45
41
 
46
42
  void recursiveH3IndexToHier(H3Index h, int res) {
47
43
  for (int d = 0; d < 7; d++) {
48
44
  H3_SET_INDEX_DIGIT(h, res, d);
49
45
 
50
46
  // skip the pentagonal deleted subsequence
51
-
52
47
  if (_isBaseCellPentagon(H3_GET_BASE_CELL(h)) &&
53
48
  _h3LeadingNonZeroDigit(h) == 1) {
54
49
  continue;
@@ -62,28 +57,54 @@ void recursiveH3IndexToHier(H3Index h, int res) {
62
57
  }
63
58
  }
64
59
 
65
- int main(int argc, char* argv[]) {
66
- // check command line args
67
- if (argc < 2 || argc > 3) {
68
- fprintf(stderr, "usage: %s [resolution H3Index]\n", argv[0]);
69
- exit(1);
70
- }
60
+ int main(int argc, char *argv[]) {
61
+ int res;
62
+ H3Index parentIndex = 0;
71
63
 
72
- int res = 0;
73
- if (!sscanf(argv[1], "%d", &res)) error("resolution must be an integer");
64
+ Arg helpArg = ARG_HELP;
65
+ Arg resArg = {.names = {"-r", "--resolution"},
66
+ .scanFormat = "%d",
67
+ .valueName = "res",
68
+ .value = &res,
69
+ .required = true,
70
+ .helpText = "Resolution, 0-15 inclusive."};
71
+ Arg parentArg = {
72
+ .names = {"-p", "--parent"},
73
+ .scanFormat = "%" PRIx64,
74
+ .valueName = "parent",
75
+ .value = &parentIndex,
76
+ .helpText = "Print only indexes descendent from this index."};
74
77
 
75
- if (res > MAX_H3_RES) error("specified resolution exceeds max resolution");
78
+ Arg *args[] = {&helpArg, &resArg, &parentArg};
79
+ const int numArgs = 3;
80
+ const char *helpText = "Print all indexes at the specified resolution";
76
81
 
77
- H3Index prefixIndex = 0;
78
- if (argc > 2) {
79
- prefixIndex = H3_EXPORT(stringToH3)(argv[2]);
80
- int h3BaseCell = H3_GET_BASE_CELL(prefixIndex);
81
- if (h3BaseCell < 0 || h3BaseCell >= NUM_BASE_CELLS) {
82
- error("invalid base cell number");
83
- }
82
+ if (parseArgs(argc, argv, numArgs, args, &helpArg, helpText)) {
83
+ return helpArg.found ? 0 : 1;
84
+ }
85
+
86
+ if (res > MAX_H3_RES) {
87
+ printHelp(stderr, argv[0], helpText, numArgs, args,
88
+ "Resolution exceeds maximum resolution.", NULL);
89
+ return 1;
90
+ }
91
+
92
+ if (parentArg.found && !H3_EXPORT(h3IsValid)(parentIndex)) {
93
+ printHelp(stderr, argv[0], helpText, numArgs, args,
94
+ "Parent index is invalid.", NULL);
95
+ return 1;
84
96
  }
85
97
 
86
- if (prefixIndex == 0) {
98
+ if (parentArg.found) {
99
+ // parent is the same or higher resolution than the target.
100
+ if (res <= H3_GET_RESOLUTION(parentIndex)) {
101
+ h3Println(parentIndex);
102
+ } else {
103
+ int rootRes = H3_GET_RESOLUTION(parentIndex);
104
+ H3_SET_RESOLUTION(parentIndex, res);
105
+ recursiveH3IndexToHier(parentIndex, rootRes + 1);
106
+ }
107
+ } else {
87
108
  // Generate all
88
109
  for (int bc = 0; bc < NUM_BASE_CELLS; bc++) {
89
110
  H3Index rootCell = H3_INIT;
@@ -96,15 +117,5 @@ int main(int argc, char* argv[]) {
96
117
  recursiveH3IndexToHier(rootCell, 1);
97
118
  }
98
119
  }
99
- } else {
100
- // prefix is the same or higher resolution than
101
- // the target.
102
- if (res <= H3_GET_RESOLUTION(prefixIndex)) {
103
- h3Println(prefixIndex);
104
- } else {
105
- int rootRes = H3_GET_RESOLUTION(prefixIndex);
106
- H3_SET_RESOLUTION(prefixIndex, res);
107
- recursiveH3IndexToHier(prefixIndex, rootRes + 1);
108
- }
109
120
  }
110
121
  }
@@ -17,7 +17,7 @@
17
17
  * @brief generates random lat/lon pairs and bins them at the specified
18
18
  * resolution
19
19
  *
20
- * usage: `mkRandGeo numPoints resolution`
20
+ * See `mkRandGeo --help` for usage.
21
21
  *
22
22
  * The program generates `numPoints` random lat/lon coordinates and outputs
23
23
  * them along with the corresponding H3Index at the specified `resolution`.
@@ -25,38 +25,43 @@
25
25
 
26
26
  #include <stdio.h>
27
27
  #include <stdlib.h>
28
- #include <time.h>
29
- #include "baseCells.h"
30
- #include "h3Index.h"
28
+ #include "args.h"
31
29
  #include "utility.h"
32
30
 
33
- void randomGeo(GeoCoord* g) {
34
- static int init = 0;
35
- if (!init) {
36
- srand((unsigned int)time(0));
37
- init = 1;
38
- }
39
-
40
- g->lat = H3_EXPORT(degsToRads)(
41
- (((float)rand() / (float)(RAND_MAX)) * 180.0) - 90.0);
42
- g->lon = H3_EXPORT(degsToRads)((float)rand() / (float)(RAND_MAX)) * 360.0;
43
- }
44
-
45
31
  int main(int argc, char* argv[]) {
46
- // check command line args
47
- if (argc > 3) {
48
- fprintf(stderr, "usage: %s numPoints resolution\n", argv[0]);
49
- exit(1);
50
- }
51
-
32
+ int res = 0;
52
33
  int numPoints = 0;
53
- if (!sscanf(argv[1], "%d", &numPoints))
54
- error("numPoints must be an integer");
55
34
 
56
- int res = 0;
57
- if (!sscanf(argv[2], "%d", &res)) error("resolution must be an integer");
35
+ Arg helpArg = ARG_HELP;
36
+ Arg numPointsArg = {
37
+ .names = {"-n", "--num-points"},
38
+ .required = true,
39
+ .scanFormat = "%d",
40
+ .valueName = "num",
41
+ .value = &numPoints,
42
+ .helpText = "Number of random lat/lon pairs to generate."};
43
+ Arg resArg = {.names = {"-r", "--resolution"},
44
+ .required = true,
45
+ .scanFormat = "%d",
46
+ .valueName = "res",
47
+ .value = &res,
48
+ .helpText = "Resolution, 0-15 inclusive."};
49
+
50
+ Arg* args[] = {&helpArg, &numPointsArg, &resArg};
51
+ const int numArgs = 3;
52
+ const char* helpText =
53
+ "Generates random lat/lon pairs and indexes them at the specified "
54
+ "resolution.";
58
55
 
59
- if (res > MAX_H3_RES) error("specified resolution exceeds max resolution");
56
+ if (parseArgs(argc, argv, numArgs, args, &helpArg, helpText)) {
57
+ return helpArg.found ? 0 : 1;
58
+ }
59
+
60
+ if (res > MAX_H3_RES) {
61
+ printHelp(stderr, argv[0], helpText, numArgs, args,
62
+ "Resolution exceeds maximum resolution.", NULL);
63
+ return 1;
64
+ }
60
65
 
61
66
  for (int i = 0; i < numPoints; i++) {
62
67
  GeoCoord g;
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2016-2017 Uber Technologies, Inc.
2
+ * Copyright 2016-2017, 2019 Uber Technologies, Inc.
3
3
  *
4
4
  * Licensed under the Apache License, Version 2.0 (the "License");
5
5
  * you may not use this file except in compliance with the License.
@@ -16,7 +16,7 @@
16
16
  /** @file
17
17
  * @brief generates random cell indexes and the corresponding cell boundaries
18
18
  *
19
- * usage: `mkRandGeoBoundary numPoints resolution`
19
+ * See `mkRandGeoBoundary --help` for usage.
20
20
  *
21
21
  * The program generates `numPoints` random lat/lon coordinates and outputs
22
22
  * them along with the corresponding H3Index at the specified `resolution`.
@@ -24,38 +24,43 @@
24
24
 
25
25
  #include <stdio.h>
26
26
  #include <stdlib.h>
27
- #include <time.h>
28
- #include "baseCells.h"
29
- #include "h3Index.h"
27
+ #include "args.h"
30
28
  #include "utility.h"
31
29
 
32
- void randomGeo(GeoCoord* g) {
33
- static int init = 0;
34
- if (!init) {
35
- srand((unsigned int)time(0));
36
- init = 1;
37
- }
38
-
39
- g->lat = H3_EXPORT(degsToRads)(
40
- (((float)rand() / (float)(RAND_MAX)) * 180.0) - 90.0);
41
- g->lon = H3_EXPORT(degsToRads)((float)rand() / (float)(RAND_MAX)) * 360.0;
42
- }
43
-
44
30
  int main(int argc, char* argv[]) {
45
- // check command line args
46
- if (argc > 3) {
47
- fprintf(stderr, "usage: %s numPoints resolution\n", argv[0]);
48
- exit(1);
49
- }
50
-
31
+ int res = 0;
51
32
  int numPoints = 0;
52
- if (!sscanf(argv[1], "%d", &numPoints))
53
- error("numPoints must be an integer");
54
33
 
55
- int res = 0;
56
- if (!sscanf(argv[2], "%d", &res)) error("resolution must be an integer");
34
+ Arg helpArg = ARG_HELP;
35
+ Arg numPointsArg = {
36
+ .names = {"-n", "--num-points"},
37
+ .required = true,
38
+ .scanFormat = "%d",
39
+ .valueName = "num",
40
+ .value = &numPoints,
41
+ .helpText = "Number of random lat/lon pairs to generate."};
42
+ Arg resArg = {.names = {"-r", "--resolution"},
43
+ .required = true,
44
+ .scanFormat = "%d",
45
+ .valueName = "res",
46
+ .value = &res,
47
+ .helpText = "Resolution, 0-15 inclusive."};
48
+
49
+ Arg* args[] = {&helpArg, &numPointsArg, &resArg};
50
+ const int numArgs = 3;
51
+ const char* helpText =
52
+ "Generates random cell indexes and cell boundaries at the specified "
53
+ "resolution.";
57
54
 
58
- if (res > MAX_H3_RES) error("specified resolution exceeds max resolution");
55
+ if (parseArgs(argc, argv, numArgs, args, &helpArg, helpText)) {
56
+ return helpArg.found ? 0 : 1;
57
+ }
58
+
59
+ if (res > MAX_H3_RES) {
60
+ printHelp(stderr, argv[0], helpText, numArgs, args,
61
+ "Resolution exceeds maximum resolution.", NULL);
62
+ return 1;
63
+ }
59
64
 
60
65
  for (int i = 0; i < numPoints; i++) {
61
66
  GeoCoord g;
@@ -0,0 +1,136 @@
1
+ /*
2
+ * Copyright 2019 Uber Technologies, Inc.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * http://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ /** @file
17
+ * @brief tests the h3GetFaces function
18
+ */
19
+
20
+ #include <stdio.h>
21
+ #include <stdlib.h>
22
+ #include "baseCells.h"
23
+ #include "h3Index.h"
24
+ #include "h3api.h"
25
+ #include "test.h"
26
+ #include "utility.h"
27
+
28
+ static int countFaces(H3Index h3, int expectedMax) {
29
+ int sz = H3_EXPORT(maxFaceCount)(h3);
30
+ t_assert(sz == expectedMax, "got expected max face count");
31
+ int *faces = calloc(sz, sizeof(int));
32
+
33
+ H3_EXPORT(h3GetFaces)(h3, faces);
34
+
35
+ int validCount = 0;
36
+ for (int i = 0; i < sz; i++) {
37
+ if (faces[i] >= 0 && faces[i] <= 19) validCount++;
38
+ }
39
+
40
+ free(faces);
41
+ return validCount;
42
+ }
43
+
44
+ static void assertSingleHexFace(H3Index h3) {
45
+ int validCount = countFaces(h3, 2);
46
+ t_assert(validCount == 1, "got a single valid face");
47
+ }
48
+
49
+ static void assertMultipleHexFaces(H3Index h3) {
50
+ int validCount = countFaces(h3, 2);
51
+ t_assert(validCount == 2, "got multiple valid faces for a hexagon");
52
+ }
53
+
54
+ static void assertPentagonFaces(H3Index h3) {
55
+ t_assert(H3_EXPORT(h3IsPentagon)(h3), "got a pentagon");
56
+ int validCount = countFaces(h3, 5);
57
+ t_assert(validCount == 5, "got 5 valid faces for a pentagon");
58
+ }
59
+
60
+ SUITE(h3GetFaces) {
61
+ TEST(singleFaceHexes) {
62
+ // base cell 16 is at the center of an icosahedron face,
63
+ // so all children should have the same face
64
+ iterateBaseCellIndexesAtRes(2, assertSingleHexFace, 16);
65
+ iterateBaseCellIndexesAtRes(3, assertSingleHexFace, 16);
66
+ }
67
+
68
+ TEST(hexagonWithEdgeVertices) {
69
+ // Class II pentagon neighbor - one face, two adjacent vertices on edge
70
+ H3Index h3 = 0x821c37fffffffff;
71
+ assertSingleHexFace(h3);
72
+ }
73
+
74
+ TEST(hexagonWithDistortion) {
75
+ // Class III pentagon neighbor, distortion across faces
76
+ H3Index h3 = 0x831c06fffffffff;
77
+ assertMultipleHexFaces(h3);
78
+ }
79
+
80
+ TEST(hexagonCrossingFaces) {
81
+ // Class II hex with two vertices on edge
82
+ H3Index h3 = 0x821ce7fffffffff;
83
+ assertMultipleHexFaces(h3);
84
+ }
85
+
86
+ TEST(classIIIPentagon) {
87
+ H3Index pentagon;
88
+ setH3Index(&pentagon, 1, 4, 0);
89
+ assertPentagonFaces(pentagon);
90
+ }
91
+
92
+ TEST(classIIPentagon) {
93
+ H3Index pentagon;
94
+ setH3Index(&pentagon, 2, 4, 0);
95
+ assertPentagonFaces(pentagon);
96
+ }
97
+
98
+ TEST(res15Pentagon) {
99
+ H3Index pentagon;
100
+ setH3Index(&pentagon, 15, 4, 0);
101
+ assertPentagonFaces(pentagon);
102
+ }
103
+
104
+ TEST(baseCellHexagons) {
105
+ int singleCount = 0;
106
+ int multipleCount = 0;
107
+ for (int i = 0; i < NUM_BASE_CELLS; i++) {
108
+ if (!_isBaseCellPentagon(i)) {
109
+ // Make the base cell index
110
+ H3Index baseCell;
111
+ setH3Index(&baseCell, 0, i, 0);
112
+ int validCount = countFaces(baseCell, 2);
113
+ t_assert(validCount > 0, "got at least one face");
114
+ if (validCount == 1)
115
+ singleCount++;
116
+ else
117
+ multipleCount++;
118
+ }
119
+ }
120
+ t_assert(singleCount == 4 * 20,
121
+ "got single face for 4 aligned hex base cells per face");
122
+ t_assert(multipleCount == 1.5 * 20,
123
+ "got multiple faces for non-aligned hex base cells");
124
+ }
125
+
126
+ TEST(baseCellPentagons) {
127
+ for (int i = 0; i < NUM_BASE_CELLS; i++) {
128
+ if (_isBaseCellPentagon(i)) {
129
+ // Make the base cell index
130
+ H3Index baseCell;
131
+ setH3Index(&baseCell, 0, i, 0);
132
+ assertPentagonFaces(baseCell);
133
+ }
134
+ }
135
+ }
136
+ }
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright 2016-2018 Uber Technologies, Inc.
2
+ * Copyright 2016-2019 Uber Technologies, Inc.
3
3
  *
4
4
  * Licensed under the Apache License, Version 2.0 (the "License");
5
5
  * you may not use this file except in compliance with the License.
@@ -50,10 +50,6 @@ typedef struct {
50
50
  extern const GeoCoord faceCenterGeo[NUM_ICOSA_FACES];
51
51
 
52
52
  // indexes for faceNeighbors table
53
- /** Invalid faceNeighbors table direction */
54
- #define INVALID -1
55
- /** Center faceNeighbors table direction */
56
- #define CENTER 0
57
53
  /** IJ quadrant faceNeighbors table direction */
58
54
  #define IJ 1
59
55
  /** KI quadrant faceNeighbors table direction */
@@ -61,6 +57,19 @@ extern const GeoCoord faceCenterGeo[NUM_ICOSA_FACES];
61
57
  /** JK quadrant faceNeighbors table direction */
62
58
  #define JK 3
63
59
 
60
+ /** Invalid face index */
61
+ #define INVALID_FACE -1
62
+
63
+ /** Digit representing overage type */
64
+ typedef enum {
65
+ /** No overage (on original face) */
66
+ NO_OVERAGE = 0,
67
+ /** On face edge (only occurs on substrate grids) */
68
+ FACE_EDGE = 1,
69
+ /** Overage on new face interior */
70
+ NEW_FACE = 2
71
+ } Overage;
72
+
64
73
  // Internal functions
65
74
 
66
75
  void _geoToFaceIjk(const GeoCoord* g, int res, FaceIJK* h);
@@ -69,8 +78,11 @@ void _faceIjkToGeo(const FaceIJK* h, int res, GeoCoord* g);
69
78
  void _faceIjkToGeoBoundary(const FaceIJK* h, int res, int isPentagon,
70
79
  GeoBoundary* g);
71
80
  void _faceIjkPentToGeoBoundary(const FaceIJK* h, int res, GeoBoundary* g);
81
+ void _faceIjkToVerts(FaceIJK* fijk, int* res, FaceIJK* fijkVerts);
82
+ void _faceIjkPentToVerts(FaceIJK* fijk, int* res, FaceIJK* fijkVerts);
72
83
  void _hex2dToGeo(const Vec2d* v, int face, int res, int substrate, GeoCoord* g);
73
- int _adjustOverageClassII(FaceIJK* fijk, int res, int pentLeading4,
74
- int substrate);
84
+ Overage _adjustOverageClassII(FaceIJK* fijk, int res, int pentLeading4,
85
+ int substrate);
86
+ Overage _adjustPentVertOverage(FaceIJK* fijk, int res);
75
87
 
76
88
  #endif