@wemap/osm 2.7.6 → 2.7.7
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/assets/itinerary-montpellier-outdoor-errored.json +1 -0
- package/assets/itinerary-montpellier-outdoor-without-steps.json +1 -0
- package/assets/network-conveying-backward.osm +74 -0
- package/assets/network-elevator.osm +48 -0
- package/assets/network-simple.osm +27 -0
- package/assets/network-with-modifiers.osm +39 -0
- package/assets/simple.osm +31 -0
- package/package.json +5 -5
- package/src/model/OsmElement.js +5 -2
- package/src/model/OsmElement.spec.js +11 -0
- package/src/model/OsmModel.js +11 -9
- package/src/model/OsmModel.spec.js +57 -0
- package/src/model/OsmNode.js +5 -13
- package/src/model/OsmNode.spec.js +14 -0
- package/src/model/OsmParser.js +18 -6
- package/src/model/OsmParser.spec.js +49 -0
- package/src/model/OsmWay.js +4 -8
- package/src/network/OsmNetwork.js +7 -8
- package/src/network/OsmNetwork.spec.js +103 -0
- package/src/network/OsmRouter.js +13 -15
- package/src/network/OsmRouter.spec.js +34 -19
- package/src/osrm/OsrmUtils.js +61 -61
- package/src/osrm/OsrmUtils.spec.js +184 -97
- /package/assets/{itinerary-osrm.json → itinerary-montpellier-outdoor.json} +0 -0
|
@@ -12,16 +12,153 @@ import OsmRouter from '../network/OsmRouter';
|
|
|
12
12
|
import OsmNetwork from '../network/OsmNetwork';
|
|
13
13
|
import OsrmUtils from './OsrmUtils';
|
|
14
14
|
|
|
15
|
-
import {
|
|
16
|
-
itineraryStart, itineraryEnd
|
|
17
|
-
} from '../../../graph/tests/CommonTest';
|
|
18
15
|
|
|
19
|
-
|
|
16
|
+
const load = fileName => {
|
|
17
|
+
const filePath = path.resolve(__dirname, '../../assets/' + fileName);
|
|
18
|
+
const osmXmlString = fs.readFileSync(filePath, 'utf8');
|
|
19
|
+
const model = OsmParser.parseOsmXmlString(osmXmlString);
|
|
20
|
+
const network = OsmNetwork.fromOsmModel(model);
|
|
21
|
+
const router = new OsmRouter(network);
|
|
22
|
+
return {
|
|
23
|
+
network,
|
|
24
|
+
router
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
let wemapItinerary, wemapJsonItinerary, wemapStart, wemapEnd;
|
|
29
|
+
|
|
30
|
+
describe('OsrmUtils - itineraryToOsrmJson', () => {
|
|
31
|
+
|
|
32
|
+
it('With levels (Bureaux Wemap)', () => {
|
|
33
|
+
|
|
34
|
+
const {
|
|
35
|
+
network, router
|
|
36
|
+
} = load('bureaux-wemap-montpellier-network.osm');
|
|
37
|
+
|
|
38
|
+
wemapStart = new WGS84(43.6092754, 3.8842306, null, new Level(2));
|
|
39
|
+
wemapEnd = new WGS84(43.6092602, 3.8842669, null, new Level(1));
|
|
40
|
+
const itinerary = router.getShortestPath(wemapStart, wemapEnd);
|
|
41
|
+
wemapItinerary = itinerary;
|
|
42
|
+
|
|
43
|
+
const osrmJson = OsrmUtils.itineraryToOsrmJson(itinerary);
|
|
44
|
+
wemapJsonItinerary = osrmJson;
|
|
45
|
+
const itinerarySteps = itinerary.steps;
|
|
46
|
+
|
|
47
|
+
const {
|
|
48
|
+
geometry, legs
|
|
49
|
+
} = osrmJson.routes[0];
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Verify if JSON geometry corresponds to Itinerary points
|
|
53
|
+
*/
|
|
54
|
+
const { coordinates } = geometry;
|
|
55
|
+
expect(coordinates.length).equal(11);
|
|
56
|
+
for (let i = 1; i < 11; i++) {
|
|
57
|
+
expect(
|
|
58
|
+
network.getNodeByName('p' + (i + 6)).coords.equalsTo(
|
|
59
|
+
OsrmUtils.jsonToWgs84(coordinates[i]))
|
|
60
|
+
).true;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Verify location, type and modifier of each step
|
|
65
|
+
*/
|
|
66
|
+
const { steps } = legs[0];
|
|
67
|
+
for (let i = 0; i < steps.length; i++) {
|
|
68
|
+
const {
|
|
69
|
+
location, type
|
|
70
|
+
} = steps[i].maneuver;
|
|
71
|
+
expect(itinerarySteps[i].node.coords.equalsTo(OsrmUtils.jsonToWgs84(location))).true;
|
|
72
|
+
|
|
73
|
+
let expectedType;
|
|
74
|
+
switch (i) {
|
|
75
|
+
case 0:
|
|
76
|
+
expectedType = 'depart';
|
|
77
|
+
break;
|
|
78
|
+
case steps.length - 1:
|
|
79
|
+
expectedType = 'arrive';
|
|
80
|
+
break;
|
|
81
|
+
default:
|
|
82
|
+
expectedType = 'turn';
|
|
83
|
+
}
|
|
84
|
+
expect(type).equals(expectedType);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// The first modifier is not mandatory by OSRM.
|
|
88
|
+
expect(steps[0].maneuver.modifier).equals('left');
|
|
89
|
+
expect(steps[0].distance).be.closeTo(2.33, 0.01);
|
|
90
|
+
expect(steps[0].maneuver.bearing_after).be.closeTo(11.90, 0.01);
|
|
91
|
+
|
|
92
|
+
expect(steps[1].maneuver.modifier).equals('right');
|
|
93
|
+
expect(steps[1].distance).be.closeTo(1.76, 0.01);
|
|
94
|
+
expect(steps[1].maneuver.bearing_after).be.closeTo(56.90, 0.01);
|
|
95
|
+
|
|
96
|
+
expect(steps[2].maneuver.modifier).equals('left');
|
|
97
|
+
expect(steps[2].distance).be.closeTo(1.15, 0.01);
|
|
98
|
+
expect(steps[2].maneuver.bearing_after).be.closeTo(11.90, 0.01);
|
|
99
|
+
|
|
100
|
+
expect(steps[3].maneuver.modifier).equals('left');
|
|
101
|
+
expect(steps[3].distance).be.closeTo(5.95, 0.01);
|
|
102
|
+
expect(steps[3].maneuver.bearing_after).be.closeTo(281.93, 0.01);
|
|
103
|
+
|
|
104
|
+
expect(steps[4].maneuver.modifier).equals('right');
|
|
105
|
+
expect(steps[4].distance).be.closeTo(10.71, 0.01);
|
|
106
|
+
expect(steps[4].maneuver.bearing_after).be.closeTo(12.22, 0.01);
|
|
107
|
+
expect(steps[4].levelChange).is.not.null;
|
|
108
|
+
expect(steps[4].levelChange.direction).equals('down');
|
|
109
|
+
expect(steps[4].levelChange.diff).equals(-1);
|
|
110
|
+
|
|
111
|
+
expect(steps[5].maneuver.modifier).equals('left');
|
|
112
|
+
expect(steps[5].distance).be.closeTo(4.23, 0.01);
|
|
113
|
+
expect(steps[5].maneuver.bearing_after).be.closeTo(102.00, 0.01);
|
|
114
|
+
|
|
115
|
+
expect(steps[6].maneuver.modifier).equals('right');
|
|
116
|
+
expect(steps[6].distance).be.closeTo(5.03, 0.01);
|
|
117
|
+
expect(steps[6].maneuver.bearing_after).be.closeTo(191.75, 0.01);
|
|
118
|
+
|
|
119
|
+
expect(steps[7].maneuver.modifier).equals('left');
|
|
120
|
+
expect(steps[7].distance).be.closeTo(0, 0.01);
|
|
121
|
+
expect(steps[7].maneuver.bearing_after).be.closeTo(0, 0.01);
|
|
122
|
+
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
it('Without levels', () => {
|
|
126
|
+
|
|
127
|
+
const {
|
|
128
|
+
network, router
|
|
129
|
+
} = load('network-simple.osm');
|
|
130
|
+
|
|
131
|
+
const start = network.getNodeByName('p1');
|
|
132
|
+
const end = network.getNodeByName('p3');
|
|
133
|
+
|
|
134
|
+
const itinerary = router.getShortestPath(start, end);
|
|
135
|
+
expect(() => OsrmUtils.itineraryToOsrmJson(itinerary)).not.throw(Error);
|
|
136
|
+
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it('Itinerary with modifiers', () => {
|
|
140
|
+
|
|
141
|
+
const {
|
|
142
|
+
network, router
|
|
143
|
+
} = load('network-with-modifiers.osm');
|
|
144
|
+
|
|
145
|
+
const start = network.getNodeByName('start');
|
|
146
|
+
const end = network.getNodeByName('end');
|
|
147
|
+
|
|
148
|
+
const itinerary = router.getShortestPath(start, end);
|
|
149
|
+
expect(() => OsrmUtils.itineraryToOsrmJson(itinerary)).not.throw(Error);
|
|
150
|
+
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
});
|
|
154
|
+
|
|
20
155
|
|
|
156
|
+
describe('OsrmUtils - createItineraryFromJson', () => {
|
|
21
157
|
|
|
22
|
-
it('OSRM JSON to Itinerary', () => {
|
|
23
158
|
|
|
24
|
-
|
|
159
|
+
it('Without levels (Montpellier outdoor)', () => {
|
|
160
|
+
|
|
161
|
+
const filePath = path.resolve(__dirname, '../../assets/itinerary-montpellier-outdoor.json');
|
|
25
162
|
const fileString = fs.readFileSync(filePath, 'utf8');
|
|
26
163
|
|
|
27
164
|
const json = JSON.parse(fileString);
|
|
@@ -96,108 +233,33 @@ describe('OsrmUtils', () => {
|
|
|
96
233
|
expect(itinerary._nextStepsIndexes[18]).equals(4);
|
|
97
234
|
});
|
|
98
235
|
|
|
99
|
-
let osrmWemapJson, wemapItinerary;
|
|
100
|
-
it('Itinerary to OSRM JSON', () => {
|
|
101
|
-
|
|
102
|
-
const filePath = path.resolve(__dirname, '../../assets/bureaux-wemap-montpellier-network.osm');
|
|
103
|
-
const osmXmlString = fs.readFileSync(filePath, 'utf8');
|
|
104
|
-
|
|
105
|
-
const osmModel = OsmParser.parseOsmXmlString(osmXmlString);
|
|
106
|
-
const networkModel = OsmNetwork.fromOsmModel(osmModel);
|
|
107
|
-
const router = new OsmRouter(networkModel);
|
|
108
|
-
|
|
109
|
-
wemapItinerary = router.getShortestPath(itineraryStart, itineraryEnd);
|
|
110
|
-
|
|
111
|
-
osrmWemapJson = OsrmUtils.itineraryToOsrmJson(wemapItinerary);
|
|
112
|
-
const itinerarySteps = wemapItinerary.steps;
|
|
113
|
-
|
|
114
|
-
const {
|
|
115
|
-
geometry, legs
|
|
116
|
-
} = osrmWemapJson.routes[0];
|
|
117
|
-
|
|
118
|
-
const p = [];
|
|
119
|
-
for (let i = 1; i <= 16; i++) {
|
|
120
|
-
p[i] = networkModel.getNodeByName('p' + i);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Verify if JSON geometry corresponds to Itinerary points
|
|
126
|
-
*/
|
|
127
|
-
const { coordinates } = geometry;
|
|
128
|
-
expect(coordinates.length).equal(11);
|
|
129
|
-
for (let i = 1; i < 11; i++) {
|
|
130
|
-
expect(p[i + 6].coords.equalsTo(OsrmUtils.jsonToWgs84(coordinates[i]))).true;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Verify location, type and modifier of each step
|
|
135
|
-
*/
|
|
136
|
-
const { steps } = legs[0];
|
|
137
|
-
for (let i = 0; i < steps.length; i++) {
|
|
138
|
-
const {
|
|
139
|
-
location, type
|
|
140
|
-
} = steps[i].maneuver;
|
|
141
|
-
expect(itinerarySteps[i].node.coords.equalsTo(OsrmUtils.jsonToWgs84(location))).true;
|
|
142
|
-
|
|
143
|
-
let expectedType;
|
|
144
|
-
switch (i) {
|
|
145
|
-
case 0:
|
|
146
|
-
expectedType = 'depart';
|
|
147
|
-
break;
|
|
148
|
-
case steps.length - 1:
|
|
149
|
-
expectedType = 'arrive';
|
|
150
|
-
break;
|
|
151
|
-
default:
|
|
152
|
-
expectedType = 'turn';
|
|
153
|
-
}
|
|
154
|
-
expect(type).equals(expectedType);
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
// The first modifier is not mandatory by OSRM.
|
|
158
|
-
expect(steps[0].maneuver.modifier).equals('left');
|
|
159
|
-
expect(steps[0].distance).be.closeTo(2.33, 0.01);
|
|
160
|
-
expect(steps[0].maneuver.bearing_after).be.closeTo(11.90, 0.01);
|
|
161
|
-
|
|
162
|
-
expect(steps[1].maneuver.modifier).equals('right');
|
|
163
|
-
expect(steps[1].distance).be.closeTo(1.76, 0.01);
|
|
164
|
-
expect(steps[1].maneuver.bearing_after).be.closeTo(56.90, 0.01);
|
|
165
236
|
|
|
166
|
-
|
|
167
|
-
expect(steps[2].distance).be.closeTo(1.15, 0.01);
|
|
168
|
-
expect(steps[2].maneuver.bearing_after).be.closeTo(11.90, 0.01);
|
|
237
|
+
it('Without steps (Montpellier outdoor)', () => {
|
|
169
238
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
239
|
+
const filePath = path.resolve(__dirname,
|
|
240
|
+
'../../assets/itinerary-montpellier-outdoor-without-steps.json');
|
|
241
|
+
const fileString = fs.readFileSync(filePath, 'utf8');
|
|
173
242
|
|
|
174
|
-
|
|
175
|
-
expect(steps[4].distance).be.closeTo(10.71, 0.01);
|
|
176
|
-
expect(steps[4].maneuver.bearing_after).be.closeTo(12.22, 0.01);
|
|
177
|
-
expect(steps[4].levelChange).is.not.null;
|
|
178
|
-
expect(steps[4].levelChange.direction).equals('down');
|
|
179
|
-
expect(steps[4].levelChange.diff).equals(-1);
|
|
243
|
+
const json = JSON.parse(fileString);
|
|
180
244
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
expect(steps[5].maneuver.bearing_after).be.closeTo(102.00, 0.01);
|
|
245
|
+
const start = new WGS84(43.6007871, 3.8757218000000004);
|
|
246
|
+
const end = new WGS84(43.598877, 3.873866);
|
|
184
247
|
|
|
185
|
-
|
|
186
|
-
expect(steps[6].distance).be.closeTo(5.03, 0.01);
|
|
187
|
-
expect(steps[6].maneuver.bearing_after).be.closeTo(191.75, 0.01);
|
|
248
|
+
const itinerary = OsrmUtils.createItineraryFromJson(json, start, end);
|
|
188
249
|
|
|
189
|
-
expect(
|
|
190
|
-
expect(
|
|
191
|
-
expect(
|
|
250
|
+
expect(json.routes[0].geometry.coordinates.length).equal(itinerary.nodes.length);
|
|
251
|
+
expect(itinerary.nodes.length).equal(itinerary.edges.length + 1);
|
|
252
|
+
expect(itinerary.nodes.length).equal(19);
|
|
192
253
|
|
|
254
|
+
const { steps } = itinerary;
|
|
255
|
+
expect(steps.length).equal(7);
|
|
193
256
|
});
|
|
194
257
|
|
|
195
258
|
|
|
196
|
-
it('
|
|
197
|
-
|
|
198
|
-
const json = osrmWemapJson;
|
|
259
|
+
it('With levels (from itineraryToOsrmJson)', () => {
|
|
199
260
|
|
|
200
|
-
const itinerary = OsrmUtils.createItineraryFromJson(
|
|
261
|
+
const itinerary = OsrmUtils.createItineraryFromJson(wemapJsonItinerary,
|
|
262
|
+
wemapStart, wemapEnd);
|
|
201
263
|
|
|
202
264
|
expect(itinerary.nodes.length).equal(wemapItinerary.nodes.length);
|
|
203
265
|
for (let i = 0; i < itinerary.nodes.length; i++) {
|
|
@@ -219,4 +281,29 @@ describe('OsrmUtils', () => {
|
|
|
219
281
|
|
|
220
282
|
});
|
|
221
283
|
|
|
284
|
+
it('Errored (Montpellier outdoor)', () => {
|
|
285
|
+
|
|
286
|
+
const filePath = path.resolve(__dirname,
|
|
287
|
+
'../../assets/itinerary-montpellier-outdoor-errored.json');
|
|
288
|
+
const fileString = fs.readFileSync(filePath, 'utf8');
|
|
289
|
+
|
|
290
|
+
const json = JSON.parse(fileString);
|
|
291
|
+
|
|
292
|
+
const start = new WGS84(43.6007871, 3.8757218000000004);
|
|
293
|
+
const end = new WGS84(43.598877, 3.873866);
|
|
294
|
+
|
|
295
|
+
expect(() => OsrmUtils.createItineraryFromJson(json, start, end)).throw(Error);
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
describe('OsrmUtils - Output JSON', () => {
|
|
301
|
+
|
|
302
|
+
it('noRouteFoundJson', () => {
|
|
303
|
+
expect(OsrmUtils.noRouteFoundJson('foo')).deep.equals({
|
|
304
|
+
'code': 'NoRoute',
|
|
305
|
+
'message': 'foo'
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
|
|
222
309
|
});
|
|
File without changes
|