in h3_vertex.c [210:291]
H3Error H3_EXPORT(cellToVertex)(H3Index cell, int vertexNum, H3Index *out) {
int cellIsPentagon = H3_EXPORT(isPentagon)(cell);
int cellNumVerts = cellIsPentagon ? NUM_PENT_VERTS : NUM_HEX_VERTS;
int res = H3_GET_RESOLUTION(cell);
// Check for invalid vertexes
if (vertexNum < 0 || vertexNum > cellNumVerts - 1) return E_DOMAIN;
// Default the owner and vertex number to the input cell
H3Index owner = cell;
int ownerVertexNum = vertexNum;
// Determine the owner, looking at the three cells that share the vertex.
// By convention, the owner is the cell with the lowest numerical index.
// If the cell is the center child of its parent, it will always have
// the lowest index of any neighbor, so we can skip determining the owner
if (res == 0 || H3_GET_INDEX_DIGIT(cell, res) != CENTER_DIGIT) {
// Get the left neighbor of the vertex, with its rotations
Direction left = directionForVertexNum(cell, vertexNum);
if (left == INVALID_DIGIT) return E_FAILED;
int lRotations = 0;
H3Index leftNeighbor;
H3Error leftNeighborError =
h3NeighborRotations(cell, left, &lRotations, &leftNeighbor);
if (leftNeighborError) return leftNeighborError;
// Set to owner if lowest index
if (leftNeighbor < owner) owner = leftNeighbor;
// As above, skip the right neighbor if the left is known lowest
if (res == 0 || H3_GET_INDEX_DIGIT(leftNeighbor, res) != CENTER_DIGIT) {
// Get the right neighbor of the vertex, with its rotations
// Note that vertex - 1 is the right side, as vertex numbers are CCW
Direction right = directionForVertexNum(
cell, (vertexNum - 1 + cellNumVerts) % cellNumVerts);
// This case should be unreachable; invalid verts fail earlier
if (NEVER(right == INVALID_DIGIT)) return E_FAILED;
int rRotations = 0;
H3Index rightNeighbor;
H3Error rightNeighborError =
h3NeighborRotations(cell, right, &rRotations, &rightNeighbor);
if (rightNeighborError) return rightNeighborError;
// Set to owner if lowest index
if (rightNeighbor < owner) {
owner = rightNeighbor;
Direction dir =
H3_EXPORT(isPentagon)(owner)
? directionForNeighbor(owner, cell)
: DIRECTIONS[(revNeighborDirectionsHex[right] +
rRotations) %
NUM_HEX_VERTS];
ownerVertexNum = vertexNumForDirection(owner, dir);
}
}
// Determine the vertex number for the left neighbor
if (owner == leftNeighbor) {
int ownerIsPentagon = H3_EXPORT(isPentagon)(owner);
Direction dir =
ownerIsPentagon
? directionForNeighbor(owner, cell)
: DIRECTIONS[(revNeighborDirectionsHex[left] + lRotations) %
NUM_HEX_VERTS];
// For the left neighbor, we need the second vertex of the
// edge, which may involve looping around the vertex nums
ownerVertexNum = vertexNumForDirection(owner, dir) + 1;
if (ownerVertexNum == NUM_HEX_VERTS ||
(ownerIsPentagon && ownerVertexNum == NUM_PENT_VERTS)) {
ownerVertexNum = 0;
}
}
}
// Create the vertex index
H3Index vertex = owner;
H3_SET_MODE(vertex, H3_VERTEX_MODE);
H3_SET_RESERVED_BITS(vertex, ownerVertexNum);
*out = vertex;
return E_SUCCESS;
}