H3Error H3_EXPORT()

in src/h3lib/lib/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;
}