UNPKG

@geoapify/route-planner-sdk

Version:

TypeScript SDK for the Geoapify Route Planner API. Supports route optimization, delivery planning, and timeline visualization in browser and Node.js

160 lines (159 loc) 7.34 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; export const MISSING_LEG_DATA = -1; export class LegRecalculator { static replaceLegsForInsertedWaypoint(context, agentIndex, waypointIndex) { const agentFeature = context.getAgentFeature(agentIndex); const properties = agentFeature.properties; if (!properties.legs) { properties.legs = []; } const legs = properties.legs; const waypoints = properties.waypoints; const leg1 = { from_waypoint_index: waypointIndex - 1, to_waypoint_index: waypointIndex, time: MISSING_LEG_DATA, distance: MISSING_LEG_DATA, steps: [] }; const leg2 = { from_waypoint_index: waypointIndex, to_waypoint_index: waypointIndex + 1, time: MISSING_LEG_DATA, distance: MISSING_LEG_DATA, steps: [] }; if (waypoints.length <= 1) { // do nothing, no legs return; } if (waypointIndex === 0) { legs.splice(waypointIndex, 0, leg2); } else if (waypointIndex === waypoints.length - 1) { legs.splice(waypointIndex, 0, leg1); } else { // Middle insertion, first remove the existing leg and add 2 legs.splice(waypointIndex - 1, 1, leg1, leg2); } // reindex waypoints legs.forEach((leg, index) => { leg.from_waypoint_index = index; leg.to_waypoint_index = index + 1; }); } static fillMissingLegData(context, agentFeature) { return __awaiter(this, void 0, void 0, function* () { const waypoints = agentFeature.properties.waypoints || []; const legs = agentFeature.properties.legs || []; const missingLegIndices = this.findMissingLegIndices(legs); if (missingLegIndices.length > 0) { yield this.fillMissingOrderedLegs(context, waypoints, legs, missingLegIndices); } this.recreateGeometry(agentFeature, waypoints, legs); }); } static fillMissingOrderedLegs(context, waypoints, legs, missingLegIndices) { var _a, _b, _c, _d, _e, _f; return __awaiter(this, void 0, void 0, function* () { const routingHelper = context.getRoutingHelper(); const routeResults = yield Promise.all(missingLegIndices.map((legIndex) => __awaiter(this, void 0, void 0, function* () { const fromWaypoint = waypoints[legIndex]; const toWaypoint = waypoints[legIndex + 1]; const fromLocation = this.getWaypointLocation(fromWaypoint); const toLocation = this.getWaypointLocation(toWaypoint); if (!fromLocation || !toLocation) { return { legIndex, routeData: null }; } try { const routeData = yield routingHelper.calculateRouteData([fromLocation, toLocation]); return { legIndex, routeData }; } catch (_error) { return { legIndex, routeData: null }; } }))); for (const result of routeResults) { const leg = legs[result.legIndex]; if (!leg) { continue; } const routeLeg = (_b = (_a = result.routeData) === null || _a === void 0 ? void 0 : _a.legs) === null || _b === void 0 ? void 0 : _b[0]; if (routeLeg) { leg.time = (_c = routeLeg.time) !== null && _c !== void 0 ? _c : 0; leg.distance = (_d = routeLeg.distance) !== null && _d !== void 0 ? _d : 0; leg.steps = [{ distance: leg.distance, time: routeLeg.time, from_index: 0, to_index: 1 }]; } else { leg.time = 0; leg.distance = 0; leg.steps = []; } const fromLocation = this.getMappedRouteWaypointLocation((_e = result.routeData) === null || _e === void 0 ? void 0 : _e.waypoints, 0); const toLocation = this.getMappedRouteWaypointLocation((_f = result.routeData) === null || _f === void 0 ? void 0 : _f.waypoints, 1); if (fromLocation) { waypoints[result.legIndex].location = fromLocation; } if (toLocation) { waypoints[result.legIndex + 1].location = toLocation; } } }); } static recreateGeometry(agentFeature, waypoints, legs) { const coordinates = []; for (let i = 0; i < legs.length; i++) { const fromLocation = this.getWaypointLocation(waypoints[i]); const toLocation = this.getWaypointLocation(waypoints[i + 1]); if (!fromLocation || !toLocation) { continue; } legs[i].from_waypoint_index = i; legs[i].to_waypoint_index = i + 1; coordinates.push([fromLocation, toLocation]); } agentFeature.geometry = Object.assign(Object.assign({}, agentFeature.geometry), { type: "MultiLineString", coordinates }); } static getMappedRouteWaypointLocation(routeWaypoints, originalIndex) { var _a; if (!routeWaypoints || routeWaypoints.length === 0) { return undefined; } const mappedWaypoint = routeWaypoints.find((waypoint) => (waypoint === null || waypoint === void 0 ? void 0 : waypoint.original_index) === originalIndex); return (mappedWaypoint === null || mappedWaypoint === void 0 ? void 0 : mappedWaypoint.location) || ((_a = routeWaypoints[originalIndex]) === null || _a === void 0 ? void 0 : _a.location); } static getWaypointLocation(waypoint) { if (!waypoint) { return undefined; } return waypoint.location || waypoint.original_location; } static findMissingLegIndices(legs) { const missingLegs = []; for (let i = 0; i < legs.length; i++) { const leg = legs[i]; if (!leg) { continue; } if (leg.time === undefined || leg.time === MISSING_LEG_DATA || leg.time < 0 || leg.distance === undefined || leg.distance === MISSING_LEG_DATA || leg.distance < 0) { missingLegs.push(i); } } return missingLegs; } }