in src/h3lib/lib/algos.c [572:638]
int H3_EXPORT(hexRing)(H3Index origin, int k, H3Index* out) {
// Short-circuit on 'identity' ring
if (k == 0) {
out[0] = origin;
return 0;
}
int idx = 0;
// Number of 60 degree ccw rotations to perform on the direction (based on
// which faces have been crossed.)
int rotations = 0;
// Scratch structure for checking for pentagons
if (H3_EXPORT(h3IsPentagon)(origin)) {
// Pentagon was encountered; bail out as user doesn't want this.
return HEX_RANGE_PENTAGON;
}
for (int ring = 0; ring < k; ring++) {
origin = h3NeighborRotations(origin, NEXT_RING_DIRECTION, &rotations);
if (origin == 0) { // LCOV_EXCL_BR_LINE
// Should not be possible because `origin` would have to be a
// pentagon
return HEX_RANGE_K_SUBSEQUENCE; // LCOV_EXCL_LINE
}
if (H3_EXPORT(h3IsPentagon)(origin)) {
return HEX_RANGE_PENTAGON;
}
}
H3Index lastIndex = origin;
out[idx] = origin;
idx++;
for (int direction = 0; direction < 6; direction++) {
for (int pos = 0; pos < k; pos++) {
origin =
h3NeighborRotations(origin, DIRECTIONS[direction], &rotations);
if (origin == 0) { // LCOV_EXCL_BR_LINE
// Should not be possible because `origin` would have to be a
// pentagon
return HEX_RANGE_K_SUBSEQUENCE; // LCOV_EXCL_LINE
}
// Skip the very last index, it was already added. We do
// however need to traverse to it because of the pentagonal
// distortion check, below.
if (pos != k - 1 || direction != 5) {
out[idx] = origin;
idx++;
if (H3_EXPORT(h3IsPentagon)(origin)) {
return HEX_RANGE_PENTAGON;
}
}
}
}
// Check that this matches the expected lastIndex, if it doesn't,
// it indicates pentagonal distortion occurred and we should report
// failure.
if (lastIndex != origin) {
return HEX_RANGE_PENTAGON;
} else {
return HEX_RANGE_SUCCESS;
}
}