@wemap/osm 5.0.4 → 5.0.6

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.
@@ -0,0 +1 @@
1
+ {"code":"Ok","routes":[{"geometry":{"coordinates":[[3.887244,43.605663],[3.887534,43.605579],[3.887765,43.605512],[3.887776,43.605508],[3.887849,43.605489]],"type":"LineString"},"legs":[{"steps":[{"intersections":[{"out":0,"entry":[true],"bearings":[112],"location":[3.887244,43.605663]},{"out":1,"location":[3.887534,43.605579],"bearings":[30,105,285],"entry":[true,true,false],"in":2}],"driving_side":"right","geometry":{"coordinates":[[3.887244,43.605663],[3.887534,43.605579],[3.887765,43.605512],[3.887776,43.605508],[3.887849,43.605489]],"type":"LineString"},"mode":"walking","duration":39.7,"maneuver":{"bearing_after":112,"location":[3.887244,43.605663],"bearing_before":0,"type":"depart"},"weight":39.7,"distance":52.4,"name":"Avenue du Pont Juvénal"},{"intersections":[{"in":0,"entry":[true],"bearings":[290],"location":[3.887849,43.605489]}],"driving_side":"right","geometry":{"coordinates":[[3.887849,43.605489],[3.887849,43.605489]],"type":"LineString"},"mode":"walking","duration":0,"maneuver":{"bearing_after":0,"type":"arrive","modifier":"right","bearing_before":110,"location":[3.887849,43.605489]},"weight":0,"distance":0,"name":"Avenue du Pont Juvénal"}],"distance":52.4,"duration":39.7,"summary":"Avenue du Pont Juvénal","weight":39.7}],"distance":52.4,"duration":39.7,"weight_name":"duration","weight":39.7}],"waypoints":[{"hint":"-y1UgREuVIG1AAAAbQEAAAAAAAAWAAAAtQAAAG0BAAAAAAAAFgAAAAIAAACMUDsAn16ZAoxQOwCfXpkCAAA_Eg61bn8=","name":"Avenue du Pont Juvénal","location":[3.887244,43.605663]},{"hint":"-S1UgRUuVIEtAAAALAAAAKsAAAAAAAAALQAAACwAAACrAAAAAAAAAAIAAADpUjsA8V2ZAsNSOwCjXZkCAwDfBg61bn8=","name":"Avenue du Pont Juvénal","location":[3.887849,43.605489]}]}
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  "directory": "packages/osm"
12
12
  },
13
13
  "name": "@wemap/osm",
14
- "version": "5.0.4",
14
+ "version": "5.0.6",
15
15
  "bugs": {
16
16
  "url": "https://github.com/wemap/wemap-modules-js/issues"
17
17
  },
@@ -31,5 +31,5 @@
31
31
  "@wemap/maths": "^5.0.0",
32
32
  "sax": "^1.2.4"
33
33
  },
34
- "gitHead": "8793fda524d493f3b954d8b61d3d523a32b2f275"
34
+ "gitHead": "412142e60e70b1e18989c616c6c7d3b6f577ef2c"
35
35
  }
@@ -1,6 +1,7 @@
1
1
  /* eslint-disable max-statements */
2
2
  import { Coordinates, Network } from '@wemap/geo';
3
3
  import Leg from './Leg.js';
4
+ import Step from './Step.js';
4
5
 
5
6
  /**
6
7
  * Main attributes are:
@@ -53,6 +54,15 @@ class Itinerary {
53
54
  return this._coords;
54
55
  }
55
56
 
57
+ set steps(_) {
58
+ throw new Error('Itinerary.step cannot be set. They are calculated from Itinerary.legs.');
59
+ }
60
+
61
+ /** @type {!(Step[])} */
62
+ get steps() {
63
+ return this.legs.map(leg => leg.steps).flat();
64
+ }
65
+
56
66
  /**
57
67
  * @returns {Network}
58
68
  */
