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;
}