Public
Edited
Nov 7, 2023
6 forks
Importers
13 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
edgeSpeedsMPH = {
const edgeSpeeds = new Map();
for (const {seg: coordinates, mph} of roadSpeeds) {
for (let i = 0; i < coordinates.length - 1; i++) {
const [lng1, lat1] = coordinates[i];
const [lng2, lat2] = coordinates[i + 1];
const start = h3.geoToH3(lat1, lng1, h3Resolution);
const end = h3.geoToH3(lat2, lng2, h3Resolution);
if (start !== end) {
const cells = h3.h3Line(start, end);
for (let j = 0; j < cells.length - 1; j++) {
const edge = h3.getH3UnidirectionalEdge(cells[j], cells[j + 1]);
if (!edgeSpeeds.has(edge) || mph > edgeSpeeds.get(edge)) {
edgeSpeeds.set(edge, mph);
}
}
}
}
}
return edgeSpeeds;
}
Insert cell
Insert cell
cellTravelTimes = {
let interCellDist = null;
const {point} = map;
const origin = h3.geoToH3(point.lat, point.lng, h3Resolution);
// Use a priority queue to track the current set of cells to evaluate
const queue = new Heapify(1028, [], [], Array);
queue.push(origin, 0);
// init output map
const output = new Map([[origin, 0]]);
while (queue.length > 0) {
const cell = queue.pop();
const edges = h3.getH3UnidirectionalEdgesFromHexagon(cell);
for (const edge of edges) {
if (edgeSpeedsMPH.has(edge)) {
const dest = h3.getDestinationH3IndexFromUnidirectionalEdge(edge);
// lazy calculation of inter-cell distance
if (interCellDist === null) {
const coord1 = h3.h3ToGeo(cell);
const coord2 = h3.h3ToGeo(dest);
// transform km -> miles
interCellDist = h3.pointDist(coord1, coord2, h3.UNITS.km) * 0.621371;
}
// travel time between current cells
const minutes = (interCellDist / edgeSpeedsMPH.get(edge)) * 60;
// cumulative travel time
const travelTime = output.get(cell) + minutes;
if (!output.has(dest) || travelTime < output.get(dest)) {
output.set(dest, travelTime);
queue.push(dest, travelTime);
}
}
}
}
return output;
}
Insert cell
Insert cell
isochrone = {
const set = [];
for (const [h3Index, minutes] of cellTravelTimes) {
if (minutes < isochroneThreshold) {
set.push(h3Index);
}
}
return {
type: 'Feature',
geometry: {
type: 'MultiPolygon',
coordinates: h3.h3SetToMultiPolygon(set, true)
}
}
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more