@@ -38,6 +38,7 @@ export function verifyStepData(step) {
38
38
  expect(step.duration).satisfies(isNullOrNumber);
39
39
  expect(step.name).satisfies(isNullOrString);
40
40
  expect(step.levelChange).satisfies(isNullOrLevelChange);
41
+ expect(step._idCoordsInLeg).be.a('number');
41
42
 
42
43
  expect(step.extras).satisfies(isNullOrObject);
43
44
  if (step.extras !== null) {
@@ -43,6 +43,9 @@ class Step {
43
43
  /** @type {?{?subwayEntrance: boolean, ?subwayEntranceRef: string}} */
44
44
  extras = {};
45
45
 
46
+ /** @type {!number} */
47
+ _idCoordsInLeg = null;
48
+
46
49
  /**
47
50
  * @returns {object}
48
51
  */
@@ -53,7 +56,8 @@ class Step {
53
56
  angle: this.angle,
54
57
  previousBearing: this.previousBearing,
55
58
  nextBearing: this.nextBearing,
56
- distance: this.distance
59
+ distance: this.distance,
60
+ _idCoordsInLeg: this._idCoordsInLeg
57
61
  };
58
62
  if (this.firstStep) {
59
63
  output.firstStep = true;
@@ -88,6 +92,7 @@ class Step {
88
92
  step.previousBearing = json.previousBearing;
89
93
  step.nextBearing = json.nextBearing;
90
94
  step.distance = json.distance;
95
+ step._idCoordsInLeg = json._idCoordsInLeg;
91
96
  if (json.firstStep) {
92
97
  step.firstStep = json.firstStep;
93
98
  }
@@ -1,10 +1,14 @@
1
+ import { diffAngle } from '@wemap/maths';
2
+
1
3
  import Itinerary from './Itinerary.js';
2
4
 
3
5
  /**
4
6
  * @param {Itinerary} itinerary
5
7
  */
6
- export function generateStepsNumbers(itinerary) {
8
+ export function generateStepsMetadata(itinerary) {
9
+
7
10
  let counter = 1;
11
+
8
12
  itinerary.legs.forEach((leg, legId) => {
9
13
  leg.steps.forEach((step, stepId) => {
10
14
 
@@ -17,6 +21,34 @@ export function generateStepsNumbers(itinerary) {
17
21
  }
18
22
 
19
23
  step.number = counter++;
24
+
25
+
26
+ /*
27
+ * Generate previousBearing, nextBearing and angle
28
+ */
29
+
30
+ let coordsBeforeStep;
31
+ if (step._idCoordsInLeg > 0) {
32
+ coordsBeforeStep = leg.coords[step._idCoordsInLeg - 1];
33
+ } else if (legId === 0) {
34
+ coordsBeforeStep = itinerary.from;
35
+ } else {
36
+ coordsBeforeStep = itinerary.legs[legId - 1].to.coords;
37
+ }
38
+
39
+ let coordsAfterStep;
40
+ if (step._idCoordsInLeg !== leg.coords.length - 1) {
41
+ coordsAfterStep = leg.coords[step._idCoordsInLeg + 1];
42
+ } else if (legId === itinerary.legs.length - 1) {
43
+ coordsAfterStep = itinerary.to;
44
+ } else {
45
+ coordsAfterStep = itinerary.legs[legId + 1].from.coords;
46
+ }
47
+
48
+ step.previousBearing = coordsBeforeStep.bearingTo(step.coords);
49
+ step.nextBearing = step.coords.bearingTo(coordsAfterStep);
50
+ step.angle = diffAngle(step.previousBearing, step.nextBearing + Math.PI);
51
+
20
52
  });
21
53
  });
22
54
  }
@@ -36,10 +36,7 @@ class ItineraryInfoManager {
36
36
  set itinerary(itinerary) {
37
37
 
38
38
  this._itinerary = itinerary;
39
- this._steps = itinerary.legs.reduce((acc, { steps }) => {
40
- acc.push(...steps);
41
- return acc;
42
- }, []);
39
+ this._steps = itinerary.steps;
43
40
  this._network = itinerary.toNetwork();
44
41
  this._mapMatching = new MapMatching(this._network);
45
42
 
@@ -1,15 +1,13 @@
1
1
  /* eslint-disable max-statements */
2
2
 
3
3
  import { Level, Coordinates } from '@wemap/geo';
4
- import {
5
- rad2deg, positiveMod, diffAngle, deg2rad
6
- } from '@wemap/maths';
4
+ import { rad2deg, positiveMod } from '@wemap/maths';
7
5
 
8
6
  import Itinerary from '../Itinerary.js';
9
7
  import Leg from '../Leg.js';
10
8
  import RouterResponse from '../RouterResponse.js';
11
9
  import Step from '../Step.js';
12
- import { generateStepsNumbers } from '../Utils.js';
10
+ import { generateStepsMetadata } from '../Utils.js';
13
11
 
14
12
  /**
15
13
  * @param {Coordinates} coordinates
@@ -151,11 +149,10 @@ export function itineraryToOsrmJson(itinerary) {
151
149
 
152
150
  /**
153
151
  * @param {object} jsonSteps
154
- * @param {Coordinates} itineraryStart
155
- * @param {Coordinates} itineraryEnd
152
+ * @param {Coordinates[]} legCoords
156
153
  * @returns {Step[]}
157
154
  */
158
- function parseJsonSteps(jsonSteps, itineraryStart, itineraryEnd) {
155
+ function parseJsonSteps(jsonSteps, legCoords) {
159
156
 
160
157
  if (!jsonSteps) {
161
158
  return [];
@@ -166,14 +163,12 @@ function parseJsonSteps(jsonSteps, itineraryStart, itineraryEnd) {
166
163
  const step = new Step();
167
164
  step.coords = jsonToCoordinates(jsonStep.maneuver.location);
168
165
 
169
- step.previousBearing = step.firstStep
170
- ? itineraryStart.bearingTo(step.coords)
171
- : deg2rad(jsonStep.maneuver.bearing_before);
172
- step.nextBearing = step.lastStep
173
- ? step.coords.bearingTo(itineraryEnd)
174
- : deg2rad(jsonStep.maneuver.bearing_after);
166
+ const idStepCoordsInLeg = legCoords.findIndex(coords => step.coords.equalsTo(coords));
167
+ if (idStepCoordsInLeg < 0) {
168
+ throw new Error('Osrm Parser: Cannot find step coords in leg coordinates');
169
+ }
170
+ step._idCoordsInLeg = idStepCoordsInLeg;
175
171
 
176
- step.angle = diffAngle(step.previousBearing, step.nextBearing + Math.PI);
177
172
  step.name = jsonStep.name;
178
173
  step.levelChange = jsonStep.levelChange ? jsonStep.levelChange : null;
179
174
 
@@ -240,17 +235,11 @@ export function createRouterResponseFromJson(json, from, to, routingMode = 'walk
240
235
  leg.distance = jsonLeg.distance;
241
236
  leg.duration = jsonLeg.duration;
242
237
 
243
- leg.coords = jsonLeg.steps.reduce((acc, step) => {
244
- acc.push(...step.geometry.coordinates.map(jsonToCoordinates));
245
- return acc;
246
- }, []);
247
- // Remove duplicates
248
- leg.coords = leg.coords.reduce((acc, val) => {
249
- if (acc.length === 0 || !acc[acc.length - 1].equalsTo(val)) {
250
- acc.push(val);
251
- }
252
- return acc;
253
- }, []);
238
+ leg.coords = jsonLeg.steps
239
+ .map(step => step.geometry.coordinates.map(jsonToCoordinates))
240
+ .flat()
241
+ // Remove duplicates
242
+ .filter((coords, idx, arr) => idx === 0 || !arr[idx - 1].equalsTo(coords));
254
243
 
255
244
  leg.from = {
256
245
  name: null,
@@ -261,12 +250,14 @@ export function createRouterResponseFromJson(json, from, to, routingMode = 'walk
261
250
  coords: leg.coords[leg.coords.length - 1]
262
251
  };
263
252
 
264
- leg.steps = parseJsonSteps(jsonLeg.steps, from, to);
253
+ leg.steps = parseJsonSteps(jsonLeg.steps, leg.coords);
265
254
 
266
255
  itinerary.legs.push(leg);
267
256
  }
268
257
 
269
- generateStepsNumbers(itinerary);
258
+ // All legs have to be parsed before computing steps metadata
259
+ generateStepsMetadata(itinerary);
260
+
270
261
  }
271
262
 
272
263
  return routerResponse;
@@ -1,5 +1,6 @@
1
1
  /* eslint-disable max-statements */
2
2
  import chai from 'chai';
3
+ import chaiAlmost from 'chai-almost';
3
4
  import fs from 'fs';
4
5
  import path from 'path';
5
6
  import { fileURLToPath } from 'url';
@@ -21,6 +22,8 @@ import {
21
22
  import { verifyRouterResponseData } from '../RouterResponse.type.spec.js';
22
23
 
23
24
  const { expect } = chai;
25
+ chai.use(chaiAlmost(0.1));
26
+
24
27
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
25
28
 
26
29
 
@@ -427,5 +430,28 @@ describe('OsrmUtils - createRouterResponseFromJson', () => {
427
430
 
428
431
  });
429
432
 
433
+
434
+ it('RouterResponse - 2', () => {
435
+
436
+ const filePath = path.resolve(__dirname, '../../../assets/itinerary-montpellier-osrm-3.json');
437
+ const fileString = fs.readFileSync(filePath, 'utf8');
438
+ const json = JSON.parse(fileString);
439
+
440
+ const from = new Coordinates(43.605663, 3.887244);
441
+ const to = new Coordinates(43.6054106, 3.8878106);
442
+ const routerResponse = createRouterResponseFromJson(json, from, to);
443
+ verifyRouterResponseData(routerResponse);
444
+
445
+ expect(routerResponse.routerName).equal('osrm');
446
+ expect(routerResponse.itineraries.length).equal(1);
447
+ expect(routerResponse.from.equalsTo(from)).true;
448
+ expect(routerResponse.to.equalsTo(to)).true;
449
+
450
+ const steps = routerResponse.itineraries[0].steps;
451
+ expect(steps.length).equal(2);
452
+ expect(steps[1].angle).almost.equal(1.575);
453
+
454
+ });
455
+
430
456
  });
431
457
 
@@ -2,13 +2,12 @@
2
2
  import Polyline from '@mapbox/polyline';
3
3
 
4
4
  import { Coordinates } from '@wemap/geo';
5
- import { diffAngle } from '@wemap/maths';
6
5
 
7
6
  import Itinerary from '../Itinerary.js';
8
7
  import Leg from '../Leg.js';
9
8
  import RouterResponse from '../RouterResponse.js';
10
9
  import Step from '../Step.js';
11
- import { generateStepsNumbers } from '../Utils.js';
10
+ import { generateStepsMetadata } from '../Utils.js';
12
11
 
13
12
  /**
14
13
  * @param {object} json
@@ -21,11 +20,9 @@ export function jsonToCoordinates(json) {
21
20
  /**
22
21
  * @param {object} jsonSteps
23
22
  * @param {Coordinates[]} legCoords
24
- * @param {Coordinates} itineraryStart
25
- * @param {Coordinates} itineraryEnd
26
23
  * @returns {Step[]}
27
24
  */
28
- function parseJsonSteps(jsonSteps, legCoords, itineraryStart) {
25
+ function parseJsonSteps(jsonSteps, legCoords) {
29
26
 
30
27
  if (!jsonSteps) {
31
28
  return [];
@@ -44,15 +41,7 @@ function parseJsonSteps(jsonSteps, legCoords, itineraryStart) {
44
41
  throw new Error('OTP Parser: Cannot find closest step');
45
42
  }
46
43
  step.coords = legCoords[idStepCoordsInLeg];
47
-
48
- step.previousBearing = idStepCoordsInLeg === 0
49
- ? itineraryStart.bearingTo(step.coords)
50
- : legCoords[idStepCoordsInLeg - 1].bearingTo(legCoords[idStepCoordsInLeg]);
51
- step.nextBearing = idStepCoordsInLeg === legCoords.length - 1
52
- ? 0
53
- : legCoords[idStepCoordsInLeg].bearingTo(legCoords[idStepCoordsInLeg + 1]);
54
-
55
- step.angle = diffAngle(step.previousBearing, step.nextBearing + Math.PI);
44
+ step._idCoordsInLeg = idStepCoordsInLeg;
56
45
 
57
46
  step.name = jsonStep.streetName;
58
47
  step.levelChange = null;
@@ -112,6 +101,8 @@ export function createRouterResponseFromJson(json) {
112
101
  };
113
102
  leg.coords = Polyline.decode(jsonLeg.legGeometry.points).map(([lat, lon]) => new Coordinates(lat, lon));
114
103
 
104
+ leg.steps = parseJsonSteps(jsonLeg.steps, leg.coords);
105
+
115
106
  if (leg.mode === 'BUS' || leg.mode === 'TRAM') {
116
107
  leg.transportInfo = {
117
108
  name: jsonLeg.route,
@@ -119,6 +110,14 @@ export function createRouterResponseFromJson(json) {
119
110
  routeTextColor: jsonLeg.routeTextColor,
120
111
  directionName: jsonLeg.headsign
121
112
  };
113
+
114
+ const legStep = new Step();
115
+ legStep.coords = leg.coords[0];
116
+ legStep._idCoordsInLeg = 0;
117
+ legStep.name = jsonLeg.headsign;
118
+ legStep.levelChange = null;
119
+ legStep.distance = jsonLeg.distance;
120
+ leg.steps = [legStep];
122
121
  }
123
122
 
124
123
  // jsonLeg.distance is not reliable when compared to the array of leg coords.
@@ -130,32 +129,10 @@ export function createRouterResponseFromJson(json) {
130
129
  return acc + arr[idx - 1].distanceTo(coords);
131
130
  }, 0);
132
131
 
133
- let previousPoint;
134
- if (itinerary.legs.length === 0) {
135
- previousPoint = itinerary.from;
136
- } else {
137
- const lastLeg = itinerary.legs[itinerary.legs.length - 1];
138
- previousPoint = lastLeg.coords[lastLeg.coords.length - 1];
139
- }
140
-
141
- leg.steps = parseJsonSteps(
142
- jsonLeg.steps,
143
- leg.coords,
144
- previousPoint
145
- );
146
- // itinerary.coords.push(...leg.coords);
147
132
  itinerary.legs.push(leg);
148
133
 
149
134
  }
150
135
 
151
- // Remove duplicates
152
- // itinerary.coords = itinerary.coords.reduce((acc, val) => {
153
- // if (acc.length === 0 || !acc[acc.length - 1].equalsTo(val)) {
154
- // acc.push(val);
155
- // }
156
- // return acc;
157
- // }, []);
158
-
159
136
  itinerary.distance = itinerary.coords.reduce((acc, coords, idx, arr) => {
160
137
  if (idx === 0) {
161
138
  return acc;
@@ -163,7 +140,8 @@ export function createRouterResponseFromJson(json) {
163
140
  return acc + arr[idx - 1].distanceTo(coords);
164
141
  }, 0);
165
142
 
166
- generateStepsNumbers(itinerary);
143
+ // All legs have to be parsed before computing steps metadata
144
+ generateStepsMetadata(itinerary);
167
145
  }
168
146
 
169
147
  return routerResponse;