Skip to content

Refactor edge boundary, implement core vertex mode logic #391

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

Merged
merged 22 commits into from
Sep 24, 2020

Conversation

nrabinowitz
Copy link
Collaborator

Changes

  • Adds a new module, vertex.c, which will eventually hold vertex mode functions.
  • Implements vertexNumForDirection, which allows us to get the number (index, in the traditional sense) of the topological vertex in a given direction. The logic here is based on determining the number of rotations of the vertexes compared to a given "base" arrangement of direction-to-vertex. The base arrangement occurs when a cell is on the "home" face of its base cell. Additional rotations are required when the cell appears on a different face from its base cell's home face.
  • Most of the rotation information is included in faceIjkBaseCells, but that table is not optimized for this lookup, and there are additional rules for pentagons and polar pentagons. I've created a new lookup table to facilitate this operation, baseCellVertexRotations, along with a script to generate it.
  • Using vertexNumForDirection and a small refactor of faceIjkToGeoBoundary, allowing it to take a start vertex and sequence length, I've refactored getH3UnidirectionalEdgeBoundary to stop comparing geo coordinates and instead look up the vertex directly based on the direction.
  • Adds additional exhaustive tests down to res 6 to catch more edge cases.

Benefits

  • Fixes getH3UnidirectionalEdgeBoundary at resolutions > 12 (see changes in testH3UniEdge.c), which were broken due to inaccuracies in comparing geo coordinates.
  • Speeds up getH3UnidirectionalEdgeBoundary by about 3x:

Before

    -- getH3UnidirectionalEdgeBoundary: 58.733300 microseconds per iteration (10000 iterations) 

After

    -- getH3UnidirectionalEdgeBoundary: 18.856600 microseconds per iteration (10000 iterations)

Future Work

Implementing vertexNumForDirection and a more efficient version of getH3UnidirectionalEdgeBoundary set us up nicely for Vertex Mode functions and a significantly more efficient version of h3SetToLinkedGeo.

@coveralls
Copy link

coveralls commented Sep 8, 2020

Coverage Status

Coverage increased (+0.02%) to 99.149% when pulling 7acd21a on nrabinowitz:edge-boundary-refactor into 50e1206 on uber:master.

* @param g The spherical coordinates of the cell boundary.
*/
void _faceIjkToGeoBoundary(const FaceIJK* h, int res, int isPentagon,
void _faceIjkToGeoBoundary(const FaceIJK* h, int res, int start, int length,
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

There are two main changes to _faceIjkToGeoBoundary:

  • It now takes start and length to allow it to efficiently return only a subset of the vertex sequence
  • The caller is now responsible for switching between _faceIjkToGeoBoundary and _faceIjkPentToGeoBoundary, instead of passing in isPentagon. This is in part to limit the number of arguments, and in part because requesting all vertexes now requires passing in different lengths for hexes and pentagons.

There was only one other callsite, so this was an easy refactor.

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 one minor nit from my end. This is great! :)

Comment on lines 86 to 87
// Get the res 2 pentagon, whose neighbors have the same base cell
// and are unambiguously on the correct faces
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why is res 2 used here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

See the comment.

  • res 0 doesn't have any cells other than the base cell
  • res 1 cells cross two faces
  • res 2 cells are each on a single face, so there's no ambiguity about whether they have the right baseCell/face pair

image

I assume I could use any Class II resolution other than 0.

@nrabinowitz nrabinowitz marked this pull request as draft September 8, 2020 18:20
@nrabinowitz nrabinowitz marked this pull request as ready for review September 8, 2020 21:27
@nrabinowitz nrabinowitz force-pushed the edge-boundary-refactor branch from 88b2b71 to 4f59c03 Compare September 12, 2020 06:25

SUITE(Vertex) {
TEST(vertexNumForDirection_hex) {
H3Index origin = 0x823d6ffffffffff;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Does this need the L suffix?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Apparently not? We don't seem to be consistent, and there are a number of indexes in tests and benchmarks that don't include the L suffix and work fine. Is there a reason we thought it was required?

* Note that faces are in directional order, starting at J_AXES_DIGIT.
* This table is generated by the generatePentagonDirectionFaces script.
*/
static const PentagonDirectionFaces pentagonDirectionFaces[NUM_PENTAGONS] = {
Copy link
Collaborator

Choose a reason for hiding this comment

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

aside: this table could be used to implement getPentagonIndexes rather than looping through the base cell table.

// additional CCW rotation for polar neighbors or IK neighbors
if (fijk.face != baseFijk.face &&
(_isBaseCellPolarPentagon(baseCell) ||
fijk.face == dirFaces.faces[IK_AXES_DIGIT - 2])) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I find this table a little confusing to use because it starts indexing directions starting with J (2) rather than 0 or 1. Perhaps at least extract the 2 to a reused constant for this function?

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 extract to a const. The alternative was adding two INVALID_FACE entries to each array in the table, which didn't seem worthwhile.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Added as a defined macro (I put this in the .c file itself, rather than the header file, because this seemed clearer and it didn't make sense to export it - let me know if you disagree).

@nrabinowitz nrabinowitz merged commit f8bbc4b into uber:master Sep 24, 2020
mrdvt92 pushed a commit to mrdvt92/h3 that referenced this pull request Jun 19, 2022
Refactor edge boundary, implement core vertex mode logic
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.

4 participants