Public
Edited
Nov 20, 2024
Fork of H3 Centroid
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function polyfillCenter() {
return h3.polygonToCells(geometry, h3Resolution, true);
}
Insert cell
// first approach, using ij coordinates, n

centroid = {
console.time("Calculating centroid, 1");
const ijAverage = result.cells
.map((cell) => h3.cellToLocalIj(result.cells[0], cell))
.map((ijCoordinates) => [ijCoordinates.i, ijCoordinates.j])
.reduce(
function (sum, value) {
return [sum[0] + value[0], sum[1] + value[1]];
},
[0, 0]
)
.map((d) => d / result.cells.length);

const ijObject = {
i: Math.round(ijAverage[0]),
j: Math.round(ijAverage[1])
};

console.timeEnd("Calculating centroid, 1");

return h3.localIjToCell(result.cells[0], ijObject);
}
Insert cell
// second approach, converting to lat/lng (not robust along the 180th Meridian)

centroid2 = {
console.time("Calculating centroid, 2");

// Convert each H3 cell to its lat/lng center
const latLngs = result.cells.map((cell) => h3.cellToLatLng(cell));

// Sum up the latitudes and longitudes
const sumLatLng = latLngs.reduce(
(sum, latLng) => [sum[0] + latLng[0], sum[1] + latLng[1]],
[0, 0]
);

// Calculate the average latitude and longitude
const avgLatLng = [
sumLatLng[0] / result.cells.length,
sumLatLng[1] / result.cells.length
];

// Convert the average lat/lng to an H3 index at the same resolution
const centroidH3Index = h3.latLngToCell(
avgLatLng[0],
avgLatLng[1],
h3.getResolution(result.cells[0])
);

console.timeEnd("Calculating centroid, 2");

return centroidH3Index;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
result = {
return timed(polyfillCenter);
}
Insert cell
function getCommonAncestor(h3Cells) {
if (h3Cells.length === 0) return null;

// Get the resolution of the first cell
const initialResolution = h3.getResolution(h3Cells[0]);

// Ensure all cells are at the same resolution
for (let i = 0; i < h3Cells.length; i++) {
if (h3.getResolution(h3Cells[i]) !== initialResolution) {
throw new Error("All H3 cells must be at the same resolution");
}
}

// Find common parent at progressively lower resolutions
for (let res = initialResolution; res >= 0; res--) {
const parentCells = new Set(
h3Cells.map((cell) => h3.cellToParent(cell, res))
);
if (parentCells.size === 1) {
return Array.from(parentCells)[0];
}
}

// If no common parent is found, return null
return null;
}
Insert cell
cellsResolution = h3.getResolution(result.cells[0])
Insert cell
commonAncestor = getCommonAncestor(result.cells)
Insert cell
commonAncestorCenter = h3.cellToCenterChild(commonAncestor, cellsResolution)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more