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
@@ -0,0 +1,122 @@
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 args.h
17
+ * @brief Miscellaneous functions and constants.
18
+ */
19
+
20
+ #ifndef ARGS_H
21
+ #define ARGS_H
22
+
23
+ #include <inttypes.h>
24
+ #include <stdbool.h>
25
+ #include <stdio.h>
26
+ #include "utility.h"
27
+
28
+ /** Maximum number of names an argument may have. */
29
+ #define NUM_ARG_NAMES 2
30
+
31
+ /**
32
+ * An argument accepted by on the command line of an H3 application. Specifies
33
+ * how the argument is presented, parsed, and where parsed values are stored.
34
+ */
35
+ typedef struct {
36
+ /**
37
+ * Both short and long names of the argument. A name may be null, but the
38
+ * first name must be non-null.
39
+ */
40
+ const char* const names[NUM_ARG_NAMES];
41
+
42
+ /**
43
+ * If true, this argument must be specified. If the argument is not
44
+ * specified, argument parsing will fail.
45
+ */
46
+ const bool required;
47
+
48
+ /**
49
+ * Scan format for the argument, which will be passed to sscanf. May be null
50
+ * to indicate the argument does not take a value.
51
+ */
52
+ const char* const scanFormat;
53
+
54
+ /**
55
+ * Name to present the value as when printing help.
56
+ */
57
+ const char* const valueName;
58
+
59
+ /**
60
+ * Value will be placed here if the argument is present and scanFormat is
61
+ * not null.
62
+ */
63
+ void* const value;
64
+
65
+ /**
66
+ * Will be set to true if the argument is present. Should be false when
67
+ * passed in to parseArgs.
68
+ */
69
+ bool found;
70
+
71
+ /**
72
+ * Help text for this argument.
73
+ */
74
+ const char* const helpText;
75
+ } Arg;
76
+
77
+ // prototypes
78
+
79
+ int parseArgs(int argc, char* argv[], int numArgs, Arg* args[],
80
+ const Arg* helpArg, const char* helpText);
81
+ void printHelp(FILE* out, const char* programName, const char* helpText,
82
+ int numArgs, Arg* args[], const char* errorMessage,
83
+ const char* errorDetails);
84
+
85
+ int _parseArgsList(int argc, char* argv[], int numArgs, Arg* args[],
86
+ const Arg* helpArg, const char** errorMessage,
87
+ const char** errorDetail);
88
+
89
+ // common arguments
90
+
91
+ #define ARG_HELP \
92
+ { .names = {"-h", "--help"}, .helpText = "Show this help message." }
93
+ #define DEFINE_INDEX_ARG(varName, argName) \
94
+ H3Index varName = 0; \
95
+ Arg argName = { \
96
+ .names = {"-i", "--index"}, \
97
+ .scanFormat = "%" PRIx64, \
98
+ .valueName = "index", \
99
+ .value = &varName, \
100
+ .helpText = \
101
+ "Index, or not specified to read indexes from standard input."}
102
+ #define ARG_KML \
103
+ { .names = {"-k", "--kml"}, .helpText = "Print output in KML format." }
104
+ #define DEFINE_KML_NAME_ARG(varName, argName) \
105
+ char varName[BUFF_SIZE] = {0}; \
106
+ Arg argName = { \
107
+ .names = {"--kn", "--kml-name"}, \
108
+ .scanFormat = "%255c", /* BUFF_SIZE - 1 */ \
109
+ .valueName = "name", \
110
+ .value = &varName, \
111
+ .helpText = "Text for the KML name tag, if --kml is specified."}
112
+ #define DEFINE_KML_DESC_ARG(varName, argName) \
113
+ char varName[BUFF_SIZE] = {0}; \
114
+ Arg argName = { \
115
+ .names = {"--kd", "--kml-description"}, \
116
+ .scanFormat = "%255c", /* BUFF_SIZE - 1 */ \
117
+ .valueName = "description", \
118
+ .value = &varName, \
119
+ .helpText = \
120
+ "Text for the KML description tag, if --kml is specified."}
121
+
122
+ #endif
@@ -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.
@@ -29,63 +29,6 @@
29
29
  /** Macro: Get the size of a fixed-size array */
30
30
  #define ARRAY_SIZE(x) sizeof(x) / sizeof(x[0])
31
31
 
