Migrate geolib to turf, reduce bundle size
This commit is contained in:
parent
3b8a0de9b0
commit
35cd0e1e72
File diff suppressed because it is too large
Load Diff
|
@ -13,12 +13,14 @@
|
|||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@turf/along": "^6.0.1",
|
||||
"@turf/helpers": "^6.1.4",
|
||||
"@turf/length": "^6.0.2",
|
||||
"@turf/turf": "^5.1.6",
|
||||
"axios": "^0.19.2",
|
||||
"color": "^3.1.2",
|
||||
"csv-parse": "^4.8.3",
|
||||
"express": "^4.17.1",
|
||||
"geolib": "^3.2.1",
|
||||
"ol": "^6.1.1",
|
||||
"unzip-stream": "^0.3.0"
|
||||
},
|
||||
|
|
|
@ -3,6 +3,9 @@ require('ol/ol.css');
|
|||
const axios = require('axios');
|
||||
const {Map, View} = require('ol');
|
||||
|
||||
const GeoJSON = require('ol/format/GeoJSON').default;
|
||||
const reader = new GeoJSON({featureProjection: 'EPSG:3857'});
|
||||
|
||||
const TileLayer = require('ol/layer/Tile').default;
|
||||
const XYZSource = require('ol/source/XYZ').default;
|
||||
|
||||
|
@ -25,22 +28,6 @@ h0NmFsdzQ3emxqIn0.cyxF0h36emIMTk3cc4VqUw`;
|
|||
const simulation = require('../tam/simulation');
|
||||
const network = require('../tam/network.json');
|
||||
|
||||
const getRoutesLines = routes => routes.filter(
|
||||
// Only consider normal routes (excluding alternate routes)
|
||||
([lineRef, routeRef]) =>
|
||||
network.lines[lineRef].routes[routeRef].state === 'normal'
|
||||
).map(([lineRef]) => lineRef);
|
||||
|
||||
const getLinesColors = lines =>
|
||||
{
|
||||
if (lines.length >= 1)
|
||||
{
|
||||
return lines.map(lineRef => network.lines[lineRef].color);
|
||||
}
|
||||
|
||||
return ['#FFFFFF'];
|
||||
};
|
||||
|
||||
const lineFeaturesOrder = (feature1, feature2) =>
|
||||
{
|
||||
const lines1 = feature1.get('lines');
|
||||
|
@ -65,28 +52,29 @@ const makeDataSources = () =>
|
|||
const segmentsSource = new VectorSource();
|
||||
const stopsSource = new VectorSource();
|
||||
|
||||
segmentsSource.addFeatures(
|
||||
Object.values(network.segments).map(({routes, nodes}) =>
|
||||
new Feature({
|
||||
lines: getRoutesLines(routes),
|
||||
colors: getLinesColors(getRoutesLines(routes)),
|
||||
geometry: new LineString(nodes.map(
|
||||
({lat, lon}) => proj.fromLonLat([lon, lat])
|
||||
)),
|
||||
})
|
||||
)
|
||||
);
|
||||
const readFeatures = hash => Object.values(hash).map(json =>
|
||||
{
|
||||
json.properties.lines = json.properties.routes.filter(
|
||||
// Only consider normal routes (excluding alternate routes)
|
||||
([lineRef, routeRef]) =>
|
||||
network.lines[lineRef].routes[routeRef].state === 'normal'
|
||||
).map(([lineRef]) => lineRef);
|
||||
|
||||
stopsSource.addFeatures(
|
||||
Object.values(network.stops).map(({routes, lon, lat}) =>
|
||||
new Feature({
|
||||
lines: getRoutesLines(routes),
|
||||
colors: getLinesColors(getRoutesLines(routes)),
|
||||
geometry: new Point(proj.fromLonLat([lon, lat])),
|
||||
})
|
||||
)
|
||||
);
|
||||
if (json.properties.lines.length >= 1)
|
||||
{
|
||||
json.properties.colors = json.properties.lines.map(
|
||||
lineRef => network.lines[lineRef].color);
|
||||
}
|
||||
else
|
||||
{
|
||||
json.properties.colors = ['#FFFFFF'];
|
||||
}
|
||||
|
||||
return reader.readFeature(json);
|
||||
});
|
||||
|
||||
segmentsSource.addFeatures(readFeatures(network.segments));
|
||||
stopsSource.addFeatures(readFeatures(network.stops));
|
||||
return {segmentsSource, stopsSource};
|
||||
};
|
||||
|
||||
|
|
|
@ -12,7 +12,8 @@
|
|||
* the `script/update-network` script.
|
||||
*/
|
||||
|
||||
const geolib = require('geolib');
|
||||
const turfHelpers = require('@turf/helpers');
|
||||
const turfLength = require('@turf/length').default;
|
||||
const util = require('../util');
|
||||
const osm = require('./sources/osm');
|
||||
const tam = require('./sources/tam');
|
||||
|
@ -89,16 +90,20 @@ a “ref” tag`);
|
|||
|
||||
if (!(stop.tags.ref in stops))
|
||||
{
|
||||
stops[stop.tags.ref] = {
|
||||
lat: stop.lat,
|
||||
lon: stop.lon,
|
||||
stops[stop.tags.ref] = turfHelpers.point([
|
||||
stop.lon,
|
||||
stop.lat
|
||||
], {
|
||||
name: stop.tags.name,
|
||||
routes: [[lineRef, routeRef]],
|
||||
};
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
stops[stop.tags.ref].routes.push([lineRef, routeRef]);
|
||||
stops[stop.tags.ref].properties.routes.push([
|
||||
lineRef,
|
||||
routeRef
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -215,42 +220,31 @@ ${name} is one-way and cannot be used in reverse.`);
|
|||
|
||||
if (id in segments)
|
||||
{
|
||||
if (!util.arraysEqual(nodesIds, segments[id].nodesIds))
|
||||
if (!util.arraysEqual(
|
||||
nodesIds,
|
||||
segments[id].properties.nodesIds
|
||||
))
|
||||
{
|
||||
throw new Error(`Segment ${id} is defined as a
|
||||
different sequence of nodes in two or more lines.`);
|
||||
}
|
||||
|
||||
segments[id].routes.push([lineRef, routeRef]);
|
||||
segments[id].properties.routes.push([lineRef, routeRef]);
|
||||
}
|
||||
else
|
||||
{
|
||||
const nodes = nodesIds.map(id => ({
|
||||
lat: elements[id].lat,
|
||||
lon: elements[id].lon
|
||||
}));
|
||||
|
||||
if (nodes.length)
|
||||
{
|
||||
// Augment each node with the distance to the start
|
||||
nodes[0].distance = 0;
|
||||
|
||||
for (let i = 1; i < nodes.length; ++i)
|
||||
{
|
||||
nodes[i].distance = geolib.getPreciseDistance(
|
||||
nodes[i - 1],
|
||||
nodes[i],
|
||||
) + nodes[i - 1].distance;
|
||||
}
|
||||
}
|
||||
|
||||
segments[id] = {
|
||||
segments[id] = turfHelpers.lineString(nodesIds.map(id => [
|
||||
elements[id].lon,
|
||||
elements[id].lat
|
||||
]), {
|
||||
// Keep track of the original sequence of nodes to
|
||||
// compare with duplicates
|
||||
nodesIds,
|
||||
nodes,
|
||||
routes: [[lineRef, routeRef]],
|
||||
};
|
||||
});
|
||||
|
||||
segments[id].properties.length = (
|
||||
1000 * turfLength(segments[id]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -269,7 +263,7 @@ different sequence of nodes in two or more lines.`);
|
|||
// Remove OSM nodes from segments that were only used for checking validity
|
||||
for (let segment of Object.values(segments))
|
||||
{
|
||||
delete segment.nodesIds;
|
||||
delete segment.properties.nodesIds;
|
||||
}
|
||||
|
||||
return {stops, lines, segments};
|
||||
|
|
61432
src/tam/network.json
61432
src/tam/network.json
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,6 @@
|
|||
const axios = require('axios');
|
||||
const turf = require('@turf/turf');
|
||||
const turfAlong = require('@turf/along').default;
|
||||
const turfProjection = require('@turf/projection');
|
||||
const network = require('./network.json');
|
||||
|
||||
const server = 'http://localhost:4321';
|
||||
|
@ -137,78 +138,36 @@ class Course
|
|||
|
||||
tick(time)
|
||||
{
|
||||
if (this.state === null)
|
||||
{
|
||||
// Ignore uninitalized courses
|
||||
}
|
||||
else if (this.state === 'moving')
|
||||
if (this.state === 'moving')
|
||||
{
|
||||
// Integrate current speed in travelled distance
|
||||
const delta = this.speed * time;
|
||||
|
||||
this.traveledDistance += this.speed * time;
|
||||
const segment = this.currentSegment;
|
||||
const length = segment.nodes[segment.nodes.length - 1].distance;
|
||||
this.traveledDistance += delta;
|
||||
|
||||
if (this.traveledDistance >= length)
|
||||
if (this.traveledDistance >= segment.properties.length)
|
||||
{
|
||||
this.arriveToStop(this.arrivalStop);
|
||||
return;
|
||||
}
|
||||
|
||||
// Recompute updated position
|
||||
const departureStop = network.stops[this.departureStop];
|
||||
const arrivalStop = network.stops[this.arrivalStop];
|
||||
const nextNodeIndex = segment.nodes.findIndex(
|
||||
({distance}) => distance >= this.traveledDistance);
|
||||
// Compute updated position and angle based on a small step
|
||||
const step = 10; // In meters
|
||||
|
||||
if (nextNodeIndex === 0)
|
||||
{
|
||||
this.position = turf.toMercator([
|
||||
departureStop.lon,
|
||||
departureStop.lat
|
||||
]);
|
||||
}
|
||||
else
|
||||
{
|
||||
const previousNode = segment.nodes[nextNodeIndex - 1];
|
||||
const nextNode = segment.nodes[nextNodeIndex];
|
||||
const positions = [
|
||||
Math.max(0, this.traveledDistance - step / 2),
|
||||
this.traveledDistance,
|
||||
this.traveledDistance + step / 2
|
||||
].map(distance => turfProjection.toMercator(turfAlong(
|
||||
segment,
|
||||
distance / 1000
|
||||
)).geometry.coordinates);
|
||||
|
||||
const previousPoint = turf.toMercator([
|
||||
previousNode.lon,
|
||||
previousNode.lat
|
||||
]);
|
||||
this.angle = Math.atan2(
|
||||
positions[0][1] - positions[2][1],
|
||||
positions[2][0] - positions[0][0],
|
||||
);
|
||||
|
||||
const nextPoint = turf.toMercator([
|
||||
nextNode.lon,
|
||||
nextNode.lat
|
||||
]);
|
||||
|
||||
const curLength = this.traveledDistance
|
||||
- previousNode.distance;
|
||||
const totalLength = nextNode.distance
|
||||
- previousNode.distance;
|
||||
const t = curLength / totalLength;
|
||||
|
||||
this.position = [
|
||||
t * nextPoint[0] + (1 - t) * previousPoint[0],
|
||||
t * nextPoint[1] + (1 - t) * previousPoint[1],
|
||||
];
|
||||
|
||||
this.angle = Math.atan2(
|
||||
previousPoint[1] - nextPoint[1],
|
||||
nextPoint[0] - previousPoint[0],
|
||||
);
|
||||
}
|
||||
}
|
||||
else // this.state === 'stopped'
|
||||
{
|
||||
const currentNode = network.stops[this.currentStop];
|
||||
|
||||
this.position = turf.toMercator([
|
||||
currentNode.lon,
|
||||
currentNode.lat
|
||||
]);
|
||||
this.position = positions[1];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -221,10 +180,9 @@ class Course
|
|||
{
|
||||
this.state = 'stopped';
|
||||
this.currentStop = stop;
|
||||
this.position = turf.toMercator([
|
||||
network.stops[this.currentStop].lon,
|
||||
network.stops[this.currentStop].lat,
|
||||
]);
|
||||
this.position = (
|
||||
turfProjection.toMercator(network.stops[stop])
|
||||
.geometry.coordinates);
|
||||
this.history.push(['arriveToStop', stop]);
|
||||
}
|
||||
|
||||
|
@ -250,10 +208,6 @@ ${this.currentStop} to stop ${stop}. Teleporting to ${stop}`);
|
|||
this.arrivalTime = arrivalTime;
|
||||
this.traveledDistance = 0;
|
||||
this.speed = 0;
|
||||
this.position = turf.toMercator([
|
||||
network.stops[this.departureStop].lon,
|
||||
network.stops[this.departureStop].lat,
|
||||
]);
|
||||
this.history.push(['moveToStop', stop, arrivalTime]);
|
||||
|
||||
console.info(`Course ${this.id} leaving stop ${this.currentStop} \
|
||||
|
@ -271,10 +225,10 @@ with initial speed ${this.computeTheoreticalSpeed() * 3600} km/h`);
|
|||
}
|
||||
|
||||
const segment = this.currentSegment;
|
||||
const length = segment.nodes[segment.nodes.length - 1].distance;
|
||||
|
||||
const remainingTime = this.arrivalTime - Date.now();
|
||||
const remainingDistance = length - this.traveledDistance;
|
||||
const remainingDistance = (
|
||||
segment.properties.length - this.traveledDistance
|
||||
);
|
||||
|
||||
if (remainingDistance <= 0)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue