mobility-toolbox-js
Version:
Toolbox for JavaScript applications in the domains of mobility and logistics.
75 lines (74 loc) • 3.43 kB
JavaScript
import { LineString } from 'ol/geom';
/**
* Interpolate or not the vehicle position from a trajectory at a specific date.
*
* @param {number} now Current date to interpolate a position with. In ms.
* @param {RealtimeTrajectory} trajectory The trajectory to interpolate.
* @param {boolean} noInterpolate If true, the vehicle position is not interpolated on each render but only once.
* @returns {VehiclePosition}
* @private
*/
const getVehiclePosition = (now, trajectory, noInterpolate) => {
var _a;
const { coordinate, olGeometry, rotation: oldRotation, time_intervals: timeIntervals, } = trajectory.properties;
let { coordinates, type } = trajectory.geometry;
let geometry = olGeometry;
let coord;
let rotation = oldRotation;
// If an olGeometry exists we use it. It avoids to create one each time.
if (geometry) {
// @ts-expect-error improve types
type = geometry.getType();
coordinates = (_a = geometry.getCoordinates()) !== null && _a !== void 0 ? _a : [];
}
if (noInterpolate && coordinate) {
coord = coordinate;
}
else if (type === 'Point') {
coord = coordinates;
}
else if (type === 'LineString') {
geometry !== null && geometry !== void 0 ? geometry : (geometry = new LineString(coordinates));
const intervals = timeIntervals || [[]];
const firstInterval = intervals[0];
const lastInterval = intervals[intervals.length - 1];
// Between the last time interval of a trajectory event and the beginning
// of the new trajectory event, there is few seconds, can be 6 to 30
// seconds (that's why the vehicle jumps sometimes).
// So we make the choice here to display the last (or the first) position
// of an trajectory event instead of removing them, if the current date is
// outside the time intervals we display the vehicle at the last (or first) position known.
if (now < firstInterval[0]) {
// Display first position known.
[, , rotation] = firstInterval;
coord = geometry.getFirstCoordinate();
}
else if (now > lastInterval[0]) {
// Display last position known.
[, , rotation] = lastInterval;
coord = geometry.getLastCoordinate();
}
else {
// Interpolate position using time intervals.
for (let j = 0; j < intervals.length - 1; j += 1) {
// Rotation only available in realtime layer.
const [start, startFrac] = intervals[j];
const [end, endFrac] = intervals[j + 1];
if (start <= now && now <= end) {
// interpolate position inside the time interval.
const timeFrac = Math.min((now - start) / (end - start), 1);
const geomFrac = timeFrac * (endFrac - startFrac) + startFrac;
coord = geometry === null || geometry === void 0 ? void 0 : geometry.getCoordinateAt(geomFrac);
[, , rotation] = intervals[j];
break;
}
}
}
}
else {
// eslint-disable-next-line no-console
console.error('This geometry type is not supported. Only Point or LineString are. Current geometry: ', geometry);
}
return { coord, rotation };
};
export default getVehiclePosition;