32
- /** Maximum number of names an argument may have. */
33
- #define NUM_ARG_NAMES 2
34
-
35
- /**
36
- * An argument accepted by on the command line of an H3 application. Specifies
37
- * how the argument is presented, parsed, and where parsed values are stored.
38
- */
39
- typedef struct {
40
- /**
41
- * Both short and long names of the argument. A name may be null, but the
42
- * first name must be non-null.
43
- */
44
- const char* const names[NUM_ARG_NAMES];
45
-
46
- /**
47
- * If true, this argument must be specified. If the argument is not
48
- * specified, argument parsing will fail.
49
- */
50
- const bool required;
51
-
52
- /**
53
- * Scan format for the argument, which will be passed to sscanf. May be null
54
- * to indicate the argument does not take a value.
55
- */
56
- const char* const scanFormat;
57
-
58
- /**
59
- * Name to present the value as when printing help.
60
- */
61
- const char* const valueName;
62
-
63
- /**
64
- * Value will be placed here if the argument is present and scanFormat is
65
- * not null.
66
- */
67
- void* const value;
68
-
69
- /**
70
- * Will be set to true if the argument is present. Should be false when
71
- * passed in to parseArgs.
72
- */
73
- bool found;
74
-
75
- /**
76
- * Help text for this argument.
77
- */
78
- const char* const helpText;
79
- } Arg;
80
-
81
- // prototypes
82
-
83
- int parseArgs(int argc, char* argv[], int numArgs, Arg* args[],
84
- const Arg* helpArg, const char* helpText);
85
- void printHelp(FILE* out, const char* programName, const char* helpText,
86
- int numArgs, Arg* args[], const char* errorMessage,
87
- const char* errorDetails);
88
-
89
32
  void error(const char* msg);
90
33
  void h3Print(H3Index h); // prints as integer
91
34
  void h3Println(H3Index h); // prints as integer
@@ -104,12 +47,12 @@ void geoBoundaryPrint(const GeoBoundary* b);
104
47
  void geoBoundaryPrintln(const GeoBoundary* b);
105
48
  int readBoundary(FILE* f, GeoBoundary* b);
106
49
 
50
+ void randomGeo(GeoCoord* p);
51
+
107
52
  void iterateAllIndexesAtRes(int res, void (*callback)(H3Index));
108
53
  void iterateAllIndexesAtResPartial(int res, void (*callback)(H3Index),
109
54
  int maxBaseCell);
110
-
111
- int _parseArgsList(int argc, char* argv[], int numArgs, Arg* args[],
112
- const Arg* helpArg, const char** errorMessage,
113
- const char** errorDetail);
55
+ void iterateBaseCellIndexesAtRes(int res, void (*callback)(H3Index),
56
+ int baseCell);
114
57
 
115
58
  #endif
