@wemap/osm 5.0.3 → 5.0.5

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.3",
14
+ "version": "5.0.5",
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": "09b11e320c82084d52e6721317d051fe4447849d"
34
+ "gitHead": "8810cc32fb87c196e8350e0a0e6f6f7671fe4246"
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
  }
@@ -8,7 +8,12 @@ import OsmWay from '../../model/OsmWay.js';
8
8
 
9
9
  export const HIGHWAYS_PEDESTRIANS = ['footway', 'steps', 'pedestrian', 'living_street', 'path', 'track', 'sidewalk'];
10
10
 
11
- export const DEFAULT_WAY_SELECTOR = way => HIGHWAYS_PEDESTRIANS.includes(way.tags.highway) || way.tags.footway === 'sidewalk';
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
+ };
12
17
 
13
18
  /**
14
19
  * @param {Network<OsmElement>} network
@@ -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;
@@ -130,32 +119,12 @@ export function createRouterResponseFromJson(json) {
130
119
  return acc + arr[idx - 1].distanceTo(coords);
131
120
  }, 0);
132
121
 
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
- }
122
+ leg.steps = parseJsonSteps(jsonLeg.steps, leg.coords);
140
123
 
141
- leg.steps = parseJsonSteps(
142
- jsonLeg.steps,
143
- leg.coords,
144
- previousPoint
145
- );
146
- // itinerary.coords.push(...leg.coords);
147
124
  itinerary.legs.push(leg);
148
125
 
149
126
  }
150
127
 
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
128
  itinerary.distance = itinerary.coords.reduce((acc, coords, idx, arr) => {
160
129
  if (idx === 0) {
161
130
  return acc;
@@ -163,7 +132,8 @@ export function createRouterResponseFromJson(json) {
163
132
  return acc + arr[idx - 1].distanceTo(coords);
164
133
  }, 0);
165
134
 
166
- generateStepsNumbers(itinerary);
135
+ // All legs have to be parsed before computing steps metadata
136
+ generateStepsMetadata(itinerary);
167
137
  }
168
138
 
169
139
  return routerResponse;