Browse Source

Load simulation in front

main
Mattéo Delabre 4 years ago
parent
commit
d688bff813
Signed by: matteo GPG Key ID: AE3FBD02DC583ABB
  1. 3
      src/front/index.js
  2. 67
      src/front/map.js
  3. 85
      src/tam/simulation.js

3
src/front/index.js

@ -1,7 +1,4 @@
require('regenerator-runtime/runtime');
const {createMap} = require('./map');
require('../tam/simulation');
createMap(/* map = */ 'map');

67
src/front/map.js

@ -21,6 +21,7 @@ const color = require('color');
const mapboxToken = `pk.eyJ1IjoibWF0dGVvZGVsYWJyZSIsImEiOiJja2NxaTUyMmUwcmFhMn\
h0NmFsdzQ3emxqIn0.cyxF0h36emIMTk3cc4VqUw`;
const simulation = require('../tam/simulation');
const network = require('../tam/network.json');
const getRouteColors = routes =>
@ -39,7 +40,7 @@ const getRouteColors = routes =>
return ['#FFFFFF'];
};
const makeDataSources = async () =>
const makeDataSources = () =>
{
const segmentsSource = new VectorSource();
const stopsSource = new VectorSource();
@ -101,7 +102,7 @@ const stopsStyle = feature => new Style({
}),
});
const createMap = async (target) =>
const createMap = target =>
{
// Map background
const backgroundSource = new XYZSource({
@ -116,8 +117,8 @@ const createMap = async (target) =>
source: backgroundSource,
});
// Data overlay
const {segmentsSource, stopsSource} = await makeDataSources();
// Static data overlay
const {segmentsSource, stopsSource} = makeDataSources();
const segmentsBorderLayer = new VectorLayer({
source: segmentsSource,
@ -144,6 +145,63 @@ const createMap = async (target) =>
updateWhileAnimating: true,
});
// Dynamic data overlay
const coursesSource = new VectorSource();
const onFrame = courses =>
{
// Remove stale courses
for (let feature of coursesSource.getFeatures())
{
if (!(feature.getId() in courses))
{
coursesSource.removeFeature(feature);
}
}
// Add new courses or update existing courses
const newFeatures = [];
for (let [courseId, course] of Object.entries(courses))
{
if ('position' in course)
{
const feature = coursesSource.getFeatureById(courseId);
const coords = proj.fromLonLat([
course.position.lon,
course.position.lat
]);
if (feature === null)
{
const feature = new Feature({
colors: ['#FF0000'],
geometry: new Point(coords)
});
feature.setId(courseId);
newFeatures.push(feature);
}
else
{
feature.getGeometry().setCoordinates(coords);
}
}
}
coursesSource.addFeatures(newFeatures);
};
simulation.run(onFrame);
const coursesLayer = new VectorLayer({
source: coursesSource,
style: stopsStyle,
updateWhileInteracting: true,
updateWhileAnimating: true,
});
// Setup map
const map = new Map({
target,
@ -152,6 +210,7 @@ const createMap = async (target) =>
segmentsBorderLayer,
segmentsInnerLayer,
stopsLayer,
coursesLayer,
],
view: new View({
center: proj.fromLonLat([3.88, 43.605]),

85
src/tam/simulation.js

@ -149,6 +149,7 @@ const updatePositions = (courses, time) =>
{
if (course.state === 'moving')
{
// Increase the travelled distance respective to the current speed
const delta = course.speed * time;
const segment = getCurrentSegment(course);
@ -162,28 +163,82 @@ const updatePositions = (courses, time) =>
{
course.traveledDistance += delta;
}
// Recompute updated position
const departureStop = network.stops[course.departureStop];
const arrivalStop = network.stops[course.arrivalStop];
const nextNodeIndex = segment.points.findIndex(
({distance}) => distance >= course.traveledDistance);
if (nextNodeIndex === 0)
{
course.position = {
lat: departureStop.lat,
lon: departureStop.lon
};
}
else if (nextNodeIndex === -1)
{
course.position = {
lat: arrivalStop.lat,
lon: arrivalStop.lon
};
}
else
{
const previousNode = segment.points[nextNodeIndex - 1];
const nextNode = segment.points[nextNodeIndex];
const curLength = course.traveledDistance
- previousNode.distance;
const totalLength = nextNode.distance
- previousNode.distance;
const progression = curLength / totalLength;
course.position = {
lat: progression * nextNode.lat
+ (1 - progression) * previousNode.lat,
lon: progression * nextNode.lon
+ (1 - progression) * previousNode.lon,
};
}
}
else
{
const currentStop = network.stops[course.currentStop];
course.position = {
lat: currentStop.lat,
lon: currentStop.lon,
};
}
}
};
const courses = {};
let lastFrame = null;
let lastUpdate = null;
const loop = now =>
const run = callback =>
{
const time = lastFrame === null ? 0 : now - lastFrame;
const courses = {};
let lastFrame = null;
let lastUpdate = null;
lastFrame = now;
updatePositions(courses, time);
if (lastUpdate === null || lastUpdate + 5000 <= now)
const loop = () =>
{
lastUpdate = now;
updateFromTam(courses);
}
const now = Date.now();
if (lastUpdate === null || lastUpdate + 5000 <= now)
{
lastUpdate = now;
updateFromTam(courses);
}
const time = lastFrame === null ? 0 : now - lastFrame;
lastFrame = now;
updatePositions(courses, time);
callback(courses);
};
requestAnimationFrame(loop);
const interval = setInterval(loop, 24);
return () => clearInterval(interval);
};
requestAnimationFrame(loop);
exports.run = run;

Loading…
Cancel
Save