Skip to content

Add Gosper island boundary edge iterator#1138

Open
ajfriend wants to merge 4 commits into
uber:masterfrom
ajfriend:gosper_iter
Open

Add Gosper island boundary edge iterator#1138
ajfriend wants to merge 4 commits into
uber:masterfrom
ajfriend:gosper_iter

Conversation

@ajfriend
Copy link
Copy Markdown
Collaborator

@ajfriend ajfriend commented Mar 10, 2026

Closes #1114

Adds IterEdgesGosper, an iterator that yields the directed edges forming the boundary (Gosper island outline) of a cell's child set at a given resolution.

  • Each edge's origin cell is a child of the parent cell; its destination cell is not
  • Edges form a closed counter-clockwise loop
  • For a parent at resolution r expanded to child resolution R: hexagons produce 6 * 3^(R-r) edges, pentagons produce 5 * 3^(R-r)
  • For now, this is an internal-only iterator, not included in the public API

Usage

IterEdgesGosper iter = iterInitGosper(cell, childRes);
while (iter.e) {
    // iter.e is the current directed edge
    // iter.remaining is the number of edges left
    iterStepGosper(&iter);
}

Next step: Speed up cellsToMultiPolygon

This is a building block for a faster cellsToMultiPolygon. When given a pre-compacted input cell set, the iterator allows the cellsToMultiPolygon algorithm to walk the Gosper island boundary edges directly, skipping all internal edges. On a Colorado polygon at resolution 8, this yields a 35x speedup. The higher the resolution, the better the speedup. This speedup is separate from the 3-4x improvement already achieved with the new cellsToMultiPolygon algorithm.

@coveralls
Copy link
Copy Markdown

coveralls commented Mar 10, 2026

Coverage Status

coverage: 99.081% (-0.01%) from 99.095%
when pulling d96092e on ajfriend:gosper_iter
into 1d5346b on uber:master.

@ajfriend
Copy link
Copy Markdown
Collaborator Author

Talk explaining how this fits in: https://ajfriend.com/h3c2p-talk/

Comment thread src/h3lib/lib/iterGosper.c Outdated

// H3 edge direction at each edge index, in counter-clockwise order around the
// hexagon. Stored in the directed edge's reserved bits.
static const int8_t edge_dir[] = {3, 1, 5, 4, 6, 2};
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

You could also write this with type Direction and use I_AXIS_DIGIT, etc.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yeah, that's better. Updated.

I left some comments on the numeric sequence, because I think that makes it easier to see the shared pattern.

for (i = 0; iter.e; i++) {
H3Index prev = iter.e;
iterStepGosper(&iter);
t_assert(iter.e != prev, "edge should advance");
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This checks that the new cell is different but not necessarily unique (i.e., the iterator could swap between two different values and still pass this test). The comment on this function implies a more involved test that the same value will not be returned twice.

I guess this is handled practically by do_edges_connect/check_expected_edges?

Comment on lines +69 to +72
H3_EXPORT(getDirectedEdgeOrigin)(iter.e, &s); // source/origin cell
H3_EXPORT(getDirectedEdgeDestination)(iter.e, &d); // destination cell
H3_EXPORT(cellToParent)(s, parentRes, &ps); // parent of source
H3_EXPORT(cellToParent)(d, parentRes, &pd); // parent of destination
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think these should have t_assertSuccess?

Comment on lines +93 to +94
H3_EXPORT(directedEdgeToBoundary)(edge_a, &bd_a);
H3_EXPORT(directedEdgeToBoundary)(edge_b, &bd_b);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

guard with t_assertSuccess?

Comment on lines +214 to +215
0x1320807fffffffff, 0x1520807fffffffff, 0x1420807fffffffff,
0x1620807fffffffff, 0x1220807fffffffff,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

note: it would be nice if we could paste this list into h3geo.org and see the edges visualized alongside the cell

Comment on lines +136 to +139
while (iter->_isPentagon && ALWAYS(iter->e != H3_NULL) &&
H3_GET_INDEX_DIGIT(iter->e, iter->_parentRes + 1) == 1) {
advanceEdge(iter);
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I wonder if it could be possible to fast-forward to the next non-deleted edge, as an optimization.

I guess it's possible we start somewhere in the middle of the deleted subsequence, in which case it would probably be harder to compute how to get out of it in a single step.

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.

Implement iterator for edges in "Gosper Island"

3 participants