h3 3.6.2 → 3.7.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/ext/h3/src/RELEASE.md
CHANGED
@@ -2,8 +2,10 @@
|
|
2
2
|
|
3
3
|
1. Create a PR "Preparing for release X.Y.Z" against master branch
|
4
4
|
* Alter CHANGELOG.md from `[Unreleased]` to `[X.Y.Z] YYYY-MM-DD`
|
5
|
-
* Run `make update-version` and give `X.Y.Z` when prompted
|
5
|
+
* Run `make update-version` and give `X.Y.Z` when prompted (this updates
|
6
|
+
the VERSION file, so don't change it manually)
|
6
7
|
* Check that all merges that need to be in the changelog are present
|
8
|
+
* Get reviews and merge the PR
|
7
9
|
|
8
10
|
2. Create a release "Release X.Y.Z" on Github
|
9
11
|
* Create Tag `vX.Y.Z`
|
data/ext/h3/src/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.
|
1
|
+
3.7.1
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# RFC: <Subject>
|
2
|
+
|
3
|
+
* **Authors**: -
|
4
|
+
* **Date**: -
|
5
|
+
* **Status**: Draft
|
6
|
+
|
7
|
+
## Abstract
|
8
|
+
|
9
|
+
*Brief overview of the subject and proposal*
|
10
|
+
|
11
|
+
## Motivation
|
12
|
+
|
13
|
+
*Why is this important?*
|
14
|
+
|
15
|
+
## Approaches
|
16
|
+
|
17
|
+
*What are the various options to address this issue?*
|
18
|
+
|
19
|
+
## Proposal
|
20
|
+
|
21
|
+
*What is the recommended approach?*
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# RFC: Consistent error handling
|
2
|
+
|
3
|
+
* **Authors**: -
|
4
|
+
* **Date**: -
|
5
|
+
* **Status**: Draft
|
6
|
+
|
7
|
+
## Abstract
|
8
|
+
|
9
|
+
Error handling in the H3 library is inconsistent across functions, many of which have no explicit mechanism to indicate that an error occured. This RFC proposes updating all functions that allocate blocks of memory or that could receive invalid input to return an integer code indicating success or error.
|
10
|
+
|
11
|
+
## Motivation
|
12
|
+
|
13
|
+
*Why is this important?*
|
14
|
+
|
15
|
+
## Approaches
|
16
|
+
|
17
|
+
*What are the various options to address this issue?*
|
18
|
+
|
19
|
+
## Proposal
|
20
|
+
|
21
|
+
*What is the recommended approach?*
|
@@ -0,0 +1,276 @@
|
|
1
|
+
# RFC: Names for H3 Concepts, Types, and Functions
|
2
|
+
|
3
|
+
- **Authors**:
|
4
|
+
- AJ Friend
|
5
|
+
- Nick Rabinowitz
|
6
|
+
- Isaac Brodsky
|
7
|
+
- David Ellis
|
8
|
+
- **Dates**:
|
9
|
+
- Started: 2020-02-02
|
10
|
+
- Accepted: 2020-03-26
|
11
|
+
- **Status**: Accepted
|
12
|
+
- **Discussions**:
|
13
|
+
- <https://github.com/uber/h3/pull/308>
|
14
|
+
|
15
|
+
## Motivation
|
16
|
+
|
17
|
+
Concepts like `hexagon`, `cell`, and `index` are currently used ambiguously in the H3 codebase and in documentation.
|
18
|
+
This can cause confusion, for example, when a function might only work on strict H3 *hexagons*, but fails when encountering H3 *pentagons*.
|
19
|
+
|
20
|
+
Reaching a consensus on the precise, technical language used when discussing H3 concepts will clarify future library discussions and improve end-user documentation.
|
21
|
+
|
22
|
+
We would also like to standardize a function-naming scheme.
|
23
|
+
|
24
|
+
## Terminology
|
25
|
+
|
26
|
+
The following technical terms should be used in the documentation, the H3 codebase, and precise technical discussions of the library.
|
27
|
+
|
28
|
+
- `H3Index`:
|
29
|
+
- an unsigned 64-bit integer representing *any* H3 object (hexagon, pentagon, directed edge ...)
|
30
|
+
- often represented as a 15-character (or 16-character) hexadecimal string, like `'8928308280fffff'`
|
31
|
+
- the full term "H3 index" should be used to avoid confusion with other common uses of "index";
|
32
|
+
when a "traditional" index is needed, prefer using "number", "pos", or another term to avoid confusion
|
33
|
+
- **mode**:
|
34
|
+
- an integer describing the type of object being represented by an H3 index
|
35
|
+
- this integer is encoded in the `H3Index`
|
36
|
+
- **cell** or **H3 cell**:
|
37
|
+
- a geometric/geographic unit polygon in the H3 grid, corresponding to an `H3Index` of `mode 1` (hexagon or pentagon)
|
38
|
+
- for functions that can handle either hexagons or pentagons, the more general term "cell" should be used whenever possible
|
39
|
+
- **hexagon**:
|
40
|
+
- an H3 **cell** that is a **topological** hexagon
|
41
|
+
- below, we explain that functions that *only* work with **hexagons** have an `Unsafe` suffix;
|
42
|
+
these functions are paired with ones having a `Safe` suffix, meaning they can handle **pentagons**, but are slower
|
43
|
+
- **pentagon**:
|
44
|
+
- an H3 **cell** that is a **topological** pentagon
|
45
|
+
- **directed edge**:
|
46
|
+
- represents a traversal from an origin **cell** to an adjacent destination **cell**
|
47
|
+
- corresponds to an `H3Index` of `mode 2`
|
48
|
+
- **grid**:
|
49
|
+
- the graph with nodes corresponding to H3 cells, and edges given by pairs of adjacent cells
|
50
|
+
- for example, `gridDistance` is the minimal number of edges in a graph path connecting two cells
|
51
|
+
- **point**:
|
52
|
+
- a representation of a geographic point in terms of a latitude/longitude pair
|
53
|
+
- **topological**:
|
54
|
+
- H3 cells are **topological** pentagons or hexagons, in the sense that they have 5 or 6 neighbors, respectively, in the H3 **grid**
|
55
|
+
- the majority of **hexagons** are also **geometric** hexagons (similarly with **pentagons**), in that they have 6 edges and vertices when represented as polygons of lat/lng points
|
56
|
+
- a small number of **hexagons** are not **geometric** hexagons (similarly with **pentagons**), in that they have extra vertices and edges due to distortion around icosahedron boundaries
|
57
|
+
- for more details, see this [h3-js issue](https://github.com/uber/h3-js/issues/53) or this [Observable post](https://observablehq.com/@fil/h3-oddities)
|
58
|
+
- **base cell**:
|
59
|
+
- one of the 122 H3 **cells** (110 hexagons and 12 pentagons) of resolution `0`
|
60
|
+
- every other cell in H3 is a child of a base cell
|
61
|
+
- each base cell has a "base cell number" (0--121), which is encoded into the `H3Index` representation of every H3 cell
|
62
|
+
- there is a one-to-one correspondence between the "base cell number" and the `H3Index` representation of resolution `0` cells
|
63
|
+
+ e.g., base cell 0 has `H3Index` hexadecimal representation `'8001fffffffffff'`
|
64
|
+
- **boundary**:
|
65
|
+
- all or part of the list of geometric points that enclose an H3 cell
|
66
|
+
- may include more than 6 points in the case that a cell is not a geometric hexagon, such as when a hexagon crosses an icosahedron boundary
|
67
|
+
- may also be used to describe the boundary between two geometric cells, as in the case of an edge
|
68
|
+
- represented in the H3 codebase with the `CellBoundary` struct (previously `GeoBoundary` before v4.0)
|
69
|
+
- `H3_NULL`;
|
70
|
+
- equivalent to `0` and guaranteed to never be a valid `H3Index` (even after any future H3 **modes** are added)
|
71
|
+
- returned by functions to denote an error, or to denote missing data in arrays of `H3Index`
|
72
|
+
- analogous to `NaN` in floating point
|
73
|
+
|
74
|
+
|
75
|
+
### Use of "hex", "hexagon", "cell", "pentagon", etc.
|
76
|
+
|
77
|
+
We realize that "hex" or "hexagon" will still be used informally to refer to the concept of "cell" (As the development team, we do it ourselves!).
|
78
|
+
This should be expected in casual, informal discussions of H3.
|
79
|
+
However, when *precision* is required, we advise the use of strict technical terms like "index", "cell", "hexagon", "pentagon", etc.
|
80
|
+
In the codebase and in the documentation, strictly correct terminology should *always* be used, as many functions and algorithms distinguish between hexagons and pentagons.
|
81
|
+
|
82
|
+
|
83
|
+
## `H3_EXPORT` and C name collisions
|
84
|
+
|
85
|
+
To avoid C name collisions, we should build the bindings (`h3-py`, `h3-java`, `h3-go`, and `h3-node`) with a standard function prefix, using the `H3_EXPORT` C macro.
|
86
|
+
The `h3-js` binding would not need this.
|
87
|
+
|
88
|
+
The proposed prefix is `h3_`.
|
89
|
+
|
90
|
+
## Functions
|
91
|
+
|
92
|
+
### Conventions for "property getters" and transforms
|
93
|
+
|
94
|
+
- use `get` prefix for
|
95
|
+
+ constant data (`getNumCells`, `getRes0Cells`)
|
96
|
+
+ object properties (`getResolution`, `getBaseCellNumber`)
|
97
|
+
- use `to` to denote transforms
|
98
|
+
+ different representations of the same object
|
99
|
+
+ when doing a lossy transformation to a new object (`cellToParent`, `pointToCell`)
|
100
|
+
- do not use `get` or `to` for *computations*
|
101
|
+
+ e.g., `polyfill`, `compact`, `cellAreaKm2`
|
102
|
+
|
103
|
+
There is some ambiguity between property, transform, and computation, so use your best judgement with these guidelines in mind.
|
104
|
+
|
105
|
+
### Validity checks
|
106
|
+
|
107
|
+
- `isValid*` should mean that a *full* validity check is made
|
108
|
+
- without `Valid` (like in the case of `isPentagon`), we do not guarantee
|
109
|
+
that a full validity check is made; instead, a user should assume only a
|
110
|
+
minimal bit mask check is done
|
111
|
+
- we could imagine a `isValidPengaton` function, if full verification
|
112
|
+
would be convenient
|
113
|
+
- similarly, a function like `areNeighborCells` will assume each cell
|
114
|
+
has passed the `isValidCell` check; the function will do only minimal
|
115
|
+
work to determine if they are neighbors
|
116
|
+
|
117
|
+
|
118
|
+
### General Function Names
|
119
|
+
|
120
|
+
| Current name | Proposed name |
|
121
|
+
|-------------------------------|-----------------------|
|
122
|
+
| *Does Not Exist (DNE)* | `isValidIndex` |
|
123
|
+
| `h3IsValid` | `isValidCell` |
|
124
|
+
| `h3UnidirectionalEdgeIsValid` | `isValidDirectedEdge` |
|
125
|
+
| `h3IsPentagon` | `isPentagon` |
|
126
|
+
| `h3IsResClassIII` | `isResClassIII` |
|
127
|
+
| `h3IndexesAreNeighbors` | `areNeighborCells` |
|
128
|
+
| `h3ToParent` | `cellToParent` |
|
129
|
+
| `h3ToCenterChild` | `cellToCenterChild` |
|
130
|
+
| `h3ToChildren` | `cellToChildren` |
|
131
|
+
| `numHexagons` | `getNumCells` |
|
132
|
+
| `getRes0Indexes` | `getRes0Cells` |
|
133
|
+
| `getPentagonIndexes` | `getPentagons` |
|
134
|
+
| `h3GetBaseCell` | `getBaseCellNumber` |
|
135
|
+
| `h3GetResolution` | `getResolution` |
|
136
|
+
| *DNE* | `getMode` |
|
137
|
+
| `h3GetFaces` | `getIcosahedronFaces` |
|
138
|
+
| `geoToH3` | `pointToCell` |
|
139
|
+
| `h3ToGeo` | `cellToPoint` |
|
140
|
+
| `compact` | `compactCells` |
|
141
|
+
| `uncompact` | `uncompactCells` |
|
142
|
+
| `polyfill` | `polygonToCells` |
|
143
|
+
|
144
|
+
**Note**: `getResolution` and `getBaseCellNumber` should work for both cells and edges.
|
145
|
+
|
146
|
+
|
147
|
+
### H3 Grid Functions
|
148
|
+
|
149
|
+
Many of these functions will have three forms:
|
150
|
+
- `<func_name>`
|
151
|
+
- `<func_name>Unsafe`
|
152
|
+
- `<func_name>Safe`
|
153
|
+
|
154
|
+
The `Unsafe` version is fast, but may fail if it encounters a pentagon.
|
155
|
+
It should return a failure code in this case.
|
156
|
+
|
157
|
+
The `Safe` version is slower, but will work in all cases.
|
158
|
+
|
159
|
+
The version without either suffix is intended to be the one typically
|
160
|
+
used.
|
161
|
+
This version will first attempt the `Unsafe` version, and if
|
162
|
+
it detects failure, will fall back to the `Safe` version.
|
163
|
+
Encountering pentagons is rare in most use-cases, so this version
|
164
|
+
should usually be equivalent to the fast version, but with a guarantee
|
165
|
+
that it will not fail.
|
166
|
+
|
167
|
+
Initially, we **will not** expose the `Safe` versions to users in the API.
|
168
|
+
We may expose them in the future if a need becomes clear.
|
169
|
+
|
170
|
+
|
171
|
+
#### Distance
|
172
|
+
|
173
|
+
| Current name | Proposed name |
|
174
|
+
|--------------|-------------------------|
|
175
|
+
| `h3Distance` | `gridDistance` |
|
176
|
+
| `h3Line` | `gridPathCells` |
|
177
|
+
| *DNE* | `gridPathEdges` |
|
178
|
+
| *DNE* | `gridPathDirectedEdges` |
|
179
|
+
|
180
|
+
|
181
|
+
#### Filled-In Disk With Distances
|
182
|
+
|
183
|
+
| Current name | Proposed name | Calls |
|
184
|
+
|---------------------|---------------------------|---------------------------------------|
|
185
|
+
| `hexRangeDistances` | `gridDiskDistancesUnsafe` | NONE |
|
186
|
+
| `_kRingInternal` | `gridDiskDistancesSafe` | NONE |
|
187
|
+
| `kRingDistances` | `gridDiskDistances` | `hexRangeDistances`, `_kRingInternal` |
|
188
|
+
|
189
|
+
|
190
|
+
#### Filled-In Disk Without Distances
|
191
|
+
|
192
|
+
| Current name | Proposed name | Calls |
|
193
|
+
|--------------|-------------------|---------------------|
|
194
|
+
| `hexRange` | `gridDiskUnsafe` | `hexRangeDistances` |
|
195
|
+
| *DNE* | `gridDiskSafe` | |
|
196
|
+
| `kRing` | `gridDisk` | `kRingDistances` |
|
197
|
+
| `hexRanges` | `gridDisksUnsafe` | N x `hexRange` |
|
198
|
+
|
199
|
+
- **Note**: We may remove `hexRanges` from the API, as it is just a very simple wrapper around
|
200
|
+
`hexRange`. Inclusion is a discussion separate from this RFC. We'll simply state that
|
201
|
+
*if we do* include it, we will rename it `gridDisksUnsafe`.
|
202
|
+
|
203
|
+
|
204
|
+
#### Hollow Ring
|
205
|
+
|
206
|
+
| Current name | Proposed name | Calls |
|
207
|
+
|--------------|------------------|----------------------------------|
|
208
|
+
| `hexRing` | `gridRingUnsafe` | NONE |
|
209
|
+
| *DNE* | `gridRingSafe` | `gridDiskDistancesSafe` |
|
210
|
+
| *DNE* | `gridRing` | `gridRingUnsafe`, `gridRingSafe` |
|
211
|
+
|
212
|
+
### H3 Edge Types
|
213
|
+
|
214
|
+
Instead of `UnidirectionalEdge`, use the term `DirectedEdge`.
|
215
|
+
|
216
|
+
For a future undirected edge mode, use the term `Edge`.
|
217
|
+
|
218
|
+
| Current name | Proposed name |
|
219
|
+
|-----------------------------------------------|------------------------------|
|
220
|
+
| `h3UnidirectionalEdgeIsValid` | `isValidDirectedEdge` |
|
221
|
+
| `getH3UnidirectionalEdge` | `cellsToDirectedEdge` |
|
222
|
+
| `getH3IndexesFromUnidirectionalEdge` | `directedEdgeToCells` |
|
223
|
+
| `getH3UnidirectionalEdgesFromHexagon` | `originToDirectedEdges` |
|
224
|
+
| *DNE* | `destinationToDirectedEdges` |
|
225
|
+
| `getH3UnidirectionalEdgeBoundary` | `directedEdgeToBoundary` |
|
226
|
+
| `getOriginH3IndexFromUnidirectionalEdge` | `getDirectedEdgeOrigin` |
|
227
|
+
| `getDestinationH3IndexFromUnidirectionalEdge` | `getDirectedEdgeDestination` |
|
228
|
+
|
229
|
+
|
230
|
+
### Area/Length Functions
|
231
|
+
|
232
|
+
| Current name | Proposed name |
|
233
|
+
|----------------|-----------------------------|
|
234
|
+
| `hexAreaKm2` | `getHexagonAreaAvgKm2` |
|
235
|
+
| `hexAreaM2` | `getHexagonAreaAvgM2` |
|
236
|
+
| `edgeLengthKm` | `getHexagonEdgeLengthAvgKm` |
|
237
|
+
| `edgeLengthM` | `getHexagonEdgeLengthAvgM` |
|
238
|
+
| *DNE* | `getPentagonAreaAvg*` |
|
239
|
+
| *DNE* | `getPentagonEdgeLengthAvg*` |
|
240
|
+
| *DNE* | `cellAreaKm2` |
|
241
|
+
| *DNE* | `cellAreaM2` |
|
242
|
+
|
243
|
+
**Note**: `cellAreaKm2` and `cellAreaM2` would return the actual area of
|
244
|
+
the passed-in cell.
|
245
|
+
|
246
|
+
|
247
|
+
## Polygons
|
248
|
+
|
249
|
+
**Note**: In addition to the changes listed in this section, we are considering
|
250
|
+
removing the `Linked*` data types from the public API. However, that is a larger
|
251
|
+
discussion requiring benchmarking, so we will defer that to a
|
252
|
+
[separate issue](https://github.com/uber/h3/issues/323) outside of this RFC.
|
253
|
+
|
254
|
+
|
255
|
+
### Data Structures
|
256
|
+
|
257
|
+
- rename `GeoBoundary` to `CellBoundary` to indicate it is space-limited to describing the geometry of cells
|
258
|
+
|
259
|
+
| Current name | Proposed name | Notes |
|
260
|
+
|-------------------|-------------------|-----------------------------------|
|
261
|
+
| `GeoBoundary` | `CellBoundary` | <= 10 stack-allocated `GeoPoint`s |
|
262
|
+
| `GeoCoord` | `GeoPoint` | |
|
263
|
+
| `Geofence` | `GeoLoop` | heap-allocated `GeoPoint`s |
|
264
|
+
| `GeoPolygon` | `GeoPolygon` | |
|
265
|
+
| `GeoMultiPolygon` | `GeoMultiPolygon` | currently not used |
|
266
|
+
|
267
|
+
|
268
|
+
### Functions
|
269
|
+
|
270
|
+
| Current name | Proposed name | Notes |
|
271
|
+
|-----------------------------------|--------------------------|------------------------|
|
272
|
+
| `h3ToGeoBoundary` | `cellToBoundary` | returns `CellBoundary` |
|
273
|
+
| *DNE* | `cellToLoop` | returns `GeoLoop` |
|
274
|
+
| *DNE* | `loopToBoundary` | |
|
275
|
+
| *DNE* | `boundaryToLoop` | |
|
276
|
+
| `getH3UnidirectionalEdgeBoundary` | `directedEdgeToBoundary` | returns `CellBoundary` |
|
@@ -0,0 +1,141 @@
|
|
1
|
+
# RFC: Overrideable allocation functions for H3
|
2
|
+
|
3
|
+
* **Authors**: Isaac Brodsky (@isaacbrodsky)
|
4
|
+
* **Date**: February 7, 2020
|
5
|
+
* **Status**: Draft
|
6
|
+
|
7
|
+
## Overview
|
8
|
+
|
9
|
+
This is a proposal for adding a mechanism for users of the H3 library to provide heap allocator instead of the default
|
10
|
+
malloc implementation.
|
11
|
+
|
12
|
+
## Motivation
|
13
|
+
|
14
|
+
This will address the following use cases:
|
15
|
+
|
16
|
+
* H3 is used inside of another application which has its own heap management scheme. For example, using the allocation
|
17
|
+
functions provided by Postgres or the Java Virtual Machine.
|
18
|
+
* Testing of failure cases of H3, by simulating allocation failures.
|
19
|
+
|
20
|
+
Most H3 functions accept memory from the caller in order to avoid this problem. This will still be the preferred way
|
21
|
+
to handle memory management in H3. Stack allocation is avoided because H3 cannot know whether there is sufficient stack
|
22
|
+
memory available. (Note that `_kRingInternal`/`kRingDistances` implicitly uses stack allocation because it implements DFS
|
23
|
+
recursively.)
|
24
|
+
|
25
|
+
A few functions in H3 do heap allocate memory because it is not feasible to do otherwise, or as a convenience. The
|
26
|
+
functions that heap allocate are:
|
27
|
+
|
28
|
+
| Function | Reason
|
29
|
+
| --- | ---
|
30
|
+
| `kRing`| Convenience wrapper around `kRingDistances`
|
31
|
+
| `polyfill` | Convenience (could be passed in, requires internal knowledge)
|
32
|
+
| `compact` | Convenience (could be passed in, requires internal knowledge)
|
33
|
+
| `h3SetToLinkedGeo` | Requires knowledge of how to initialize the internal struct
|
34
|
+
| `destroyLinkedPolygon` | Required for `h3SetToLinkedGeo`
|
35
|
+
|
36
|
+
## Prior Art
|
37
|
+
|
38
|
+
Reading materials to reference:
|
39
|
+
|
40
|
+
* [C++ `vector`](http://www.cplusplus.com/reference/vector/vector/) (via templates)
|
41
|
+
* [SDL](https://discourse.libsdl.org/t/sdl-2-0-7-prerelease/23232) (via `SDL_SetMemoryFunctions`)
|
42
|
+
* [PostgreSQL](https://www.postgresql.org/docs/10/xfunc-c.html) (via `palloc`)
|
43
|
+
* [SQLite](https://sqlite.org/malloc.html)
|
44
|
+
|
45
|
+
## Approaches
|
46
|
+
|
47
|
+
All approaches assume the user has defined the following functions:
|
48
|
+
|
49
|
+
```
|
50
|
+
void* my_malloc(size_t size);
|
51
|
+
void* my_calloc(size_t count, size_t size);
|
52
|
+
void my_free(void* pointer);
|
53
|
+
|
54
|
+
// TODO: Do we want my_realloc?
|
55
|
+
```
|
56
|
+
|
57
|
+
### Global statics
|
58
|
+
|
59
|
+
In this approach, H3 stores the allocation functions in a set of static variables.
|
60
|
+
|
61
|
+
```
|
62
|
+
h3SetAllocator(&my_alloc, &my_calloc, &my_free);
|
63
|
+
|
64
|
+
// call into H3 as before
|
65
|
+
polyfill(geoPolygon, res, out);
|
66
|
+
```
|
67
|
+
|
68
|
+
Pro:
|
69
|
+
* Allows the user to replace allocators at run time.
|
70
|
+
|
71
|
+
Con:
|
72
|
+
* Not thread safe, or an additional, complicated dependency is needed to ensure thread safety.
|
73
|
+
* Global state.
|
74
|
+
|
75
|
+
### Templates
|
76
|
+
|
77
|
+
This approach is similar to how C++ handles allocator replacement in its standard library, by accepting the allocator
|
78
|
+
as a template argument. However, H3 is written in C and must implement templates using macros.
|
79
|
+
|
80
|
+
```
|
81
|
+
POLYFILL_WITH_ALLLOCATORS(my_polyfill, my_malloc, my_calloc, my_free);
|
82
|
+
|
83
|
+
// Call the function created by the template
|
84
|
+
my_polyfill(geoPolygon, res, out);
|
85
|
+
```
|
86
|
+
|
87
|
+
Pro:
|
88
|
+
* Allows the user to have multiple allocator replacements in use at once.
|
89
|
+
|
90
|
+
Con:
|
91
|
+
* Exposes a complicated build process to the user in the form of macros.
|
92
|
+
|
93
|
+
### Allocator argument approach
|
94
|
+
|
95
|
+
In this approach, every function call includes allocators.
|
96
|
+
|
97
|
+
```
|
98
|
+
H3MemoryManager allocFunctions = {
|
99
|
+
.malloc = &my_malloc,
|
100
|
+
.calloc = &my_calloc,
|
101
|
+
.free = &my_free
|
102
|
+
};
|
103
|
+
|
104
|
+
polyfill(geoPolygon, res, out, &allocFunctions);
|
105
|
+
```
|
106
|
+
|
107
|
+
Pro:
|
108
|
+
* Allowing replacement on a per-call basis allows for maximum control by the user.
|
109
|
+
|
110
|
+
Con:
|
111
|
+
* The user must always specify allocators, which is unlikely to be needed by most users.
|
112
|
+
* Alternately, additional overloads of all H3 functions that heap-allocate are needed.
|
113
|
+
|
114
|
+
### `#define` approach
|
115
|
+
|
116
|
+
In this approach, the allocators are specified at build time.
|
117
|
+
|
118
|
+
```
|
119
|
+
# In build process:
|
120
|
+
cmake -DH3_ALLOC_PREFIX=my_ ...
|
121
|
+
|
122
|
+
// in source file, functions are used as before.
|
123
|
+
```
|
124
|
+
|
125
|
+
Alternately, instead of setting a prefix, the build could accept individual options
|
126
|
+
for functions, such as `-DH3_MALLOC=my_malloc -DH3_CALLOC=my_calloc`. (Although this
|
127
|
+
could allow a user to accidentally override `malloc` but not `free`, which is generally
|
128
|
+
very bad.)
|
129
|
+
|
130
|
+
Pro:
|
131
|
+
* Minimal overhead for users and developers when allocator replacement is not needed.
|
132
|
+
|
133
|
+
Con:
|
134
|
+
* Complex allocator replacement (i.e. different allocators for different calls) is possible but requires implementation
|
135
|
+
by the user.
|
136
|
+
|
137
|
+
## Proposal
|
138
|
+
|
139
|
+
`#define` based allocator replacement seems like the clearest and lowest overhead to implement, while still supporting
|
140
|
+
the full range of use cases. A user could optionally implement a more complicated replacement inside their custom
|
141
|
+
allocator functions.
|