@wemap/osm 4.0.14 → 5.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.
- package/assets/itinerary-grenoble-otp-1.json +1536 -0
- package/assets/itinerary-grenoble-otp-2.json +1092 -0
- package/assets/itinerary-montpellier-outdoor-without-steps.json +110 -1
- package/assets/itinerary-montpellier-outdoor.json +513 -1
- package/index.js +21 -2
- package/package.json +6 -5
- package/src/routers/Itinerary.js +185 -0
- package/src/routers/Itinerary.type.spec.js +104 -0
- package/src/routers/Leg.js +101 -0
- package/src/routers/LevelChange.js +65 -0
- package/src/routers/RouterResponse.js +19 -0
- package/src/routers/RouterResponse.type.spec.js +24 -0
- package/src/routers/Step.js +113 -0
- package/src/routers/Utils.js +22 -0
- package/src/routers/custom/OsmNetworkUtils.js +194 -0
- package/src/{network → routers/custom}/OsmNetworkUtils.spec.js +13 -34
- package/src/routers/custom/OsmRouter.js +27 -0
- package/src/routers/custom/OsmRouter.spec.js +222 -0
- package/src/routers/custom/OsmRouterOptions.js +33 -0
- package/src/routers/custom/OsmRouterUtils.js +46 -0
- package/src/routers/custom/StepsGeneration.js +104 -0
- package/src/routers/info/ItineraryInfo.js +34 -0
- package/src/routers/info/ItineraryInfoManager.js +142 -0
- package/src/routers/info/ItineraryInfoManager.spec.js +54 -0
- package/src/routers/osrm/OsrmUtils.js +273 -0
- package/src/routers/osrm/OsrmUtils.spec.js +431 -0
- package/src/routers/otp/OtpUtils.js +172 -0
- package/src/routers/otp/OtpUtils.spec.js +97 -0
- package/src/network/OsmNetworkUtils.js +0 -163
- package/src/network/OsmRouter.spec.js +0 -174
- package/src/osrm/OsrmUtils.js +0 -284
- package/src/osrm/OsrmUtils.spec.js +0 -384
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"directory": "packages/osm"
|
|
12
12
|
},
|
|
13
13
|
"name": "@wemap/osm",
|
|
14
|
-
"version": "
|
|
14
|
+
"version": "5.0.0",
|
|
15
15
|
"bugs": {
|
|
16
16
|
"url": "https://github.com/wemap/wemap-modules-js/issues"
|
|
17
17
|
},
|
|
@@ -25,10 +25,11 @@
|
|
|
25
25
|
],
|
|
26
26
|
"license": "ISC",
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@
|
|
29
|
-
"@wemap/
|
|
30
|
-
"@wemap/
|
|
28
|
+
"@mapbox/polyline": "^1.1.1",
|
|
29
|
+
"@wemap/geo": "^5.0.0",
|
|
30
|
+
"@wemap/logger": "^5.0.0",
|
|
31
|
+
"@wemap/maths": "^5.0.0",
|
|
31
32
|
"sax": "^1.2.4"
|
|
32
33
|
},
|
|
33
|
-
"gitHead": "
|
|
34
|
+
"gitHead": "73607e294f29d3f9a41673bfc25ad9489a1da7f4"
|
|
34
35
|
}
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
/* eslint-disable max-statements */
|
|
2
|
+
import { Coordinates, Network } from '@wemap/geo';
|
|
3
|
+
import Leg from './Leg.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Main attributes are:
|
|
7
|
+
* nodes: the ordered list of Node
|
|
8
|
+
* edges: the ordered list of Edge
|
|
9
|
+
* start: the start point (Coordinates)
|
|
10
|
+
* end: the end point (Coordinates)
|
|
11
|
+
* length: the route length
|
|
12
|
+
*/
|
|
13
|
+
class Itinerary {
|
|
14
|
+
|
|
15
|
+
/** @type {!Coordinates} */
|
|
16
|
+
from;
|
|
17
|
+
|
|
18
|
+
/** @type {!Coordinates} */
|
|
19
|
+
to;
|
|
20
|
+
|
|
21
|
+
/** @type {!number} */
|
|
22
|
+
distance;
|
|
23
|
+
|
|
24
|
+
/** @type {!number} */
|
|
25
|
+
duration;
|
|
26
|
+
|
|
27
|
+
/** @type {?number} */
|
|
28
|
+
startTime = null;
|
|
29
|
+
|
|
30
|
+
/** @type {?number} */
|
|
31
|
+
endTime = null;
|
|
32
|
+
|
|
33
|
+
/** @type {!(Leg[])} */
|
|
34
|
+
legs = [];
|
|
35
|
+
|
|
36
|
+
/** @type {?Coordinates[]} */
|
|
37
|
+
_coords = null;
|
|
38
|
+
|
|
39
|
+
set coords(_) {
|
|
40
|
+
throw new Error('Itinerary.coords cannot be set. They are calculated from Itinerary.legs.');
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** @type {!(Coordinates[])} */
|
|
44
|
+
get coords() {
|
|
45
|
+
if (!this._coords) {
|
|
46
|
+
// Returns the coordinates contained in all legs and remove duplicates between array
|
|
47
|
+
this._coords = this.legs.reduce((acc, val) => {
|
|
48
|
+
const isDuplicate = acc.length && val.coords.length && acc[acc.length - 1].equalsTo(val.coords[0]);
|
|
49
|
+
acc.push(...val.coords.slice(isDuplicate ? 1 : 0));
|
|
50
|
+
return acc;
|
|
51
|
+
}, []);
|
|
52
|
+
}
|
|
53
|
+
return this._coords;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* @returns {Network}
|
|
58
|
+
*/
|
|
59
|
+
toNetwork() {
|
|
60
|
+
return Network.fromCoordinates([this.coords]);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* @param {Itinerary[]} itineraries
|
|
65
|
+
* @returns {Itinerary}
|
|
66
|
+
*/
|
|
67
|
+
static fromItineraries(...itineraries) {
|
|
68
|
+
const itinerary = new Itinerary();
|
|
69
|
+
itinerary.from = itineraries[0].from;
|
|
70
|
+
itinerary.to = itineraries[itineraries.length - 1].to;
|
|
71
|
+
itinerary.distance = 0;
|
|
72
|
+
itinerary.duration = 0;
|
|
73
|
+
itinerary.legs = [];
|
|
74
|
+
|
|
75
|
+
itineraries.forEach(_itinerary => {
|
|
76
|
+
itinerary.distance += _itinerary.distance;
|
|
77
|
+
itinerary.duration += _itinerary.duration;
|
|
78
|
+
itinerary.legs.push(..._itinerary.legs);
|
|
79
|
+
itinerary.legs.forEach(leg => {
|
|
80
|
+
leg.steps[0].firstStep = false;
|
|
81
|
+
leg.steps[leg.steps.length - 1].lastStep = false;
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
itinerary.legs[0].steps[0].firstStep = true;
|
|
86
|
+
const lastLeg = itinerary.legs[itinerary.legs.length - 1];
|
|
87
|
+
lastLeg.steps[lastLeg.steps.length - 1].lastStep = true;
|
|
88
|
+
|
|
89
|
+
return itinerary;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Convert lat/lng/level points to Itinerary
|
|
94
|
+
* @param {number[][]} points 2D points array of lat/lng/level (level is optional)
|
|
95
|
+
* @param {Coordinates} from
|
|
96
|
+
* @param {Coordinates} to
|
|
97
|
+
* @param {string} mode
|
|
98
|
+
* @returns {Itinerary}
|
|
99
|
+
*/
|
|
100
|
+
static fromOrderedPointsArray(points, start, end) {
|
|
101
|
+
|
|
102
|
+
const pointToCoordinates = point => new Coordinates(point[0], point[1], null, point[2]);
|
|
103
|
+
|
|
104
|
+
return this.fromOrderedCoordinates(
|
|
105
|
+
points.map(pointToCoordinates),
|
|
106
|
+
pointToCoordinates(start),
|
|
107
|
+
pointToCoordinates(end)
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Convert ordered Coordinates to Itinerary
|
|
113
|
+
* @param {Coordinates[]} points
|
|
114
|
+
* @param {Coordinates} from
|
|
115
|
+
* @param {Coordinates} to
|
|
116
|
+
* @param {string} mode
|
|
117
|
+
* @returns {Itinerary}
|
|
118
|
+
*/
|
|
119
|
+
static fromOrderedCoordinates(points, from, to, mode = 'WALK') {
|
|
120
|
+
|
|
121
|
+
const itinerary = new Itinerary();
|
|
122
|
+
itinerary.from = from;
|
|
123
|
+
itinerary.to = to;
|
|
124
|
+
|
|
125
|
+
const leg = new Leg();
|
|
126
|
+
leg.mode = mode;
|
|
127
|
+
leg.from = from;
|
|
128
|
+
leg.to = to;
|
|
129
|
+
|
|
130
|
+
leg.coords = points;
|
|
131
|
+
leg.distance = points.reduce((acc, coords, idx, arr) => {
|
|
132
|
+
if (idx !== 0) {
|
|
133
|
+
return acc + arr[idx - 1].distanceTo(coords);
|
|
134
|
+
}
|
|
135
|
+
return acc;
|
|
136
|
+
}, 0);
|
|
137
|
+
leg.duration = leg.distance;
|
|
138
|
+
|
|
139
|
+
itinerary.distance = leg.distance;
|
|
140
|
+
itinerary.duration = leg.duration;
|
|
141
|
+
|
|
142
|
+
return itinerary;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* @returns {object}
|
|
147
|
+
*/
|
|
148
|
+
toJson() {
|
|
149
|
+
const output = {
|
|
150
|
+
from: this.from.toCompressedJson(),
|
|
151
|
+
to: this.to.toCompressedJson(),
|
|
152
|
+
distance: this.distance,
|
|
153
|
+
duration: this.duration,
|
|
154
|
+
legs: this.legs.map(leg => leg.toJson())
|
|
155
|
+
};
|
|
156
|
+
if (this.startTime !== null) {
|
|
157
|
+
output.startTime = this.startTime;
|
|
158
|
+
}
|
|
159
|
+
if (this.endTime !== null) {
|
|
160
|
+
output.endTime = this.endTime;
|
|
161
|
+
}
|
|
162
|
+
return output;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* @param {object} json
|
|
167
|
+
* @returns {Itinerary}
|
|
168
|
+
*/
|
|
169
|
+
static fromJson(json) {
|
|
170
|
+
const itinerary = new Itinerary();
|
|
171
|
+
itinerary.from = Coordinates.fromCompressedJson(json.from);
|
|
172
|
+
itinerary.to = Coordinates.fromCompressedJson(json.to);
|
|
173
|
+
itinerary.distance = json.distance;
|
|
174
|
+
itinerary.duration = json.duration;
|
|
175
|
+
itinerary.legs = json.legs.map(Leg.fromJson);
|
|
176
|
+
if (json.startTime) {
|
|
177
|
+
itinerary.startTime = json.startTime;
|
|
178
|
+
}
|
|
179
|
+
if (json.endTime) {
|
|
180
|
+
itinerary.endTime = json.endTime;
|
|
181
|
+
}
|
|
182
|
+
return itinerary;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
export default Itinerary;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import chai from 'chai';
|
|
2
|
+
|
|
3
|
+
import { Coordinates } from '@wemap/geo';
|
|
4
|
+
|
|
5
|
+
import LevelChange from './LevelChange.js';
|
|
6
|
+
import Leg from './Leg.js';
|
|
7
|
+
import Itinerary from './Itinerary.js';
|
|
8
|
+
import Step from './Step.js';
|
|
9
|
+
|
|
10
|
+
const { expect } = chai;
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
const isNullOrNumber = val => val === null || typeof val === 'number';
|
|
14
|
+
const isNullOrString = val => val === null || typeof val === 'string';
|
|
15
|
+
const isNullOrObject = val => val === null || typeof val === 'object';
|
|
16
|
+
const isNullOrArray = val => val === null || Array.isArray(val);
|
|
17
|
+
const isNullOrLevelChange = val => val === null || val instanceof LevelChange;
|
|
18
|
+
|
|
19
|
+
const isUndefinedOrBoolean = val => typeof val === 'undefined' || typeof val === 'boolean';
|
|
20
|
+
const isUndefinedOrString = val => typeof val === 'undefined' || typeof val === 'string';
|
|
21
|
+
|
|
22
|
+
const stepExtraProperties = ['subwayEntrance', 'subwayEntranceRef'];
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @param {Step} step
|
|
26
|
+
*/
|
|
27
|
+
export function verifyStepData(step) {
|
|
28
|
+
|
|
29
|
+
expect(step).instanceOf(Step);
|
|
30
|
+
expect(step.firstStep).be.a('boolean');
|
|
31
|
+
expect(step.lastStep).be.a('boolean');
|
|
32
|
+
expect(step.number).be.a('number');
|
|
33
|
+
expect(step.coords).instanceOf(Coordinates);
|
|
34
|
+
expect(step.angle).be.a('number');
|
|
35
|
+
expect(step.previousBearing).be.a('number');
|
|
36
|
+
expect(step.nextBearing).be.a('number');
|
|
37
|
+
expect(step.distance).be.a('number');
|
|
38
|
+
expect(step.duration).satisfies(isNullOrNumber);
|
|
39
|
+
expect(step.name).satisfies(isNullOrString);
|
|
40
|
+
expect(step.levelChange).satisfies(isNullOrLevelChange);
|
|
41
|
+
|
|
42
|
+
expect(step.extras).satisfies(isNullOrObject);
|
|
43
|
+
if (step.extras !== null) {
|
|
44
|
+
for (const key of Object.keys(step.extras)) {
|
|
45
|
+
expect(stepExtraProperties).includes(key);
|
|
46
|
+
}
|
|
47
|
+
expect(step.extras.subwayEntrance).satisfies(isUndefinedOrBoolean);
|
|
48
|
+
expect(step.extras.subwayEntranceRef).satisfies(isUndefinedOrString);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @param {Leg} routerResponse
|
|
54
|
+
*/
|
|
55
|
+
export function verifyLegData(leg) {
|
|
56
|
+
|
|
57
|
+
expect(leg).instanceOf(Leg);
|
|
58
|
+
expect(leg.mode).be.a('string');
|
|
59
|
+
expect(leg.distance).be.a('number');
|
|
60
|
+
expect(leg.duration).be.a('number');
|
|
61
|
+
expect(leg.startTime).satisfies(isNullOrNumber);
|
|
62
|
+
expect(leg.endTime).satisfies(isNullOrNumber);
|
|
63
|
+
expect(leg.from).be.an('object');
|
|
64
|
+
expect(leg.from.name).satisfies(isNullOrString);
|
|
65
|
+
expect(leg.from.coords).instanceOf(Coordinates);
|
|
66
|
+
expect(leg.to).be.an('object');
|
|
67
|
+
expect(leg.to.name).satisfies(isNullOrString);
|
|
68
|
+
expect(leg.to.coords).instanceOf(Coordinates);
|
|
69
|
+
expect(leg.coords).be.an('array');
|
|
70
|
+
leg.coords.forEach(coords => expect(coords).instanceOf(Coordinates));
|
|
71
|
+
|
|
72
|
+
expect(leg.transportInfo).satisfies(isNullOrObject);
|
|
73
|
+
if (leg.transportInfo !== null) {
|
|
74
|
+
expect(leg.transportInfo.name).be.a('string');
|
|
75
|
+
expect(leg.transportInfo.routeColor).satisfies(isNullOrString);
|
|
76
|
+
expect(leg.transportInfo.routeTextColor).satisfies(isNullOrString);
|
|
77
|
+
expect(leg.transportInfo.directionName).satisfies(isNullOrString);
|
|
78
|
+
}
|
|
79
|
+
expect(leg.steps).satisfies(isNullOrArray);
|
|
80
|
+
if (leg.steps !== null) {
|
|
81
|
+
leg.steps.forEach(verifyStepData);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* @param {Itinerary} itinerary
|
|
88
|
+
*/
|
|
89
|
+
export function verifyItineraryData(itinerary) {
|
|
90
|
+
|
|
91
|
+
expect(itinerary).instanceOf(Itinerary);
|
|
92
|
+
expect(itinerary.from).instanceOf(Coordinates);
|
|
93
|
+
expect(itinerary.to).instanceOf(Coordinates);
|
|
94
|
+
expect(itinerary.coords).be.an('array');
|
|
95
|
+
for (const coords of itinerary.coords) {
|
|
96
|
+
expect(coords).instanceOf(Coordinates);
|
|
97
|
+
}
|
|
98
|
+
expect(itinerary.distance).be.a('number');
|
|
99
|
+
expect(itinerary.duration).be.a('number');
|
|
100
|
+
expect(itinerary.startTime).satisfies(isNullOrNumber);
|
|
101
|
+
expect(itinerary.endTime).satisfies(isNullOrNumber);
|
|
102
|
+
expect(itinerary.legs).be.an('array');
|
|
103
|
+
itinerary.legs.forEach(verifyLegData);
|
|
104
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { Coordinates, Network } from '@wemap/geo';
|
|
2
|
+
|
|
3
|
+
import Step from './Step.js';
|
|
4
|
+
|
|
5
|
+
class Leg {
|
|
6
|
+
|
|
7
|
+
/** @type {!string} can be WALK, BIKE, BUS, TRAM, CAR */
|
|
8
|
+
mode;
|
|
9
|
+
|
|
10
|
+
/** @type {!number} */
|
|
11
|
+
distance;
|
|
12
|
+
|
|
13
|
+
/** @type {!number} */
|
|
14
|
+
duration;
|
|
15
|
+
|
|
16
|
+
/** @type {?number} */
|
|
17
|
+
startTime = null;
|
|
18
|
+
|
|
19
|
+
/** @type {?number} */
|
|
20
|
+
endTime = null;
|
|
21
|
+
|
|
22
|
+
/** @type {!{name: ?string, coords: !Coordinates}} */
|
|
23
|
+
from;
|
|
24
|
+
|
|
25
|
+
/** @type {!{name: ?string, coords: !Coordinates}} */
|
|
26
|
+
to;
|
|
27
|
+
|
|
28
|
+
/** @type {!Coordinates[]} */
|
|
29
|
+
coords;
|
|
30
|
+
|
|
31
|
+
/** @type {?{name: !string, routeColor: ?string, routeTextColor: ?string, directionName: ?string}} */
|
|
32
|
+
transportInfo = null;
|
|
33
|
+
|
|
34
|
+
/** @type {?(Step[])} */
|
|
35
|
+
steps = null;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @returns {Network}
|
|
39
|
+
*/
|
|
40
|
+
toNetwork() {
|
|
41
|
+
return Network.fromCoordinates([this.coords]);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* @returns {object}
|
|
46
|
+
*/
|
|
47
|
+
toJson() {
|
|
48
|
+
const output = {
|
|
49
|
+
mode: this.mode,
|
|
50
|
+
from: this.from.toCompressedJson(),
|
|
51
|
+
to: this.to.toCompressedJson(),
|
|
52
|
+
distance: this.distance,
|
|
53
|
+
duration: this.duration,
|
|
54
|
+
coords: this.coords.map(coords => coords.toCompressedJson())
|
|
55
|
+
};
|
|
56
|
+
if (this.startTime !== null) {
|
|
57
|
+
output.startTime = this.startTime;
|
|
58
|
+
}
|
|
59
|
+
if (this.endTime !== null) {
|
|
60
|
+
output.endTime = this.endTime;
|
|
61
|
+
}
|
|
62
|
+
if (this.transportInfo !== null) {
|
|
63
|
+
output.transportInfo = this.transportInfo;
|
|
64
|
+
}
|
|
65
|
+
if (this.steps !== null && this.steps.length > 0) {
|
|
66
|
+
output.steps = this.steps.map(step => step.toJson());
|
|
67
|
+
}
|
|
68
|
+
return output;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* @param {object} json
|
|
74
|
+
* @returns {Leg}
|
|
75
|
+
*/
|
|
76
|
+
static fromJson(json) {
|
|
77
|
+
const leg = new Leg();
|
|
78
|
+
leg.mode = json.mode;
|
|
79
|
+
leg.from = Coordinates.fromCompressedJson(json.from);
|
|
80
|
+
leg.to = Coordinates.fromCompressedJson(json.to);
|
|
81
|
+
leg.distance = json.distance;
|
|
82
|
+
leg.duration = json.duration;
|
|
83
|
+
leg.coords = json.coords.map(Coordinates.fromCompressedJson);
|
|
84
|
+
if (json.startTime) {
|
|
85
|
+
leg.startTime = json.startTime;
|
|
86
|
+
}
|
|
87
|
+
if (json.endTime) {
|
|
88
|
+
leg.endTime = json.endTime;
|
|
89
|
+
}
|
|
90
|
+
if (json.transportInfo) {
|
|
91
|
+
leg.transportInfo = json.transportInfo;
|
|
92
|
+
}
|
|
93
|
+
if (json.steps) {
|
|
94
|
+
leg.steps = json.steps.map(Step.fromJson);
|
|
95
|
+
}
|
|
96
|
+
return leg;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export default Leg;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Level, GraphNode, GraphUtils } from '@wemap/geo';
|
|
2
|
+
|
|
3
|
+
import OsmElement from '../model/OsmElement.js';
|
|
4
|
+
|
|
5
|
+
class LevelChange {
|
|
6
|
+
|
|
7
|
+
/** @type {!string} [up|down] */
|
|
8
|
+
direction;
|
|
9
|
+
|
|
10
|
+
/** @type {!number} [-2, -1, 1, ...] */
|
|
11
|
+
difference;
|
|
12
|
+
|
|
13
|
+
/** @type {?string} [elevator|conveyor|stairs] */
|
|
14
|
+
type = null;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @param {GraphNode<OsmElement>} firstNode
|
|
18
|
+
* @param {GraphNode<OsmElement>} secondNode
|
|
19
|
+
* @returns {LevelChange}
|
|
20
|
+
*/
|
|
21
|
+
static fromTwoNodes(firstNode, secondNode) {
|
|
22
|
+
|
|
23
|
+
const levelChange = new LevelChange();
|
|
24
|
+
|
|
25
|
+
const edge = GraphUtils.getEdgeByNodes(firstNode.edges, firstNode, secondNode);
|
|
26
|
+
|
|
27
|
+
if (edge.builtFrom.isElevator) {
|
|
28
|
+
levelChange.type = 'elevator';
|
|
29
|
+
} else if (edge.builtFrom.isConveying) {
|
|
30
|
+
levelChange.type = 'conveyor';
|
|
31
|
+
} else if (edge.builtFrom.areStairs) {
|
|
32
|
+
levelChange.type = 'stairs';
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
levelChange.difference = Level.diff(firstNode.coords.level, secondNode.coords.level);
|
|
36
|
+
levelChange.direction = levelChange.difference > 0 ? 'up' : 'down';
|
|
37
|
+
|
|
38
|
+
return levelChange;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @returns {object}
|
|
43
|
+
*/
|
|
44
|
+
toJson() {
|
|
45
|
+
return {
|
|
46
|
+
direction: this.direction,
|
|
47
|
+
difference: this.difference,
|
|
48
|
+
type: this.type
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* @param {object} json
|
|
54
|
+
* @returns {LevelChange}
|
|
55
|
+
*/
|
|
56
|
+
static fromJson(json) {
|
|
57
|
+
const levelChange = new LevelChange();
|
|
58
|
+
levelChange.direction = json.direction;
|
|
59
|
+
levelChange.difference = json.difference;
|
|
60
|
+
levelChange.type = json.type;
|
|
61
|
+
return levelChange;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export default LevelChange;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Coordinates } from '@wemap/geo';
|
|
2
|
+
|
|
3
|
+
import Itinerary from './Itinerary.js';
|
|
4
|
+
class RouterResponse {
|
|
5
|
+
|
|
6
|
+
/** @type {!string} */
|
|
7
|
+
routerName;
|
|
8
|
+
|
|
9
|
+
/** @type {!Coordinates} */
|
|
10
|
+
from;
|
|
11
|
+
|
|
12
|
+
/** @type {!Coordinates} */
|
|
13
|
+
to;
|
|
14
|
+
|
|
15
|
+
/** @type {!(Itinerary[])} */
|
|
16
|
+
itineraries = [];
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export default RouterResponse;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import chai from 'chai';
|
|
2
|
+
|
|
3
|
+
import { Coordinates } from '@wemap/geo';
|
|
4
|
+
|
|
5
|
+
import RouterResponse from './RouterResponse.js';
|
|
6
|
+
|
|
7
|
+
import { verifyItineraryData } from './Itinerary.type.spec.js';
|
|
8
|
+
|
|
9
|
+
const { expect } = chai;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @param {RouterResponse} routerResponse
|
|
13
|
+
*/
|
|
14
|
+
export function verifyRouterResponseData(routerResponse) {
|
|
15
|
+
|
|
16
|
+
expect(routerResponse).instanceOf(RouterResponse);
|
|
17
|
+
expect(routerResponse.routerName).be.a('string');
|
|
18
|
+
expect(routerResponse.from).instanceOf(Coordinates);
|
|
19
|
+
expect(routerResponse.to).instanceOf(Coordinates);
|
|
20
|
+
expect(routerResponse.itineraries).be.an('array');
|
|
21
|
+
routerResponse.itineraries.forEach(verifyItineraryData);
|
|
22
|
+
|
|
23
|
+
}
|
|
24
|
+
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { Coordinates } from '@wemap/geo';
|
|
2
|
+
|
|
3
|
+
import LevelChange from './LevelChange.js';
|
|
4
|
+
|
|
5
|
+
class Step {
|
|
6
|
+
|
|
7
|
+
/** @type {!boolean} */
|
|
8
|
+
firstStep = false;
|
|
9
|
+
|
|
10
|
+
/** @type {!boolean} */
|
|
11
|
+
lastStep = false;
|
|
12
|
+
|
|
13
|
+
/** @type {!number} */
|
|
14
|
+
number;
|
|
15
|
+
|
|
16
|
+
/** @type {!Coordinates} */
|
|
17
|
+
coords = [];
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
/** @type {!number} */
|
|
21
|
+
angle;
|
|
22
|
+
|
|
23
|
+
/** @type {!number} */
|
|
24
|
+
previousBearing;
|
|
25
|
+
|
|
26
|
+
/** @type {!number} */
|
|
27
|
+
nextBearing;
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
/** @type {!number} */
|
|
31
|
+
distance;
|
|
32
|
+
|
|
33
|
+
/** @type {?number} */
|
|
34
|
+
duration = null;
|
|
35
|
+
|
|
36
|
+
/** @type {?string} */
|
|
37
|
+
name = null;
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
/** @type {?LevelChange} */
|
|
41
|
+
levelChange = null;
|
|
42
|
+
|
|
43
|
+
/** @type {?{?subwayEntrance: boolean, ?subwayEntranceRef: string}} */
|
|
44
|
+
extras = {};
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* @returns {object}
|
|
48
|
+
*/
|
|
49
|
+
toJson() {
|
|
50
|
+
const output = {
|
|
51
|
+
number: this.number,
|
|
52
|
+
coords: this.coords.toCompressedJson(),
|
|
53
|
+
angle: this.angle,
|
|
54
|
+
previousBearing: this.previousBearing,
|
|
55
|
+
nextBearing: this.nextBearing,
|
|
56
|
+
distance: this.distance
|
|
57
|
+
};
|
|
58
|
+
if (this.firstStep) {
|
|
59
|
+
output.firstStep = true;
|
|
60
|
+
}
|
|
61
|
+
if (this.lastStep) {
|
|
62
|
+
output.lastStep = true;
|
|
63
|
+
}
|
|
64
|
+
if (this.duration !== null) {
|
|
65
|
+
output.duration = this.duration;
|
|
66
|
+
}
|
|
67
|
+
if (this.name !== null) {
|
|
68
|
+
output.name = this.name;
|
|
69
|
+
}
|
|
70
|
+
if (this.levelChange !== null) {
|
|
71
|
+
output.levelChange = this.levelChange.toJson();
|
|
72
|
+
}
|
|
73
|
+
if (this.extras !== null) {
|
|
74
|
+
output.extras = this.extras;
|
|
75
|
+
}
|
|
76
|
+
return output;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* @param {object} json
|
|
81
|
+
* @returns {Step}
|
|
82
|
+
*/
|
|
83
|
+
static fromJson(json) {
|
|
84
|
+
const step = new Step();
|
|
85
|
+
step.number = json.number;
|
|
86
|
+
step.coords = Coordinates.fromCompressedJson(json.coords);
|
|
87
|
+
step.angle = json.angle;
|
|
88
|
+
step.previousBearing = json.previousBearing;
|
|
89
|
+
step.nextBearing = json.nextBearing;
|
|
90
|
+
step.distance = json.distance;
|
|
91
|
+
if (json.firstStep) {
|
|
92
|
+
step.firstStep = json.firstStep;
|
|
93
|
+
}
|
|
94
|
+
if (json.lastStep) {
|
|
95
|
+
step.lastStep = json.lastStep;
|
|
96
|
+
}
|
|
97
|
+
if (json.duration) {
|
|
98
|
+
step.duration = json.duration;
|
|
99
|
+
}
|
|
100
|
+
if (json.name) {
|
|
101
|
+
step.name = json.name;
|
|
102
|
+
}
|
|
103
|
+
if (json.levelChange) {
|
|
104
|
+
step.levelChange = LevelChange.fromJson(json.levelChange);
|
|
105
|
+
}
|
|
106
|
+
if (json.extras) {
|
|
107
|
+
step.extras = json.extras;
|
|
108
|
+
}
|
|
109
|
+
return step;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export default Step;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import Itinerary from './Itinerary.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @param {Itinerary} itinerary
|
|
5
|
+
*/
|
|
6
|
+
export function generateStepsNumbers(itinerary) {
|
|
7
|
+
let counter = 1;
|
|
8
|
+
itinerary.legs.forEach((leg, legId) => {
|
|
9
|
+
leg.steps.forEach((step, stepId) => {
|
|
10
|
+
|
|
11
|
+
if (counter === 1) {
|
|
12
|
+
step.firstStep = true;
|
|
13
|
+
}
|
|
14
|
+
if (legId === itinerary.legs.length - 1
|
|
15
|
+
&& stepId === leg.steps.length - 1) {
|
|
16
|
+
step.lastStep = true;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
step.number = counter++;
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
}
|