in src/h3lib/lib/algos.c [825:877]
H3Error _getEdgeHexagons(const GeoLoop *geoloop, int64_t numHexagons, int res,
int64_t *numSearchHexes, H3Index *search,
H3Index *found) {
for (int i = 0; i < geoloop->numVerts; i++) {
LatLng origin = geoloop->verts[i];
LatLng destination = i == geoloop->numVerts - 1 ? geoloop->verts[0]
: geoloop->verts[i + 1];
int64_t numHexesEstimate;
H3Error estimateErr =
lineHexEstimate(&origin, &destination, res, &numHexesEstimate);
if (estimateErr) {
return estimateErr;
}
for (int64_t j = 0; j < numHexesEstimate; j++) {
LatLng interpolate;
double invNumHexesEst = 1.0 / numHexesEstimate;
interpolate.lat =
(origin.lat * (numHexesEstimate - j) * invNumHexesEst) +
(destination.lat * j * invNumHexesEst);
interpolate.lng =
(origin.lng * (numHexesEstimate - j) * invNumHexesEst) +
(destination.lng * j * invNumHexesEst);
H3Index pointHex;
H3Error e = H3_EXPORT(latLngToCell)(&interpolate, res, &pointHex);
if (e) {
return e;
}
// A simple hash to store the hexagon, or move to another place if
// needed
int64_t loc = (int64_t)(pointHex % numHexagons);
int64_t loopCount = 0;
while (found[loc] != 0) {
// If this conditional is reached, the `found` memory block is
// too small for the given polygon. This should not happen.
// TODO: Reachable via fuzzer
if (loopCount > numHexagons) return E_FAILED;
if (found[loc] == pointHex)
break; // At least two points of the geoloop index to the
// same cell
loc = (loc + 1) % numHexagons;
loopCount++;
}
if (found[loc] == pointHex)
continue; // Skip this hex, already exists in the found hash
// Otherwise, set it in the found hash for now
found[loc] = pointHex;
search[*numSearchHexes] = pointHex;
(*numSearchHexes)++;
}
}
return E_SUCCESS;
}