@wemap/osm 3.2.16 → 4.0.0

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.
@@ -5,16 +5,19 @@ import path from 'path';
5
5
  import { fileURLToPath } from 'url';
6
6
 
7
7
  import {
8
- Level, Coordinates
8
+ Level, Coordinates, Edge, GraphRouter
9
9
  } from '@wemap/geo';
10
- import { Edge } from '@wemap/graph';
10
+ import { verifyCoherence } from '@wemap/geo/tests/CommonTest.js';
11
11
 
12
12
  import OsmParser from '../model/OsmParser.js';
13
- import OsmRouter from '../network/OsmRouter.js';
14
- import OsmNetwork from '../network/OsmNetwork.js';
15
- import OsrmUtils from './OsrmUtils.js';
16
- import OsmNode from '../model/OsmNode.js';
17
- import OsmWay from '../model/OsmWay.js';
13
+ import OsmNetworkUtils from '../network/OsmNetworkUtils.js';
14
+ import {
15
+ itineraryToOsrmJson,
16
+ jsonToCoordinates,
17
+ createItineraryFromJson,
18
+ getModifierFromAngle,
19
+ noRouteFoundJson
20
+ } from './OsrmUtils.js';
18
21
 
19
22
  const { expect } = chai;
20
23
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
@@ -24,8 +27,8 @@ const load = fileName => {
24
27
  const filePath = path.resolve(__dirname, '../../assets/' + fileName);
25
28
  const osmXmlString = fs.readFileSync(filePath, 'utf8');
26
29
  const model = OsmParser.parseOsmXmlString(osmXmlString);
27
- const network = OsmNetwork.fromOsmModel(model);
28
- const router = new OsmRouter(network);
30
+ const network = OsmNetworkUtils.createNetworkFromOsmModel(model);
31
+ const router = new GraphRouter(network);
29
32
  return {
30
33
  network,
31
34
  router
@@ -48,7 +51,7 @@ describe('OsrmUtils - itineraryToOsrmJson', () => {
48
51
  const itinerary = router.getShortestPath(wemapIndoorStart, wemapIndoorEnd);
49
52
  wemapIndoorItinerary = itinerary;
50
53
 
51
- const osrmJson = OsrmUtils.itineraryToOsrmJson(itinerary);
54
+ const osrmJson = itineraryToOsrmJson(itinerary);
52
55
  wemapIndoorJsonItinerary = osrmJson;
53
56
  const itinerarySteps = itinerary.steps;
54
57
 
@@ -64,7 +67,7 @@ describe('OsrmUtils - itineraryToOsrmJson', () => {
64
67
  for (let i = 1; i < 11; i++) {
65
68
  expect(
66
69
  network.getNodeByName('p' + (i + 6)).coords.equalsTo(
67
- OsrmUtils.jsonToCoordinates(coordinates[i]))
70
+ jsonToCoordinates(coordinates[i]))
68
71
  ).true;
69
72
  }
70
73
 
@@ -76,7 +79,7 @@ describe('OsrmUtils - itineraryToOsrmJson', () => {
76
79
  const {
77
80
  location, type
78
81
  } = steps[i].maneuver;
79
- expect(itinerarySteps[i].node.coords.equalsTo(OsrmUtils.jsonToCoordinates(location))).true;
82
+ expect(itinerarySteps[i].node.coords.equalsTo(jsonToCoordinates(location))).true;
80
83
 
81
84
  let expectedType;
82
85
  switch (i) {
@@ -141,7 +144,7 @@ describe('OsrmUtils - itineraryToOsrmJson', () => {
141
144
 
142
145
  const itinerary = router.getShortestPath(start, end);
143
146
 
144
- wemapOutdoorJsonItinerary = OsrmUtils.itineraryToOsrmJson(itinerary);
147
+ wemapOutdoorJsonItinerary = itineraryToOsrmJson(itinerary);
145
148
 
146
149
  wemapOutdoorStart = start.coords;
147
150
  wemapOutdoorEnd = end.coords;
@@ -158,7 +161,7 @@ describe('OsrmUtils - itineraryToOsrmJson', () => {
158
161
  const end = network.getNodeByName('end');
159
162
 
160
163
  const itinerary = router.getShortestPath(start, end);
161
- expect(() => OsrmUtils.itineraryToOsrmJson(itinerary)).not.throw(Error);
164
+ expect(() => itineraryToOsrmJson(itinerary)).not.throw(Error);
162
165
 
163
166
  });
164
167
 
@@ -178,7 +181,7 @@ describe('OsrmUtils - createItineraryFromJson', () => {
178
181
  const start = new Coordinates(43.6007871, 3.8757218000000004);
179
182
  const end = new Coordinates(43.598877, 3.873866);
180
183
 
181
- const itinerary = OsrmUtils.createItineraryFromJson(json, start, end);
184
+ const itinerary = createItineraryFromJson(json, start, end);
182
185
 
183
186
  expect(json.routes[0].geometry.coordinates.length).equal(itinerary.nodes.length);
184
187
  expect(itinerary.nodes.length).equal(itinerary.edges.length + 1);
@@ -190,7 +193,7 @@ describe('OsrmUtils - createItineraryFromJson', () => {
190
193
  let step;
191
194
  step = steps[0];
192
195
  expect(Coordinates.equalsTo(step.location, new Coordinates(43.600777, 3.875607))).true;
193
- expect(OsrmUtils.getModifierFromAngle(step.angle)).equals('left');
196
+ expect(getModifierFromAngle(step.angle)).equals('left');
194
197
  expect(step.nodes.length).equals(6);
195
198
  expect(step.edges.length).equals(5);
196
199
  expect(step.firstStep).true;
@@ -199,7 +202,7 @@ describe('OsrmUtils - createItineraryFromJson', () => {
199
202
 
200
203
  step = steps[1];
201
204
  expect(Coordinates.equalsTo(step.location, new Coordinates(43.599881, 3.876396))).true;
202
- expect(OsrmUtils.getModifierFromAngle(step.angle)).equals('right');
205
+ expect(getModifierFromAngle(step.angle)).equals('right');
203
206
  expect(step.nodes.length).equals(12);
204
207
  expect(step.edges.length).equals(11);
205
208
  expect(step.firstStep).false;
@@ -208,7 +211,7 @@ describe('OsrmUtils - createItineraryFromJson', () => {
208
211
 
209
212
  step = steps[2];
210
213
  expect(Coordinates.equalsTo(step.location, new Coordinates(43.599577, 3.874655))).true;
211
- expect(OsrmUtils.getModifierFromAngle(step.angle)).equals('left');
214
+ expect(getModifierFromAngle(step.angle)).equals('left');
212
215
  expect(step.nodes.length).equals(2);
213
216
  expect(step.edges.length).equals(1);
214
217
  expect(step.firstStep).false;
@@ -217,7 +220,7 @@ describe('OsrmUtils - createItineraryFromJson', () => {
217
220
 
218
221
  step = steps[3];
219
222
  expect(Coordinates.equalsTo(step.location, new Coordinates(43.599063, 3.874623))).true;
220
- expect(OsrmUtils.getModifierFromAngle(step.angle)).equals('right');
223
+ expect(getModifierFromAngle(step.angle)).equals('right');
221
224
  expect(step.nodes.length).equals(2);
222
225
  expect(step.edges.length).equals(1);
223
226
  expect(step.firstStep).false;
@@ -226,7 +229,7 @@ describe('OsrmUtils - createItineraryFromJson', () => {
226
229
 
227
230
  step = steps[4];
228
231
  expect(Coordinates.equalsTo(step.location, new Coordinates(43.59906, 3.873865))).true;
229
- expect(OsrmUtils.getModifierFromAngle(step.angle)).equals('left');
232
+ expect(getModifierFromAngle(step.angle)).equals('left');
230
233
  expect(step.nodes.length).equals(1);
231
234
  expect(step.edges.length).equals(0);
232
235
  expect(step.firstStep).false;
@@ -248,7 +251,7 @@ describe('OsrmUtils - createItineraryFromJson', () => {
248
251
 
249
252
  it('Without levels (from itineraryToOsrmJson)', () => {
250
253
 
251
- const itinerary = OsrmUtils.createItineraryFromJson(wemapOutdoorJsonItinerary,
254
+ const itinerary = createItineraryFromJson(wemapOutdoorJsonItinerary,
252
255
  wemapOutdoorStart, wemapOutdoorEnd);
253
256
 
254
257
  expect(itinerary.nodes.length).equal(wemapOutdoorItinerary.nodes.length);
@@ -282,7 +285,7 @@ describe('OsrmUtils - createItineraryFromJson', () => {
282
285
  const start = new Coordinates(43.6007871, 3.8757218000000004);
283
286
  const end = new Coordinates(43.598877, 3.873866);
284
287
 
285
- const itinerary = OsrmUtils.createItineraryFromJson(json, start, end);
288
+ const itinerary = createItineraryFromJson(json, start, end);
286
289
 
287
290
  expect(json.routes[0].geometry.coordinates.length).equal(itinerary.nodes.length);
288
291
  expect(itinerary.nodes.length).equal(itinerary.edges.length + 1);
@@ -295,7 +298,7 @@ describe('OsrmUtils - createItineraryFromJson', () => {
295
298
 
296
299
  it('With levels (from itineraryToOsrmJson)', () => {
297
300
 
298
- const itinerary = OsrmUtils.createItineraryFromJson(wemapIndoorJsonItinerary,
301
+ const itinerary = createItineraryFromJson(wemapIndoorJsonItinerary,
299
302
  wemapIndoorStart, wemapIndoorEnd);
300
303
 
301
304
  expect(itinerary.nodes.length).equal(wemapIndoorItinerary.nodes.length);
@@ -329,7 +332,7 @@ describe('OsrmUtils - createItineraryFromJson', () => {
329
332
  const start = new Coordinates(44.810569099999995, 4.9503924999999995);
330
333
  const end = new Coordinates(44.302673, 4.556377);
331
334
 
332
- const itinerary = OsrmUtils.createItineraryFromJson(json, start, end);
335
+ const itinerary = createItineraryFromJson(json, start, end);
333
336
  itinerary.edges.forEach(edge => {
334
337
  expect(edge).instanceOf(Edge);
335
338
  });
@@ -352,22 +355,34 @@ describe('OsrmUtils - itineraryToOsrmJson - createItineraryFromJson - way/node',
352
355
  const end = new Coordinates(43.60949854, 3.88452048, null, new Level(0));
353
356
  const itinerary = router.getShortestPath(start, end);
354
357
 
355
- const osrmJson = OsrmUtils.itineraryToOsrmJson(itinerary);
358
+ const osrmJson = itineraryToOsrmJson(itinerary);
356
359
  const jsonSteps = osrmJson.routes[0].legs[0].steps;
357
360
 
358
- expect(jsonSteps[0].wemap.nextEdgeData.type).equals('way');
359
- expect(jsonSteps[4].wemap.nextEdgeData.type).equals('node');
361
+ expect(jsonSteps[0].wemap.nextEdgeProperties.name).equals('w2');
362
+ expect(jsonSteps[0].wemap.nextEdgeProperties.level).equals('2');
363
+ expect(jsonSteps[0].wemap.nodeProperties.name).equals('w2');
364
+
365
+ expect(jsonSteps[4].wemap.nextEdgeProperties.name).equals('p19');
366
+ expect(jsonSteps[4].wemap.nextEdgeProperties.level).equals('0;2');
367
+ expect(jsonSteps[4].wemap.nodeProperties.name).equals('p19');
368
+
369
+ expect(jsonSteps[6].name).equals('p21');
370
+ expect(jsonSteps[6].wemap.nextEdgeProperties).is.undefined;
371
+ expect(jsonSteps[6].wemap.nodeProperties.name).equals('p21');
372
+
373
+ const itineraryBis = createItineraryFromJson(osrmJson, start, end);
374
+ verifyCoherence(itineraryBis);
360
375
 
361
- const itineraryBis = OsrmUtils.createItineraryFromJson(osrmJson, start, end);
362
- expect(itineraryBis.steps[4].edges[0].data).instanceOf(OsmNode);
363
- expect(itineraryBis.steps[0].edges[0].data).instanceOf(OsmWay);
376
+ expect(itineraryBis.nodes.length).equals(itinerary.nodes.length);
377
+ expect(itineraryBis.edges.length).equals(itinerary.edges.length);
378
+ expect(itineraryBis.steps.length).equals(itinerary.steps.length);
364
379
  });
365
380
  });
366
381
 
367
382
  describe('OsrmUtils - Output JSON', () => {
368
383
 
369
384
  it('noRouteFoundJson', () => {
370
- expect(OsrmUtils.noRouteFoundJson('foo')).deep.equals({
385
+ expect(noRouteFoundJson('foo')).deep.equals({
371
386
  'code': 'NoRoute',
372
387
  'message': 'foo'
373
388
  });
@@ -1,156 +0,0 @@
1
- import { Level } from '@wemap/geo';
2
- import {
3
- Edge, Node, Network
4
- } from '@wemap/graph';
5
-
6
- import OsmModel from '../model/OsmModel.js';
7
-
8
- const HIGHWAYS_PEDESTRIANS = ['footway', 'steps', 'pedestrian', 'living_street', 'path', 'track', 'sidewalk'];
9
- const DEFAULT_WAY_SELECTOR = way => HIGHWAYS_PEDESTRIANS.includes(way.tags.highway) || way.tags.footway === 'sidewalk';
10
-
11
- /**
12
- * A typical network with nodes (Node) and edges (Edge)
13
- */
14
- class OsmNetwork extends Network {
15
-
16
- /**
17
- * @param {OsmModel} osmModel
18
- * @param {function} _waySelectionFilter
19
- * @returns {OsmNetwork}
20
- */
21
- static fromOsmModel(osmModel, _waySelectionFilter) {
22
-
23
- const waySelectionFilter = _waySelectionFilter || DEFAULT_WAY_SELECTOR;
24
-
25
- const networkModel = new OsmNetwork();
26
-
27
- const getOrCreateNode = osmNode => {
28
- let node = networkModel.nodes.find(graphNode => osmNode.id === graphNode.data.id);
29
- if (!node) {
30
- node = new Node(osmNode.coords, osmNode);
31
- networkModel.nodes.push(node);
32
- }
33
- return node;
34
- };
35
-
36
- osmModel.ways.forEach(way => {
37
- if (!waySelectionFilter(way)) {
38
- return;
39
- }
40
-
41
- let firstNode = getOrCreateNode(way.nodes[0]);
42
- for (let i = 1; i < way.nodes.length; i++) {
43
- const secondNode = getOrCreateNode(way.nodes[i]);
44
-
45
- const edge = new Edge(firstNode, secondNode);
46
- edge.data = way;
47
- edge.level = way.level;
48
- networkModel.edges.push(edge);
49
-
50
- firstNode = secondNode;
51
- }
52
-
53
- });
54
-
55
- networkModel.nodes.forEach(node => {
56
- if (node.data.tags.highway === 'elevator') {
57
- // We have to clone this node for each connected edge
58
- OsmNetwork._createNodesAndEdgesFromElevator(networkModel, node);
59
- }
60
- });
61
-
62
- Node.generateNodesLevels(networkModel.nodes);
63
-
64
- return networkModel;
65
- }
66
-
67
- static _createNodesAndEdgesFromElevator(networkModel, node) {
68
-
69
- const createdNodes = [];
70
- const isLevelAlreadyCreated = level => createdNodes.some(
71
- createdNode => Level.equalsTo(level, createdNode.coords.level)
72
- );
73
-
74
- // Create nodes from node.edges
75
- node.edges.forEach(edge => {
76
- if (edge.level.isRange) {
77
- throw new Error('Cannot handle this elevator edge due to ambiguity');
78
- }
79
-
80
- if (isLevelAlreadyCreated(edge.level)) {
81
- return;
82
- }
83
-
84
- const newNode = node.clone();
85
- newNode.coords = node.coords.clone();
86
- newNode.coords.level = edge.level.clone();
87
-
88
- const otherNode = edge.node1 === node ? edge.node2 : edge.node1;
89
- otherNode.edges = otherNode.edges.filter(_edge => _edge !== edge);
90
- const modifiedEdge = new Edge(newNode, otherNode, edge.data, edge.level);
91
- networkModel.edges.push(modifiedEdge);
92
-
93
- createdNodes.push(newNode);
94
- networkModel.nodes.push(newNode);
95
- });
96
-
97
- // Create edges from createdNodes
98
- for (let i = 0; i < createdNodes.length; i++) {
99
- for (let j = i + 1; j < createdNodes.length; j++) {
100
-
101
- const createdNode1 = createdNodes[i];
102
- const createdNode2 = createdNodes[j];
103
-
104
- const newEdge = new Edge(
105
- createdNode1,
106
- createdNode2,
107
- createdNode1.data,
108
- new Level(createdNode1.coords.level.val, createdNode2.coords.level.val)
109
- );
110
- networkModel.edges.push(newEdge);
111
- }
112
- }
113
-
114
- networkModel.nodes = networkModel.nodes.filter(_node => _node !== node);
115
- networkModel.edges = networkModel.edges.filter(edge =>
116
- !node.edges.some(_edge => _edge === edge)
117
- );
118
- }
119
-
120
- /**
121
- * @param {number} id
122
- * @returns {Node}
123
- */
124
- getNodeById(id) {
125
- return this.nodes.find(node => node.data.id === id);
126
- }
127
-
128
- /**
129
- * @param {name} name
130
- * @returns {Node}
131
- */
132
- getNodeByName(name) {
133
- return this.nodes.find(node => node.data.tags.name === name);
134
- }
135
-
136
- /**
137
- * @param {number} id
138
- * @returns {Edge[]}
139
- */
140
- getEdgesById(id) {
141
- return this.edges.filter(edge => edge.data.id === id);
142
- }
143
-
144
- /**
145
- * @returns {string}
146
- */
147
- toDetailedString() {
148
- return super.toDetailedString(
149
- node => node.data.tags.name,
150
- edge => edge.data.id
151
- );
152
- }
153
-
154
- }
155
-
156
- export default OsmNetwork;
@@ -1,107 +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 OsmParser from '../model/OsmParser.js';
8
- import OsmNetwork from './OsmNetwork.js';
9
-
10
- const { expect } = chai;
11
- const __dirname = path.dirname(fileURLToPath(import.meta.url));
12
-
13
-
14
- const loadFile = fileName => {
15
- const filePath = path.resolve(__dirname, '../../assets/' + fileName);
16
- return fs.readFileSync(filePath, 'utf8');
17
- };
18
-
19
- describe('OsmNetwork - simple', () => {
20
-
21
- let osmModel, osmNetwork;
22
- const osmXmlString = loadFile('network-simple.osm');
23
-
24
- it('Network creation', () => {
25
-
26
- osmModel = OsmParser.parseOsmXmlString(osmXmlString);
27
- osmNetwork = OsmNetwork.fromOsmModel(osmModel);
28
-
29
- expect(osmNetwork.nodes.length).equals(3);
30
- expect(osmNetwork.edges.length).equals(2);
31
- });
32
-
33
-
34
- it('Network creation - waySelectionFilter', () => {
35
-
36
- const selectionNetwork = OsmNetwork.fromOsmModel(osmModel, () => true);
37
-
38
- expect(selectionNetwork.nodes.length).equals(4);
39
- expect(selectionNetwork.edges.length).equals(3);
40
- });
41
-
42
- it('Network creation - elevator', () => {
43
-
44
- const elevatorModel = OsmParser.parseOsmXmlString(loadFile('network-elevator.osm'));
45
- const elevatorNetwork = OsmNetwork.fromOsmModel(elevatorModel);
46
-
47
- expect(elevatorNetwork.nodes.length).equals(7);
48
- expect(elevatorNetwork.edges.length).equals(6);
49
-
50
-
51
- const osmModel2 = OsmParser.parseOsmXmlString(`
52
- <osm>
53
- <node id='1' lat='43' lon='4'>
54
- <tag k='highway' v='elevator' />
55
- <tag k='level' v='0;1' />
56
- </node>
57
- <node id='2' lat='43' lon='3' />
58
- <way id='3'>
59
- <nd ref='1' />
60
- <nd ref='2' />
61
- <tag k='highway' v='footway' />
62
- <tag k='level' v='0;1' />
63
- </way>
64
- </osm>
65
- `);
66
- expect(() => OsmNetwork.fromOsmModel(osmModel2)).throw(Error);
67
- });
68
-
69
-
70
- it('getNodeById', () => {
71
- let node = osmNetwork.getNodeById(1);
72
- expect(node).not.null;
73
- expect(node.data.tags.name).equals('p1');
74
-
75
- node = osmNetwork.getNodeById(5);
76
- expect(node).undefined;
77
- });
78
-
79
-
80
- it('getNodeByName', () => {
81
- let node = osmNetwork.getNodeByName('p1');
82
- expect(node).not.undefined;
83
-
84
- node = osmNetwork.getNodeByName('p5');
85
- expect(node).undefined;
86
- });
87
-
88
- it('getEdgesById', () => {
89
- let edges = osmNetwork.getEdgesById(101);
90
- expect(edges.length).equals(2);
91
- expect(edges[0].data.tags.name).equals('w1');
92
- expect(edges[0].node1.data.tags.name).equals('p1');
93
- expect(edges[0].node2.data.tags.name).equals('p2');
94
- expect(edges[1].data.tags.name).equals('w1');
95
- expect(edges[1].node1.data.tags.name).equals('p2');
96
- expect(edges[1].node2.data.tags.name).equals('p3');
97
-
98
- edges = osmNetwork.getEdgesById(3);
99
- expect(edges.length).equals(0);
100
- });
101
-
102
- it('toDetailedString', () => {
103
- expect(() => osmNetwork.toDetailedString()).not.throw(Error);
104
- });
105
- });
106
-
107
-
@@ -1,75 +0,0 @@
1
- import { Coordinates } from '@wemap/geo';
2
- import {
3
- Edge, GraphRouter, Node, Utils
4
- } from '@wemap/graph';
5
-
6
- const DEFAULT_OPTIONS = { useStairs: true };
7
-
8
- class OsmRouter extends GraphRouter {
9
-
10
- /**
11
- * @param {Node|Coordinates} start
12
- * @param {Node|Coordinates} end
13
- * @param {object} _options
14
- */
15
- getShortestPath(start, end, _options) {
16
-
17
- const options = Object.assign({}, DEFAULT_OPTIONS, _options);
18
-
19
- return super.getShortestPath(
20
- start, end,
21
- options.useStairs ? null : OsmRouter.edgeSelectionFilter,
22
- OsmRouter.edgeWeightFn,
23
- OsmRouter.acceptOneWayFn
24
- );
25
- }
26
-
27
- /**
28
- * @param {Edge} edge
29
- * @returns {boolean}
30
- */
31
- static edgeSelectionFilter = edge => {
32
- return !edge.data || !edge.data.tags
33
- || (
34
- edge.data.tags.stairs !== 'yes'
35
- && edge.data.tags.highway !== 'steps'
36
- );
37
- }
38
-
39
- /**
40
- * @param {Edge} edge
41
- * @returns {boolean}
42
- */
43
- static edgeWeightFn = edge => {
44
- if (edge.data.tags.highway === 'elevator') {
45
- return 30;
46
- }
47
- return Utils.getDurationFromLength(edge.length);
48
- };
49
-
50
- /**
51
- * @param {Edge} edge
52
- * @param {boolean} reversed
53
- * @returns {boolean}
54
- */
55
- static acceptOneWayFn = (edge, reversed) => {
56
- const {
57
- oneway, highway, conveying
58
- } = edge.data.tags;
59
- if (reversed && (oneway === 'yes' || oneway === 'true' || oneway === '1')) {
60
- return false;
61
- }
62
- if (conveying && highway) {
63
- if (conveying === 'forward' && reversed) {
64
- return false;
65
- } if (conveying === 'backward' && !reversed) {
66
- return false;
67
- } if (conveying === 'yes' && reversed) {
68
- return false;
69
- }
70
- }
71
- return true;
72
- };
73
- }
74
-
75
- export default OsmRouter;