@wemap/routers 12.10.8 → 12.10.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/helpers/InstructionManager.d.ts +20 -0
- package/dist/helpers/InstructionManagerV1.d.ts +7 -0
- package/{index.ts → dist/index.d.ts} +1 -11
- package/dist/index.js +1 -5099
- package/dist/index.js.map +1 -1
- package/dist/src/ItineraryInfoManager.d.ts +31 -0
- package/dist/src/RoutingError.d.ts +24 -0
- package/{src/StatusCode.ts → dist/src/StatusCode.d.ts} +2 -3
- package/dist/src/Utils.d.ts +6 -0
- package/dist/src/graph/Edge.d.ts +32 -0
- package/dist/src/graph/Graph.d.ts +40 -0
- package/dist/src/graph/GraphProjection.d.ts +11 -0
- package/dist/src/graph/GraphProjectionOptions.d.ts +7 -0
- package/dist/src/graph/GraphRoute.d.ts +19 -0
- package/dist/src/graph/GraphRouter.d.ts +20 -0
- package/dist/src/graph/GraphRouterEngine.d.ts +77 -0
- package/{src/graph/GraphRouterOptions.ts → dist/src/graph/GraphRouterOptions.d.ts} +5 -7
- package/dist/src/graph/GraphRouterOptionsBuilder.d.ts +20 -0
- package/dist/src/graph/NoRouteFoundError.d.ts +12 -0
- package/dist/src/graph/Vertex.d.ts +19 -0
- package/dist/src/model/Itinerary.d.ts +81 -0
- package/dist/src/model/Leg.d.ts +66 -0
- package/dist/src/model/LevelChange.d.ts +7 -0
- package/dist/src/model/RouterRequest.d.ts +40 -0
- package/dist/src/model/Step.d.ts +42 -0
- package/dist/src/model/StepExtra.d.ts +3 -0
- package/dist/src/model/StepsBuilder.d.ts +16 -0
- package/dist/src/model/TransitMode.d.ts +5 -0
- package/{src/model/TravelMode.ts → dist/src/model/TravelMode.d.ts} +1 -2
- package/dist/src/model/generateSteps.d.ts +0 -0
- package/{src/remote/RemoteRouter.ts → dist/src/remote/RemoteRouter.d.ts} +2 -7
- package/dist/src/remote/RemoteRouterManager.d.ts +731 -0
- package/dist/src/remote/RemoteRouterUtils.d.ts +6 -0
- package/dist/src/remote/cityway/CitywayRemoteRouter.d.ts +109 -0
- package/dist/src/remote/deutsche-bahn/DeutscheBahnRemoteRouter.d.ts +31 -0
- package/dist/src/remote/geovelo/GeoveloRemoteRouter.d.ts +106 -0
- package/dist/src/remote/idfm/IdfmRemoteRouter.d.ts +123 -0
- package/dist/src/remote/navitia/NavitiaRemoteRouter.d.ts +34 -0
- package/dist/src/remote/navitia/types.d.ts +87 -0
- package/dist/src/remote/osrm/OsrmRemoteRouter.d.ts +70 -0
- package/dist/src/remote/otp/OtpRemoteRouter.d.ts +69 -0
- package/dist/src/remote/wemap-multi/WemapMultiRemoteRouter.d.ts +19 -0
- package/dist/src/types.d.ts +31 -0
- package/dist/src/wemap-multi/CustomGraphMap.d.ts +56 -0
- package/dist/src/wemap-multi/CustomGraphMapTester.d.ts +39 -0
- package/dist/src/wemap-multi/WemapMultiRouter.d.ts +14 -0
- package/dist/src/wemap-osm/OsmGraphUtils.d.ts +11 -0
- package/dist/tests/CommonTest.d.ts +8 -0
- package/package.json +11 -8
- package/assets/biocbon-bergere-rdc-network.osm +0 -163
- package/assets/bureaux-wemap-montpellier-network.osm +0 -174
- package/assets/components.osm +0 -146
- package/assets/elevator-models-4.osm +0 -89
- package/assets/elevator-models.osm +0 -354
- package/assets/exit-graph.osm +0 -25
- package/assets/gare-de-lest-network-pp-bounds.osm +0 -1613
- package/assets/gare-de-lyon-extract.osm +0 -174
- package/assets/geovelo-montpellier.json +0 -1144
- package/assets/horizontal-elevator.osm +0 -12
- package/assets/itinerary-deutsche-bahn-1.json +0 -368
- package/assets/itinerary-grenoble-otp-1.json +0 -1536
- package/assets/itinerary-grenoble-otp-2.json +0 -1092
- package/assets/itinerary-info-two-points-proj.osm +0 -39
- package/assets/itinerary-info-two-points.osm +0 -24
- package/assets/itinerary-lehavre-cityway-1.json +0 -6799
- package/assets/itinerary-lehavre-cityway-2.json +0 -2133
- package/assets/itinerary-lehavre-cityway-3.json +0 -12577
- package/assets/itinerary-lehavre-cityway-4.json +0 -1451
- package/assets/itinerary-lehavre-cityway-5.json +0 -5925
- package/assets/itinerary-lemans-navitia.json +0 -7768
- package/assets/itinerary-montpellier-osrm-3.json +0 -185
- package/assets/itinerary-montpellier-outdoor-without-steps.json +0 -110
- package/assets/itinerary-montpellier-outdoor.json +0 -513
- package/assets/itinerary-paris-idfm-2.json +0 -1838
- package/assets/itinerary-paris-idfm.json +0 -27727
- package/assets/itinerary-step-not-on-path-osrm.json +0 -457
- package/assets/itinerary-with-duplicate-nodes.json +0 -110
- package/assets/network-conveying-backward.osm +0 -74
- package/assets/network-elevator.osm +0 -48
- package/assets/network-escalators.osm +0 -50
- package/assets/network-simple.osm +0 -27
- package/assets/network-steps-same-level.osm +0 -283
- package/assets/network-with-modifiers.osm +0 -39
- package/assets/one-way.osm +0 -46
- package/assets/report-map-1.osm +0 -36
- package/assets/report-map-2.osm +0 -29
- package/assets/report-map-3.osm +0 -15
- package/assets/rr-wemap-multi-indoor-outdoor-indoor.json +0 -1352
- package/assets/rr-wemap-multi-indoor-outdoor.json +0 -145
- package/assets/rr-wemap-multi-multi-level.json +0 -262
- package/assets/rr-wemap-multi-outdoor-indoor.json +0 -145
- package/assets/rr-wemap-multi-outdoor-outdoor.json +0 -207
- package/assets/rr-wemap-multi-remote-indoor-indoor.json +0 -155
- package/assets/rr-wemap-multi-remote-indoor-outdoor-indoor.json +0 -668
- package/assets/rr-wemap-multi-remote-indoor-outdoor.json +0 -154
- package/assets/rr-wemap-multi-remote-outdoor-indoor.json +0 -179
- package/assets/rr-wemap-multi-remote-outdoor-outdoor.json +0 -109
- package/assets/stairs-and-exit.osm +0 -47
- package/helpers/InstructionManager.ts +0 -184
- package/helpers/InstructionManagerV1.ts +0 -95
- package/src/ItineraryInfoManager.spec.ts +0 -183
- package/src/ItineraryInfoManager.ts +0 -181
- package/src/RoutingError.ts +0 -60
- package/src/Utils.ts +0 -8
- package/src/graph/Edge.spec.ts +0 -32
- package/src/graph/Edge.ts +0 -64
- package/src/graph/Graph.spec.ts +0 -509
- package/src/graph/Graph.ts +0 -272
- package/src/graph/GraphProjection.ts +0 -15
- package/src/graph/GraphProjectionOptions.ts +0 -8
- package/src/graph/GraphRoute.spec.ts +0 -15
- package/src/graph/GraphRoute.ts +0 -43
- package/src/graph/GraphRouter.spec.ts +0 -317
- package/src/graph/GraphRouter.ts +0 -229
- package/src/graph/GraphRouterEngine.ts +0 -248
- package/src/graph/GraphRouterOptionsBuilder.ts +0 -98
- package/src/graph/NoRouteFoundError.ts +0 -39
- package/src/graph/Vertex.spec.ts +0 -42
- package/src/graph/Vertex.ts +0 -45
- package/src/model/Itinerary.spec.ts +0 -134
- package/src/model/Itinerary.ts +0 -370
- package/src/model/Leg.spec.ts +0 -107
- package/src/model/Leg.ts +0 -224
- package/src/model/LevelChange.spec.ts +0 -50
- package/src/model/LevelChange.ts +0 -14
- package/src/model/RouterRequest.ts +0 -33
- package/src/model/Step.spec.ts +0 -99
- package/src/model/Step.ts +0 -90
- package/src/model/StepExtra.ts +0 -1
- package/src/model/StepsBuilder.ts +0 -242
- package/src/model/TransitMode.spec.ts +0 -31
- package/src/model/TransitMode.ts +0 -28
- package/src/model/generateSteps.ts +0 -102
- package/src/remote/RemoteRouterManager.spec.ts +0 -178
- package/src/remote/RemoteRouterManager.ts +0 -72
- package/src/remote/RemoteRouterUtils.ts +0 -25
- package/src/remote/cityway/CitywayRemoteRouter.spec.ts +0 -122
- package/src/remote/cityway/CitywayRemoteRouter.ts +0 -435
- package/src/remote/deutsche-bahn/DeutscheBahnRemoteRouter.spec.ts +0 -52
- package/src/remote/deutsche-bahn/DeutscheBahnRemoteRouter.ts +0 -85
- package/src/remote/geovelo/GeoveloRemoteRouter.spec.ts +0 -54
- package/src/remote/geovelo/GeoveloRemoteRouter.ts +0 -293
- package/src/remote/idfm/IdfmRemoteRouter.spec.ts +0 -102
- package/src/remote/idfm/IdfmRemoteRouter.ts +0 -523
- package/src/remote/navitia/NavitiaRemoteRouter.spec.ts +0 -116
- package/src/remote/navitia/NavitiaRemoteRouter.ts +0 -445
- package/src/remote/navitia/types.ts +0 -73
- package/src/remote/osrm/OsrmRemoteRouter.spec.ts +0 -127
- package/src/remote/osrm/OsrmRemoteRouter.ts +0 -303
- package/src/remote/otp/OtpRemoteRouter.spec.ts +0 -103
- package/src/remote/otp/OtpRemoteRouter.ts +0 -223
- package/src/remote/wemap-multi/WemapMultiRemoteRouter.spec.ts +0 -103
- package/src/remote/wemap-multi/WemapMultiRemoteRouter.ts +0 -56
- package/src/types.ts +0 -32
- package/src/wemap-multi/CustomGraphMap.spec.ts +0 -40
- package/src/wemap-multi/CustomGraphMap.ts +0 -213
- package/src/wemap-multi/CustomGraphMapTester.spec.ts +0 -48
- package/src/wemap-multi/CustomGraphMapTester.ts +0 -90
- package/src/wemap-multi/WemapMultiRouter.spec.ts +0 -138
- package/src/wemap-multi/WemapMultiRouter.ts +0 -329
- package/src/wemap-osm/OsmGraphUtils.spec.ts +0 -165
- package/src/wemap-osm/OsmGraphUtils.ts +0 -173
- package/src/wemap-osm/OsmRouter.elevators.spec.ts +0 -106
- package/src/wemap-osm/OsmRouter.spec.ts +0 -292
- package/tests/CommonTest.ts +0 -78
- package/tsconfig.json +0 -3
- package/vite.config.ts +0 -4
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import { Coordinates } from '@wemap/geo';
|
|
2
|
-
import ItineraryInfoManager from '../src/ItineraryInfoManager.js';
|
|
3
|
-
import { Step } from '../src/model/Step.js';
|
|
4
|
-
import OsrmRemoteRouter from '../src/remote/osrm/OsrmRemoteRouter.js';
|
|
5
|
-
|
|
6
|
-
export default class InstructionManagerV1 {
|
|
7
|
-
|
|
8
|
-
// eslint-disable-next-line max-statements, complexity
|
|
9
|
-
static getInstructionFromStep(step: Step) {
|
|
10
|
-
|
|
11
|
-
const modifier = OsrmRemoteRouter.getModifierFromAngle(step.angle);
|
|
12
|
-
let direction, directionExtra;
|
|
13
|
-
if (modifier.includes('left')) {
|
|
14
|
-
direction = 'left';
|
|
15
|
-
} else if (modifier.includes('right')) {
|
|
16
|
-
direction = 'right';
|
|
17
|
-
}
|
|
18
|
-
if (modifier.includes('slight')) {
|
|
19
|
-
directionExtra = 'slight';
|
|
20
|
-
}
|
|
21
|
-
const isTurn = modifier !== 'straight';
|
|
22
|
-
|
|
23
|
-
if (step.lastStep) {
|
|
24
|
-
if (isTurn && direction === 'left') {
|
|
25
|
-
return 'Your destination is on your left';
|
|
26
|
-
} else if (isTurn && direction === 'right') {
|
|
27
|
-
return 'Your destination is on your right';
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const suffix = step.name ? ` on ${step.name}` : '';
|
|
32
|
-
|
|
33
|
-
if (step.levelChange) {
|
|
34
|
-
if (step.levelChange.direction === 'up') {
|
|
35
|
-
if (step.levelChange.type === 'escalator') {
|
|
36
|
-
return 'Go up the escalator';
|
|
37
|
-
}
|
|
38
|
-
if (step.levelChange.type === 'stairs') {
|
|
39
|
-
return 'Go up the stairs';
|
|
40
|
-
}
|
|
41
|
-
return 'Go up' + suffix;
|
|
42
|
-
}
|
|
43
|
-
if (step.levelChange.direction === 'down') {
|
|
44
|
-
if (step.levelChange.type === 'escalator') {
|
|
45
|
-
return 'Go down the escalator';
|
|
46
|
-
}
|
|
47
|
-
if (step.levelChange.type === 'stairs') {
|
|
48
|
-
return 'Go down the stairs';
|
|
49
|
-
}
|
|
50
|
-
return 'Go down' + suffix;
|
|
51
|
-
}
|
|
52
|
-
if (step.extras?.subwayEntrance) {
|
|
53
|
-
return `Take exit ${step.extras.subwayEntranceRef}`;
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (isTurn) {
|
|
58
|
-
if (direction === 'left') {
|
|
59
|
-
if (directionExtra === 'slight') {
|
|
60
|
-
return 'Turn slightly left' + suffix;
|
|
61
|
-
}
|
|
62
|
-
return 'Turn left' + suffix;
|
|
63
|
-
}
|
|
64
|
-
if (direction === 'right') {
|
|
65
|
-
if (directionExtra === 'slight') {
|
|
66
|
-
return 'Turn slightly right' + suffix;
|
|
67
|
-
}
|
|
68
|
-
return 'Turn right' + suffix;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
return '';
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
static getInstructionFromPosition(itineraryInfoManager: ItineraryInfoManager, position: Coordinates) {
|
|
77
|
-
const itineraryInfo = itineraryInfoManager.getInfo(position);
|
|
78
|
-
if (!itineraryInfo) {
|
|
79
|
-
return null;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const { nextStep } = itineraryInfo;
|
|
83
|
-
if (!nextStep) {
|
|
84
|
-
return null;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const distNextStep = position.distanceTo(nextStep.coords);
|
|
88
|
-
const nextStep2 = itineraryInfoManager._steps.find(step => step.number > nextStep.number);
|
|
89
|
-
if (distNextStep < 3 && nextStep2) {
|
|
90
|
-
return InstructionManagerV1.getInstructionFromStep(nextStep2);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return InstructionManagerV1.getInstructionFromStep(nextStep);
|
|
94
|
-
}
|
|
95
|
-
}
|
|
@@ -1,183 +0,0 @@
|
|
|
1
|
-
import chai from 'chai';
|
|
2
|
-
import chaiAlmost from 'chai-almost';
|
|
3
|
-
import fs from 'fs';
|
|
4
|
-
import path from 'path';
|
|
5
|
-
import { fileURLToPath } from 'url';
|
|
6
|
-
|
|
7
|
-
import { Coordinates, Utils as GeoUtils } from '@wemap/geo';
|
|
8
|
-
import { OsmParser } from '@wemap/osm';
|
|
9
|
-
|
|
10
|
-
import ItineraryInfoManager, { ItineraryInfo } from './ItineraryInfoManager.js';
|
|
11
|
-
import OtpRemoteRouter from './remote/otp/OtpRemoteRouter.js';
|
|
12
|
-
import OsmGraphUtils from './wemap-osm/OsmGraphUtils.js';
|
|
13
|
-
import GraphRouter from './graph/GraphRouter.js';
|
|
14
|
-
import Itinerary from './model/Itinerary.js';
|
|
15
|
-
import Vertex from './graph/Vertex.js';
|
|
16
|
-
import Edge from './graph/Edge.js';
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const { expect } = chai;
|
|
20
|
-
chai.use(chaiAlmost(0.1));
|
|
21
|
-
|
|
22
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
23
|
-
|
|
24
|
-
const load = (fileName: string) => {
|
|
25
|
-
const filePath = path.resolve(__dirname, '../assets/' + fileName);
|
|
26
|
-
const osmXmlString = fs.readFileSync(filePath, 'utf8');
|
|
27
|
-
const model = OsmParser.parseOsmXmlString(osmXmlString);
|
|
28
|
-
const graph = OsmGraphUtils.createGraphFromOsmModel(model);
|
|
29
|
-
const osmRouter = new GraphRouter(graph);
|
|
30
|
-
|
|
31
|
-
const from = model.getNodeByName('origin')?.coords as Coordinates;
|
|
32
|
-
const to = model.getNodeByName('destination')?.coords as Coordinates;
|
|
33
|
-
|
|
34
|
-
const itinerary = Itinerary.fromGraphRoute(osmRouter.calculateShortestPath(from, to).route());
|
|
35
|
-
const iim = new ItineraryInfoManager();
|
|
36
|
-
iim.itinerary = itinerary;
|
|
37
|
-
|
|
38
|
-
return { model, graph, iim, from, to, itinerary };
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
let resItineraryInfo: ItineraryInfo | null;
|
|
42
|
-
let itineraryInfo: ItineraryInfo;
|
|
43
|
-
|
|
44
|
-
describe('ItineraryInfoManager', () => {
|
|
45
|
-
|
|
46
|
-
it('Itinerary 2 points', () => {
|
|
47
|
-
|
|
48
|
-
const { from, to, iim, model, itinerary } = load('itinerary-info-two-points.osm');
|
|
49
|
-
|
|
50
|
-
// Projection on origin
|
|
51
|
-
const position1 = model.getNodeByName('position 1')?.coords as Coordinates;
|
|
52
|
-
resItineraryInfo = iim.getInfo(position1);
|
|
53
|
-
expect(resItineraryInfo).is.not.null;
|
|
54
|
-
itineraryInfo = resItineraryInfo as ItineraryInfo;
|
|
55
|
-
expect(itineraryInfo.projection.nearestElement).instanceOf(Vertex);
|
|
56
|
-
expect(itineraryInfo.projection.coords.equals(from)).is.true;
|
|
57
|
-
expect(itineraryInfo.previousStep).is.null;
|
|
58
|
-
expect(itineraryInfo.nextStep?.number).equals(1);
|
|
59
|
-
expect(itineraryInfo.remainingDistance).closeTo(8.29, 0.1);
|
|
60
|
-
expect(itineraryInfo.remainingPercentage).almost.equals(1);
|
|
61
|
-
expect(itineraryInfo.traveledDistance).almost.equals(0);
|
|
62
|
-
expect(itineraryInfo.traveledPercentage).almost.equals(0);
|
|
63
|
-
expect(itineraryInfo.leg).almost.equals(itinerary.legs[0]);
|
|
64
|
-
|
|
65
|
-
// Projection on middle
|
|
66
|
-
const position2 = model.getNodeByName('position 2')?.coords as Coordinates;
|
|
67
|
-
resItineraryInfo = iim.getInfo(position2);
|
|
68
|
-
expect(resItineraryInfo).is.not.null;
|
|
69
|
-
itineraryInfo = resItineraryInfo as ItineraryInfo;
|
|
70
|
-
expect(itineraryInfo.projection.nearestElement).instanceOf(Edge);
|
|
71
|
-
expect(itineraryInfo.previousStep?.number).equals(1);
|
|
72
|
-
expect(itineraryInfo.nextStep).is.null;
|
|
73
|
-
expect(itineraryInfo.remainingDistance).closeTo(4.3, 0.1);
|
|
74
|
-
expect(itineraryInfo.remainingPercentage).closeTo(0.59, 0.01);
|
|
75
|
-
expect(itineraryInfo.traveledDistance).closeTo(3, 0.1);
|
|
76
|
-
expect(itineraryInfo.traveledPercentage).closeTo(0.41, 0.01);
|
|
77
|
-
expect(itineraryInfo.leg).almost.equals(itinerary.legs[0]);
|
|
78
|
-
|
|
79
|
-
// Projection on destination
|
|
80
|
-
const position3 = model.getNodeByName('position 3')?.coords as Coordinates;
|
|
81
|
-
resItineraryInfo = iim.getInfo(position3);
|
|
82
|
-
expect(resItineraryInfo).is.not.null;
|
|
83
|
-
itineraryInfo = resItineraryInfo as ItineraryInfo;
|
|
84
|
-
expect(itineraryInfo.projection.nearestElement).instanceOf(Vertex);
|
|
85
|
-
expect(itineraryInfo.projection.coords.equals(to)).is.true;
|
|
86
|
-
expect(itineraryInfo.previousStep?.number).equals(1);
|
|
87
|
-
expect(itineraryInfo.nextStep).is.null;
|
|
88
|
-
expect(itineraryInfo.remainingDistance).closeTo(1.65, 0.1);
|
|
89
|
-
expect(itineraryInfo.remainingPercentage).closeTo(0.21, 0.01);
|
|
90
|
-
expect(itineraryInfo.traveledDistance).closeTo(itinerary.distance, 0.1);
|
|
91
|
-
expect(itineraryInfo.traveledPercentage).closeTo(0.78, 0.01);
|
|
92
|
-
expect(itineraryInfo.leg).almost.equals(itinerary.legs[0]);
|
|
93
|
-
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
it('Itinerary 2 points - from & to projection', () => {
|
|
97
|
-
|
|
98
|
-
const { iim, model, itinerary, to } = load('itinerary-info-two-points-proj.osm');
|
|
99
|
-
const porigin = model.getNodeByName('porigin')?.coords as Coordinates;
|
|
100
|
-
const pdest = model.getNodeByName('pdest')?.coords as Coordinates;
|
|
101
|
-
|
|
102
|
-
// Projection on origin
|
|
103
|
-
const position1 = model.getNodeByName('position 1')?.coords as Coordinates;
|
|
104
|
-
resItineraryInfo = iim.getInfo(position1);
|
|
105
|
-
expect(resItineraryInfo).is.not.null;
|
|
106
|
-
itineraryInfo = resItineraryInfo as ItineraryInfo;
|
|
107
|
-
expect(itineraryInfo.projection.nearestElement).instanceOf(Vertex);
|
|
108
|
-
expect(itineraryInfo.previousStep).is.null;
|
|
109
|
-
expect(itineraryInfo.nextStep?.number).equals(1);
|
|
110
|
-
expect(itineraryInfo.remainingDistance).almost.equals(GeoUtils.calcDistance([position1, porigin, pdest]));
|
|
111
|
-
expect(itineraryInfo.remainingPercentage).almost.equals(1);
|
|
112
|
-
expect(itineraryInfo.traveledDistance).almost.equals(0);
|
|
113
|
-
expect(itineraryInfo.traveledPercentage).almost.equals(0);
|
|
114
|
-
expect(itineraryInfo.leg).almost.equals(itinerary.legs[0]);
|
|
115
|
-
|
|
116
|
-
// Projection on middle
|
|
117
|
-
const position2 = model.getNodeByName('position 2')?.coords as Coordinates;
|
|
118
|
-
const p2 = model.getNodeByName('p2')?.coords as Coordinates;
|
|
119
|
-
resItineraryInfo = iim.getInfo(position2);
|
|
120
|
-
expect(resItineraryInfo).is.not.null;
|
|
121
|
-
itineraryInfo = resItineraryInfo as ItineraryInfo;
|
|
122
|
-
expect(itineraryInfo.projection.nearestElement).instanceOf(Edge);
|
|
123
|
-
expect(itineraryInfo.previousStep?.number).equals(1);
|
|
124
|
-
expect(itineraryInfo.nextStep?.number).equals(2);
|
|
125
|
-
expect(itineraryInfo.remainingDistance).closeTo(GeoUtils.calcDistance([position2, p2, pdest]), 0.1);
|
|
126
|
-
expect(itineraryInfo.remainingPercentage).closeTo(3.4 / 4.78, 0.1);
|
|
127
|
-
expect(itineraryInfo.traveledDistance).closeTo(GeoUtils.calcDistance([porigin, p2]), 0.1);
|
|
128
|
-
expect(itineraryInfo.traveledPercentage).closeTo(1.38 / 4.78, 0.1);
|
|
129
|
-
expect(itineraryInfo.leg).almost.equals(itinerary.legs[0]);
|
|
130
|
-
|
|
131
|
-
// Projection on end
|
|
132
|
-
const position3 = model.getNodeByName('position 3')?.coords as Coordinates;
|
|
133
|
-
resItineraryInfo = iim.getInfo(position3);
|
|
134
|
-
expect(resItineraryInfo).is.not.null;
|
|
135
|
-
itineraryInfo = resItineraryInfo as ItineraryInfo;
|
|
136
|
-
expect(itineraryInfo.projection.nearestElement).instanceOf(Vertex);
|
|
137
|
-
expect(itineraryInfo.previousStep?.number).equals(1);
|
|
138
|
-
expect(itineraryInfo.nextStep?.number).equals(2);
|
|
139
|
-
expect(itineraryInfo.remainingDistance).almost.equals(GeoUtils.calcDistance([position3, pdest]));
|
|
140
|
-
expect(itineraryInfo.remainingPercentage).closeTo(0.25, 0.01);
|
|
141
|
-
expect(itineraryInfo.traveledDistance).almost.equals(GeoUtils.calcDistance([porigin, pdest]));
|
|
142
|
-
expect(itineraryInfo.traveledPercentage).closeTo(0.75, 0.01);
|
|
143
|
-
expect(itineraryInfo.leg).almost.equals(itinerary.legs[0]);
|
|
144
|
-
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
it('Itinerary OTP', () => {
|
|
149
|
-
|
|
150
|
-
let position;
|
|
151
|
-
|
|
152
|
-
const filePath = path.resolve(__dirname, '../assets/itinerary-grenoble-otp-1.json');
|
|
153
|
-
const fileString = fs.readFileSync(filePath, 'utf8');
|
|
154
|
-
const json = JSON.parse(fileString);
|
|
155
|
-
const itineraries = OtpRemoteRouter.parseResponse(json);
|
|
156
|
-
|
|
157
|
-
const itinerary = itineraries[0];
|
|
158
|
-
const iim = new ItineraryInfoManager();
|
|
159
|
-
iim.itinerary = itinerary;
|
|
160
|
-
|
|
161
|
-
position = new Coordinates(45.1641153, 5.741293);
|
|
162
|
-
resItineraryInfo = iim.getInfo(position);
|
|
163
|
-
expect(resItineraryInfo).is.not.null;
|
|
164
|
-
itineraryInfo = resItineraryInfo as ItineraryInfo;
|
|
165
|
-
expect(itineraryInfo.projection.nearestElement).instanceOf(Vertex);
|
|
166
|
-
expect(itineraryInfo.previousStep?.number).equals(14);
|
|
167
|
-
expect(itineraryInfo.nextStep?.number).equals(15);
|
|
168
|
-
expect(itineraryInfo.remainingDistance).closeTo(56.9, 0.1);
|
|
169
|
-
expect(itineraryInfo.remainingPercentage).closeTo(0.0155, 0.01);
|
|
170
|
-
expect(itineraryInfo.leg).almost.equals(itinerary.legs[2]);
|
|
171
|
-
|
|
172
|
-
position = new Coordinates(45.1641691, 5.7413891);
|
|
173
|
-
resItineraryInfo = iim.getInfo(position);
|
|
174
|
-
expect(resItineraryInfo).is.not.null;
|
|
175
|
-
itineraryInfo = resItineraryInfo as ItineraryInfo;
|
|
176
|
-
expect(itineraryInfo.projection.nearestElement).instanceOf(Edge);
|
|
177
|
-
expect(itineraryInfo.nextStep?.number).equals(15);
|
|
178
|
-
expect(itineraryInfo.previousStep?.number).equals(14);
|
|
179
|
-
expect(itineraryInfo.remainingDistance).closeTo(66.4, 0.1);
|
|
180
|
-
expect(itineraryInfo.remainingPercentage).closeTo(0.018, 0.01);
|
|
181
|
-
expect(itineraryInfo.leg).almost.equals(itinerary.legs[2]);
|
|
182
|
-
});
|
|
183
|
-
});
|
|
@@ -1,181 +0,0 @@
|
|
|
1
|
-
import { Coordinates } from '@wemap/geo';
|
|
2
|
-
|
|
3
|
-
import Itinerary from './model/Itinerary.js';
|
|
4
|
-
import Leg from './model/Leg.js';
|
|
5
|
-
import { Step } from './model/Step.js';
|
|
6
|
-
import Graph from './graph/Graph.js';
|
|
7
|
-
import GraphProjection from './graph/GraphProjection.js';
|
|
8
|
-
import Vertex from './graph/Vertex.js';
|
|
9
|
-
import Edge from './graph/Edge.js';
|
|
10
|
-
|
|
11
|
-
export type ItineraryInfo<U extends Coordinates = Coordinates> = {
|
|
12
|
-
nextStep: Step | null;
|
|
13
|
-
previousStep: Step | null;
|
|
14
|
-
projection: GraphProjection<U>;
|
|
15
|
-
leg: Leg;
|
|
16
|
-
traveledDistance: number;
|
|
17
|
-
remainingDistance: number;
|
|
18
|
-
traveledPercentage: number;
|
|
19
|
-
remainingPercentage: number;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
class ItineraryInfoManager {
|
|
23
|
-
|
|
24
|
-
_itinerary: Itinerary | null = null;
|
|
25
|
-
_graph: Graph | null = null;
|
|
26
|
-
|
|
27
|
-
_steps: Step[] = [];
|
|
28
|
-
_coordsNextStep: (Step | null)[] = [];
|
|
29
|
-
_coordsPreviousStep: (Step | null)[] = [];
|
|
30
|
-
_coordsDistanceTraveled: number[] = [];
|
|
31
|
-
_coordsLeg: Leg[] = [];
|
|
32
|
-
_itineraryDistanceWithoutProjections = 0;
|
|
33
|
-
|
|
34
|
-
constructor(itinerary: Itinerary | null = null) {
|
|
35
|
-
this.itinerary = itinerary;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
get itinerary() {
|
|
39
|
-
return this._itinerary;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
set itinerary(itinerary) {
|
|
43
|
-
|
|
44
|
-
if (itinerary === null) {
|
|
45
|
-
this._itinerary = null;
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
this._itinerary = itinerary;
|
|
50
|
-
this._steps = itinerary.steps;
|
|
51
|
-
this._graph = itinerary.toGraph();
|
|
52
|
-
|
|
53
|
-
this._coordsNextStep = new Array(itinerary.coords.length);
|
|
54
|
-
this._coordsPreviousStep = new Array(itinerary.coords.length);
|
|
55
|
-
this._coordsDistanceTraveled = new Array(itinerary.coords.length);
|
|
56
|
-
this._coordsLeg = new Array(itinerary.coords.length);
|
|
57
|
-
this._itineraryDistanceWithoutProjections = itinerary.distance;
|
|
58
|
-
|
|
59
|
-
let stepId = 0;
|
|
60
|
-
let previousStep: Step | null = null;
|
|
61
|
-
let nextStep: Step | null = this._steps[0];
|
|
62
|
-
let distanceTraveled = 0;
|
|
63
|
-
|
|
64
|
-
itinerary.coords.forEach((coords, idx, arr) => {
|
|
65
|
-
if (idx !== 0) {
|
|
66
|
-
distanceTraveled += arr[idx - 1].distanceTo(coords);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
this._coordsNextStep[idx] = nextStep;
|
|
70
|
-
this._coordsPreviousStep[idx] = previousStep;
|
|
71
|
-
this._coordsDistanceTraveled[idx] = distanceTraveled;
|
|
72
|
-
this._coordsLeg[idx] = itinerary.legs.find(leg => leg.coords.includes(coords)) as Leg;
|
|
73
|
-
|
|
74
|
-
if (stepId < this._steps.length && this._steps[stepId].coords.equals(coords)) {
|
|
75
|
-
previousStep = this._steps[stepId];
|
|
76
|
-
nextStep = stepId === this._steps.length - 1 ? null : this._steps[stepId + 1];
|
|
77
|
-
stepId++;
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
getInfo<U extends Coordinates = Coordinates>(position: U) {
|
|
83
|
-
|
|
84
|
-
if (!this._itinerary || !this._graph) {
|
|
85
|
-
return null;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const projection = this._graph.getProjection(position);
|
|
89
|
-
if (!projection) {
|
|
90
|
-
return null;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
let itineraryInfo: ItineraryInfo<U> | null = null;
|
|
94
|
-
|
|
95
|
-
if (projection.nearestElement instanceof Vertex) {
|
|
96
|
-
const idx = this._itinerary.coords.findIndex(
|
|
97
|
-
coords => (projection.nearestElement as Vertex).coords === coords
|
|
98
|
-
);
|
|
99
|
-
if (idx === -1) {
|
|
100
|
-
throw new Error('ItineraryInfoManager: could not find projection in itinerary (Node)');
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
const traveledDistanceOnItinerary = this._coordsDistanceTraveled[idx];
|
|
104
|
-
|
|
105
|
-
// Traveled distance takes into account:
|
|
106
|
-
// - projection of the origin
|
|
107
|
-
const traveledDistance = traveledDistanceOnItinerary;
|
|
108
|
-
|
|
109
|
-
// Remaining distance takes into account:
|
|
110
|
-
// - projection of the current position
|
|
111
|
-
// - distance remaining on the itinerary
|
|
112
|
-
const remainingDistanceOnItinerary = this._itineraryDistanceWithoutProjections - traveledDistanceOnItinerary;
|
|
113
|
-
const remainingDistance = projection.distanceFromNearestElement + remainingDistanceOnItinerary;
|
|
114
|
-
|
|
115
|
-
const distanceForPercentage = traveledDistance + remainingDistance
|
|
116
|
-
const traveledPercentage = traveledDistance / distanceForPercentage;
|
|
117
|
-
const remainingPercentage = 1 - traveledPercentage;
|
|
118
|
-
|
|
119
|
-
itineraryInfo = {
|
|
120
|
-
nextStep: this._coordsNextStep[idx],
|
|
121
|
-
previousStep: this._coordsPreviousStep[idx],
|
|
122
|
-
projection: projection,
|
|
123
|
-
leg: this._coordsLeg[idx],
|
|
124
|
-
traveledDistance: traveledDistanceOnItinerary,
|
|
125
|
-
remainingDistance,
|
|
126
|
-
traveledPercentage,
|
|
127
|
-
remainingPercentage
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
} else if (projection.nearestElement instanceof Edge) {
|
|
131
|
-
|
|
132
|
-
let firstNode = projection.nearestElement.vertex1.coords;
|
|
133
|
-
let idx = this._itinerary.coords.findIndex(coords => firstNode === coords);
|
|
134
|
-
if (idx === -1) {
|
|
135
|
-
throw new Error('ItineraryInfoManager: could not find projection in itinerary (Edge)');
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// graphEdge is not necessarly ordered. We have to look for the first point
|
|
139
|
-
if (idx === this._itinerary.coords.length - 1
|
|
140
|
-
|| this._itinerary.coords[idx + 1] !== projection.nearestElement.vertex2.coords
|
|
141
|
-
) {
|
|
142
|
-
firstNode = projection.nearestElement.vertex2.coords;
|
|
143
|
-
idx--;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
const traveledDistanceOnItinerary = this._coordsDistanceTraveled[idx]
|
|
147
|
-
+ projection.coords.distanceTo(firstNode);
|
|
148
|
-
|
|
149
|
-
// Traveled distance takes into account:
|
|
150
|
-
// - distance traveled on the itinerary
|
|
151
|
-
const traveledDistance = traveledDistanceOnItinerary;
|
|
152
|
-
|
|
153
|
-
// Remaining distance takes into account:
|
|
154
|
-
// - projection of the current position
|
|
155
|
-
// - distance remaining on the itinerary
|
|
156
|
-
const remainingDistanceOnItinerary = this._itineraryDistanceWithoutProjections - traveledDistanceOnItinerary;
|
|
157
|
-
const remainingDistance = projection.distanceFromNearestElement + remainingDistanceOnItinerary
|
|
158
|
-
|
|
159
|
-
const distanceForPercentage = traveledDistance + remainingDistance
|
|
160
|
-
const traveledPercentage = traveledDistance / distanceForPercentage;
|
|
161
|
-
const remainingPercentage = 1 - traveledPercentage;
|
|
162
|
-
|
|
163
|
-
itineraryInfo = {
|
|
164
|
-
nextStep: this._coordsNextStep[idx + 1],
|
|
165
|
-
previousStep: this._coordsPreviousStep[idx + 1],
|
|
166
|
-
projection: projection,
|
|
167
|
-
leg: this._coordsLeg[idx + 1],
|
|
168
|
-
traveledDistance,
|
|
169
|
-
remainingDistance,
|
|
170
|
-
traveledPercentage,
|
|
171
|
-
remainingPercentage
|
|
172
|
-
};
|
|
173
|
-
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
return itineraryInfo;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
export default ItineraryInfoManager;
|
package/src/RoutingError.ts
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
// Based on GRPC status code
|
|
2
|
-
|
|
3
|
-
import { StatusCode } from "./StatusCode";
|
|
4
|
-
import { TravelMode } from "./model/TravelMode";
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
export class RoutingError extends Error {
|
|
8
|
-
|
|
9
|
-
public customMapName?: string | null;
|
|
10
|
-
|
|
11
|
-
constructor(public code = StatusCode.UNKNOWN, message?: string) {
|
|
12
|
-
super(message)
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
static notFound(details?: string) {
|
|
16
|
-
return new RoutingError(StatusCode.NOT_FOUND, `Cannot found an itinerary. Details: ${details}`)
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
export class WemapMultiRoutingError extends RoutingError {
|
|
22
|
-
|
|
23
|
-
constructor(public code = StatusCode.UNKNOWN, public mapName: string | null, message?: string) {
|
|
24
|
-
super(code, message);
|
|
25
|
-
this.mapName = mapName;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
static notFound(mapName: string, details?: string) {
|
|
29
|
-
return new WemapMultiRoutingError(StatusCode.NOT_FOUND, mapName, `Cannot found an itinerary in map ${mapName}. Details: ${details || 'No details'}`)
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export class RemoteRoutingError extends RoutingError {
|
|
35
|
-
|
|
36
|
-
constructor(public code = StatusCode.UNKNOWN, public routerName: string, message?: string) {
|
|
37
|
-
super(code, message);
|
|
38
|
-
this.routerName = routerName;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
static notFound(routerName: string, details?: string) {
|
|
42
|
-
return new RemoteRoutingError(StatusCode.NOT_FOUND, routerName, `Cannot found an itinerary with ${routerName}. Details: ${details || 'No details'}`)
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
static missingApiKey(routerName: string, details?: string) {
|
|
46
|
-
return new RemoteRoutingError(StatusCode.UNAUTHENTICATED, routerName, `API key is missing for ${routerName}. Details: ${details}`)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
static unreachableServer(routerName: string, url: string) {
|
|
50
|
-
return new RemoteRoutingError(StatusCode.NOT_FOUND, routerName, `Remote router server ${routerName} is unreachable. URL: ${url}`)
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
static responseNotParsing(routerName: string, url: string) {
|
|
54
|
-
return new RemoteRoutingError(StatusCode.NOT_FOUND, routerName, `Remote router server response ${routerName} cannot be parsed. URL: ${url}`)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
static travelModeUnimplemented(routerName: string, travelMode: TravelMode) {
|
|
58
|
-
return new RemoteRoutingError(StatusCode.UNIMPLEMENTED, routerName, `Travel mode "${travelMode}" is not implemented for ${routerName}`)
|
|
59
|
-
}
|
|
60
|
-
}
|
package/src/Utils.ts
DELETED
package/src/graph/Edge.spec.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import chai from 'chai';
|
|
2
|
-
|
|
3
|
-
import { Coordinates } from '@wemap/geo';
|
|
4
|
-
|
|
5
|
-
import Vertex from './Vertex.js';
|
|
6
|
-
import Edge from './Edge.js';
|
|
7
|
-
|
|
8
|
-
const { expect } = chai;
|
|
9
|
-
|
|
10
|
-
describe('Edge', () => {
|
|
11
|
-
|
|
12
|
-
const vertex1 = new Vertex(new Coordinates(45, 5));
|
|
13
|
-
const vertex2 = new Vertex(new Coordinates(46, 5));
|
|
14
|
-
|
|
15
|
-
it('creation', () => {
|
|
16
|
-
|
|
17
|
-
expect(() => new Edge(vertex1, vertex2)).not.throw(Error);
|
|
18
|
-
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
it('distanceTo / bearingTo', () => {
|
|
23
|
-
let newEdge = new Edge(vertex1, vertex2);
|
|
24
|
-
expect(newEdge.length).equals(vertex1.distanceTo(vertex2));
|
|
25
|
-
expect(newEdge.bearing).equals(vertex1.bearingTo(vertex2));
|
|
26
|
-
|
|
27
|
-
newEdge = new Edge(vertex1, vertex2);
|
|
28
|
-
expect(newEdge.bearing).equals(vertex1.bearingTo(vertex2));
|
|
29
|
-
expect(newEdge.length).equals(vertex1.distanceTo(vertex2));
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
});
|
package/src/graph/Edge.ts
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { Level, type Level_t } from '@wemap/geo';
|
|
2
|
-
|
|
3
|
-
import Vertex from './Vertex.js';
|
|
4
|
-
|
|
5
|
-
export type EdgeProperties = {
|
|
6
|
-
|
|
7
|
-
name?: string;
|
|
8
|
-
externalId?: string | number;
|
|
9
|
-
|
|
10
|
-
isOneway?: boolean;
|
|
11
|
-
areStairs?: boolean;
|
|
12
|
-
isElevator?: boolean;
|
|
13
|
-
areEscalators?: boolean;
|
|
14
|
-
isMovingWalkway?: boolean;
|
|
15
|
-
needTicket?: boolean;
|
|
16
|
-
incline?: 'up' | 'down';
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* An Edge is a segment composed of two Vertex
|
|
21
|
-
* An edge is mostly issued from an OsmWay, but this is not always the case.
|
|
22
|
-
* For example, edges created by mapmatching.
|
|
23
|
-
*/
|
|
24
|
-
export default class Edge {
|
|
25
|
-
|
|
26
|
-
static currentUniqueId = 0;
|
|
27
|
-
|
|
28
|
-
public readonly level: Level_t;
|
|
29
|
-
|
|
30
|
-
/** Edge bearing from vertex1 to vertex2 */
|
|
31
|
-
public readonly bearing: number;
|
|
32
|
-
public readonly length: number;
|
|
33
|
-
|
|
34
|
-
constructor(
|
|
35
|
-
public vertex1: Vertex,
|
|
36
|
-
public vertex2: Vertex,
|
|
37
|
-
public properties: EdgeProperties = {},
|
|
38
|
-
public readonly id: number = Edge.currentUniqueId++
|
|
39
|
-
) {
|
|
40
|
-
this.level = Level.union(vertex1.coords.level, vertex2.coords.level)
|
|
41
|
-
this.length = this.vertex1.distanceTo(this.vertex2);
|
|
42
|
-
this.bearing = this.vertex1.bearingTo(this.vertex2);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
static getEdgeByVertices(
|
|
46
|
-
edges: Edge[],
|
|
47
|
-
vertex1: Vertex,
|
|
48
|
-
vertex2: Vertex
|
|
49
|
-
) {
|
|
50
|
-
return edges.find(edge => vertex1 === edge.vertex1 && vertex2 === edge.vertex2
|
|
51
|
-
|| vertex2 === edge.vertex1 && vertex1 === edge.vertex2
|
|
52
|
-
);
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
reverseProperties() {
|
|
56
|
-
const { properties } = this;
|
|
57
|
-
if (properties.incline) {
|
|
58
|
-
properties.incline = properties.incline === 'up' ? 'down' : 'up';
|
|
59
|
-
}
|
|
60
|
-
if (properties.isOneway) {
|
|
61
|
-
properties.isOneway = false;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
}
|