Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement vertex mode #417

Merged
merged 19 commits into from
Jan 9, 2021
Merged

Implement vertex mode #417

merged 19 commits into from
Jan 9, 2021

Conversation

nrabinowitz
Copy link
Collaborator

This implements a new H3 index mode, VERTEX_MODE, which allows an H3 index to represent a shared vertex. This allows us to represent a vertex with an index rather than a geo coord, which is beneficial to some algorithms, and will allow us to fix issues in the current codebase that stem from trying to compare geo coords from different cells that might vary due to FPE.

Public functions implemented

  • cellToVertex(cell, vertexNum) - gets the H3Index representation of a single vertex for a cell. This vertex will have the same index for all three adjoining cells.
  • cellToVertexes(cell, out) - gets all vertexes for the given cell.
  • vertexToPoint(vertex, out) - gets the GeoCoord for the given vertex

To implement in a later PR

  • isValidVertex(vertex)
  • vertexToCells(vertex, out)
  • cellToCanonicalBoundary(cell)

This PR also includes benchmarks for cellToVertexes (pretty fast - on my machine, 130 microseconds for all vertexes in a 2-ring) and exhaustive tests for cellToVertexes and vertexToPoint up to res 4.

* TODO: This is currently a brute-force algorithm, but as it's O(6) that's
* probably acceptible.
*/
Direction directionForNeighbor(H3Index origin, H3Index destination) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I broke this out from getH3UnidirectionalEdge for reuse. I tried several much more clever approaches to getting the direction, but they all ended up being significantly slower than just checking all neighbors 🤷‍♂️

* Functions for cellToVertexes
* @{
*/
/** @brief Returns a single vertex for a given cell, as an H3 index */
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be "array of vertexes"? And what do folks think about using the word "returns" when the function is void and doesn't actually return anything? Do we have a more accurate alternative? Maybe "writes out"?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoops, copy/pasta error. Updated to Returns all vertexes for a given cell, as H3 indexes - "returns" seems to be what we use elsewhere, and makes more sense for the bindings (returning via modifiying the out array is basically an implementation detail).

* @{
*/
/** @brief Returns a single vertex for a given cell, as an H3 index */
DECLSPEC H3Index H3_EXPORT(cellToVertex)(H3Index origin, int vertexNum);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would getCellVertex be a better name, since this function isn't actually mapping a sell to a single vertex?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's what I originally had, but I was trying to follow the naming RFC - this is similar in meaning to cellToBoundary or directedEdgeToCells I think, a transformation rather than a property lookup.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Though I see what you're saying, it's one of many not 1:1. Hrm. Open to opinions, but cellToVertexes definitely makes sense and I like the parallel structure.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about cellToVertices? Should we spell it the right way or the "programmer way"? ;)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We (I? I can't remember if this was a discussion) decided a while back to use vertexes consistently in the codebase. Both are technically correct (see https://www.merriam-webster.com/dictionary/vertex), and I think vertexes is easier to remember, use in parallel structure, better for non-native English speakers, etc.

@coveralls
Copy link

coveralls commented Jan 5, 2021

Coverage Status

Coverage increased (+0.05%) to 99.242% when pulling edfb4dc on nrabinowitz:vertex-mode into 29e353f on uber:master.

@@ -80,5 +80,7 @@
/** H3 index modes */
#define H3_HEXAGON_MODE 1
#define H3_UNIEDGE_MODE 2
#define H3_EDGE_MODE 3
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the edge mode is reserved I presume?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes - I added H3_EDGE_MODE proactively because it made more sense for it to be sequentially next to H3_UNIEDGE_MODE, and we're pretty sure we're going to add it. Could remove here, I just thought it would look funny to have H3_UNIEDGE_MODE, H3_VERTEX_MODE, and H3_EDGE_MODE in that order.

@@ -80,5 +80,7 @@
/** H3 index modes */
#define H3_HEXAGON_MODE 1
#define H3_UNIEDGE_MODE 2
#define H3_EDGE_MODE 3
#define H3_VERTEX_MODE 4
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add the new mode to the specification in docs

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the Indexing docs, reformatting, clarifying a bit, and adding the new mode.

@@ -411,6 +411,32 @@ H3Index h3NeighborRotations(H3Index origin, Direction dir, int* rotations) {
return out;
}

/**
* Get the direction for a given neighbor. This is effectively the reverse
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This gives the direction to move from origin to destination?
Please add a comment about what this does in error cases

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will update comment

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you want more error explanation than Returns INVALID_DIGIT if the cells are not neighbors? This is the only error case AFAIK, though invalid indexes might incorrectly return a direction (depending on what h3NeighborRotations does with invalid indexes).

* @param cell Cell to get the vertexes for
* @param vertexes Array to hold vertex output. Must have length >= 6.
*/
void H3_EXPORT(cellToVertexes)(H3Index cell, H3Index* vertexes) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as part of the return code work I imagine these function signatures will get updated. Can't do that in this PR because some needed types are not present.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possibly? There isn't an error case for this function if cell is valid (and, per similar discussions, I'm not verifying that here). I'm actually not certain what would happen here if an invalid cell is passed in (likely the output is undefined, possibly it's all H3_NULL)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As with #359 I'd like to make all public functions have a mechanism to return error information since we don't have an exception capacity otherwise.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, that makes sense. So we'd include the mechanism even when unused.

Copy link
Collaborator

@dfellis dfellis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only minor comments. Look great!

* @{
*/
/** @brief Returns a single vertex for a given cell, as an H3 index */
DECLSPEC H3Index H3_EXPORT(cellToVertex)(H3Index origin, int vertexNum);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about cellToVertices? Should we spell it the right way or the "programmer way"? ;)


The three bits for each unused digit are set to 7.
An H3 Vertex index (mode 4) represents a single topological vertex in H3 grid system, shared by three cells. Note that this does not include the distortion vertexes occasionally present in a cell's geo boundary. An H3 Vertex is arbitrarily assigned one of the three neighboring cells as its "owner". The components of the H3 Vertex index are packed into a 64-bit integer in order, highest bit first, as follows:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment that the owner is used to calculate the canonical index of the vertex? Otherwise not clear what "owner" means.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will do

@nrabinowitz nrabinowitz merged commit 5988d7c into uber:master Jan 9, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants