h3 3.4.4 → 3.5.0

Sign up to get free protection for your applications and to get access to all the features.
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