H3Error H3_EXPORT()

in h3_directedEdge.c [38:123]


H3Error H3_EXPORT(areNeighborCells)(H3Index origin, H3Index destination,
                                    int *out) {
    // Make sure they're hexagon indexes
    if (H3_GET_MODE(origin) != H3_CELL_MODE ||
        H3_GET_MODE(destination) != H3_CELL_MODE) {
        return E_CELL_INVALID;
    }

    // Hexagons cannot be neighbors with themselves
    if (origin == destination) {
        *out = 0;
        return E_SUCCESS;
    }

    // Only hexagons in the same resolution can be neighbors
    if (H3_GET_RESOLUTION(origin) != H3_GET_RESOLUTION(destination)) {
        return E_RES_MISMATCH;
    }

    // H3 Indexes that share the same parent are very likely to be neighbors
    // Child 0 is neighbor with all of its parent's 'offspring', the other
    // children are neighbors with 3 of the 7 children. So a simple comparison
    // of origin and destination parents and then a lookup table of the children
    // is a super-cheap way to possibly determine they are neighbors.
    int parentRes = H3_GET_RESOLUTION(origin) - 1;
    if (parentRes > 0) {
        // TODO: Return error codes here
        H3Index originParent;
        H3_EXPORT(cellToParent)(origin, parentRes, &originParent);
        H3Index destinationParent;
        H3_EXPORT(cellToParent)(destination, parentRes, &destinationParent);
        if (originParent == destinationParent) {
            Direction originResDigit =
                H3_GET_INDEX_DIGIT(origin, parentRes + 1);
            Direction destinationResDigit =
                H3_GET_INDEX_DIGIT(destination, parentRes + 1);
            if (originResDigit == CENTER_DIGIT ||
                destinationResDigit == CENTER_DIGIT) {
                *out = 1;
                return E_SUCCESS;
            }
            if (originResDigit >= INVALID_DIGIT) {
                // Prevent indexing off the end of the array below
                return E_CELL_INVALID;
            }
            if ((originResDigit == K_AXES_DIGIT ||
                 destinationResDigit == K_AXES_DIGIT) &&
                H3_EXPORT(isPentagon)(originParent)) {
                // If these are invalid cells, fail rather than incorrectly
                // reporting neighbors. For pentagon cells that are actually
                // neighbors across the deleted subsequence, they will fail the
                // optimized check below, but they will be accepted by the
                // gridDisk check below that.
                return E_CELL_INVALID;
            }
            // These sets are the relevant neighbors in the clockwise
            // and counter-clockwise
            const Direction neighborSetClockwise[] = {
                CENTER_DIGIT,  JK_AXES_DIGIT, IJ_AXES_DIGIT, J_AXES_DIGIT,
                IK_AXES_DIGIT, K_AXES_DIGIT,  I_AXES_DIGIT};
            const Direction neighborSetCounterclockwise[] = {
                CENTER_DIGIT,  IK_AXES_DIGIT, JK_AXES_DIGIT, K_AXES_DIGIT,
                IJ_AXES_DIGIT, I_AXES_DIGIT,  J_AXES_DIGIT};
            if (neighborSetClockwise[originResDigit] == destinationResDigit ||
                neighborSetCounterclockwise[originResDigit] ==
                    destinationResDigit) {
                *out = 1;
                return E_SUCCESS;
            }
        }
    }

    // Otherwise, we have to determine the neighbor relationship the "hard" way.
    H3Index neighborRing[7] = {0};
    H3_EXPORT(gridDisk)(origin, 1, neighborRing);
    for (int i = 0; i < 7; i++) {
        if (neighborRing[i] == destination) {
            *out = 1;
            return E_SUCCESS;
        }
    }

    // Made it here, they definitely aren't neighbors
    *out = 0;
    return E_SUCCESS;
}