isochrone-explorer
Version:
A powerful isochrone and routing engine based on Dijkstra's algorithm for accurate travel time calculations.
55 lines (42 loc) • 1.69 kB
JavaScript
const { getOsmData } = require('./osm/overpass');
const { parseGraph, findClosestNode } = require('./utils/osmUtils');
const { MODE_SPEEDS } = require('./constants');
function findShortestPath(graph, startNode, endNode) {
const distances = {};
const prev = {};
const queue = [];
for (let node in graph) distances[node] = Infinity;
distances[startNode] = 0;
queue.push({ node: startNode, cost: 0 });
while (queue.length > 0) {
queue.sort((a, b) => a.cost - b.cost);
const { node: current } = queue.shift();
if (current === endNode) break;
for (const neighbor of graph[current]) {
const alt = distances[current] + neighbor.distance;
if (alt < distances[neighbor.node]) {
distances[neighbor.node] = alt;
prev[neighbor.node] = current;
queue.push({ node: neighbor.node, cost: alt });
}
}
}
const path = [];
let currentNode = endNode;
while (currentNode !== undefined) {
path.unshift(currentNode);
currentNode = prev[currentNode];
}
return path.length > 1 ? path : null;
}
async function findRoute(startCoord, endCoord) {
const osmData = await getOsmData(startCoord[1], startCoord[0]);
const { graph, nodeCoords } = parseGraph(osmData);
const startNode = findClosestNode(nodeCoords, startCoord[1], startCoord[0]);
const endNode = findClosestNode(nodeCoords, endCoord[1], endCoord[0]);
if (!startNode || !endNode) return [];
const path = findShortestPath(graph, startNode, endNode);
if (!path) return [];
return path.map(nodeId => [nodeCoords[nodeId].lon, nodeCoords[nodeId].lat]);
}
module.exports = { findRoute };