@@ -0,0 +1,216 @@
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 args.c
17
+ * @brief Miscellaneous useful functions.
18
+ */
19
+
20
+ #include "args.h"
21
+ #include <stdbool.h>
22
+ #include <stdio.h>
23
+ #include <stdlib.h>
24
+ #include <string.h>
25
+ #include "h3api.h"
26
+
27
+ /*
28
+ * Return codes from parseArgs.
29
+ */
30
+
31
+ #define PARSE_ARGS_SUCCESS 0
32
+ #define PARSE_ARGS_HELP 1
33
+ #define PARSE_ARGS_REPEATED_ARGUMENT 2
34
+ #define PARSE_ARGS_MISSING_VALUE 3
35
+ #define PARSE_ARGS_FAILED_PARSE 4
36
+ #define PARSE_ARGS_UNKNOWN_ARGUMENT 5
37
+ #define PARSE_ARGS_MISSING_REQUIRED 6
38
+
39
+ /**
40
+ * Parse command line arguments and prints help, if needed.
41
+ *
42
+ * Uses the provided arguments to populate argument values and records in the
43
+ * argument if it is found.
44
+ *
45
+ * Returns non-zero if all required arguments are not present, an argument fails
46
+ * to parse, is missing its associated value, or arguments are specified more
47
+ * than once.
48
+ *
49
+ * Help is printed to stdout if a argument with isHelp = true is found, and help
50
+ * is printed to stderr if argument parsing fails.
51
+ *
52
+ * @param argc argc from main
53
+ * @param argv argv from main
54
+ * @param numArgs Number of elements in the args array
55
+ * @param args Pointer to each argument to parse
56
+ * @param helpArg Pointer to the argument for "--help"
57
+ * @param helpText Explanatory text for this program printed with help
58
+ * @return 0 if argument parsing succeeded, otherwise non-0. If help is printed,
59
+ * return value is non-0.
60
+ */
61
+ int parseArgs(int argc, char* argv[], int numArgs, Arg* args[],
62
+ const Arg* helpArg, const char* helpText) {
63
+ const char* errorMessage = NULL;
64
+ const char* errorDetails = NULL;
65
+
66
+ int failed = _parseArgsList(argc, argv, numArgs, args, helpArg,
67
+ &errorMessage, &errorDetails);
68
+
69
+ if (failed || helpArg->found) {
70
+ printHelp(helpArg->found ? stdout : stderr, argv[0], helpText, numArgs,
71
+ args, errorMessage, errorDetails);
72
+ return failed != PARSE_ARGS_SUCCESS ? failed : PARSE_ARGS_HELP;
73
+ }
74
+ return PARSE_ARGS_SUCCESS;
75
+ }
76
+
77
+ /**
78
+ * Parse command line arguments.
79
+ *
80
+ * Uses the provided arguments to populate argument values.
81
+ *
82
+ * Returns non-zero if all required arguments are not present, an argument fails
83
+ * to parse, is missing its associated value, or arguments are specified more
84
+ * than once.
85
+ *
86
+ * @param argc argc from main
87
+ * @param argv argv from main
88
+ * @param numArgs Number of elements in the args array
89
+ * @param args Pointer to each argument to parse.
90
+ * @param helpArg Pointer to the argument for "--help" that suppresses checking
91
+ * for required arguments.
92
+ * @param errorMessage Error message to display, if returning non-zero.
93
+ * @param errorDetail Additional error details, if returning non-zero. May be
94
+ * null, and may be a pointer from `argv` or `args`.
95
+ * @return 0 if argument parsing succeeded, otherwise non-0.
96
+ */
97
+ int _parseArgsList(int argc, char* argv[], int numArgs, Arg* args[],
98
+ const Arg* helpArg, const char** errorMessage,
99
+ const char** errorDetail) {
100
+ // Whether help was found and required arguments do not need to be checked
101
+ bool foundHelp = false;
102
+
103
+ for (int i = 1; i < argc; i++) {
104
+ bool foundMatch = false;
105
+
106
+ for (int j = 0; j < numArgs; j++) {
107
+ // Test this argument, which may have multiple names, for whether it
108
+ // matches. argName will be set to the name used for this argument
109
+ // if it matches.
110
+ const char* argName = NULL;
111
+ for (int k = 0; k < NUM_ARG_NAMES; k++) {
112
+ if (args[j]->names[k] == NULL) continue;
113
+
114
+ if (strcmp(argv[i], args[j]->names[k]) == 0) {
115
+ argName = args[j]->names[k];
116
+ break;
117
+ }
118
+ }
119
+ // argName unchanged from NULL indicates this didn't match, try the
120
+ // next argument.
121
+ if (argName == NULL) continue;
122
+
123
+ if (args[j]->found) {
124
+ *errorMessage = "Argument specified multiple times";
125
+ *errorDetail = argName;
126
+ return PARSE_ARGS_REPEATED_ARGUMENT;
127
+ }
128
+
129
+ if (args[j]->scanFormat != NULL) {
130
+ // Argument has a value, need to advance one and read the value.
131
+ i++;
132
+ if (i >= argc) {
133
+ *errorMessage = "Argument value not present";
134
+ *errorDetail = argName;
135
+ return PARSE_ARGS_MISSING_VALUE;
136
+ }
137
+
138
+ if (!sscanf(argv[i], args[j]->scanFormat, args[j]->value)) {
139
+ *errorMessage = "Failed to parse argument";
140
+ *errorDetail = argName;
141
+ return PARSE_ARGS_FAILED_PARSE;
142
+ }
143
+ }
144
+
145
+ if (args[j] == helpArg) {
146
+ foundHelp = true;
147
+ }
148
+
149
+ args[j]->found = true;
150
+ foundMatch = true;
151
+ break;
152
+ }
153
+
154
+ if (!foundMatch) {
155
+ *errorMessage = "Unknown argument";
156
+ // Don't set errorDetail, since the input could be unprintable.
157
+ return PARSE_ARGS_UNKNOWN_ARGUMENT;
158
+ }
159
+ }
160
+
161
+ // Check for missing required arguments.
162
+ if (!foundHelp) {
163
+ for (int i = 0; i < numArgs; i++) {
164
+ if (args[i]->required && !args[i]->found) {
165
+ *errorMessage = "Required argument missing";
166
+ *errorDetail = args[i]->names[0];
167
+ return PARSE_ARGS_MISSING_REQUIRED;
168
+ }
169
+ }
170
+ }
171
+
172
+ return PARSE_ARGS_SUCCESS;
173
+ }
174
+
175
+ /**
176
+ * Print a help message.
177
+ *
178
+ * @param out Stream to print to, e.g. stdout
179
+ * @param programName Program name, such as from argv[0]
180
+ * @param helpText Explanation of what the program does
181
+ * @param numArgs Number of arguments to print help for
182
+ * @param args Pointer to arguments to print help for
183
+ * @param errorMessage Error message, or null
184
+ * @param errorDetails Additional error detail message, or null
185
+ */
186
+ void printHelp(FILE* out, const char* programName, const char* helpText,
187
+ int numArgs, Arg* args[], const char* errorMessage,
188
+ const char* errorDetails) {
189
+ if (errorMessage != NULL) {
190
+ fprintf(out, "%s: %s", programName, errorMessage);
191
+ if (errorDetails != NULL) {
192
+ fprintf(out, ": %s", errorDetails);
193
+ }
194
+ fprintf(out, "\n");
195
+ }
196
+ fprintf(out, "%s: %s\n", programName, helpText);
197
+ fprintf(out, "H3 %d.%d.%d\n\n", H3_VERSION_MAJOR, H3_VERSION_MINOR,
198
+ H3_VERSION_PATCH);
199
+
200
+ for (int i = 0; i < numArgs; i++) {
201
+ fprintf(out, "\t");
202
+ for (int j = 0; j < NUM_ARG_NAMES; j++) {
203
+ if (args[i]->names[j] == NULL) continue;
204
+ if (j != 0) fprintf(out, ", ");
205
+ fprintf(out, "%s", args[i]->names[j]);
206
+ }
207
+ if (args[i]->scanFormat != NULL) {
208
+ fprintf(out, " <%s>", args[i]->valueName);
209
+ }
210
+ fprintf(out, "\t");
211
+ if (args[i]->required) {
212
+ fprintf(out, "Required. ");
213
+ }
214
+ fprintf(out, "%s\n", args[i]->helpText);
215
+ }
216
+ }
@@ -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.
@@ -20,206 +20,14 @@
20
20
  #include "utility.h"
