@wemap/osm 5.8.0 → 6.2.2
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/wemap-osm.es.js +2 -1760
- package/dist/wemap-osm.es.js.map +1 -1
- package/index.js +5 -28
- package/package.json +4 -6
- package/src/{model/OsmParser.spec.js → OsmParser.spec.js} +1 -1
- package/assets/bureaux-wemap-montpellier-network.osm +0 -162
- package/assets/gare-de-lyon-extract.osm +0 -174
- 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-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-montpellier-osrm-3.json +0 -1
- package/assets/itinerary-montpellier-outdoor-without-steps.json +0 -110
- package/assets/itinerary-montpellier-outdoor.json +0 -513
- 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-simple.osm +0 -27
- package/assets/network-with-modifiers.osm +0 -39
- package/assets/one-way.osm +0 -46
- package/src/routers/Itinerary.js +0 -197
- package/src/routers/Itinerary.type.spec.js +0 -105
- package/src/routers/Leg.js +0 -113
- package/src/routers/LevelChange.js +0 -65
- package/src/routers/RouterResponse.js +0 -19
- package/src/routers/RouterResponse.type.spec.js +0 -24
- package/src/routers/Step.js +0 -118
- package/src/routers/Utils.js +0 -54
- package/src/routers/cityway/CitywayUtils.js +0 -240
- package/src/routers/cityway/CitywayUtils.spec.js +0 -109
- package/src/routers/custom/OsmNetworkUtils.js +0 -199
- package/src/routers/custom/OsmNetworkUtils.spec.js +0 -109
- package/src/routers/custom/OsmRouter.js +0 -27
- package/src/routers/custom/OsmRouter.spec.js +0 -222
- package/src/routers/custom/OsmRouterOptions.js +0 -33
- package/src/routers/custom/OsmRouterUtils.js +0 -46
- package/src/routers/custom/StepsGeneration.js +0 -104
- package/src/routers/deutsche-bahn/DeutscheBahnRouterUtils.js +0 -93
- package/src/routers/deutsche-bahn/DeutscheBahnRouterUtils.spec.js +0 -54
- package/src/routers/info/ItineraryInfo.js +0 -34
- package/src/routers/info/ItineraryInfoManager.js +0 -148
- package/src/routers/info/ItineraryInfoManager.spec.js +0 -54
- package/src/routers/osrm/OsrmUtils.js +0 -269
- package/src/routers/osrm/OsrmUtils.spec.js +0 -457
- package/src/routers/otp/OtpUtils.js +0 -150
- package/src/routers/otp/OtpUtils.spec.js +0 -97
- /package/src/{model/OsmElement.js → OsmElement.js} +0 -0
- /package/src/{model/OsmElement.spec.js → OsmElement.spec.js} +0 -0
- /package/src/{model/OsmModel.js → OsmModel.js} +0 -0
- /package/src/{model/OsmModel.spec.js → OsmModel.spec.js} +0 -0
- /package/src/{model/OsmNode.js → OsmNode.js} +0 -0
- /package/src/{model/OsmNode.spec.js → OsmNode.spec.js} +0 -0
- /package/src/{model/OsmParser.js → OsmParser.js} +0 -0
- /package/src/{model/OsmWay.js → OsmWay.js} +0 -0
- /package/src/{model/OsmWay.spec.js → OsmWay.spec.js} +0 -0
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
/* eslint-disable max-statements */
|
|
2
|
-
import chai from 'chai';
|
|
3
|
-
import fs from 'fs';
|
|
4
|
-
import path from 'path';
|
|
5
|
-
import { fileURLToPath } from 'url';
|
|
6
|
-
|
|
7
|
-
import { Coordinates } from '@wemap/geo';
|
|
8
|
-
|
|
9
|
-
import { createRouterResponseFromJson } from './CitywayUtils.js';
|
|
10
|
-
|
|
11
|
-
import { verifyRouterResponseData } from '../RouterResponse.type.spec.js';
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const { expect } = chai;
|
|
15
|
-
|
|
16
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
17
|
-
|
|
18
|
-
describe('CitywayUtils - createRouterResponseFromJson', () => {
|
|
19
|
-
|
|
20
|
-
it('RouterResponse - 1', () => {
|
|
21
|
-
|
|
22
|
-
const filePath = path.resolve(__dirname, '../../../assets/itinerary-lehavre-cityway-1.json');
|
|
23
|
-
const fileString = fs.readFileSync(filePath, 'utf8');
|
|
24
|
-
const json = JSON.parse(fileString);
|
|
25
|
-
|
|
26
|
-
const routerResponse = createRouterResponseFromJson(json);
|
|
27
|
-
verifyRouterResponseData(routerResponse);
|
|
28
|
-
|
|
29
|
-
expect(routerResponse.routerName).equal('cityway');
|
|
30
|
-
expect(routerResponse.itineraries.length).equal(3);
|
|
31
|
-
expect(routerResponse.from.equalsTo(new Coordinates(49.515093882362159, 0.093417496193663158))).true;
|
|
32
|
-
expect(routerResponse.to.equalsTo(new Coordinates(49.5067090188444, 0.16948421154178309))).true;
|
|
33
|
-
|
|
34
|
-
const itinerary1 = routerResponse.itineraries[0];
|
|
35
|
-
expect(itinerary1.distance).to.be.closeTo(6887, 1);
|
|
36
|
-
expect(itinerary1.duration).equal(2379);
|
|
37
|
-
// Do not work because of the input time format
|
|
38
|
-
// expect(itinerary1.startTime).equal(1620659156000);
|
|
39
|
-
// expect(itinerary1.endTime).equal(1620661535000);
|
|
40
|
-
expect(itinerary1.legs.length).equal(5);
|
|
41
|
-
|
|
42
|
-
const itinerary1leg1 = itinerary1.legs[0];
|
|
43
|
-
// Do not work because of the input time format
|
|
44
|
-
// expect(itinerary1leg1.startTime).equal(1620659156000);
|
|
45
|
-
// expect(itinerary1leg1.endTime).equal(1620659340000);
|
|
46
|
-
expect(itinerary1leg1.distance).to.be.closeTo(200.14, 0.1);
|
|
47
|
-
expect(itinerary1leg1.mode).equal('WALK');
|
|
48
|
-
expect(itinerary1leg1.transportInfo).is.null;
|
|
49
|
-
expect(itinerary1leg1.from.name).equal('RUE DU QUARTIER NEUF');
|
|
50
|
-
expect(itinerary1leg1.from.coords.equalsTo(new Coordinates(49.515093882362159, 0.093417496193663158))).true;
|
|
51
|
-
expect(itinerary1leg1.to.name).equal('T. Gautier');
|
|
52
|
-
expect(itinerary1leg1.to.coords.equalsTo(new Coordinates(49.5147550229, 0.0911025378))).true;
|
|
53
|
-
|
|
54
|
-
const itinerary1leg2 = itinerary1.legs[1];
|
|
55
|
-
expect(itinerary1leg2.mode).equal('BUS');
|
|
56
|
-
expect(itinerary1leg2.transportInfo).is.not.null;
|
|
57
|
-
expect(itinerary1leg2.transportInfo.name).equal('03');
|
|
58
|
-
expect(itinerary1leg2.transportInfo.routeColor).equal('3FA435');
|
|
59
|
-
expect(itinerary1leg2.transportInfo.routeTextColor).is.null;
|
|
60
|
-
expect(itinerary1leg2.transportInfo.directionName).equal('Graville');
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it('RouterResponse - 2', () => {
|
|
64
|
-
const filePath = path.resolve(__dirname, '../../../assets/itinerary-lehavre-cityway-2.json');
|
|
65
|
-
const fileString = fs.readFileSync(filePath, 'utf8');
|
|
66
|
-
const json = JSON.parse(fileString);
|
|
67
|
-
|
|
68
|
-
const routerResponse = createRouterResponseFromJson(json);
|
|
69
|
-
verifyRouterResponseData(routerResponse);
|
|
70
|
-
|
|
71
|
-
expect(routerResponse.itineraries.length).equal(1);
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it('RouterResponse - 3', () => {
|
|
75
|
-
const filePath = path.resolve(__dirname, '../../../assets/itinerary-lehavre-cityway-3.json');
|
|
76
|
-
const fileString = fs.readFileSync(filePath, 'utf8');
|
|
77
|
-
const json = JSON.parse(fileString);
|
|
78
|
-
|
|
79
|
-
const routerResponse = createRouterResponseFromJson(json);
|
|
80
|
-
verifyRouterResponseData(routerResponse);
|
|
81
|
-
|
|
82
|
-
expect(routerResponse.itineraries[0].legs[1].mode).equal('FUNICULAR');
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
it('RouterResponse - 4', () => {
|
|
86
|
-
const filePath = path.resolve(__dirname, '../../../assets/itinerary-lehavre-cityway-4.json');
|
|
87
|
-
const fileString = fs.readFileSync(filePath, 'utf8');
|
|
88
|
-
const json = JSON.parse(fileString);
|
|
89
|
-
|
|
90
|
-
const routerResponse = createRouterResponseFromJson(json);
|
|
91
|
-
verifyRouterResponseData(routerResponse);
|
|
92
|
-
|
|
93
|
-
expect(routerResponse.itineraries[0].legs[0].mode).equal('BICYCLE');
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
it('RouterResponse - 5', () => {
|
|
97
|
-
const filePath = path.resolve(__dirname, '../../../assets/itinerary-lehavre-cityway-5.json');
|
|
98
|
-
const fileString = fs.readFileSync(filePath, 'utf8');
|
|
99
|
-
const json = JSON.parse(fileString);
|
|
100
|
-
|
|
101
|
-
const routerResponse = createRouterResponseFromJson(json);
|
|
102
|
-
verifyRouterResponseData(routerResponse);
|
|
103
|
-
|
|
104
|
-
expect(routerResponse.itineraries[1].legs[1].mode).equal('TRAM');
|
|
105
|
-
expect(routerResponse.itineraries[1].legs[1].transportInfo.name).equal('B');
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
});
|
|
109
|
-
|
|
@@ -1,199 +0,0 @@
|
|
|
1
|
-
import { Level, GraphEdge, GraphNode, Network } from '@wemap/geo';
|
|
2
|
-
|
|
3
|
-
import OsmElement from '../../model/OsmElement.js';
|
|
4
|
-
import OsmModel from '../../model/OsmModel.js';
|
|
5
|
-
import OsmNode from '../../model/OsmNode.js';
|
|
6
|
-
import OsmWay from '../../model/OsmWay.js';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
export const HIGHWAYS_PEDESTRIANS = ['footway', 'steps', 'pedestrian', 'living_street', 'path', 'track', 'sidewalk'];
|
|
10
|
-
|
|
11
|
-
export const DEFAULT_WAY_SELECTOR = way => {
|
|
12
|
-
return HIGHWAYS_PEDESTRIANS.includes(way.tags.highway)
|
|
13
|
-
|| way.tags.footway === 'sidewalk'
|
|
14
|
-
|| way.tags.public_transport === 'platform'
|
|
15
|
-
|| way.tags.railway === 'platform';
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @param {Network<OsmElement>} network
|
|
20
|
-
* @param {string} name
|
|
21
|
-
*/
|
|
22
|
-
export function getNodeByName(network, name) {
|
|
23
|
-
return network.nodes.find(({ builtFrom }) => builtFrom.tags.name === name);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* @param {Network<OsmElement>} network
|
|
28
|
-
* @param {string} name
|
|
29
|
-
*/
|
|
30
|
-
export function getEdgeByName(network, name) {
|
|
31
|
-
return network.edges.find(({ builtFrom }) => builtFrom.tags.name === name);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* @param {GraphEdge<OsmElement>} edge
|
|
36
|
-
* @param {OsmWay} way
|
|
37
|
-
* @returns {boolean}
|
|
38
|
-
*/
|
|
39
|
-
function manageOneWay(edge, way) {
|
|
40
|
-
|
|
41
|
-
const { highway, oneway, conveying } = way.tags;
|
|
42
|
-
|
|
43
|
-
edge.isOneway = Boolean((oneway === 'yes' || oneway === 'true' || oneway === '1')
|
|
44
|
-
|| (conveying && highway && ['yes', 'forward', 'backward'].includes(conveying)));
|
|
45
|
-
|
|
46
|
-
if (edge.isOneway && conveying === 'backward') {
|
|
47
|
-
const tmpNode = edge.node1;
|
|
48
|
-
edge.node1 = edge.node2;
|
|
49
|
-
edge.node2 = tmpNode;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* @param {Network} networkModel
|
|
55
|
-
* @param {GraphNode} node
|
|
56
|
-
*/
|
|
57
|
-
function createNodesAndEdgesFromElevator(networkModel, node) {
|
|
58
|
-
|
|
59
|
-
/** @type {GraphNode[]} */
|
|
60
|
-
const createdNodes = [];
|
|
61
|
-
const getOrCreateLevelNode = (level, builtFrom) => {
|
|
62
|
-
let levelNode = createdNodes.find(({ coords }) => Level.equalsTo(level, coords.level));
|
|
63
|
-
if (!levelNode) {
|
|
64
|
-
levelNode = new GraphNode(node.coords.clone(), builtFrom);
|
|
65
|
-
levelNode.coords.level = level;
|
|
66
|
-
createdNodes.push(levelNode);
|
|
67
|
-
networkModel.nodes.push(levelNode);
|
|
68
|
-
}
|
|
69
|
-
return levelNode;
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
// Create nodes from node.edges
|
|
73
|
-
node.edges.forEach(edge => {
|
|
74
|
-
if (edge.level.isRange) {
|
|
75
|
-
throw new Error('Cannot handle this elevator edge due to ambiguity');
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const levelNode = getOrCreateLevelNode(edge.level, node.builtFrom);
|
|
79
|
-
if (edge.node1 === node) {
|
|
80
|
-
edge.node1 = levelNode;
|
|
81
|
-
} else {
|
|
82
|
-
edge.node2 = levelNode;
|
|
83
|
-
}
|
|
84
|
-
levelNode.edges.push(edge);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
// Create edges from createdNodes
|
|
88
|
-
for (let i = 0; i < createdNodes.length; i++) {
|
|
89
|
-
for (let j = i + 1; j < createdNodes.length; j++) {
|
|
90
|
-
|
|
91
|
-
const createdNode1 = createdNodes[i];
|
|
92
|
-
const createdNode2 = createdNodes[j];
|
|
93
|
-
|
|
94
|
-
const newEdge = new GraphEdge(
|
|
95
|
-
createdNode1,
|
|
96
|
-
createdNode2,
|
|
97
|
-
new Level(createdNode1.coords.level.val, createdNode2.coords.level.val),
|
|
98
|
-
node.builtFrom
|
|
99
|
-
);
|
|
100
|
-
networkModel.edges.push(newEdge);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Remove the historical elevator node from the network
|
|
105
|
-
networkModel.nodes = networkModel.nodes.filter(_node => _node !== node);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* @param {OsmModel} osmModel
|
|
111
|
-
* @param {function} _waySelectionFilter
|
|
112
|
-
* @returns {Network<OsmElement>}
|
|
113
|
-
*/
|
|
114
|
-
export function createNetworkFromOsmModel(
|
|
115
|
-
osmModel,
|
|
116
|
-
waySelectionFilter = DEFAULT_WAY_SELECTOR
|
|
117
|
-
) {
|
|
118
|
-
|
|
119
|
-
const networkModel = new Network();
|
|
120
|
-
|
|
121
|
-
const nodesCreated = {};
|
|
122
|
-
const elevatorNodes = [];
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* @param {OsmNode} osmNode
|
|
126
|
-
*/
|
|
127
|
-
const getOrCreateNode = osmNode => {
|
|
128
|
-
let node = nodesCreated[osmNode.id];
|
|
129
|
-
if (!node) {
|
|
130
|
-
node = new GraphNode(osmNode.coords, osmNode);
|
|
131
|
-
nodesCreated[osmNode.id] = node;
|
|
132
|
-
networkModel.nodes.push(node);
|
|
133
|
-
|
|
134
|
-
if (osmNode.tags.highway === 'elevator') {
|
|
135
|
-
elevatorNodes.push(node);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
return node;
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
osmModel.ways.forEach(way => {
|
|
142
|
-
if (!waySelectionFilter(way)) {
|
|
143
|
-
return;
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
let firstNode = getOrCreateNode(way.nodes[0]);
|
|
147
|
-
for (let i = 1; i < way.nodes.length; i++) {
|
|
148
|
-
const secondNode = getOrCreateNode(way.nodes[i]);
|
|
149
|
-
|
|
150
|
-
const edge = new GraphEdge(firstNode, secondNode, way.level, way);
|
|
151
|
-
manageOneWay(edge, way);
|
|
152
|
-
networkModel.edges.push(edge);
|
|
153
|
-
firstNode = secondNode;
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
});
|
|
157
|
-
|
|
158
|
-
elevatorNodes.forEach(node => {
|
|
159
|
-
// We have to clone this node for each connected edge
|
|
160
|
-
createNodesAndEdgesFromElevator(networkModel, node);
|
|
161
|
-
});
|
|
162
|
-
|
|
163
|
-
GraphNode.generateNodesLevels(networkModel.nodes);
|
|
164
|
-
|
|
165
|
-
return networkModel;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
// /**
|
|
170
|
-
// * @param {GraphNode} node
|
|
171
|
-
// * @param {object} tags
|
|
172
|
-
// */
|
|
173
|
-
// static _applyNodePropertiesFromTags(node, tags) {
|
|
174
|
-
// node.name = tags.name || null;
|
|
175
|
-
// node.subwayEntrance = tags.railway === 'subway_entrance';
|
|
176
|
-
// if (node.subwayEntrance && tags.ref) {
|
|
177
|
-
// node.subwayEntranceRef = tags.ref;
|
|
178
|
-
// }
|
|
179
|
-
// }
|
|
180
|
-
|
|
181
|
-
// /**
|
|
182
|
-
// * @param {GraphEdge} edge
|
|
183
|
-
// * @param {object} tags
|
|
184
|
-
// */
|
|
185
|
-
// static _applyEdgePropertiesFromTags(edge, tags) {
|
|
186
|
-
// const { highway, oneway, conveying, name } = tags;
|
|
187
|
-
// edge.name = name || null;
|
|
188
|
-
// edge.isStairs = highway === 'steps';
|
|
189
|
-
// edge.isConveying = 'conveying' in tags;
|
|
190
|
-
// edge.isOneway = Boolean((oneway === 'yes' || oneway === 'true' || oneway === '1')
|
|
191
|
-
// || (conveying && highway && ['yes', 'forward', 'backward'].includes(conveying)));
|
|
192
|
-
|
|
193
|
-
// if (conveying === 'backward') {
|
|
194
|
-
// const tmpNode = edge.node1;
|
|
195
|
-
// edge.node1 = edge.node2;
|
|
196
|
-
// edge.node2 = tmpNode;
|
|
197
|
-
// }
|
|
198
|
-
|
|
199
|
-
// }
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
/* eslint-disable max-statements */
|
|
2
|
-
import chai from 'chai';
|
|
3
|
-
import fs from 'fs';
|
|
4
|
-
import path from 'path';
|
|
5
|
-
import { fileURLToPath } from 'url';
|
|
6
|
-
|
|
7
|
-
import { Network } from '@wemap/geo';
|
|
8
|
-
import { verifyCoherence } from '@wemap/geo/tests/CommonTest.js';
|
|
9
|
-
|
|
10
|
-
import OsmParser from '../../model/OsmParser.js';
|
|
11
|
-
import OsmModel from '../../model/OsmModel.js';
|
|
12
|
-
import { createNetworkFromOsmModel, getNodeByName, getEdgeByName } from './OsmNetworkUtils.js';
|
|
13
|
-
|
|
14
|
-
const { expect } = chai;
|
|
15
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
const loadFile = fileName => {
|
|
19
|
-
const filePath = path.resolve(__dirname, '../../../assets/' + fileName);
|
|
20
|
-
return fs.readFileSync(filePath, 'utf8');
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
describe('OsmNetwork - simple', () => {
|
|
24
|
-
|
|
25
|
-
/** @type {OsmModel} */
|
|
26
|
-
let osmModel;
|
|
27
|
-
|
|
28
|
-
/** @type {Network} */
|
|
29
|
-
let network;
|
|
30
|
-
const osmXmlString = loadFile('network-simple.osm');
|
|
31
|
-
|
|
32
|
-
it('Network creation', () => {
|
|
33
|
-
|
|
34
|
-
osmModel = OsmParser.parseOsmXmlString(osmXmlString);
|
|
35
|
-
network = createNetworkFromOsmModel(osmModel);
|
|
36
|
-
|
|
37
|
-
verifyCoherence(network);
|
|
38
|
-
expect(network.nodes.length).equals(3);
|
|
39
|
-
expect(network.edges.length).equals(2);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
it('Network creation - waySelectionFilter', () => {
|
|
44
|
-
|
|
45
|
-
const selectionNetwork = createNetworkFromOsmModel(osmModel, () => true);
|
|
46
|
-
|
|
47
|
-
verifyCoherence(selectionNetwork);
|
|
48
|
-
expect(selectionNetwork.nodes.length).equals(4);
|
|
49
|
-
expect(selectionNetwork.edges.length).equals(3);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it('Network creation - elevator', () => {
|
|
53
|
-
|
|
54
|
-
const elevatorModel = OsmParser.parseOsmXmlString(loadFile('network-elevator.osm'));
|
|
55
|
-
const elevatorNetwork = createNetworkFromOsmModel(elevatorModel);
|
|
56
|
-
|
|
57
|
-
verifyCoherence(elevatorNetwork);
|
|
58
|
-
expect(elevatorNetwork.nodes.length).equals(7);
|
|
59
|
-
expect(elevatorNetwork.edges.length).equals(7);
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const osmModel2 = OsmParser.parseOsmXmlString(`
|
|
63
|
-
<osm>
|
|
64
|
-
<node id='1' lat='43' lon='4'>
|
|
65
|
-
<tag k='highway' v='elevator' />
|
|
66
|
-
<tag k='level' v='0;1' />
|
|
67
|
-
</node>
|
|
68
|
-
<node id='2' lat='43' lon='3' />
|
|
69
|
-
<way id='3'>
|
|
70
|
-
<nd ref='1' />
|
|
71
|
-
<nd ref='2' />
|
|
72
|
-
<tag k='highway' v='footway' />
|
|
73
|
-
<tag k='level' v='0;1' />
|
|
74
|
-
</way>
|
|
75
|
-
</osm>
|
|
76
|
-
`);
|
|
77
|
-
expect(() => createNetworkFromOsmModel(osmModel2)).throw(Error);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it('getNodeByName', () => {
|
|
81
|
-
let node = getNodeByName(network, 'p1');
|
|
82
|
-
expect(node).not.undefined;
|
|
83
|
-
|
|
84
|
-
node = getNodeByName(network, 'p5');
|
|
85
|
-
expect(node).is.undefined;
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
describe('OsmNetwork - with stairs', () => {
|
|
91
|
-
|
|
92
|
-
/** @type {OsmModel} */
|
|
93
|
-
let osmModel;
|
|
94
|
-
|
|
95
|
-
/** @type {Network} */
|
|
96
|
-
let network;
|
|
97
|
-
const osmXmlString = loadFile('bureaux-wemap-montpellier-network.osm');
|
|
98
|
-
|
|
99
|
-
it('Network creation', () => {
|
|
100
|
-
|
|
101
|
-
osmModel = OsmParser.parseOsmXmlString(osmXmlString);
|
|
102
|
-
network = createNetworkFromOsmModel(osmModel);
|
|
103
|
-
|
|
104
|
-
verifyCoherence(network);
|
|
105
|
-
|
|
106
|
-
expect(getEdgeByName(network, 'w6').builtFrom.tags.highway).equal('steps');
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
});
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { Coordinates, GraphItinerary, GraphRouter, Network } from '@wemap/geo';
|
|
2
|
-
|
|
3
|
-
import OsmRouterOptions from './OsmRouterOptions.js';
|
|
4
|
-
import OsmElement from '../../model/OsmElement.js';
|
|
5
|
-
|
|
6
|
-
class OsmRouter extends GraphRouter {
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* @param {!Network<OsmElement>} network
|
|
10
|
-
*/
|
|
11
|
-
constructor(network) {
|
|
12
|
-
super(network);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
/**
|
|
16
|
-
* @param {Coordinates} start
|
|
17
|
-
* @param {Coordinates} end
|
|
18
|
-
* @param {OsmRouterOptions} options
|
|
19
|
-
* @returns {GraphItinerary<OsmElement>}
|
|
20
|
-
*/
|
|
21
|
-
getShortestPath(start, end, options = new OsmRouterOptions()) {
|
|
22
|
-
return super.getShortestPath(start, end, options);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export default OsmRouter;
|
|
@@ -1,222 +0,0 @@
|
|
|
1
|
-
/* eslint-disable max-statements */
|
|
2
|
-
import chai from 'chai';
|
|
3
|
-
import chaiAlmost from 'chai-almost';
|
|
4
|
-
import fs from 'fs';
|
|
5
|
-
import path from 'path';
|
|
6
|
-
import { fileURLToPath } from 'url';
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
Level, Coordinates, GraphNode, Network, GraphItinerary
|
|
10
|
-
} from '@wemap/geo';
|
|
11
|
-
|
|
12
|
-
import OsmParser from '../../model/OsmParser.js';
|
|
13
|
-
import OsmElement from '../../model/OsmElement.js';
|
|
14
|
-
|
|
15
|
-
import OsmRouter from './OsmRouter.js';
|
|
16
|
-
import OsmRouterOptions from './OsmRouterOptions.js';
|
|
17
|
-
import StepsGeneration from './StepsGeneration.js';
|
|
18
|
-
import { createNetworkFromOsmModel, getNodeByName } from './OsmNetworkUtils.js';
|
|
19
|
-
|
|
20
|
-
import LevelChange from '../LevelChange.js';
|
|
21
|
-
|
|
22
|
-
const { expect } = chai;
|
|
23
|
-
chai.use(chaiAlmost(0.01));
|
|
24
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* @param {GraphItinerary<OsmElement>} _itinerary
|
|
29
|
-
* @returns {string[]}
|
|
30
|
-
*/
|
|
31
|
-
const getNodesNames = _itinerary => {
|
|
32
|
-
return _itinerary.nodes.map(({ builtFrom }) => builtFrom.tags.name || null);
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const itineraryStart = new Coordinates(43.6092754, 3.8842306, null, new Level(2));
|
|
37
|
-
const itineraryEnd = new Coordinates(43.6092602, 3.8842669, null, new Level(1));
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* @param {string} fileName
|
|
42
|
-
* @returns {Network}
|
|
43
|
-
*/
|
|
44
|
-
const loadNetwork = fileName => {
|
|
45
|
-
const filePath = path.resolve(__dirname, '../../../assets/' + fileName);
|
|
46
|
-
const osmXmlString = fs.readFileSync(filePath, 'utf8');
|
|
47
|
-
const osmModel = OsmParser.parseOsmXmlString(osmXmlString);
|
|
48
|
-
return createNetworkFromOsmModel(osmModel);
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
const generateNodeNames = (start, end) =>
|
|
52
|
-
new Array(end - start + 1).fill().map((_, idx) => 'p' + (idx + start));
|
|
53
|
-
|
|
54
|
-
describe('OsmRouter - Multi-level itinerary', () => {
|
|
55
|
-
|
|
56
|
-
const networkModel = loadNetwork('bureaux-wemap-montpellier-network.osm');
|
|
57
|
-
const router = new OsmRouter(networkModel);
|
|
58
|
-
|
|
59
|
-
const itinerary = router.getShortestPath(itineraryStart, itineraryEnd);
|
|
60
|
-
|
|
61
|
-
/** @type {GraphNode<OsmElement>[]} */
|
|
62
|
-
const p = [];
|
|
63
|
-
|
|
64
|
-
it('Search for nodes', () => {
|
|
65
|
-
for (let i = 1; i <= 16; i++) {
|
|
66
|
-
p[i] = getNodeByName(networkModel, 'p' + i);
|
|
67
|
-
expect(p[i]).instanceOf(GraphNode);
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
it('Router return shortest path', () => {
|
|
72
|
-
expect(getNodesNames(itinerary)).deep.equals(
|
|
73
|
-
['w2', ...generateNodeNames(7, 16)]
|
|
74
|
-
);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it('Verify steps', () => {
|
|
78
|
-
|
|
79
|
-
const steps = StepsGeneration.fromGraphItinerary(itinerary);
|
|
80
|
-
expect(steps.length).equal(8);
|
|
81
|
-
|
|
82
|
-
expect(steps[0].coords.equalsTo(itineraryStart.getSegmentProjection(p[6].coords, p[7].coords))).true;
|
|
83
|
-
expect(steps[0].name).equals('w2');
|
|
84
|
-
expect(steps[0].number).equals(1);
|
|
85
|
-
expect(steps[0].angle).almost.equals(-1.57);
|
|
86
|
-
expect(steps[0].previousBearing).almost.equals(1.778);
|
|
87
|
-
expect(steps[0].nextBearing).almost.equals(0.207);
|
|
88
|
-
expect(steps[0].distance).almost.equals(2.328);
|
|
89
|
-
expect(steps[0].duration).almost.equals(1.676);
|
|
90
|
-
expect(steps[0].firstStep).true;
|
|
91
|
-
expect(steps[0].lastStep).false;
|
|
92
|
-
expect(steps[0].levelChange).is.null;
|
|
93
|
-
expect(steps[0].extras).is.empty;
|
|
94
|
-
|
|
95
|
-
expect(steps[1].coords.equalsTo(p[8].coords)).true;
|
|
96
|
-
expect(steps[1].name).equals('w3');
|
|
97
|
-
expect(steps[1].number).equals(2);
|
|
98
|
-
expect(steps[1].distance).almost.equals(1.764);
|
|
99
|
-
expect(steps[1].firstStep).false;
|
|
100
|
-
expect(steps[1].lastStep).false;
|
|
101
|
-
|
|
102
|
-
expect(steps[2].coords.equalsTo(p[9].coords)).true;
|
|
103
|
-
expect(steps[2].name).equals('w3');
|
|
104
|
-
|
|
105
|
-
expect(steps[3].coords.equalsTo(p[10].coords)).true;
|
|
106
|
-
expect(steps[3].name).equals('w5');
|
|
107
|
-
|
|
108
|
-
expect(steps[4].coords.equalsTo(p[11].coords)).true;
|
|
109
|
-
expect(steps[4].name).equals('w6');
|
|
110
|
-
expect(steps[4].levelChange).instanceOf(LevelChange);
|
|
111
|
-
expect(steps[4].levelChange.difference).equals(-1);
|
|
112
|
-
expect(steps[4].levelChange.direction).equals('down');
|
|
113
|
-
expect(steps[4].levelChange.type).equals('stairs');
|
|
114
|
-
|
|
115
|
-
expect(steps[5].coords.equalsTo(p[14].coords)).true;
|
|
116
|
-
expect(steps[5].name).equals('w7');
|
|
117
|
-
|
|
118
|
-
expect(steps[6].coords.equalsTo(p[15].coords)).true;
|
|
119
|
-
expect(steps[6].name).equals('w9');
|
|
120
|
-
|
|
121
|
-
expect(steps[7].coords.equalsTo(p[16].coords)).true;
|
|
122
|
-
expect(steps[7].name).is.null;
|
|
123
|
-
expect(steps[7].lastStep).true;
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
it('router returns shortest path 2', () => {
|
|
128
|
-
|
|
129
|
-
const start = new Coordinates(43.609219, 3.8841743, null, new Level(2));
|
|
130
|
-
const end = new Coordinates(43.60917216742, 3.8842355275, null, new Level(2));
|
|
131
|
-
const itinerary2 = router.getShortestPath(start, end);
|
|
132
|
-
|
|
133
|
-
expect(getNodesNames(itinerary2)).deep.equals(['w1', 'p6', 'p5']);
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
it('do not use stairs', () => {
|
|
137
|
-
|
|
138
|
-
const itineraryWithoutStairs = router.getShortestPath(
|
|
139
|
-
itineraryStart, itineraryEnd,
|
|
140
|
-
OsmRouterOptions.WITHOUT_STAIRS
|
|
141
|
-
);
|
|
142
|
-
expect(itineraryWithoutStairs.nodes.length).equal(11);
|
|
143
|
-
itineraryWithoutStairs.edges.forEach((edge) => {
|
|
144
|
-
expect(edge.builtFrom.tags.highway).is.not.equal('steps');
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
// it('toCompressedJson / fromCompressedJson', () => {
|
|
149
|
-
// const json = itinerary.toCompressedJson();
|
|
150
|
-
// expect(() => JSON.stringify(json)).not.throw(Error);
|
|
151
|
-
|
|
152
|
-
// const itineraryBis = Itinerary.fromCompressedJson(json);
|
|
153
|
-
// verifyCoherence(itineraryBis);
|
|
154
|
-
// expect(itineraryBis.nodes.length).equal(11);
|
|
155
|
-
// verifyNodesOrder(itineraryBis.nodes, ['w2', ...generateNodeNames(7, 16)]);
|
|
156
|
-
// });
|
|
157
|
-
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
describe('OsmRouter - One Way itinerary', () => {
|
|
161
|
-
|
|
162
|
-
const networkModel = loadNetwork('one-way.osm');
|
|
163
|
-
const router = new OsmRouter(networkModel);
|
|
164
|
-
|
|
165
|
-
it('do not use oneway', () => {
|
|
166
|
-
|
|
167
|
-
const start = new Coordinates(43.6094542, 3.8842072);
|
|
168
|
-
const end = new Coordinates(43.6093792, 3.8841889);
|
|
169
|
-
|
|
170
|
-
const itinerary = router.getShortestPath(start, end);
|
|
171
|
-
expect(itinerary).is.not.undefined;
|
|
172
|
-
expect(getNodesNames(itinerary)).deep.equals(['p0', 'p1', 'p2', 'p3']);
|
|
173
|
-
|
|
174
|
-
const itineraryOtherWay = router.getShortestPath(end, start);
|
|
175
|
-
expect(itineraryOtherWay).is.not.undefined;
|
|
176
|
-
expect(getNodesNames(itineraryOtherWay)).deep.equals(['p3', 'p2', 'p5', 'p4', 'p1', 'p0']);
|
|
177
|
-
});
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
describe('OsmRouter - Conveying', () => {
|
|
182
|
-
|
|
183
|
-
const networkModel = loadNetwork('gare-de-lyon-extract.osm');
|
|
184
|
-
const router = new OsmRouter(networkModel);
|
|
185
|
-
|
|
186
|
-
it('do not use oneway conveying', () => {
|
|
187
|
-
|
|
188
|
-
const start = new Coordinates(48.8445715, 2.3718927, null, new Level(0));
|
|
189
|
-
const end = new Coordinates(48.84443728652394, 2.3721685669363524, null, new Level(-1));
|
|
190
|
-
|
|
191
|
-
const itinerary = router.getShortestPath(start, end);
|
|
192
|
-
expect(itinerary).is.not.undefined;
|
|
193
|
-
expect(getNodesNames(itinerary)).deep.equals(['p11', 'p12', 'p9', 'p8', 'p6', null]);
|
|
194
|
-
|
|
195
|
-
const itineraryOtherWay = router.getShortestPath(end, start);
|
|
196
|
-
expect(itineraryOtherWay).is.not.undefined;
|
|
197
|
-
expect(getNodesNames(itineraryOtherWay)).deep.equals([null, 'p6', 'p7', 'p10', 'p11']);
|
|
198
|
-
});
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
describe('OsmRouter - Conveying - backward', () => {
|
|
203
|
-
|
|
204
|
-
const networkModel = loadNetwork('network-conveying-backward.osm');
|
|
205
|
-
const router = new OsmRouter(networkModel);
|
|
206
|
-
|
|
207
|
-
it('do not use oneway conveying', () => {
|
|
208
|
-
|
|
209
|
-
const start = getNodeByName(networkModel, 'p6');
|
|
210
|
-
const end = getNodeByName(networkModel, 'p13');
|
|
211
|
-
|
|
212
|
-
const itinerary = router.getShortestPath(start, end);
|
|
213
|
-
expect(itinerary).is.not.undefined;
|
|
214
|
-
expect(getNodesNames(itinerary)).deep.equals(['p6', 'p7', 'p10', 'p11', 'p12', 'p13']);
|
|
215
|
-
|
|
216
|
-
const itineraryOtherWay = router.getShortestPath(end, start);
|
|
217
|
-
expect(itineraryOtherWay).is.not.undefined;
|
|
218
|
-
expect(getNodesNames(itineraryOtherWay)).deep.equals(['p13', 'p12', 'p9', 'p8', 'p6']);
|
|
219
|
-
});
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
|