h3 3.6.2 → 3.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +23 -0
- data/Gemfile.lock +6 -6
- data/README.md +1 -1
- data/ext/h3/src/.github/workflows/test-linux.yml +118 -0
- data/ext/h3/src/.github/workflows/test-macos.yml +42 -0
- data/ext/h3/src/.github/workflows/test-website.yml +32 -0
- data/ext/h3/src/.github/workflows/test-windows.yml +44 -0
- data/ext/h3/src/.gitignore +5 -0
- data/ext/h3/src/.travis.yml +16 -46
- data/ext/h3/src/CHANGELOG.md +43 -0
- data/ext/h3/src/CMakeLists.txt +133 -33
- data/ext/h3/src/CONTRIBUTING.md +1 -1
- data/ext/h3/src/README.md +60 -10
- data/ext/h3/src/RELEASE.md +3 -1
- data/ext/h3/src/VERSION +1 -1
- data/ext/h3/src/dev-docs/RFCs/rfc-template.md +21 -0
- data/ext/h3/src/dev-docs/RFCs/v4.0.0/error-handling-rfc.md +21 -0
- data/ext/h3/src/dev-docs/RFCs/v4.0.0/names_for_concepts_types_functions.md +276 -0
- data/ext/h3/src/dev-docs/RFCs/v4.0.0/overrideable-allocators-rfc.md +141 -0
- data/ext/h3/src/dev-docs/RFCs/v4.0.0/polyfill-modes-rfc.md +21 -0
- data/ext/h3/src/dev-docs/RFCs/v4.0.0/vertex-mode-rfc.md +50 -0
- data/ext/h3/src/dev-docs/build_windows.md +6 -1
- data/ext/h3/src/dev-docs/creating_bindings.md +3 -3
- data/ext/h3/src/dev-docs/custom_alloc.md +27 -0
- data/ext/h3/src/docs/{overview/mainpage.md → README.md} +2 -3
- data/ext/h3/src/docs/api/misc.md +76 -0
- data/ext/h3/src/docs/community/applications.md +1 -0
- data/ext/h3/src/docs/community/bindings.md +7 -1
- data/ext/h3/src/docs/community/tutorials.md +8 -3
- data/ext/h3/src/docs/core-library/coordsystems.md +5 -4
- data/ext/h3/src/docs/core-library/filters.md +8 -9
- data/ext/h3/src/docs/core-library/geoToH3desc.md +2 -3
- data/ext/h3/src/docs/core-library/h3ToGeoBoundaryDesc.md +4 -5
- data/ext/h3/src/docs/core-library/h3ToGeoDesc.md +3 -4
- data/ext/h3/src/docs/core-library/h3indexing.md +26 -17
- data/ext/h3/src/docs/core-library/overview.md +2 -3
- data/ext/h3/src/docs/core-library/restable.md +1 -2
- data/ext/h3/src/docs/core-library/usage.md +1 -2
- data/ext/h3/src/docs/table-of-contents.json +47 -0
- data/ext/h3/src/docs/{overview/usecases.md → usecases.md} +6 -11
- data/ext/h3/src/scripts/binding_functions.sh +1 -1
- data/ext/h3/src/scripts/coverage.sh.in +1 -1
- data/ext/h3/src/scripts/update_version.sh +2 -2
- data/ext/h3/src/src/apps/applib/include/args.h +1 -0
- data/ext/h3/src/src/apps/applib/include/test.h +1 -0
- data/ext/h3/src/src/apps/applib/include/utility.h +7 -1
- data/ext/h3/src/src/apps/applib/lib/args.c +2 -0
- data/ext/h3/src/src/apps/applib/lib/kml.c +2 -0
- data/ext/h3/src/src/apps/applib/lib/test.c +1 -0
- data/ext/h3/src/src/apps/applib/lib/utility.c +133 -2
- data/ext/h3/src/src/apps/benchmarks/benchmarkH3Api.c +1 -1
- data/ext/h3/src/{website/html.config.js → src/apps/benchmarks/benchmarkH3UniEdge.c} +15 -12
- data/ext/h3/src/src/apps/filters/h3ToComponents.c +1 -0
- data/ext/h3/src/src/apps/filters/h3ToGeo.c +1 -0
- data/ext/h3/src/src/apps/filters/h3ToGeoBoundary.c +1 -0
- data/ext/h3/src/src/apps/filters/h3ToLocalIj.c +1 -0
- data/ext/h3/src/src/apps/filters/hexRange.c +1 -0
- data/ext/h3/src/src/apps/filters/kRing.c +1 -0
- data/ext/h3/src/src/apps/filters/localIjToH3.c +1 -0
- data/ext/h3/src/src/apps/miscapps/generateFaceCenterPoint.c +1 -0
- data/ext/h3/src/src/apps/miscapps/generateNumHexagons.c +1 -0
- data/ext/h3/src/src/apps/miscapps/generatePentagonDirectionFaces.c +67 -0
- data/ext/h3/src/src/apps/miscapps/h3ToGeoBoundaryHier.c +1 -0
- data/ext/h3/src/src/apps/miscapps/h3ToGeoHier.c +1 -0
- data/ext/h3/src/src/apps/miscapps/h3ToHier.c +1 -0
- data/ext/h3/src/src/apps/testapps/mkRandGeo.c +1 -0
- data/ext/h3/src/src/apps/testapps/mkRandGeoBoundary.c +1 -0
- data/ext/h3/src/src/apps/testapps/testBBox.c +1 -0
- data/ext/h3/src/src/apps/testapps/testBaseCells.c +15 -1
- data/ext/h3/src/src/apps/testapps/testCompact.c +75 -0
- data/ext/h3/src/src/apps/testapps/testCoordIj.c +1 -0
- data/ext/h3/src/src/apps/testapps/testGeoCoord.c +40 -13
- data/ext/h3/src/src/apps/testapps/testGeoToH3.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3Api.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3CellArea.c +47 -0
- data/ext/h3/src/src/apps/testapps/testH3CellAreaExhaustive.c +180 -0
- data/ext/h3/src/src/apps/testapps/testH3Distance.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3DistanceExhaustive.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3GetFaces.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3Index.c +33 -3
- data/ext/h3/src/src/apps/testapps/testH3Line.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3LineExhaustive.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3Memory.c +175 -0
- data/ext/h3/src/src/apps/testapps/testH3NeighborRotations.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3SetToLinkedGeo.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3SetToVertexGraph.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3ToCenterChild.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3ToChildren.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3ToGeo.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3ToGeoBoundary.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3ToLocalIj.c +9 -5
- data/ext/h3/src/src/apps/testapps/testH3ToLocalIjExhaustive.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3ToParent.c +1 -0
- data/ext/h3/src/src/apps/testapps/testH3UniEdge.c +45 -16
- data/ext/h3/src/src/apps/testapps/testH3UniEdgeExhaustive.c +111 -0
- data/ext/h3/src/src/apps/testapps/testHexRanges.c +1 -0
- data/ext/h3/src/src/apps/testapps/testHexRing.c +1 -0
- data/ext/h3/src/src/apps/testapps/testKRing.c +1 -0
- data/ext/h3/src/src/apps/testapps/testLinkedGeo.c +1 -0
- data/ext/h3/src/src/apps/testapps/testMaxH3ToChildrenSize.c +1 -0
- data/ext/h3/src/src/apps/testapps/testPentagonIndexes.c +1 -0
- data/ext/h3/src/src/apps/testapps/testPolyfill.c +72 -9
- data/ext/h3/src/src/apps/testapps/testPolyfillReported.c +157 -0
- data/ext/h3/src/src/apps/testapps/testPolygon.c +1 -0
- data/ext/h3/src/src/apps/testapps/testVec2d.c +1 -0
- data/ext/h3/src/src/apps/testapps/testVec3d.c +1 -0
- data/ext/h3/src/src/apps/testapps/testVertex.c +66 -0
- data/ext/h3/src/src/apps/testapps/testVertexGraph.c +1 -0
- data/ext/h3/src/src/h3lib/include/algos.h +8 -0
- data/ext/h3/src/src/h3lib/include/alloc.h +40 -0
- data/ext/h3/src/src/h3lib/include/baseCells.h +4 -0
- data/ext/h3/src/src/h3lib/include/bbox.h +4 -1
- data/ext/h3/src/src/h3lib/include/faceijk.h +3 -2
- data/ext/h3/src/src/h3lib/include/geoCoord.h +2 -3
- data/ext/h3/src/src/h3lib/include/h3Index.h +37 -4
- data/ext/h3/src/src/h3lib/include/h3api.h.in +65 -17
- data/ext/h3/src/src/h3lib/include/linkedGeo.h +1 -0
- data/ext/h3/src/src/h3lib/include/polygon.h +1 -0
- data/ext/h3/src/src/h3lib/include/polygonAlgos.h +1 -0
- data/ext/h3/src/src/h3lib/include/vertex.h +44 -0
- data/ext/h3/src/src/h3lib/include/vertexGraph.h +1 -0
- data/ext/h3/src/src/h3lib/lib/algos.c +300 -75
- data/ext/h3/src/src/h3lib/lib/baseCells.c +26 -4
- data/ext/h3/src/src/h3lib/lib/bbox.c +56 -31
- data/ext/h3/src/src/h3lib/lib/coordijk.c +2 -0
- data/ext/h3/src/src/h3lib/lib/faceijk.c +32 -21
- data/ext/h3/src/src/h3lib/lib/geoCoord.c +162 -44
- data/ext/h3/src/src/h3lib/lib/h3Index.c +81 -43
- data/ext/h3/src/src/h3lib/lib/h3UniEdge.c +42 -57
- data/ext/h3/src/src/h3lib/lib/linkedGeo.c +20 -15
- data/ext/h3/src/src/h3lib/lib/localij.c +1 -1
- data/ext/h3/src/src/h3lib/lib/polygon.c +2 -0
- data/ext/h3/src/src/h3lib/lib/vec2d.c +1 -0
- data/ext/h3/src/src/h3lib/lib/vec3d.c +1 -0
- data/ext/h3/src/src/h3lib/lib/vertex.c +134 -0
- data/ext/h3/src/src/h3lib/lib/vertexGraph.c +8 -5
- data/ext/h3/src/website/.eslintignore +2 -0
- data/ext/h3/src/website/.gitignore +57 -0
- data/ext/h3/src/website/.nvmrc +1 -0
- data/ext/h3/src/website/README.md +8 -6
- data/ext/h3/src/website/gatsby-config.js +83 -0
- data/ext/h3/src/website/package.json +20 -12
- data/ext/h3/src/website/scripts/build-to-gh-pages.sh +7 -5
- data/ext/h3/src/website/src/.gitkeep +0 -0
- data/ext/h3/src/website/templates/documentation.jsx +129 -0
- data/ext/h3/src/website/yarn.lock +13723 -0
- data/lib/h3/bindings/private.rb +3 -0
- data/lib/h3/miscellaneous.rb +123 -0
- data/lib/h3/version.rb +1 -1
- data/spec/miscellaneous_spec.rb +117 -0
- data/spec/regions_spec.rb +1 -1
- metadata +35 -14
- data/ext/h3/src/.ycm_extra_conf.py +0 -92
- data/ext/h3/src/appveyor.yml +0 -50
- data/ext/h3/src/src/apps/testapps/testPolyfill_GH136.c +0 -58
- data/ext/h3/src/website/src/config.js +0 -46
- data/ext/h3/src/website/src/mdRoutes.js +0 -151
- data/ext/h3/src/website/src/styles/_variables.scss +0 -16
- data/ext/h3/src/website/src/styles/index.scss +0 -3
- data/ext/h3/src/website/static/index.html +0 -15
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
* Copyright 2016-
|
|
2
|
+
* Copyright 2016-2020 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.
|
|
@@ -150,7 +150,7 @@ typedef struct {
|
|
|
150
150
|
* Functions for geoToH3
|
|
151
151
|
* @{
|
|
152
152
|
*/
|
|
153
|
-
/** @brief find the H3 index of the resolution res cell containing the lat/
|
|
153
|
+
/** @brief find the H3 index of the resolution res cell containing the lat/lng
|
|
154
154
|
*/
|
|
155
155
|
H3Index H3_EXPORT(geoToH3)(const GeoCoord *g, int res);
|
|
156
156
|
/** @} */
|
|
@@ -183,8 +183,7 @@ int H3_EXPORT(hexRange)(H3Index origin, int k, H3Index *out);
|
|
|
183
183
|
/** @} */
|
|
184
184
|
|
|
185
185
|
/** @brief hexagons neighbors in all directions, assuming no pentagons,
|
|
186
|
-
* reporting
|
|
187
|
-
* distance from origin */
|
|
186
|
+
* reporting distance from origin */
|
|
188
187
|
int H3_EXPORT(hexRangeDistances)(H3Index origin, int k, H3Index *out,
|
|
189
188
|
int *distances);
|
|
190
189
|
|
|
@@ -252,33 +251,77 @@ double H3_EXPORT(degsToRads)(double degrees);
|
|
|
252
251
|
double H3_EXPORT(radsToDegs)(double radians);
|
|
253
252
|
/** @} */
|
|
254
253
|
|
|
254
|
+
/** @defgroup pointDist pointDist
|
|
255
|
+
* Functions for pointDist
|
|
256
|
+
* @{
|
|
257
|
+
*/
|
|
258
|
+
/** @brief "great circle distance" between pairs of GeoCoord points in radians*/
|
|
259
|
+
double H3_EXPORT(pointDistRads)(const GeoCoord *a, const GeoCoord *b);
|
|
260
|
+
|
|
261
|
+
/** @brief "great circle distance" between pairs of GeoCoord points in
|
|
262
|
+
* kilometers*/
|
|
263
|
+
double H3_EXPORT(pointDistKm)(const GeoCoord *a, const GeoCoord *b);
|
|
264
|
+
|
|
265
|
+
/** @brief "great circle distance" between pairs of GeoCoord points in meters*/
|
|
266
|
+
double H3_EXPORT(pointDistM)(const GeoCoord *a, const GeoCoord *b);
|
|
267
|
+
/** @} */
|
|
268
|
+
|
|
255
269
|
/** @defgroup hexArea hexArea
|
|
256
270
|
* Functions for hexArea
|
|
257
271
|
* @{
|
|
258
272
|
*/
|
|
259
|
-
/** @brief hexagon area in square kilometers */
|
|
273
|
+
/** @brief average hexagon area in square kilometers (excludes pentagons) */
|
|
260
274
|
double H3_EXPORT(hexAreaKm2)(int res);
|
|
261
275
|
|
|
262
|
-
/** @brief hexagon area in square meters */
|
|
276
|
+
/** @brief average hexagon area in square meters (excludes pentagons) */
|
|
263
277
|
double H3_EXPORT(hexAreaM2)(int res);
|
|
264
278
|
/** @} */
|
|
265
279
|
|
|
280
|
+
/** @defgroup cellArea cellArea
|
|
281
|
+
* Functions for cellArea
|
|
282
|
+
* @{
|
|
283
|
+
*/
|
|
284
|
+
/** @brief exact area for a specific cell (hexagon or pentagon) in radians^2 */
|
|
285
|
+
double H3_EXPORT(cellAreaRads2)(H3Index h);
|
|
286
|
+
|
|
287
|
+
/** @brief exact area for a specific cell (hexagon or pentagon) in kilometers^2
|
|
288
|
+
*/
|
|
289
|
+
double H3_EXPORT(cellAreaKm2)(H3Index h);
|
|
290
|
+
|
|
291
|
+
/** @brief exact area for a specific cell (hexagon or pentagon) in meters^2 */
|
|
292
|
+
double H3_EXPORT(cellAreaM2)(H3Index h);
|
|
293
|
+
/** @} */
|
|
294
|
+
|
|
266
295
|
/** @defgroup edgeLength edgeLength
|
|
267
296
|
* Functions for edgeLength
|
|
268
297
|
* @{
|
|
269
298
|
*/
|
|
270
|
-
/** @brief hexagon edge length in kilometers */
|
|
299
|
+
/** @brief average hexagon edge length in kilometers (excludes pentagons) */
|
|
271
300
|
double H3_EXPORT(edgeLengthKm)(int res);
|
|
272
301
|
|
|
273
|
-
/** @brief hexagon edge length in meters */
|
|
302
|
+
/** @brief average hexagon edge length in meters (excludes pentagons) */
|
|
274
303
|
double H3_EXPORT(edgeLengthM)(int res);
|
|
275
304
|
/** @} */
|
|
276
305
|
|
|
306
|
+
/** @defgroup exactEdgeLength exactEdgeLength
|
|
307
|
+
* Functions for exactEdgeLength
|
|
308
|
+
* @{
|
|
309
|
+
*/
|
|
310
|
+
/** @brief exact length for a specific unidirectional edge in radians*/
|
|
311
|
+
double H3_EXPORT(exactEdgeLengthRads)(H3Index edge);
|
|
312
|
+
|
|
313
|
+
/** @brief exact length for a specific unidirectional edge in kilometers*/
|
|
314
|
+
double H3_EXPORT(exactEdgeLengthKm)(H3Index edge);
|
|
315
|
+
|
|
316
|
+
/** @brief exact length for a specific unidirectional edge in meters*/
|
|
317
|
+
double H3_EXPORT(exactEdgeLengthM)(H3Index edge);
|
|
318
|
+
/** @} */
|
|
319
|
+
|
|
277
320
|
/** @defgroup numHexagons numHexagons
|
|
278
321
|
* Functions for numHexagons
|
|
279
322
|
* @{
|
|
280
323
|
*/
|
|
281
|
-
/** @brief number of hexagons for a given resolution */
|
|
324
|
+
/** @brief number of cells (hexagons and pentagons) for a given resolution */
|
|
282
325
|
int64_t H3_EXPORT(numHexagons)(int res);
|
|
283
326
|
/** @} */
|
|
284
327
|
|
|
@@ -286,10 +329,10 @@ int64_t H3_EXPORT(numHexagons)(int res);
|
|
|
286
329
|
* Functions for getRes0Indexes
|
|
287
330
|
* @{
|
|
288
331
|
*/
|
|
289
|
-
/** @brief returns the number of resolution 0
|
|
332
|
+
/** @brief returns the number of resolution 0 cells (hexagons and pentagons) */
|
|
290
333
|
int H3_EXPORT(res0IndexCount)();
|
|
291
334
|
|
|
292
|
-
/** @brief provides all base cells */
|
|
335
|
+
/** @brief provides all base cells in H3Index format*/
|
|
293
336
|
void H3_EXPORT(getRes0Indexes)(H3Index *out);
|
|
294
337
|
/** @} */
|
|
295
338
|
|
|
@@ -308,7 +351,8 @@ void H3_EXPORT(getPentagonIndexes)(int res, H3Index *out);
|
|
|
308
351
|
* Functions for h3GetResolution
|
|
309
352
|
* @{
|
|
310
353
|
*/
|
|
311
|
-
/** @brief returns the resolution of the provided
|
|
354
|
+
/** @brief returns the resolution of the provided H3 index
|
|
355
|
+
* Works on both cells and unidirectional edges. */
|
|
312
356
|
int H3_EXPORT(h3GetResolution)(H3Index h);
|
|
313
357
|
/** @} */
|
|
314
358
|
|
|
@@ -316,7 +360,10 @@ int H3_EXPORT(h3GetResolution)(H3Index h);
|
|
|
316
360
|
* Functions for h3GetBaseCell
|
|
317
361
|
* @{
|
|
318
362
|
*/
|
|
319
|
-
/** @brief returns the base cell of the provided
|
|
363
|
+
/** @brief returns the base cell "number" (0 to 121) of the provided H3 cell
|
|
364
|
+
*
|
|
365
|
+
* Note: Technically works on H3 edges, but will return base cell of the
|
|
366
|
+
* origin cell. */
|
|
320
367
|
int H3_EXPORT(h3GetBaseCell)(H3Index h);
|
|
321
368
|
/** @} */
|
|
322
369
|
|
|
@@ -340,7 +387,9 @@ void H3_EXPORT(h3ToString)(H3Index h, char *str, size_t sz);
|
|
|
340
387
|
* Functions for h3IsValid
|
|
341
388
|
* @{
|
|
342
389
|
*/
|
|
343
|
-
/** @brief confirms if an H3Index is valid
|
|
390
|
+
/** @brief confirms if an H3Index is a valid cell (hexagon or pentagon)
|
|
391
|
+
* In particular, returns 0 (False) for H3 unidirectional edges or invalid data
|
|
392
|
+
*/
|
|
344
393
|
int H3_EXPORT(h3IsValid)(H3Index h);
|
|
345
394
|
/** @} */
|
|
346
395
|
|
|
@@ -358,8 +407,7 @@ H3Index H3_EXPORT(h3ToParent)(H3Index h, int parentRes);
|
|
|
358
407
|
* @{
|
|
359
408
|
*/
|
|
360
409
|
/** @brief determines the maximum number of children (or grandchildren, etc)
|
|
361
|
-
* that
|
|
362
|
-
* could be returned for the given hexagon */
|
|
410
|
+
* that could be returned for the given hexagon */
|
|
363
411
|
int H3_EXPORT(maxH3ToChildrenSize)(H3Index h, int childRes);
|
|
364
412
|
|
|
365
413
|
/** @brief provides the children (or grandchildren, etc) of the given hexagon */
|
|
@@ -410,7 +458,7 @@ int H3_EXPORT(h3IsResClassIII)(H3Index h);
|
|
|
410
458
|
* Functions for h3IsPentagon
|
|
411
459
|
* @{
|
|
412
460
|
*/
|
|
413
|
-
/** @brief determines if
|
|
461
|
+
/** @brief determines if an H3 cell is a pentagon */
|
|
414
462
|
int H3_EXPORT(h3IsPentagon)(H3Index h);
|
|
415
463
|
/** @} */
|
|
416
464
|
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright 2020 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 vertex.h
|
|
17
|
+
* @brief Functions for working with cell vertexes.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
#ifndef H3VERTEX_H
|
|
21
|
+
#define H3VERTEX_H
|
|
22
|
+
|
|
23
|
+
#include "h3Index.h"
|
|
24
|
+
#include "faceijk.h"
|
|
25
|
+
|
|
26
|
+
/** @struct PentagonDirectionFaces
|
|
27
|
+
* @brief The faces in each axial direction of a given pentagon base cell
|
|
28
|
+
*/
|
|
29
|
+
typedef struct {
|
|
30
|
+
int baseCell; ///< base cell number
|
|
31
|
+
int faces[NUM_PENT_VERTS]; ///< face numbers for each axial direction,
|
|
32
|
+
/// in order, starting with J
|
|
33
|
+
} PentagonDirectionFaces;
|
|
34
|
+
|
|
35
|
+
/** Invalid vertex number */
|
|
36
|
+
#define INVALID_VERTEX_NUM -1
|
|
37
|
+
|
|
38
|
+
/** Max number of faces a base cell's descendants may appear on */
|
|
39
|
+
#define MAX_BASE_CELL_FACES 5
|
|
40
|
+
|
|
41
|
+
int vertexRotations(H3Index cell);
|
|
42
|
+
int vertexNumForDirection(const H3Index origin, const Direction direction);
|
|
43
|
+
|
|
44
|
+
#endif
|
|
@@ -18,12 +18,15 @@
|
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
20
|
#include "algos.h"
|
|
21
|
+
|
|
21
22
|
#include <assert.h>
|
|
22
23
|
#include <float.h>
|
|
23
24
|
#include <math.h>
|
|
24
25
|
#include <stdbool.h>
|
|
25
26
|
#include <stdlib.h>
|
|
26
27
|
#include <string.h>
|
|
28
|
+
|
|
29
|
+
#include "alloc.h"
|
|
27
30
|
#include "baseCells.h"
|
|
28
31
|
#include "bbox.h"
|
|
29
32
|
#include "faceijk.h"
|
|
@@ -41,6 +44,9 @@
|
|
|
41
44
|
#define HEX_RANGE_SUCCESS 0
|
|
42
45
|
#define HEX_RANGE_PENTAGON 1
|
|
43
46
|
#define HEX_RANGE_K_SUBSEQUENCE 2
|
|
47
|
+
#define MAX_ONE_RING_SIZE 7
|
|
48
|
+
#define HEX_HASH_OVERFLOW -1
|
|
49
|
+
#define POLYFILL_BUFFER 12
|
|
44
50
|
|
|
45
51
|
/**
|
|
46
52
|
* Directions used for traversing a hexagonal ring counterclockwise around
|
|
@@ -150,74 +156,86 @@ static const Direction NEW_ADJUSTMENT_III[7][7] = {
|
|
|
150
156
|
CENTER_DIGIT, IJ_AXES_DIGIT}};
|
|
151
157
|
|
|
152
158
|
/**
|
|
153
|
-
* Maximum number of
|
|
159
|
+
* Maximum number of cells that result from the kRing algorithm with the given
|
|
154
160
|
* k. Formula source and proof: https://oeis.org/A003215
|
|
155
161
|
*
|
|
156
|
-
* @param
|
|
162
|
+
* @param k k value, k >= 0.
|
|
157
163
|
*/
|
|
158
164
|
int H3_EXPORT(maxKringSize)(int k) { return 3 * k * (k + 1) + 1; }
|
|
159
165
|
|
|
160
166
|
/**
|
|
161
|
-
*
|
|
167
|
+
* Produce cells within grid distance k of the origin cell.
|
|
162
168
|
*
|
|
163
|
-
* k-ring 0 is defined as the origin
|
|
164
|
-
* all neighboring
|
|
169
|
+
* k-ring 0 is defined as the origin cell, k-ring 1 is defined as k-ring 0 and
|
|
170
|
+
* all neighboring cells, and so on.
|
|
165
171
|
*
|
|
166
172
|
* Output is placed in the provided array in no particular order. Elements of
|
|
167
173
|
* the output array may be left zero, as can happen when crossing a pentagon.
|
|
168
174
|
*
|
|
169
|
-
* @param
|
|
170
|
-
* @param
|
|
171
|
-
* @param
|
|
175
|
+
* @param origin origin cell
|
|
176
|
+
* @param k k >= 0
|
|
177
|
+
* @param out zero-filled array which must be of size maxKringSize(k)
|
|
172
178
|
*/
|
|
173
179
|
void H3_EXPORT(kRing)(H3Index origin, int k, H3Index* out) {
|
|
174
|
-
|
|
175
|
-
int* distances = malloc(maxIdx * sizeof(int));
|
|
176
|
-
H3_EXPORT(kRingDistances)(origin, k, out, distances);
|
|
177
|
-
free(distances);
|
|
180
|
+
H3_EXPORT(kRingDistances)(origin, k, out, NULL);
|
|
178
181
|
}
|
|
179
182
|
|
|
180
183
|
/**
|
|
181
|
-
*
|
|
184
|
+
* Produce cells and their distances from the given origin cell, up to
|
|
185
|
+
* distance k.
|
|
182
186
|
*
|
|
183
|
-
* k-ring 0 is defined as the origin
|
|
184
|
-
* all neighboring
|
|
187
|
+
* k-ring 0 is defined as the origin cell, k-ring 1 is defined as k-ring 0 and
|
|
188
|
+
* all neighboring cells, and so on.
|
|
185
189
|
*
|
|
186
190
|
* Output is placed in the provided array in no particular order. Elements of
|
|
187
191
|
* the output array may be left zero, as can happen when crossing a pentagon.
|
|
188
192
|
*
|
|
189
|
-
* @param
|
|
190
|
-
* @param
|
|
191
|
-
* @param
|
|
192
|
-
* @param
|
|
193
|
+
* @param origin origin cell
|
|
194
|
+
* @param k k >= 0
|
|
195
|
+
* @param out zero-filled array which must be of size maxKringSize(k)
|
|
196
|
+
* @param distances NULL or a zero-filled array which must be of size
|
|
197
|
+
* maxKringSize(k)
|
|
193
198
|
*/
|
|
194
199
|
void H3_EXPORT(kRingDistances)(H3Index origin, int k, H3Index* out,
|
|
195
200
|
int* distances) {
|
|
196
|
-
const int maxIdx = H3_EXPORT(maxKringSize)(k);
|
|
197
201
|
// Optimistically try the faster hexRange algorithm first
|
|
198
202
|
const bool failed = H3_EXPORT(hexRangeDistances)(origin, k, out, distances);
|
|
199
203
|
if (failed) {
|
|
204
|
+
const int maxIdx = H3_EXPORT(maxKringSize)(k);
|
|
200
205
|
// Fast algo failed, fall back to slower, correct algo
|
|
201
206
|
// and also wipe out array because contents untrustworthy
|
|
202
|
-
memset(out, 0, maxIdx * sizeof(
|
|
203
|
-
|
|
204
|
-
|
|
207
|
+
memset(out, 0, maxIdx * sizeof(H3Index));
|
|
208
|
+
|
|
209
|
+
if (distances == NULL) {
|
|
210
|
+
distances = H3_MEMORY(calloc)(maxIdx, sizeof(int));
|
|
211
|
+
if (!distances) {
|
|
212
|
+
// TODO: Return an error code when this is not void
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
_kRingInternal(origin, k, out, distances, maxIdx, 0);
|
|
216
|
+
H3_MEMORY(free)(distances);
|
|
217
|
+
} else {
|
|
218
|
+
memset(distances, 0, maxIdx * sizeof(int));
|
|
219
|
+
_kRingInternal(origin, k, out, distances, maxIdx, 0);
|
|
220
|
+
}
|
|
205
221
|
}
|
|
206
222
|
}
|
|
207
223
|
|
|
208
224
|
/**
|
|
209
225
|
* Internal helper function called recursively for kRingDistances.
|
|
210
226
|
*
|
|
211
|
-
* Adds the origin
|
|
227
|
+
* Adds the origin cell to the output set (treating it as a hash set)
|
|
212
228
|
* and recurses to its neighbors, if needed.
|
|
213
229
|
*
|
|
214
|
-
* @param
|
|
215
|
-
* @param
|
|
216
|
-
* @param
|
|
217
|
-
*
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
*
|
|
230
|
+
* @param origin Origin cell
|
|
231
|
+
* @param k Maximum distance to move from the origin
|
|
232
|
+
* @param out Array treated as a hash set, elements being either
|
|
233
|
+
* H3Index or 0.
|
|
234
|
+
* @param distances Scratch area, with elements paralleling the out array.
|
|
235
|
+
* Elements indicate ijk distance from the origin cell to
|
|
236
|
+
* the output cell
|
|
237
|
+
* @param maxIdx Size of out and scratch arrays (must be maxKringSize(k))
|
|
238
|
+
* @param curK Current distance from the origin
|
|
221
239
|
*/
|
|
222
240
|
void _kRingInternal(H3Index origin, int k, H3Index* out, int* distances,
|
|
223
241
|
int maxIdx, int curK) {
|
|
@@ -260,7 +278,7 @@ void _kRingInternal(H3Index origin, int k, H3Index* out, int* distances,
|
|
|
260
278
|
* @param rotations Number of ccw rotations to perform to reorient the
|
|
261
279
|
* translation vector. Will be modified to the new number of
|
|
262
280
|
* rotations to perform (such as when crossing a face edge.)
|
|
263
|
-
* @return H3Index of the specified neighbor or
|
|
281
|
+
* @return H3Index of the specified neighbor or H3_NULL if deleted k-subsequence
|
|
264
282
|
* distortion is encountered.
|
|
265
283
|
*/
|
|
266
284
|
H3Index h3NeighborRotations(H3Index origin, Direction dir, int* rotations) {
|
|
@@ -345,7 +363,7 @@ H3Index h3NeighborRotations(H3Index origin, Direction dir, int* rotations) {
|
|
|
345
363
|
// base cell.
|
|
346
364
|
if (oldLeadingDigit == CENTER_DIGIT) {
|
|
347
365
|
// Undefined: the k direction is deleted from here
|
|
348
|
-
return
|
|
366
|
+
return H3_NULL;
|
|
349
367
|
} else if (oldLeadingDigit == JK_AXES_DIGIT) {
|
|
350
368
|
// Rotate out of the deleted k subsequence
|
|
351
369
|
// We also need an additional change to the direction we're
|
|
@@ -360,7 +378,7 @@ H3Index h3NeighborRotations(H3Index origin, Direction dir, int* rotations) {
|
|
|
360
378
|
*rotations = *rotations + 5;
|
|
361
379
|
} else {
|
|
362
380
|
// Should never occur
|
|
363
|
-
return
|
|
381
|
+
return H3_NULL; // LCOV_EXCL_LINE
|
|
364
382
|
}
|
|
365
383
|
}
|
|
366
384
|
}
|
|
@@ -410,7 +428,7 @@ H3Index h3NeighborRotations(H3Index origin, Direction dir, int* rotations) {
|
|
|
410
428
|
* @return 0 if no pentagon or pentagonal distortion area was encountered.
|
|
411
429
|
*/
|
|
412
430
|
int H3_EXPORT(hexRange)(H3Index origin, int k, H3Index* out) {
|
|
413
|
-
return H3_EXPORT(hexRangeDistances)(origin, k, out,
|
|
431
|
+
return H3_EXPORT(hexRangeDistances)(origin, k, out, NULL);
|
|
414
432
|
}
|
|
415
433
|
|
|
416
434
|
/**
|
|
@@ -623,9 +641,8 @@ int H3_EXPORT(hexRing)(H3Index origin, int k, H3Index* out) {
|
|
|
623
641
|
* maxPolyfillSize returns the number of hexagons to allocate space for when
|
|
624
642
|
* performing a polyfill on the given GeoJSON-like data structure.
|
|
625
643
|
*
|
|
626
|
-
*
|
|
627
|
-
*
|
|
628
|
-
* a Python application? ;)
|
|
644
|
+
* The size is the maximum of either the number of points in the geofence or the
|
|
645
|
+
* number of hexagons in the bounding box of the geofence.
|
|
629
646
|
*
|
|
630
647
|
* @param geoPolygon A GeoJSON-like data structure indicating the poly to fill
|
|
631
648
|
* @param res Hexagon resolution (0-15)
|
|
@@ -634,12 +651,23 @@ int H3_EXPORT(hexRing)(H3Index origin, int k, H3Index* out) {
|
|
|
634
651
|
int H3_EXPORT(maxPolyfillSize)(const GeoPolygon* geoPolygon, int res) {
|
|
635
652
|
// Get the bounding box for the GeoJSON-like struct
|
|
636
653
|
BBox bbox;
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
//
|
|
641
|
-
// the
|
|
642
|
-
|
|
654
|
+
const Geofence geofence = geoPolygon->geofence;
|
|
655
|
+
bboxFromGeofence(&geofence, &bbox);
|
|
656
|
+
int numHexagons = bboxHexEstimate(&bbox, res);
|
|
657
|
+
// This algorithm assumes that the number of vertices is usually less than
|
|
658
|
+
// the number of hexagons, but when it's wrong, this will keep it from
|
|
659
|
+
// failing
|
|
660
|
+
int totalVerts = geofence.numVerts;
|
|
661
|
+
for (int i = 0; i < geoPolygon->numHoles; i++) {
|
|
662
|
+
totalVerts += geoPolygon->holes[i].numVerts;
|
|
663
|
+
}
|
|
664
|
+
if (numHexagons < totalVerts) numHexagons = totalVerts;
|
|
665
|
+
// When the polygon is very small, near an icosahedron edge and is an odd
|
|
666
|
+
// resolution, the line tracing needs an extra buffer than the estimator
|
|
667
|
+
// function provides (but beefing that up to cover causes most situations to
|
|
668
|
+
// overallocate memory)
|
|
669
|
+
numHexagons += POLYFILL_BUFFER;
|
|
670
|
+
return numHexagons;
|
|
643
671
|
}
|
|
644
672
|
|
|
645
673
|
/**
|
|
@@ -647,15 +675,109 @@ int H3_EXPORT(maxPolyfillSize)(const GeoPolygon* geoPolygon, int res) {
|
|
|
647
675
|
* zeroed memory, and fills it with the hexagons that are contained by
|
|
648
676
|
* the GeoJSON-like data structure.
|
|
649
677
|
*
|
|
650
|
-
*
|
|
651
|
-
*
|
|
652
|
-
*
|
|
678
|
+
* This implementation traces the GeoJSON geofence(s) in cartesian space with
|
|
679
|
+
* hexagons, tests them and their neighbors to be contained by the geofence(s),
|
|
680
|
+
* and then any newly found hexagons are used to test again until no new
|
|
681
|
+
* hexagons are found.
|
|
653
682
|
*
|
|
654
683
|
* @param geoPolygon The geofence and holes defining the relevant area
|
|
655
684
|
* @param res The Hexagon resolution (0-15)
|
|
656
685
|
* @param out The slab of zeroed memory to write to. Assumed to be big enough.
|
|
657
686
|
*/
|
|
658
687
|
void H3_EXPORT(polyfill)(const GeoPolygon* geoPolygon, int res, H3Index* out) {
|
|
688
|
+
// TODO: Eliminate this wrapper with the H3 4.0.0 release
|
|
689
|
+
int failure = _polyfillInternal(geoPolygon, res, out);
|
|
690
|
+
// The polyfill algorithm can theoretically fail if the allocated memory is
|
|
691
|
+
// not large enough for the polygon, but this should be impossible given the
|
|
692
|
+
// conservative overestimation of the number of hexagons possible.
|
|
693
|
+
// LCOV_EXCL_START
|
|
694
|
+
if (failure) {
|
|
695
|
+
int numHexagons = H3_EXPORT(maxPolyfillSize)(geoPolygon, res);
|
|
696
|
+
for (int i = 0; i < numHexagons; i++) out[i] = H3_NULL;
|
|
697
|
+
}
|
|
698
|
+
// LCOV_EXCL_STOP
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
/**
|
|
702
|
+
* _getEdgeHexagons takes a given geofence ring (either the main geofence or
|
|
703
|
+
* one of the holes) and traces it with hexagons and updates the search and
|
|
704
|
+
* found memory blocks. This is used for determining the initial hexagon set
|
|
705
|
+
* for the polyfill algorithm to execute on.
|
|
706
|
+
*
|
|
707
|
+
* @param geofence The geofence (or hole) to be traced
|
|
708
|
+
* @param numHexagons The maximum number of hexagons possible for the geofence
|
|
709
|
+
* (also the bounds of the search and found arrays)
|
|
710
|
+
* @param res The hexagon resolution (0-15)
|
|
711
|
+
* @param numSearchHexes The number of hexagons found so far to be searched
|
|
712
|
+
* @param search The block of memory containing the hexagons to search from
|
|
713
|
+
* @param found The block of memory containing the hexagons found from the
|
|
714
|
+
* search
|
|
715
|
+
*
|
|
716
|
+
* @return An error code if the hash function cannot insert a found hexagon
|
|
717
|
+
* into the found array.
|
|
718
|
+
*/
|
|
719
|
+
int _getEdgeHexagons(const Geofence* geofence, int numHexagons, int res,
|
|
720
|
+
int* numSearchHexes, H3Index* search, H3Index* found) {
|
|
721
|
+
for (int i = 0; i < geofence->numVerts; i++) {
|
|
722
|
+
GeoCoord origin = geofence->verts[i];
|
|
723
|
+
GeoCoord destination = i == geofence->numVerts - 1
|
|
724
|
+
? geofence->verts[0]
|
|
725
|
+
: geofence->verts[i + 1];
|
|
726
|
+
const int numHexesEstimate =
|
|
727
|
+
lineHexEstimate(&origin, &destination, res);
|
|
728
|
+
for (int j = 0; j < numHexesEstimate; j++) {
|
|
729
|
+
GeoCoord interpolate;
|
|
730
|
+
interpolate.lat =
|
|
731
|
+
(origin.lat * (numHexesEstimate - j) / numHexesEstimate) +
|
|
732
|
+
(destination.lat * j / numHexesEstimate);
|
|
733
|
+
interpolate.lon =
|
|
734
|
+
(origin.lon * (numHexesEstimate - j) / numHexesEstimate) +
|
|
735
|
+
(destination.lon * j / numHexesEstimate);
|
|
736
|
+
H3Index pointHex = H3_EXPORT(geoToH3)(&interpolate, res);
|
|
737
|
+
// A simple hash to store the hexagon, or move to another place if
|
|
738
|
+
// needed
|
|
739
|
+
int loc = (int)(pointHex % numHexagons);
|
|
740
|
+
int loopCount = 0;
|
|
741
|
+
while (found[loc] != 0) {
|
|
742
|
+
// If this conditional is reached, the `found` memory block is
|
|
743
|
+
// too small for the given polygon. This should not happen.
|
|
744
|
+
if (loopCount > numHexagons)
|
|
745
|
+
return HEX_HASH_OVERFLOW; // LCOV_EXCL_LINE
|
|
746
|
+
if (found[loc] == pointHex)
|
|
747
|
+
break; // At least two points of the geofence index to the
|
|
748
|
+
// same cell
|
|
749
|
+
loc = (loc + 1) % numHexagons;
|
|
750
|
+
loopCount++;
|
|
751
|
+
}
|
|
752
|
+
if (found[loc] == pointHex)
|
|
753
|
+
continue; // Skip this hex, already exists in the found hash
|
|
754
|
+
// Otherwise, set it in the found hash for now
|
|
755
|
+
found[loc] = pointHex;
|
|
756
|
+
|
|
757
|
+
search[*numSearchHexes] = pointHex;
|
|
758
|
+
(*numSearchHexes)++;
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
return 0;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
/**
|
|
765
|
+
* _polyfillInternal traces the provided geoPolygon data structure with hexagons
|
|
766
|
+
* and then iteratively searches through these hexagons and their immediate
|
|
767
|
+
* neighbors to see if they are contained within the polygon or not. Those that
|
|
768
|
+
* are found are added to the out array as well as the found array. Once all
|
|
769
|
+
* hexagons to search are checked, the found hexagons become the new search
|
|
770
|
+
* array and the found array is wiped and the process repeats until no new
|
|
771
|
+
* hexagons can be found.
|
|
772
|
+
*
|
|
773
|
+
* @param geoPolygon The geofence and holes defining the relevant area
|
|
774
|
+
* @param res The Hexagon resolution (0-15)
|
|
775
|
+
* @param out The slab of zeroed memory to write to. Assumed to be big enough.
|
|
776
|
+
*
|
|
777
|
+
* @return An error code if any of the hash operations fails to insert a hexagon
|
|
778
|
+
* into an array of memory.
|
|
779
|
+
*/
|
|
780
|
+
int _polyfillInternal(const GeoPolygon* geoPolygon, int res, H3Index* out) {
|
|
659
781
|
// One of the goals of the polyfill algorithm is that two adjacent polygons
|
|
660
782
|
// with zero overlap have zero overlapping hexagons. That the hexagons are
|
|
661
783
|
// uniquely assigned. There are a few approaches to take here, such as
|
|
@@ -674,39 +796,142 @@ void H3_EXPORT(polyfill)(const GeoPolygon* geoPolygon, int res, H3Index* out) {
|
|
|
674
796
|
// This first part is identical to the maxPolyfillSize above.
|
|
675
797
|
|
|
676
798
|
// Get the bounding boxes for the polygon and any holes
|
|
677
|
-
BBox* bboxes = malloc((geoPolygon->numHoles + 1) * sizeof(BBox));
|
|
799
|
+
BBox* bboxes = H3_MEMORY(malloc)((geoPolygon->numHoles + 1) * sizeof(BBox));
|
|
678
800
|
assert(bboxes != NULL);
|
|
679
801
|
bboxesFromGeoPolygon(geoPolygon, bboxes);
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
//
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
//
|
|
693
|
-
//
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
802
|
+
|
|
803
|
+
// Get the estimated number of hexagons and allocate some temporary memory
|
|
804
|
+
// for the hexagons
|
|
805
|
+
int numHexagons = H3_EXPORT(maxPolyfillSize)(geoPolygon, res);
|
|
806
|
+
H3Index* search = H3_MEMORY(calloc)(numHexagons, sizeof(H3Index));
|
|
807
|
+
H3Index* found = H3_MEMORY(calloc)(numHexagons, sizeof(H3Index));
|
|
808
|
+
|
|
809
|
+
// Some metadata for tracking the state of the search and found memory
|
|
810
|
+
// blocks
|
|
811
|
+
int numSearchHexes = 0;
|
|
812
|
+
int numFoundHexes = 0;
|
|
813
|
+
|
|
814
|
+
// 1. Trace the hexagons along the polygon defining the outer geofence and
|
|
815
|
+
// add them to the search hash. The hexagon containing the geofence point
|
|
816
|
+
// may or may not be contained by the geofence (as the hexagon's center
|
|
817
|
+
// point may be outside of the boundary.)
|
|
818
|
+
const Geofence geofence = geoPolygon->geofence;
|
|
819
|
+
int failure = _getEdgeHexagons(&geofence, numHexagons, res, &numSearchHexes,
|
|
820
|
+
search, found);
|
|
821
|
+
// If this branch is reached, we have exceeded the maximum number of
|
|
822
|
+
// hexagons possible and need to clean up the allocated memory.
|
|
823
|
+
// LCOV_EXCL_START
|
|
824
|
+
if (failure) {
|
|
825
|
+
H3_MEMORY(free)(search);
|
|
826
|
+
H3_MEMORY(free)(found);
|
|
827
|
+
H3_MEMORY(free)(bboxes);
|
|
828
|
+
return failure;
|
|
829
|
+
}
|
|
830
|
+
// LCOV_EXCL_STOP
|
|
831
|
+
|
|
832
|
+
// 2. Iterate over all holes, trace the polygons defining the holes with
|
|
833
|
+
// hexagons and add to only the search hash. We're going to temporarily use
|
|
834
|
+
// the `found` hash to use for dedupe purposes and then re-zero it once
|
|
835
|
+
// we're done here, otherwise we'd have to scan the whole set on each insert
|
|
836
|
+
// to make sure there's no duplicates, which is very inefficient.
|
|
837
|
+
for (int i = 0; i < geoPolygon->numHoles; i++) {
|
|
838
|
+
Geofence* hole = &(geoPolygon->holes[i]);
|
|
839
|
+
failure = _getEdgeHexagons(hole, numHexagons, res, &numSearchHexes,
|
|
840
|
+
search, found);
|
|
841
|
+
// If this branch is reached, we have exceeded the maximum number of
|
|
842
|
+
// hexagons possible and need to clean up the allocated memory.
|
|
843
|
+
// LCOV_EXCL_START
|
|
844
|
+
if (failure) {
|
|
845
|
+
H3_MEMORY(free)(search);
|
|
846
|
+
H3_MEMORY(free)(found);
|
|
847
|
+
H3_MEMORY(free)(bboxes);
|
|
848
|
+
return failure;
|
|
698
849
|
}
|
|
699
|
-
//
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
850
|
+
// LCOV_EXCL_STOP
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
// 3. Re-zero the found hash so it can be used in the main loop below
|
|
854
|
+
for (int i = 0; i < numHexagons; i++) found[i] = 0;
|
|
855
|
+
|
|
856
|
+
// 4. Begin main loop. While the search hash is not empty do the following
|
|
857
|
+
while (numSearchHexes > 0) {
|
|
858
|
+
// Iterate through all hexagons in the current search hash, then loop
|
|
859
|
+
// through all neighbors and test Point-in-Poly, if point-in-poly
|
|
860
|
+
// succeeds, add to out and found hashes if not already there.
|
|
861
|
+
int currentSearchNum = 0;
|
|
862
|
+
int i = 0;
|
|
863
|
+
while (currentSearchNum < numSearchHexes) {
|
|
864
|
+
H3Index ring[MAX_ONE_RING_SIZE] = {0};
|
|
865
|
+
H3Index searchHex = search[i];
|
|
866
|
+
H3_EXPORT(kRing)(searchHex, 1, ring);
|
|
867
|
+
for (int j = 0; j < MAX_ONE_RING_SIZE; j++) {
|
|
868
|
+
if (ring[j] == H3_NULL) {
|
|
869
|
+
continue; // Skip if this was a pentagon and only had 5
|
|
870
|
+
// neighbors
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
H3Index hex = ring[j];
|
|
874
|
+
|
|
875
|
+
// A simple hash to store the hexagon, or move to another place
|
|
876
|
+
// if needed. This MUST be done before the point-in-poly check
|
|
877
|
+
// since that's far more expensive
|
|
878
|
+
int loc = (int)(hex % numHexagons);
|
|
879
|
+
int loopCount = 0;
|
|
880
|
+
while (out[loc] != 0) {
|
|
881
|
+
// If this branch is reached, we have exceeded the maximum
|
|
882
|
+
// number of hexagons possible and need to clean up the
|
|
883
|
+
// allocated memory.
|
|
884
|
+
// LCOV_EXCL_START
|
|
885
|
+
if (loopCount > numHexagons) {
|
|
886
|
+
H3_MEMORY(free)(search);
|
|
887
|
+
H3_MEMORY(free)(found);
|
|
888
|
+
H3_MEMORY(free)(bboxes);
|
|
889
|
+
return -1;
|
|
890
|
+
}
|
|
891
|
+
// LCOV_EXCL_STOP
|
|
892
|
+
if (out[loc] == hex) break; // Skip duplicates found
|
|
893
|
+
loc = (loc + 1) % numHexagons;
|
|
894
|
+
loopCount++;
|
|
895
|
+
}
|
|
896
|
+
if (out[loc] == hex) {
|
|
897
|
+
continue; // Skip this hex, already exists in the out hash
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
// Check if the hexagon is in the polygon or not
|
|
901
|
+
GeoCoord hexCenter;
|
|
902
|
+
H3_EXPORT(h3ToGeo)(hex, &hexCenter);
|
|
903
|
+
|
|
904
|
+
// If not, skip
|
|
905
|
+
if (!pointInsidePolygon(geoPolygon, bboxes, &hexCenter)) {
|
|
906
|
+
continue;
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
// Otherwise set it in the output array
|
|
910
|
+
out[loc] = hex;
|
|
911
|
+
|
|
912
|
+
// Set the hexagon in the found hash
|
|
913
|
+
found[numFoundHexes] = hex;
|
|
914
|
+
numFoundHexes++;
|
|
915
|
+
}
|
|
916
|
+
currentSearchNum++;
|
|
917
|
+
i++;
|
|
707
918
|
}
|
|
919
|
+
|
|
920
|
+
// Swap the search and found pointers, copy the found hex count to the
|
|
921
|
+
// search hex count, and zero everything related to the found memory.
|
|
922
|
+
H3Index* temp = search;
|
|
923
|
+
search = found;
|
|
924
|
+
found = temp;
|
|
925
|
+
for (int j = 0; j < numSearchHexes; j++) found[j] = 0;
|
|
926
|
+
numSearchHexes = numFoundHexes;
|
|
927
|
+
numFoundHexes = 0;
|
|
928
|
+
// Repeat until no new hexagons are found
|
|
708
929
|
}
|
|
709
|
-
|
|
930
|
+
// The out memory structure should be complete, end it here
|
|
931
|
+
H3_MEMORY(free)(bboxes);
|
|
932
|
+
H3_MEMORY(free)(search);
|
|
933
|
+
H3_MEMORY(free)(found);
|
|
934
|
+
return 0;
|
|
710
935
|
}
|
|
711
936
|
|
|
712
937
|
/**
|