21
21
  #include <assert.h>
22
22
  #include <inttypes.h>
23
- #include <stdbool.h>
24
23
  #include <stdio.h>
25
24
  #include <stdlib.h>
26
25
  #include <string.h>
26
+ #include <time.h>
27
27
  #include "coordijk.h"
28
- #include "geoCoord.h"
29
28
  #include "h3Index.h"
30
29
  #include "h3api.h"
31
30
 
32
- /*
33
- * Return codes from parseArgs.
34
- */
35
-
36
- #define PARSE_ARGS_SUCCESS 0
37
- #define PARSE_ARGS_HELP 1
38
- #define PARSE_ARGS_REPEATED_ARGUMENT 2
39
- #define PARSE_ARGS_MISSING_VALUE 3
40
- #define PARSE_ARGS_FAILED_PARSE 4
41
- #define PARSE_ARGS_UNKNOWN_ARGUMENT 5
42
- #define PARSE_ARGS_MISSING_REQUIRED 6
43
-
44
- /**
45
- * Parse command line arguments and prints help, if needed.
46
- *
47
- * Uses the provided arguments to populate argument values and records in the
48
- * argument if it is found.
49
- *
50
- * Returns non-zero if all required arguments are not present, an argument fails
51
- * to parse, is missing its associated value, or arguments are specified more
52
- * than once.
53
- *
54
- * Help is printed to stdout if a argument with isHelp = true is found, and help
55
- * is printed to stderr if argument parsing fails.
56
- *
57
- * @param argc argc from main
58
- * @param argv argv from main
59
- * @param numArgs Number of elements in the args array
60
- * @param args Pointer to each argument to parse
61
- * @param helpArg Pointer to the argument for "--help"
62
- * @param helpText Explanatory text for this program printed with help
63
- * @return 0 if argument parsing succeeded, otherwise non-0. If help is printed,
64
- * return value is non-0.
65
- */
66
- int parseArgs(int argc, char* argv[], int numArgs, Arg* args[],
67
- const Arg* helpArg, const char* helpText) {
68
- const char* errorMessage = NULL;
69
- const char* errorDetails = NULL;
70
-
71
- int failed = _parseArgsList(argc, argv, numArgs, args, helpArg,
72
- &errorMessage, &errorDetails);
73
-
74
- if (failed || helpArg->found) {
75
- printHelp(helpArg->found ? stdout : stderr, argv[0], helpText, numArgs,
76
- args, errorMessage, errorDetails);
77
- return failed != PARSE_ARGS_SUCCESS ? failed : PARSE_ARGS_HELP;
78
- }
79
- return PARSE_ARGS_SUCCESS;
80
- }
81
-
82
- /**
83
- * Parse command line arguments.
84
- *
85
- * Uses the provided arguments to populate argument values.
86
- *
87
- * Returns non-zero if all required arguments are not present, an argument fails
88
- * to parse, is missing its associated value, or arguments are specified more
89
- * than once.
90
- *
91
- * @param argc argc from main
92
- * @param argv argv from main
93
- * @param numArgs Number of elements in the args array
94
- * @param args Pointer to each argument to parse.
95
- * @param helpArg Pointer to the argument for "--help" that suppresses checking
96
- * for required arguments.
97
- * @param errorMessage Error message to display, if returning non-zero.
98
- * @param errorDetail Additional error details, if returning non-zero. May be
99
- * null, and may be a pointer from `argv` or `args`.
100
- * @return 0 if argument parsing succeeded, otherwise non-0.
101
- */
102
- int _parseArgsList(int argc, char* argv[], int numArgs, Arg* args[],
103
- const Arg* helpArg, const char** errorMessage,
104
- const char** errorDetail) {
105
- // Whether help was found and required arguments do not need to be checked
106
- bool foundHelp = false;
107
-
108
- for (int i = 1; i < argc; i++) {
109
- bool foundMatch = false;
110
-
111
- for (int j = 0; j < numArgs; j++) {
112
- // Test this argument, which may have multiple names, for whether it
113
- // matches. argName will be set to the name used for this argument
114
- // if it matches.
115
- const char* argName = NULL;
116
- for (int k = 0; k < NUM_ARG_NAMES; k++) {
117
- if (args[j]->names[k] == NULL) continue;
118
-
119
- if (strcmp(argv[i], args[j]->names[k]) == 0) {
120
- argName = args[j]->names[k];
121
- break;
122
- }
123
- }
124
- // argName unchanged from NULL indicates this didn't match, try the
125
- // next argument.
126
- if (argName == NULL) continue;
127
-
128
- if (args[j]->found) {
129
- *errorMessage = "Argument specified multiple times";
130
- *errorDetail = argName;
131
- return PARSE_ARGS_REPEATED_ARGUMENT;
132
- }
133
-
134
- if (args[j]->scanFormat != NULL) {
135
- // Argument has a value, need to advance one and read the value.
136
- i++;
137
- if (i >= argc) {
138
- *errorMessage = "Argument value not present";
139
- *errorDetail = argName;
140
- return PARSE_ARGS_MISSING_VALUE;
141
- }
142
-
143
- if (!sscanf(argv[i], args[j]->scanFormat, args[j]->value)) {
144
- *errorMessage = "Failed to parse argument";
145
- *errorDetail = argName;
146
- return PARSE_ARGS_FAILED_PARSE;
147
- }
148
- }
149
-
150
- if (args[j] == helpArg) {
151
- foundHelp = true;
152
- }
153
-
154
- args[j]->found = true;
155
- foundMatch = true;
156
- break;
157
- }
158
-
159
- if (!foundMatch) {
160
- *errorMessage = "Unknown argument";
161
- // Don't set errorDetail, since the input could be unprintable.
162
- return PARSE_ARGS_UNKNOWN_ARGUMENT;
163
- }
164
- }
165
-
166
- // Check for missing required arguments.
167
- if (!foundHelp) {
168
- for (int i = 0; i < numArgs; i++) {
169
- if (args[i]->required && !args[i]->found) {
170
- *errorMessage = "Required argument missing";
171
- *errorDetail = args[i]->names[0];
172
- return PARSE_ARGS_MISSING_REQUIRED;
173
- }
174
- }
175
- }
176
-
177
- return PARSE_ARGS_SUCCESS;
178
- }
179
-
180
- /**
181
- * Print a help message.
182
- *
183
- * @param out Stream to print to, e.g. stdout
184
- * @param programName Program name, such as from argv[0]
185
- * @param helpText Explanation of what the program does
186
- * @param numArgs Number of arguments to print help for
187
- * @param args Pointer to arguments to print help for
188
- * @param errorMessage Error message, or null
189
- * @param errorDetails Additional error detail message, or null
190
- */
191
- void printHelp(FILE* out, const char* programName, const char* helpText,
192
- int numArgs, Arg* args[], const char* errorMessage,
193
- const char* errorDetails) {
194
- if (errorMessage != NULL) {
195
- fprintf(out, "%s: %s", programName, errorMessage);
196
- if (errorDetails != NULL) {
197
- fprintf(out, ": %s", errorDetails);
198
- }
199
- fprintf(out, "\n");
200
- }
201
- fprintf(out, "%s: %s\n", programName, helpText);
202
- fprintf(out, "H3 %d.%d.%d\n\n", H3_VERSION_MAJOR, H3_VERSION_MINOR,
203
- H3_VERSION_PATCH);
204
-
205
- for (int i = 0; i < numArgs; i++) {
206
- fprintf(out, "\t");
207
- for (int j = 0; j < NUM_ARG_NAMES; j++) {
208
- if (args[i]->names[j] == NULL) continue;
209
- if (j != 0) fprintf(out, ", ");
210
- fprintf(out, "%s", args[i]->names[j]);
211
- }
212
- if (args[i]->scanFormat != NULL) {
213
- fprintf(out, " <%s>", args[i]->valueName);
214
- }
215
- fprintf(out, "\t");
216
- if (args[i]->required) {
217
- fprintf(out, "Required. ");
218
- }
219
- fprintf(out, "%s\n", args[i]->helpText);
220
- }
221
- }
222
-
223
31
  void error(const char* msg) {
224
32
  fflush(stdout);
225
33
  fflush(stderr);
@@ -382,20 +190,46 @@ void iterateAllIndexesAtResPartial(int res, void (*callback)(H3Index),
382
190
  int baseCells) {
383
191
  assert(baseCells <= NUM_BASE_CELLS);
384
192
  for (int i = 0; i < baseCells; i++) {
385
- H3Index bc;
386
- setH3Index(&bc, 0, i, 0);
387
- int childrenSz = H3_EXPORT(maxUncompactSize)(&bc, 1, res);
388
- H3Index* children = calloc(childrenSz, sizeof(H3Index));
389
- H3_EXPORT(uncompact)(&bc, 1, children, childrenSz, res);
390
-
391
- for (int j = 0; j < childrenSz; j++) {
392
- if (children[j] == 0) {
393
- continue;
394
- }
193
+ iterateBaseCellIndexesAtRes(res, callback, i);
194
+ }
195
+ }
395
196
 
396
- (*callback)(children[j]);
197
+ /**
198
+ * Call the callback for every index at the given resolution in a
199
+ * specific base cell
200
+ */
201
+ void iterateBaseCellIndexesAtRes(int res, void (*callback)(H3Index),
202
+ int baseCell) {
203
+ H3Index bc;
204
+ setH3Index(&bc, 0, baseCell, 0);
205
+ int childrenSz = H3_EXPORT(maxUncompactSize)(&bc, 1, res);
206
+ H3Index* children = calloc(childrenSz, sizeof(H3Index));
207
+ H3_EXPORT(uncompact)(&bc, 1, children, childrenSz, res);
208
+
209
+ for (int j = 0; j < childrenSz; j++) {
210
+ if (children[j] == 0) {
211
+ continue;
397
212
  }
398
213
 
399
- free(children);
214
+ (*callback)(children[j]);
400
215
  }
216
+
217
+ free(children);
218
+ }
219
+
220
+ /**
221
+ * Generates a random lat/lon pair.
222
+ *
223
+ * @param g Lat/lon will be placed here.
224
+ */
225
+ void randomGeo(GeoCoord* g) {
226
+ static int init = 0;
227
+ if (!init) {
228
+ srand((unsigned int)time(0));
229
+ init = 1;
230
+ }
231
+
232
+ g->lat = H3_EXPORT(degsToRads)(
233
+ (((float)rand() / (float)(RAND_MAX)) * 180.0) - 90.0);
234
+ g->lon = H3_EXPORT(degsToRads)((float)rand() / (float)(RAND_MAX)) * 360.0;
401
235
  }