in src/h3lib/lib/algos.c [692:761]
H3Error H3_EXPORT(gridRingUnsafe)(H3Index origin, int k, H3Index *out) {
// Short-circuit on 'identity' ring
if (k == 0) {
out[0] = origin;
return E_SUCCESS;
}
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(isPentagon)(origin)) {
// Pentagon was encountered; bail out as user doesn't want this.
return E_PENTAGON;
}
for (int ring = 0; ring < k; ring++) {
H3Error neighborResult = h3NeighborRotations(
origin, NEXT_RING_DIRECTION, &rotations, &origin);
if (neighborResult) {
// Should not be possible because `origin` would have to be a
// pentagon
// TODO: Reachable via fuzzer
return neighborResult;
}
if (H3_EXPORT(isPentagon)(origin)) {
return E_PENTAGON;
}
}
H3Index lastIndex = origin;
out[idx] = origin;
idx++;
for (int direction = 0; direction < 6; direction++) {
for (int pos = 0; pos < k; pos++) {
H3Error neighborResult = h3NeighborRotations(
origin, DIRECTIONS[direction], &rotations, &origin);
if (neighborResult) {
// Should not be possible because `origin` would have to be a
// pentagon
// TODO: Reachable via fuzzer
return neighborResult;
}
// 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(isPentagon)(origin)) {
return E_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 E_PENTAGON;
} else {
return E_SUCCESS;
}
}