in src/h3lib/lib/algos.c [565:648]
H3Error H3_EXPORT(gridDiskDistancesUnsafe)(H3Index origin, int k, H3Index *out,
int *distances) {
// Return codes:
// 1 Pentagon was encountered
// 2 Pentagon distortion (deleted k subsequence) was encountered
// Pentagon being encountered is not itself a problem; really the deleted
// k-subsequence is the problem, but for compatibility reasons we fail on
// the pentagon.
if (k < 0) {
return E_DOMAIN;
}
// k must be >= 0, so origin is always needed
int idx = 0;
out[idx] = origin;
if (distances) {
distances[idx] = 0;
}
idx++;
if (H3_EXPORT(isPentagon)(origin)) {
// Pentagon was encountered; bail out as user doesn't want this.
return E_PENTAGON;
}
// 0 < ring <= k, current ring
int ring = 1;
// 0 <= direction < 6, current side of the ring
int direction = 0;
// 0 <= i < ring, current position on the side of the ring
int i = 0;
// Number of 60 degree ccw rotations to perform on the direction (based on
// which faces have been crossed.)
int rotations = 0;
while (ring <= k) {
if (direction == 0 && i == 0) {
// Not putting in the output set as it will be done later, at
// the end of this 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)) {
// Pentagon was encountered; bail out as user doesn't want this.
return E_PENTAGON;
}
}
H3Error neighborResult = h3NeighborRotations(
origin, DIRECTIONS[direction], &rotations, &origin);
if (neighborResult) {
return neighborResult;
}
out[idx] = origin;
if (distances) {
distances[idx] = ring;
}
idx++;
i++;
// Check if end of this side of the k-ring
if (i == ring) {
i = 0;
direction++;
// Check if end of this ring.
if (direction == 6) {
direction = 0;
ring++;
}
}
if (H3_EXPORT(isPentagon)(origin)) {
// Pentagon was encountered; bail out as user doesn't want this.
return E_PENTAGON;
}
}
return E_SUCCESS;
}