@wemap/routers 11.0.0-alpha.8 → 11.0.1
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/dist/index.js +533 -291
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +536 -295
- package/dist/index.mjs.map +1 -1
- package/helpers/InstructionManager.ts +4 -4
- package/index.ts +7 -9
- package/package.json +9 -7
- package/src/ItineraryInfoManager.spec.ts +14 -14
- package/src/ItineraryInfoManager.ts +13 -13
- package/src/model/Itinerary.spec.ts +12 -6
- package/src/model/Itinerary.ts +70 -69
- package/src/model/Leg.spec.ts +4 -4
- package/src/model/Leg.ts +78 -33
- package/src/model/Step.spec.ts +99 -0
- package/src/model/Step.ts +78 -11
- package/src/model/generateSteps.ts +20 -12
- package/src/remote/RemoteRouterManager.ts +17 -15
- package/src/remote/cityway/CitywayRemoteRouter.ts +16 -11
- package/src/remote/deutsche-bahn/DeutscheBahnRemoteRouter.ts +1 -3
- package/src/remote/idfm/IdfmRemoteRouter.ts +31 -31
- package/src/remote/osrm/OsrmRemoteRouter.ts +5 -8
- package/src/remote/otp/OtpRemoteRouter.ts +9 -12
- package/src/remote/wemap-multi/WemapMultiRemoteRouter.ts +1 -3
- package/src/remote/wemap-multi/WemapMultiRemoteRouterPayload.ts +3 -3
- package/src/wemap-multi/CustomNetworkMap.ts +56 -32
- package/src/wemap-multi/WemapMultiRouter.ts +71 -24
- package/src/wemap-multi/WemapMultiRouterOptions.ts +5 -1
- package/src/wemap-osm/OsmGraph.spec.ts +99 -0
- package/src/wemap-osm/OsmGraph.ts +188 -0
- package/src/wemap-osm/{WemapOsmRouter.spec.ts → OsmRouter.spec.ts} +94 -35
- package/src/wemap-osm/OsmRouter.ts +210 -0
- package/vite.config.ts +1 -1
- package/src/model/ItineraryInfo.ts +0 -19
- package/src/model/StepInfo.spec.ts +0 -78
- package/src/model/StepInfo.ts +0 -78
- package/src/wemap-osm/WemapOsmRouter.ts +0 -82
- package/src/wemap-osm/WemapOsmRouterOptions.ts +0 -23
- package/src/wemap-osm/WemapOsmRouterUtils.ts +0 -21
package/dist/index.js
CHANGED
|
@@ -8,13 +8,14 @@ var __publicField = (obj, key, value) => {
|
|
|
8
8
|
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
9
9
|
const geo = require("@wemap/geo");
|
|
10
10
|
const maths = require("@wemap/maths");
|
|
11
|
+
const salesman = require("@wemap/salesman.js");
|
|
11
12
|
const osm = require("@wemap/osm");
|
|
12
13
|
const Logger = require("@wemap/logger");
|
|
13
14
|
const Polyline = require("@mapbox/polyline");
|
|
14
15
|
const pointInPolygon = require("@turf/boolean-point-in-polygon");
|
|
15
16
|
const convexHullFn = require("@turf/convex");
|
|
16
|
-
const helpers = require("@turf/helpers");
|
|
17
17
|
const _interopDefaultLegacy = (e) => e && typeof e === "object" && "default" in e ? e : { default: e };
|
|
18
|
+
const salesman__default = /* @__PURE__ */ _interopDefaultLegacy(salesman);
|
|
18
19
|
const Logger__default = /* @__PURE__ */ _interopDefaultLegacy(Logger);
|
|
19
20
|
const Polyline__default = /* @__PURE__ */ _interopDefaultLegacy(Polyline);
|
|
20
21
|
const pointInPolygon__default = /* @__PURE__ */ _interopDefaultLegacy(pointInPolygon);
|
|
@@ -22,53 +23,6 @@ const convexHullFn__default = /* @__PURE__ */ _interopDefaultLegacy(convexHullFn
|
|
|
22
23
|
function getDurationFromLength(length, speed = 5) {
|
|
23
24
|
return length / (speed * 1e3 / 3600);
|
|
24
25
|
}
|
|
25
|
-
function areLevelChangeEquals(l1, l2) {
|
|
26
|
-
return l1 === l2 || l1.difference === l2.difference && l1.direction === l2.direction && l1.type === l2.type;
|
|
27
|
-
}
|
|
28
|
-
class StepInfo {
|
|
29
|
-
constructor({
|
|
30
|
-
coords,
|
|
31
|
-
distance,
|
|
32
|
-
name,
|
|
33
|
-
levelChange,
|
|
34
|
-
extras,
|
|
35
|
-
duration
|
|
36
|
-
}) {
|
|
37
|
-
__publicField(this, "coords");
|
|
38
|
-
__publicField(this, "name");
|
|
39
|
-
__publicField(this, "distance");
|
|
40
|
-
__publicField(this, "duration");
|
|
41
|
-
__publicField(this, "levelChange");
|
|
42
|
-
__publicField(this, "extras");
|
|
43
|
-
this.coords = coords;
|
|
44
|
-
this.name = name || null;
|
|
45
|
-
this.distance = typeof distance === "number" ? distance : null;
|
|
46
|
-
this.duration = typeof duration === "number" ? duration : null;
|
|
47
|
-
this.levelChange = levelChange || null;
|
|
48
|
-
this.extras = extras || null;
|
|
49
|
-
}
|
|
50
|
-
static equals(obj1, obj2) {
|
|
51
|
-
return obj1.coords.equals(obj2.coords) && obj1.distance === obj2.distance && obj1.duration === obj2.duration && obj1.name === obj2.name && (obj1.levelChange === obj2.levelChange || obj1.levelChange && obj2.levelChange && areLevelChangeEquals(obj1.levelChange, obj2.levelChange));
|
|
52
|
-
}
|
|
53
|
-
equals(obj) {
|
|
54
|
-
return StepInfo.equals(this, obj);
|
|
55
|
-
}
|
|
56
|
-
toJson() {
|
|
57
|
-
return {
|
|
58
|
-
coords: this.coords.toCompressedJson(),
|
|
59
|
-
...this.distance !== null && { distance: this.distance },
|
|
60
|
-
...this.duration !== null && { duration: this.duration },
|
|
61
|
-
...this.name !== null && { name: this.name },
|
|
62
|
-
...this.levelChange !== null && { levelChange: this.levelChange },
|
|
63
|
-
...this.extras && Object.keys(this.extras).length !== 0 && { extras: this.extras }
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
static fromJson(json) {
|
|
67
|
-
return new StepInfo(Object.assign({}, json, {
|
|
68
|
-
coords: geo.Coordinates.fromCompressedJson(json.coords)
|
|
69
|
-
}));
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
26
|
const SKIP_STEP_ANGLE_MAX = maths.deg2rad(20);
|
|
73
27
|
function generateSteps(leg, rules) {
|
|
74
28
|
const steps = [];
|
|
@@ -85,26 +39,30 @@ function generateSteps(leg, rules) {
|
|
|
85
39
|
let splitByAngle = Math.abs(maths.diffAngle(Math.PI, angle)) >= SKIP_STEP_ANGLE_MAX;
|
|
86
40
|
const splitByLevel = geo.Level.isRange(edgeLevel) && !geo.Level.isRange(currentCoords.level);
|
|
87
41
|
splitByAngle = splitByAngle && !(currentCoords.level && geo.Level.isRange(currentCoords.level));
|
|
88
|
-
const
|
|
42
|
+
const previousStep = steps.length ? steps[steps.length - 1] : null;
|
|
43
|
+
const customRules = rules == null ? void 0 : rules(currentCoords, nextCoords, previousStep);
|
|
89
44
|
const splitStepCondition = splitByAngle || splitByLevel || (customRules == null ? void 0 : customRules.createNewStep);
|
|
90
45
|
if (isFirstStep || splitStepCondition) {
|
|
91
46
|
let levelChange;
|
|
92
|
-
if (splitByLevel) {
|
|
93
|
-
const difference = geo.Level.diff(currentCoords.level, nextCoords.level);
|
|
94
|
-
|
|
47
|
+
if (splitByLevel || (customRules == null ? void 0 : customRules.levelChangeType)) {
|
|
48
|
+
const difference = geo.Level.diff(currentCoords.level, nextCoords.level) || 0;
|
|
49
|
+
let direction = difference > 0 ? "up" : "down";
|
|
50
|
+
if (difference === 0 && (customRules == null ? void 0 : customRules.levelChangeDirection)) {
|
|
51
|
+
direction = customRules.levelChangeDirection;
|
|
52
|
+
}
|
|
95
53
|
levelChange = { difference, direction, type: customRules == null ? void 0 : customRules.levelChangeType };
|
|
96
54
|
}
|
|
97
55
|
if (currentStep && currentStep.duration === 0) {
|
|
98
|
-
currentStep.duration
|
|
56
|
+
delete currentStep.duration;
|
|
99
57
|
}
|
|
100
|
-
currentStep =
|
|
58
|
+
currentStep = {
|
|
101
59
|
coords: currentCoords,
|
|
102
60
|
name: customRules == null ? void 0 : customRules.stepName,
|
|
103
61
|
extras: customRules == null ? void 0 : customRules.stepExtras,
|
|
104
62
|
levelChange,
|
|
105
63
|
distance: 0,
|
|
106
64
|
duration: 0
|
|
107
|
-
}
|
|
65
|
+
};
|
|
108
66
|
steps.push(currentStep);
|
|
109
67
|
}
|
|
110
68
|
currentStep.distance += currentCoords.distanceTo(nextCoords);
|
|
@@ -115,7 +73,7 @@ function generateSteps(leg, rules) {
|
|
|
115
73
|
}
|
|
116
74
|
const lastCoords = coordsArray[coordsArray.length - 1];
|
|
117
75
|
if (!geo.Coordinates.equals(lastCoords, to.coords)) {
|
|
118
|
-
steps.push(
|
|
76
|
+
steps.push({ coords: lastCoords });
|
|
119
77
|
}
|
|
120
78
|
return steps;
|
|
121
79
|
}
|
|
@@ -131,6 +89,36 @@ function isRoutingModePublicTransport(routingMode) {
|
|
|
131
89
|
"TRAM"
|
|
132
90
|
].includes(routingMode);
|
|
133
91
|
}
|
|
92
|
+
function stepToJson(step) {
|
|
93
|
+
return {
|
|
94
|
+
...step.firstStep && { firstStep: true },
|
|
95
|
+
...step.lastStep && { lastStep: true },
|
|
96
|
+
number: step.number,
|
|
97
|
+
coords: step.coords.toCompressedJson(),
|
|
98
|
+
...step.name !== null && { name: step.name },
|
|
99
|
+
angle: Number(step.angle.toFixed(2)),
|
|
100
|
+
previousBearing: Number(step.previousBearing.toFixed(2)),
|
|
101
|
+
nextBearing: Number(step.nextBearing.toFixed(2)),
|
|
102
|
+
distance: Number(step.distance.toFixed(1)),
|
|
103
|
+
duration: Number(step.duration.toFixed(1)),
|
|
104
|
+
...step.levelChange !== null && { levelChange: step.levelChange },
|
|
105
|
+
...step.extras && Object.keys(step.extras).length !== 0 && { extras: step.extras }
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function jsonToStep(json) {
|
|
109
|
+
return Object.assign({}, json, {
|
|
110
|
+
coords: geo.Coordinates.fromCompressedJson(json.coords),
|
|
111
|
+
firstStep: Boolean(json.firstStep),
|
|
112
|
+
lastStep: Boolean(json.lastStep),
|
|
113
|
+
name: json.name || null,
|
|
114
|
+
levelChange: json.levelChange || null,
|
|
115
|
+
extras: json.extras || null
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
function stepEquals(step1, step2) {
|
|
119
|
+
var _a, _b, _c, _d, _e, _f;
|
|
120
|
+
return step1.coords.equals(step2.coords) && Math.abs(step1.angle - step2.angle) <= 5e-3 && Math.abs(step1.distance - step2.distance) <= 0.05 && Math.abs(step1.duration - step2.duration) <= 0.05 && step1.firstStep === step2.firstStep && step1.lastStep === step2.lastStep && ((_a = step1.levelChange) == null ? void 0 : _a.difference) === ((_b = step2.levelChange) == null ? void 0 : _b.difference) && ((_c = step1.levelChange) == null ? void 0 : _c.direction) === ((_d = step2.levelChange) == null ? void 0 : _d.direction) && ((_e = step1.levelChange) == null ? void 0 : _e.type) === ((_f = step2.levelChange) == null ? void 0 : _f.type) && step1.name === step2.name && Math.abs(step1.nextBearing - step2.nextBearing) <= 5e-3 && step1.number === step2.number && Math.abs(step1.previousBearing - step2.previousBearing) <= 5e-3;
|
|
121
|
+
}
|
|
134
122
|
class Leg {
|
|
135
123
|
constructor({
|
|
136
124
|
from,
|
|
@@ -151,7 +139,7 @@ class Leg {
|
|
|
151
139
|
__publicField(this, "duration");
|
|
152
140
|
__publicField(this, "startTime");
|
|
153
141
|
__publicField(this, "endTime");
|
|
154
|
-
__publicField(this, "
|
|
142
|
+
__publicField(this, "steps");
|
|
155
143
|
__publicField(this, "transportInfo");
|
|
156
144
|
this.from = {
|
|
157
145
|
name: from.name || null,
|
|
@@ -168,17 +156,22 @@ class Leg {
|
|
|
168
156
|
this.startTime = typeof startTime === "number" ? startTime : null;
|
|
169
157
|
this.endTime = typeof endTime === "number" ? endTime : null;
|
|
170
158
|
this.transportInfo = transportInfo || null;
|
|
171
|
-
|
|
159
|
+
if ("steps" in otherParams) {
|
|
160
|
+
this.steps = otherParams.steps;
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
const minStepsInfo = "minStepsInfo" in otherParams ? otherParams.minStepsInfo : generateSteps(this, otherParams.stepsGenerationRules);
|
|
164
|
+
this.steps = Leg.generateStepsFromMinStepInfo(from.coords, to.coords, coords, minStepsInfo);
|
|
172
165
|
}
|
|
173
166
|
isPublicTransport() {
|
|
174
167
|
return isRoutingModePublicTransport(this.mode);
|
|
175
168
|
}
|
|
176
|
-
|
|
177
|
-
return geo.
|
|
169
|
+
toGraph() {
|
|
170
|
+
return geo.GeoGraph.fromCoordinates([this.coords]);
|
|
178
171
|
}
|
|
179
172
|
static equals(obj1, obj2) {
|
|
180
173
|
var _a, _b;
|
|
181
|
-
const intermediate = obj1.mode === obj2.mode && obj1.duration
|
|
174
|
+
const intermediate = obj1.mode === obj2.mode && Math.abs(obj1.duration - obj2.duration) <= 0.05 && obj1.startTime === obj2.startTime && obj1.endTime === obj2.endTime && obj1.from.name === obj2.from.name && obj1.from.coords.equals(obj2.from.coords) && obj1.to.name === obj2.to.name && obj1.to.coords.equals(obj2.to.coords) && obj1.coords.length === obj2.coords.length && (obj1.steps === obj2.steps || ((_a = obj1.steps) == null ? void 0 : _a.length) === ((_b = obj2.steps) == null ? void 0 : _b.length));
|
|
182
175
|
if (!intermediate) {
|
|
183
176
|
return false;
|
|
184
177
|
}
|
|
@@ -188,11 +181,9 @@ class Leg {
|
|
|
188
181
|
return false;
|
|
189
182
|
}
|
|
190
183
|
}
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
return false;
|
|
195
|
-
}
|
|
184
|
+
for (i = 0; i < obj1.steps.length; i++) {
|
|
185
|
+
if (!stepEquals(obj1.steps[i], obj2.steps[i])) {
|
|
186
|
+
return false;
|
|
196
187
|
}
|
|
197
188
|
}
|
|
198
189
|
if (obj1.transportInfo !== obj2.transportInfo) {
|
|
@@ -219,9 +210,9 @@ class Leg {
|
|
|
219
210
|
coords: this.to.coords.toCompressedJson(),
|
|
220
211
|
...this.to.name && { name: this.to.name }
|
|
221
212
|
},
|
|
222
|
-
duration: this.duration,
|
|
213
|
+
duration: Number(this.duration.toFixed(1)),
|
|
223
214
|
coords: this.coords.map((coords) => coords.toCompressedJson()),
|
|
224
|
-
steps: this.
|
|
215
|
+
steps: this.steps.map(stepToJson),
|
|
225
216
|
...this.startTime !== null && { startTime: this.startTime },
|
|
226
217
|
...this.endTime !== null && { endTime: this.endTime },
|
|
227
218
|
...this.transportInfo !== null && { transportInfo: this.transportInfo }
|
|
@@ -239,8 +230,7 @@ class Leg {
|
|
|
239
230
|
name: json.to.name || null
|
|
240
231
|
},
|
|
241
232
|
coords: json.coords.map(geo.Coordinates.fromCompressedJson),
|
|
242
|
-
|
|
243
|
-
stepsGenerationRules: void 0
|
|
233
|
+
steps: ((_a = json.steps) == null ? void 0 : _a.map(jsonToStep)) || null
|
|
244
234
|
}));
|
|
245
235
|
return leg;
|
|
246
236
|
}
|
|
@@ -248,7 +238,7 @@ class Leg {
|
|
|
248
238
|
return new Leg({
|
|
249
239
|
from: { coords: graphItinerary.start },
|
|
250
240
|
to: { coords: graphItinerary.end },
|
|
251
|
-
coords: graphItinerary.
|
|
241
|
+
coords: graphItinerary.vertices.map((vertex) => vertex.coords),
|
|
252
242
|
duration: graphItinerary.edgesWeights.reduce((acc, weight) => acc + weight, 0),
|
|
253
243
|
mode,
|
|
254
244
|
stepsGenerationRules
|
|
@@ -260,12 +250,45 @@ class Leg {
|
|
|
260
250
|
for (const coords of this.coords) {
|
|
261
251
|
coords.level = geo.Level.multiplyBy(coords.level, levelFactor);
|
|
262
252
|
}
|
|
263
|
-
this.
|
|
253
|
+
this.steps.forEach((step) => {
|
|
264
254
|
step.coords.level = geo.Level.multiplyBy(step.coords.level, levelFactor);
|
|
265
255
|
});
|
|
266
256
|
}
|
|
267
|
-
|
|
268
|
-
return
|
|
257
|
+
static generateStepsFromMinStepInfo(from, to, legCoords, stepsInfo) {
|
|
258
|
+
return stepsInfo.map((stepInfo, stepId) => {
|
|
259
|
+
const coordsId = legCoords.findIndex((coords) => coords.equals(stepInfo.coords));
|
|
260
|
+
if (coordsId === -1) {
|
|
261
|
+
throw new Error("Cannot find step coordinates in itinerary coordinates.");
|
|
262
|
+
}
|
|
263
|
+
const coordsBeforeStep = coordsId === 0 ? from : legCoords[coordsId - 1];
|
|
264
|
+
const coordsAfterStep = coordsId === legCoords.length - 1 ? to : legCoords[coordsId + 1];
|
|
265
|
+
const previousBearing = coordsBeforeStep.bearingTo(stepInfo.coords);
|
|
266
|
+
const nextBearing = stepInfo.coords.bearingTo(coordsAfterStep);
|
|
267
|
+
let distance = 0;
|
|
268
|
+
const coordsToStopCalculation = stepId !== stepsInfo.length - 1 ? stepsInfo[stepId + 1].coords : legCoords[legCoords.length - 1];
|
|
269
|
+
let currentCoordsId = coordsId;
|
|
270
|
+
while (!legCoords[currentCoordsId].equals(coordsToStopCalculation)) {
|
|
271
|
+
distance += legCoords[currentCoordsId].distanceTo(legCoords[currentCoordsId + 1]);
|
|
272
|
+
currentCoordsId++;
|
|
273
|
+
}
|
|
274
|
+
if (currentCoordsId === legCoords.length - 1) {
|
|
275
|
+
distance += legCoords[currentCoordsId].distanceTo(to);
|
|
276
|
+
}
|
|
277
|
+
return {
|
|
278
|
+
coords: stepInfo.coords,
|
|
279
|
+
name: stepInfo.name || null,
|
|
280
|
+
number: stepId + 1,
|
|
281
|
+
previousBearing,
|
|
282
|
+
nextBearing,
|
|
283
|
+
angle: maths.diffAngle(previousBearing, nextBearing + Math.PI),
|
|
284
|
+
firstStep: stepId === 0,
|
|
285
|
+
lastStep: stepId === stepsInfo.length - 1,
|
|
286
|
+
distance,
|
|
287
|
+
duration: stepInfo.duration || getDurationFromLength(distance),
|
|
288
|
+
levelChange: stepInfo.levelChange || null,
|
|
289
|
+
extras: stepInfo.extras || null
|
|
290
|
+
};
|
|
291
|
+
});
|
|
269
292
|
}
|
|
270
293
|
}
|
|
271
294
|
class Itinerary {
|
|
@@ -285,7 +308,6 @@ class Itinerary {
|
|
|
285
308
|
__publicField(this, "startTime");
|
|
286
309
|
__publicField(this, "endTime");
|
|
287
310
|
__publicField(this, "_coords", null);
|
|
288
|
-
__publicField(this, "_steps", null);
|
|
289
311
|
__publicField(this, "_distance", null);
|
|
290
312
|
this.from = from;
|
|
291
313
|
this.to = to;
|
|
@@ -293,6 +315,7 @@ class Itinerary {
|
|
|
293
315
|
this.duration = typeof duration === "number" ? duration : this.legs.reduce((dur, leg) => dur + leg.duration, 0);
|
|
294
316
|
this.startTime = typeof startTime === "number" ? startTime : null;
|
|
295
317
|
this.endTime = typeof endTime === "number" ? endTime : null;
|
|
318
|
+
this.updateStepsFromLegs();
|
|
296
319
|
}
|
|
297
320
|
set coords(_) {
|
|
298
321
|
throw new Error("Itinerary.coords cannot be set. They are calculated from Itinerary.legs.");
|
|
@@ -307,45 +330,7 @@ class Itinerary {
|
|
|
307
330
|
throw new Error("Itinerary.step cannot be set. They are calculated from Itinerary.legs.");
|
|
308
331
|
}
|
|
309
332
|
get steps() {
|
|
310
|
-
|
|
311
|
-
return this._steps;
|
|
312
|
-
}
|
|
313
|
-
const itineraryCoords = this.coords.filter((coords, idx, arr) => idx === 0 || !arr[idx - 1].equals(coords));
|
|
314
|
-
const stepsInfo = this.legs.map((leg) => leg.stepsInfo).flat();
|
|
315
|
-
const steps = stepsInfo.map((stepInfo, stepId) => {
|
|
316
|
-
const coordsId = itineraryCoords.findIndex((coords) => coords.equals(stepInfo.coords));
|
|
317
|
-
if (coordsId === -1) {
|
|
318
|
-
throw new Error("Cannot find step coordinates in itinerary coordinates.");
|
|
319
|
-
}
|
|
320
|
-
const coordsBeforeStep = coordsId === 0 ? this.from : itineraryCoords[coordsId - 1];
|
|
321
|
-
const coordsAfterStep = coordsId === itineraryCoords.length - 1 ? this.to : itineraryCoords[coordsId + 1];
|
|
322
|
-
const previousBearing = coordsBeforeStep.bearingTo(stepInfo.coords);
|
|
323
|
-
const nextBearing = stepInfo.coords.bearingTo(coordsAfterStep);
|
|
324
|
-
let distance = 0;
|
|
325
|
-
const coordsToStopCalculation = stepId !== stepsInfo.length - 1 ? stepsInfo[stepId + 1].coords : itineraryCoords[itineraryCoords.length - 1];
|
|
326
|
-
let currentCoordsId = coordsId;
|
|
327
|
-
while (!itineraryCoords[currentCoordsId].equals(coordsToStopCalculation)) {
|
|
328
|
-
distance += itineraryCoords[currentCoordsId].distanceTo(itineraryCoords[currentCoordsId + 1]);
|
|
329
|
-
currentCoordsId++;
|
|
330
|
-
}
|
|
331
|
-
if (currentCoordsId === itineraryCoords.length - 1) {
|
|
332
|
-
distance += itineraryCoords[currentCoordsId].distanceTo(this.to);
|
|
333
|
-
}
|
|
334
|
-
return {
|
|
335
|
-
...stepInfo,
|
|
336
|
-
number: stepId + 1,
|
|
337
|
-
previousBearing,
|
|
338
|
-
nextBearing,
|
|
339
|
-
angle: maths.diffAngle(previousBearing, nextBearing + Math.PI),
|
|
340
|
-
firstStep: stepId === 0,
|
|
341
|
-
lastStep: stepId === stepsInfo.length - 1,
|
|
342
|
-
distance,
|
|
343
|
-
duration: stepInfo.duration || getDurationFromLength(distance),
|
|
344
|
-
previousStep: null,
|
|
345
|
-
nextStep: null
|
|
346
|
-
};
|
|
347
|
-
});
|
|
348
|
-
return steps;
|
|
333
|
+
return this.legs.map((leg) => leg.steps).flat();
|
|
349
334
|
}
|
|
350
335
|
set mode(_) {
|
|
351
336
|
throw new Error("Itinerary.mode cannot be set. They are calculated from Itinerary.legs.");
|
|
@@ -381,8 +366,8 @@ class Itinerary {
|
|
|
381
366
|
}
|
|
382
367
|
return this._distance;
|
|
383
368
|
}
|
|
384
|
-
|
|
385
|
-
return geo.
|
|
369
|
+
toGraph() {
|
|
370
|
+
return geo.GeoGraph.fromCoordinates([this.coords]);
|
|
386
371
|
}
|
|
387
372
|
static fromItineraries(...itineraries) {
|
|
388
373
|
let duration = 0;
|
|
@@ -416,7 +401,7 @@ class Itinerary {
|
|
|
416
401
|
return new Itinerary({ from, to, legs: [leg] });
|
|
417
402
|
}
|
|
418
403
|
static equals(obj1, obj2) {
|
|
419
|
-
const intermediate = obj1.from.equals(obj2.from) && obj1.to.equals(obj2.to) && obj1.distance
|
|
404
|
+
const intermediate = obj1.from.equals(obj2.from) && obj1.to.equals(obj2.to) && Math.abs(obj1.distance - obj2.distance) <= 0.05 && Math.abs(obj1.duration - obj2.duration) <= 0.05 && obj1.startTime === obj2.startTime && obj1.endTime === obj2.endTime && obj1.legs.length === obj2.legs.length;
|
|
420
405
|
if (!intermediate) {
|
|
421
406
|
return false;
|
|
422
407
|
}
|
|
@@ -434,7 +419,7 @@ class Itinerary {
|
|
|
434
419
|
return {
|
|
435
420
|
from: this.from.toCompressedJson(),
|
|
436
421
|
to: this.to.toCompressedJson(),
|
|
437
|
-
duration: this.duration,
|
|
422
|
+
duration: Number(this.duration.toFixed(1)),
|
|
438
423
|
mode: this.mode,
|
|
439
424
|
legs: this.legs.map((leg) => leg.toJson()),
|
|
440
425
|
...this.startTime !== null && { startTime: this.startTime },
|
|
@@ -474,8 +459,8 @@ class Itinerary {
|
|
|
474
459
|
for (const coords of leg.coords) {
|
|
475
460
|
coords.level = coords.level || 0;
|
|
476
461
|
}
|
|
477
|
-
if (leg.
|
|
478
|
-
for (const step of leg.
|
|
462
|
+
if (leg.steps) {
|
|
463
|
+
for (const step of leg.steps) {
|
|
479
464
|
step.coords.level = step.coords.level || 0;
|
|
480
465
|
}
|
|
481
466
|
}
|
|
@@ -496,6 +481,36 @@ class Itinerary {
|
|
|
496
481
|
}
|
|
497
482
|
};
|
|
498
483
|
}
|
|
484
|
+
updateStepsFromLegs() {
|
|
485
|
+
const itineraryCoords = this.coords.filter((coords, idx, arr) => idx === 0 || !arr[idx - 1].equals(coords));
|
|
486
|
+
const steps = this.legs.map((leg) => leg.steps).flat();
|
|
487
|
+
steps.map((step, stepId) => {
|
|
488
|
+
const coordsId = itineraryCoords.findIndex((coords) => coords.equals(step.coords));
|
|
489
|
+
if (coordsId === -1) {
|
|
490
|
+
throw new Error("Cannot find step coordinates in itinerary coordinates.");
|
|
491
|
+
}
|
|
492
|
+
const coordsBeforeStep = coordsId === 0 ? this.from : itineraryCoords[coordsId - 1];
|
|
493
|
+
const coordsAfterStep = coordsId === itineraryCoords.length - 1 ? this.to : itineraryCoords[coordsId + 1];
|
|
494
|
+
step.previousBearing = coordsBeforeStep.bearingTo(step.coords);
|
|
495
|
+
step.nextBearing = step.coords.bearingTo(coordsAfterStep);
|
|
496
|
+
step.angle = maths.diffAngle(step.previousBearing, step.nextBearing + Math.PI);
|
|
497
|
+
const stepDistanceBefore = step.distance;
|
|
498
|
+
step.distance = 0;
|
|
499
|
+
const coordsToStopCalculation = stepId !== steps.length - 1 ? steps[stepId + 1].coords : itineraryCoords[itineraryCoords.length - 1];
|
|
500
|
+
let currentCoordsId = coordsId;
|
|
501
|
+
while (!itineraryCoords[currentCoordsId].equals(coordsToStopCalculation)) {
|
|
502
|
+
step.distance += itineraryCoords[currentCoordsId].distanceTo(itineraryCoords[currentCoordsId + 1]);
|
|
503
|
+
currentCoordsId++;
|
|
504
|
+
}
|
|
505
|
+
if (currentCoordsId === itineraryCoords.length - 1) {
|
|
506
|
+
step.distance += itineraryCoords[currentCoordsId].distanceTo(this.to);
|
|
507
|
+
}
|
|
508
|
+
step.number = stepId + 1;
|
|
509
|
+
step.firstStep = stepId === 0;
|
|
510
|
+
step.lastStep = stepId === steps.length - 1;
|
|
511
|
+
step.duration += getDurationFromLength(step.distance - stepDistanceBefore);
|
|
512
|
+
});
|
|
513
|
+
}
|
|
499
514
|
}
|
|
500
515
|
class RouterResponse {
|
|
501
516
|
constructor({
|
|
@@ -558,71 +573,267 @@ class RouterResponse {
|
|
|
558
573
|
}
|
|
559
574
|
}
|
|
560
575
|
}
|
|
561
|
-
const
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
576
|
+
const HIGHWAYS_PEDESTRIANS = ["footway", "steps", "pedestrian", "living_street", "path", "track", "sidewalk", "elevator"];
|
|
577
|
+
const DEFAULT_WAY_SELECTOR = (way) => {
|
|
578
|
+
const isElevatorArea = way.tags.highway === "elevator" && way.isArea;
|
|
579
|
+
return HIGHWAYS_PEDESTRIANS.includes(way.tags.highway) && !isElevatorArea && !["no", "private"].includes(way.tags.access) || way.tags.footway === "sidewalk" || way.tags.public_transport === "platform" || way.tags.railway === "platform";
|
|
580
|
+
};
|
|
581
|
+
const _OsmGraph = class extends geo.GeoGraph {
|
|
582
|
+
getVertexByCoords(coords) {
|
|
583
|
+
return geo.GeoGraph.getVertexByCoords(this.vertices, coords);
|
|
584
|
+
}
|
|
585
|
+
getVertexByName(name) {
|
|
586
|
+
return super.getVertexByName(name);
|
|
587
|
+
}
|
|
588
|
+
getEdgeByName(name) {
|
|
589
|
+
return super.getEdgeByName(name);
|
|
590
|
+
}
|
|
591
|
+
static fromOsmModel(osmModel, waySelectionFilter = DEFAULT_WAY_SELECTOR) {
|
|
592
|
+
const nodes = [];
|
|
593
|
+
const edges = [];
|
|
594
|
+
const nodesCreated = {};
|
|
595
|
+
const elevatorNodes = [];
|
|
596
|
+
const getOrCreateNode = (osmNode) => {
|
|
597
|
+
let node = nodesCreated[osmNode.id];
|
|
598
|
+
if (!node) {
|
|
599
|
+
node = new geo.GeoGraphVertex(osmNode.coords, { data: osmNode, name: osmNode.tags.name });
|
|
600
|
+
nodesCreated[osmNode.id] = node;
|
|
601
|
+
nodes.push(node);
|
|
602
|
+
if (osmNode.tags.highway === "elevator") {
|
|
603
|
+
elevatorNodes.push(node);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
return node;
|
|
607
|
+
};
|
|
608
|
+
osmModel.ways.forEach((way) => {
|
|
609
|
+
if (!waySelectionFilter(way)) {
|
|
610
|
+
return;
|
|
611
|
+
}
|
|
612
|
+
let firstNode = getOrCreateNode(way.nodes[0]);
|
|
613
|
+
for (let i = 1; i < way.nodes.length; i++) {
|
|
614
|
+
const secondNode = getOrCreateNode(way.nodes[i]);
|
|
615
|
+
const edge = new geo.GeoGraphEdge(
|
|
616
|
+
firstNode,
|
|
617
|
+
secondNode,
|
|
618
|
+
{ data: way, name: way.tags.name, level: way.level }
|
|
619
|
+
);
|
|
620
|
+
_OsmGraph.manageOneWay(edge, way);
|
|
621
|
+
edges.push(edge);
|
|
622
|
+
firstNode = secondNode;
|
|
623
|
+
}
|
|
624
|
+
});
|
|
625
|
+
osmModel.ways.filter((way) => way.isElevator).forEach((way) => {
|
|
626
|
+
way.nodes.forEach((node) => {
|
|
627
|
+
const connectedWays = node.ways.filter((otherWay) => otherWay != way);
|
|
628
|
+
if (connectedWays.length) {
|
|
629
|
+
const graphVertex = getOrCreateNode(node);
|
|
630
|
+
graphVertex.data.tags.highway = "elevator";
|
|
631
|
+
elevatorNodes.push(graphVertex);
|
|
632
|
+
}
|
|
633
|
+
});
|
|
634
|
+
});
|
|
635
|
+
elevatorNodes.forEach((node) => {
|
|
636
|
+
_OsmGraph.createNodesAndEdgesFromElevator(nodes, edges, node);
|
|
637
|
+
});
|
|
638
|
+
return new _OsmGraph(nodes, edges, true);
|
|
639
|
+
}
|
|
640
|
+
static manageOneWay(edge, way) {
|
|
641
|
+
const { highway, oneway, conveying } = way.tags;
|
|
642
|
+
edge.isOneway = Boolean(oneway === "yes" || oneway === "true" || oneway === "1" || conveying && highway && ["forward", "backward"].includes(conveying));
|
|
643
|
+
if (edge.isOneway && conveying === "backward") {
|
|
644
|
+
const tmpNode = edge.vertex1;
|
|
645
|
+
edge.vertex1 = edge.vertex2;
|
|
646
|
+
edge.vertex2 = tmpNode;
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
static createNodesAndEdgesFromElevator(nodes, edges, elevatorNode) {
|
|
650
|
+
const createdNodes = [];
|
|
651
|
+
const getOrCreateLevelVertex = (level) => {
|
|
652
|
+
let levelVertex = createdNodes.find(({ coords }) => geo.Level.equals(level, coords.level));
|
|
653
|
+
if (!levelVertex) {
|
|
654
|
+
levelVertex = new geo.GeoGraphVertex(elevatorNode.coords.clone(), {
|
|
655
|
+
data: elevatorNode.data,
|
|
656
|
+
name: `${elevatorNode.name} (elevator lvl: ${level})`
|
|
657
|
+
});
|
|
658
|
+
levelVertex.coords.level = level;
|
|
659
|
+
createdNodes.push(levelVertex);
|
|
660
|
+
nodes.push(levelVertex);
|
|
661
|
+
}
|
|
662
|
+
return levelVertex;
|
|
571
663
|
};
|
|
572
|
-
|
|
664
|
+
elevatorNode.edges.forEach((edge) => {
|
|
665
|
+
if (geo.Level.isRange(edge.level)) {
|
|
666
|
+
throw new Error("Cannot handle this elevator edge due to ambiguity");
|
|
667
|
+
}
|
|
668
|
+
const levelVertex = getOrCreateLevelVertex(edge.level);
|
|
669
|
+
if (edge.vertex1 === elevatorNode) {
|
|
670
|
+
edge.vertex1 = levelVertex;
|
|
671
|
+
} else {
|
|
672
|
+
edge.vertex2 = levelVertex;
|
|
673
|
+
}
|
|
674
|
+
levelVertex.edges.push(edge);
|
|
675
|
+
});
|
|
676
|
+
for (let i = 0; i < createdNodes.length; i++) {
|
|
677
|
+
for (let j = i + 1; j < createdNodes.length; j++) {
|
|
678
|
+
const createdNode1 = createdNodes[i];
|
|
679
|
+
const createdNode2 = createdNodes[j];
|
|
680
|
+
if (createdNode1.coords.level === null || createdNode2.coords.level === null) {
|
|
681
|
+
continue;
|
|
682
|
+
}
|
|
683
|
+
const minLevel = Math.min(createdNode1.coords.level, createdNode2.coords.level);
|
|
684
|
+
const maxLevel = Math.max(createdNode1.coords.level, createdNode2.coords.level);
|
|
685
|
+
const newEdge = new geo.GeoGraphEdge(
|
|
686
|
+
createdNode1,
|
|
687
|
+
createdNode2,
|
|
688
|
+
{ data: elevatorNode.data, name: elevatorNode.name, level: [minLevel, maxLevel] }
|
|
689
|
+
);
|
|
690
|
+
edges.push(newEdge);
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
const elevatorNodeIndex = nodes.indexOf(elevatorNode);
|
|
694
|
+
if (elevatorNodeIndex > -1) {
|
|
695
|
+
nodes.splice(elevatorNodeIndex, 1);
|
|
696
|
+
}
|
|
573
697
|
}
|
|
574
698
|
};
|
|
575
|
-
let
|
|
576
|
-
__publicField(
|
|
577
|
-
|
|
578
|
-
|
|
699
|
+
let OsmGraph = _OsmGraph;
|
|
700
|
+
__publicField(OsmGraph, "HIGHWAYS_PEDESTRIANS", HIGHWAYS_PEDESTRIANS);
|
|
701
|
+
__publicField(OsmGraph, "DEFAULT_WAY_SELECTOR", DEFAULT_WAY_SELECTOR);
|
|
702
|
+
const DEFAULT_OPTIONS = Object.assign({}, geo.GeoGraphRouter.DEFAULT_OPTIONS, {
|
|
703
|
+
weightEdgeFn: (edge) => edge.data instanceof osm.OsmNode && edge.data.isElevator ? 90 : getDurationFromLength(edge.length)
|
|
704
|
+
});
|
|
705
|
+
const WITHOUT_STAIRS_OPTIONS = Object.assign({}, DEFAULT_OPTIONS, {
|
|
706
|
+
acceptEdgeFn: (edge) => edge.data.tags.highway !== "steps"
|
|
707
|
+
});
|
|
708
|
+
const buildStepsRules = (graphItinerary) => (currentCoords, nextCoords, previousStep) => {
|
|
709
|
+
var _a, _b, _c, _d, _e;
|
|
579
710
|
const edges = graphItinerary.edges;
|
|
580
|
-
const
|
|
581
|
-
const
|
|
582
|
-
const
|
|
583
|
-
if (!
|
|
711
|
+
const vertices = graphItinerary.vertices;
|
|
712
|
+
const vertex = geo.GeoGraph.getVertexByCoords(vertices, currentCoords);
|
|
713
|
+
const nextVertex = geo.GeoGraph.getVertexByCoords(vertices, nextCoords);
|
|
714
|
+
if (!vertex || !nextVertex)
|
|
584
715
|
return {};
|
|
585
|
-
const edge = geo.
|
|
716
|
+
const edge = geo.GeoGraphEdge.getEdgeByVertices(edges, vertex, nextVertex);
|
|
586
717
|
if (!edge)
|
|
587
718
|
return {};
|
|
588
719
|
const edgeId = edges.findIndex((_edge) => _edge === edge);
|
|
589
|
-
const isSubwayEntrance =
|
|
590
|
-
const isGate =
|
|
720
|
+
const isSubwayEntrance = vertex ? ((_a = vertex.data) == null ? void 0 : _a.tags.railway) === "subway_entrance" : false;
|
|
721
|
+
const isGate = vertex ? ((_b = vertex.data) == null ? void 0 : _b.tags.barrier) === "gate" || ((_c = vertex.data) == null ? void 0 : _c.tags.aeroway) === "gate" : false;
|
|
591
722
|
let levelChangeType = null;
|
|
592
|
-
if (
|
|
723
|
+
if (edge.data.isElevator) {
|
|
593
724
|
levelChangeType = "elevator";
|
|
594
|
-
} else if (edge.
|
|
725
|
+
} else if (edge.data.isConveying) {
|
|
595
726
|
levelChangeType = "conveyor";
|
|
596
|
-
} else if (edge.
|
|
727
|
+
} else if (edge.data instanceof osm.OsmWay && edge.data.areStairs) {
|
|
597
728
|
levelChangeType = "stairs";
|
|
598
729
|
}
|
|
730
|
+
const edgeTags = edge.data.tags || {};
|
|
731
|
+
let levelChangeDirection = null;
|
|
732
|
+
if (edge.data instanceof osm.OsmWay && edge.data.areStairs && ["up", "down"].includes(edgeTags.incline) && !(previousStep == null ? void 0 : previousStep.levelChange)) {
|
|
733
|
+
levelChangeDirection = edgeTags.incline;
|
|
734
|
+
for (const n of edge.data.nodes) {
|
|
735
|
+
if (n !== vertex.data)
|
|
736
|
+
continue;
|
|
737
|
+
}
|
|
738
|
+
const isReversed = edge.data.nodes.reduce((acc, n, idx, arr) => {
|
|
739
|
+
if (n !== vertex.data)
|
|
740
|
+
return acc;
|
|
741
|
+
acc = !(idx + 1 < arr.length && arr[idx + 1] === nextVertex.data);
|
|
742
|
+
return acc;
|
|
743
|
+
}, null);
|
|
744
|
+
if (isReversed) {
|
|
745
|
+
levelChangeDirection = levelChangeDirection === "up" ? "down" : "up";
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
const createNewStep = isSubwayEntrance || levelChangeDirection;
|
|
599
749
|
return {
|
|
600
|
-
createNewStep
|
|
601
|
-
stepName: (
|
|
750
|
+
createNewStep,
|
|
751
|
+
stepName: (_d = edge.data) == null ? void 0 : _d.tags.name,
|
|
602
752
|
duration: graphItinerary.edgesWeights[edgeId],
|
|
603
753
|
stepExtras: {
|
|
604
754
|
...isSubwayEntrance && { isSubwayEntrance: true },
|
|
605
|
-
...isSubwayEntrance && ((
|
|
755
|
+
...isSubwayEntrance && ((_e = vertex.data) == null ? void 0 : _e.tags.ref) && { subwayEntranceRef: vertex.data.tags.ref },
|
|
606
756
|
...isGate && { isGate: true }
|
|
607
757
|
},
|
|
608
|
-
...levelChangeType && { levelChangeType }
|
|
758
|
+
...levelChangeType && { levelChangeType },
|
|
759
|
+
...levelChangeDirection && { levelChangeDirection }
|
|
609
760
|
};
|
|
610
761
|
};
|
|
611
|
-
class WemapOsmRouter extends
|
|
612
|
-
constructor(
|
|
613
|
-
super(
|
|
762
|
+
class WemapOsmRouter extends geo.GeoGraphRouter {
|
|
763
|
+
constructor(graph) {
|
|
764
|
+
super(graph);
|
|
614
765
|
}
|
|
615
766
|
static get rname() {
|
|
616
|
-
return "wemap";
|
|
767
|
+
return "wemap-osm";
|
|
617
768
|
}
|
|
618
|
-
getShortestPath(start, end, options =
|
|
769
|
+
getShortestPath(start, end, options = DEFAULT_OPTIONS) {
|
|
619
770
|
return super.getShortestPath(start, end, options);
|
|
620
771
|
}
|
|
621
|
-
getItinerary(start, end, options =
|
|
772
|
+
getItinerary(start, end, options = DEFAULT_OPTIONS) {
|
|
622
773
|
const graphItinerary = this.getShortestPath(start, end, options);
|
|
623
774
|
return Itinerary.fromGraphItinerary(graphItinerary, "WALK", buildStepsRules(graphItinerary));
|
|
624
775
|
}
|
|
776
|
+
static getTurnInfoFromAngle(_angle) {
|
|
777
|
+
let direction, directionExtra;
|
|
778
|
+
const directionAngle = maths.rad2deg(maths.diffAngle(_angle, Math.PI));
|
|
779
|
+
const directionAngleAbs = Math.abs(directionAngle);
|
|
780
|
+
if (directionAngleAbs <= 20) {
|
|
781
|
+
direction = "straight";
|
|
782
|
+
} else {
|
|
783
|
+
direction = directionAngle > 0 ? "left" : "right";
|
|
784
|
+
if (directionAngleAbs < 55) {
|
|
785
|
+
directionExtra = "slight";
|
|
786
|
+
} else if (directionAngleAbs > 120) {
|
|
787
|
+
directionExtra = "sharp";
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
return { direction, directionExtra };
|
|
791
|
+
}
|
|
792
|
+
getShortestTrip(waypoints, options = DEFAULT_OPTIONS) {
|
|
793
|
+
const points = waypoints.map((waypoint) => {
|
|
794
|
+
const point = new salesman__default.default.Point(0, 0);
|
|
795
|
+
point.coords = waypoint;
|
|
796
|
+
return point;
|
|
797
|
+
});
|
|
798
|
+
const cache = [];
|
|
799
|
+
const solution = salesman__default.default.solve(points, 0.9, void 0, (p, q) => {
|
|
800
|
+
const osmItinerary = this.getShortestPath(
|
|
801
|
+
p.coords,
|
|
802
|
+
q.coords,
|
|
803
|
+
options
|
|
804
|
+
);
|
|
805
|
+
cache.push(osmItinerary);
|
|
806
|
+
return osmItinerary.edgesWeights.reduce((acc, weight) => acc + weight, 0);
|
|
807
|
+
});
|
|
808
|
+
const orderedPoints = solution.map((i) => points[i]);
|
|
809
|
+
const orderedItineraries = [];
|
|
810
|
+
for (let i = 0; i < orderedPoints.length - 1; i++) {
|
|
811
|
+
const p = orderedPoints[i];
|
|
812
|
+
const q = orderedPoints[i + 1];
|
|
813
|
+
let cachedItinerary = cache.find((itinerary) => itinerary.start === p.coords && itinerary.end === q.coords || itinerary.end === p.coords && itinerary.start === q.coords);
|
|
814
|
+
if (cachedItinerary.end === p.coords) {
|
|
815
|
+
cachedItinerary = geo.GeoGraphItinerary.fromGraphVertices(
|
|
816
|
+
cachedItinerary.end,
|
|
817
|
+
cachedItinerary.start,
|
|
818
|
+
cachedItinerary.vertices.reverse(),
|
|
819
|
+
cachedItinerary.edgesWeights
|
|
820
|
+
);
|
|
821
|
+
}
|
|
822
|
+
orderedItineraries.push(cachedItinerary);
|
|
823
|
+
}
|
|
824
|
+
return orderedItineraries;
|
|
825
|
+
}
|
|
826
|
+
getTripItinerary(waypoints, options = DEFAULT_OPTIONS) {
|
|
827
|
+
const shortestTrip = this.getShortestTrip(waypoints, options);
|
|
828
|
+
return new Itinerary({
|
|
829
|
+
from: shortestTrip[0].start,
|
|
830
|
+
to: shortestTrip[shortestTrip.length - 1].end,
|
|
831
|
+
legs: shortestTrip.map((graphItinerary) => Leg.fromGraphItinerary(graphItinerary))
|
|
832
|
+
});
|
|
833
|
+
}
|
|
625
834
|
}
|
|
835
|
+
__publicField(WemapOsmRouter, "DEFAULT_OPTIONS", DEFAULT_OPTIONS);
|
|
836
|
+
__publicField(WemapOsmRouter, "WITHOUT_STAIRS_OPTIONS", WITHOUT_STAIRS_OPTIONS);
|
|
626
837
|
class RemoteRouter {
|
|
627
838
|
}
|
|
628
839
|
class RemoteRouterServerUnreachable extends Error {
|
|
@@ -774,7 +985,7 @@ class CitywayRemoteRouter extends RemoteRouter {
|
|
|
774
985
|
const legCoords = [];
|
|
775
986
|
let legFrom, legTo;
|
|
776
987
|
let transportInfo;
|
|
777
|
-
let
|
|
988
|
+
let minStepsInfo;
|
|
778
989
|
if (legMode === "UNKNOWN") {
|
|
779
990
|
continue itineraryLoop;
|
|
780
991
|
}
|
|
@@ -787,7 +998,7 @@ class CitywayRemoteRouter extends RemoteRouter {
|
|
|
787
998
|
name: jsonLeg.Arrival.Site.Name,
|
|
788
999
|
coords: jsonToCoordinates$2(jsonLeg.Arrival.Site.Position)
|
|
789
1000
|
};
|
|
790
|
-
|
|
1001
|
+
minStepsInfo = [];
|
|
791
1002
|
for (const jsonPathLink of jsonLeg.pathLinks.PathLink) {
|
|
792
1003
|
let stepCoords;
|
|
793
1004
|
if (jsonPathLink.Geometry && jsonPathLink.Geometry !== "Null") {
|
|
@@ -800,11 +1011,16 @@ class CitywayRemoteRouter extends RemoteRouter {
|
|
|
800
1011
|
legCoords.push(coords);
|
|
801
1012
|
}
|
|
802
1013
|
});
|
|
803
|
-
|
|
1014
|
+
minStepsInfo.push({
|
|
804
1015
|
coords: stepCoords[0],
|
|
805
1016
|
distance: jsonPathLink.Distance,
|
|
806
1017
|
name: jsonPathLink.Departure.Site.Name
|
|
807
|
-
})
|
|
1018
|
+
});
|
|
1019
|
+
}
|
|
1020
|
+
if (jsonSection === trip.sections.Section[trip.sections.Section.length - 1]) {
|
|
1021
|
+
minStepsInfo.push({
|
|
1022
|
+
coords: legCoords[legCoords.length - 1]
|
|
1023
|
+
});
|
|
808
1024
|
}
|
|
809
1025
|
} else if (isRoutingModePublicTransport(legMode)) {
|
|
810
1026
|
legFrom = {
|
|
@@ -833,11 +1049,11 @@ class CitywayRemoteRouter extends RemoteRouter {
|
|
|
833
1049
|
}
|
|
834
1050
|
});
|
|
835
1051
|
}
|
|
836
|
-
|
|
1052
|
+
minStepsInfo = [{
|
|
837
1053
|
coords: legCoords[0],
|
|
838
1054
|
name: jsonLeg.Line.Name,
|
|
839
1055
|
distance: jsonLeg.Distance
|
|
840
|
-
}
|
|
1056
|
+
}];
|
|
841
1057
|
} else {
|
|
842
1058
|
Logger__default.default.warn(`[CitywayParser] Unknown leg mode: ${jsonLeg.TransportMode}`);
|
|
843
1059
|
continue;
|
|
@@ -851,7 +1067,7 @@ class CitywayRemoteRouter extends RemoteRouter {
|
|
|
851
1067
|
from: legFrom,
|
|
852
1068
|
to: legTo,
|
|
853
1069
|
transportInfo,
|
|
854
|
-
|
|
1070
|
+
minStepsInfo
|
|
855
1071
|
});
|
|
856
1072
|
legs.push(leg);
|
|
857
1073
|
}
|
|
@@ -1093,16 +1309,15 @@ class IdfmRemoteRouter extends RemoteRouter {
|
|
|
1093
1309
|
newCoords = last(result);
|
|
1094
1310
|
coords[_idCoordsInLeg] = newCoords;
|
|
1095
1311
|
}
|
|
1096
|
-
outputSteps.push(
|
|
1312
|
+
outputSteps.push({
|
|
1097
1313
|
...step,
|
|
1098
1314
|
coords: newCoords
|
|
1099
|
-
})
|
|
1315
|
+
});
|
|
1100
1316
|
previousStep = step;
|
|
1101
1317
|
}
|
|
1102
1318
|
return outputSteps;
|
|
1103
1319
|
}
|
|
1104
1320
|
createRouterResponseFromJson(json, from, to) {
|
|
1105
|
-
var _a;
|
|
1106
1321
|
const routerResponse = new RouterResponse({ routerName: this.rname, from, to });
|
|
1107
1322
|
if (!json || !json.journeys) {
|
|
1108
1323
|
return routerResponse;
|
|
@@ -1123,7 +1338,9 @@ class IdfmRemoteRouter extends RemoteRouter {
|
|
|
1123
1338
|
}
|
|
1124
1339
|
return acc;
|
|
1125
1340
|
}, []);
|
|
1126
|
-
let
|
|
1341
|
+
let minStepsInfo;
|
|
1342
|
+
let transportInfo;
|
|
1343
|
+
let mode = routingModeCorrespondance.get(jsonSection.mode);
|
|
1127
1344
|
if (jsonSection.path) {
|
|
1128
1345
|
const idfmIntermediateSteps = [];
|
|
1129
1346
|
for (const jsonPathLink of jsonSection.path) {
|
|
@@ -1132,10 +1349,25 @@ class IdfmRemoteRouter extends RemoteRouter {
|
|
|
1132
1349
|
distance: jsonPathLink.length
|
|
1133
1350
|
});
|
|
1134
1351
|
}
|
|
1135
|
-
|
|
1352
|
+
minStepsInfo = this.findStepsCoord(legCoords, idfmIntermediateSteps);
|
|
1353
|
+
}
|
|
1354
|
+
if (jsonSection.type === "public_transport") {
|
|
1355
|
+
transportInfo = {
|
|
1356
|
+
name: jsonSection.display_informations.code,
|
|
1357
|
+
routeColor: jsonSection.display_informations.color,
|
|
1358
|
+
routeTextColor: jsonSection.display_informations.text_color,
|
|
1359
|
+
directionName: jsonSection.display_informations.direction
|
|
1360
|
+
};
|
|
1361
|
+
mode = routingModeCorrespondance.get(jsonSection.display_informations.physical_mode);
|
|
1362
|
+
const legStep = {
|
|
1363
|
+
coords: legCoords[0],
|
|
1364
|
+
name: transportInfo.directionName,
|
|
1365
|
+
distance: jsonSection.geojson.properties[0].length
|
|
1366
|
+
};
|
|
1367
|
+
minStepsInfo = [legStep];
|
|
1136
1368
|
}
|
|
1137
1369
|
const leg = new Leg({
|
|
1138
|
-
mode
|
|
1370
|
+
mode,
|
|
1139
1371
|
duration: jsonSection.duration,
|
|
1140
1372
|
startTime: dateStringToTimestamp(jsonSection.departure_date_time, timeZone),
|
|
1141
1373
|
endTime: dateStringToTimestamp(jsonSection.arrival_date_time, timeZone),
|
|
@@ -1148,23 +1380,9 @@ class IdfmRemoteRouter extends RemoteRouter {
|
|
|
1148
1380
|
coords: toSection
|
|
1149
1381
|
},
|
|
1150
1382
|
coords: legCoords,
|
|
1151
|
-
|
|
1383
|
+
transportInfo,
|
|
1384
|
+
minStepsInfo
|
|
1152
1385
|
});
|
|
1153
|
-
if (jsonSection.type === "public_transport") {
|
|
1154
|
-
leg.transportInfo = {
|
|
1155
|
-
name: jsonSection.display_informations.code,
|
|
1156
|
-
routeColor: jsonSection.display_informations.color,
|
|
1157
|
-
routeTextColor: jsonSection.display_informations.text_color,
|
|
1158
|
-
directionName: jsonSection.display_informations.direction
|
|
1159
|
-
};
|
|
1160
|
-
leg.mode = routingModeCorrespondance.get(jsonSection.display_informations.physical_mode);
|
|
1161
|
-
const legStep = new StepInfo({
|
|
1162
|
-
coords: leg.coords[0],
|
|
1163
|
-
name: (_a = leg.transportInfo) == null ? void 0 : _a.directionName,
|
|
1164
|
-
distance: jsonSection.geojson.properties[0].length
|
|
1165
|
-
});
|
|
1166
|
-
leg.stepsInfo = [legStep];
|
|
1167
|
-
}
|
|
1168
1386
|
legs.push(leg);
|
|
1169
1387
|
}
|
|
1170
1388
|
const itinerary = new Itinerary({
|
|
@@ -1329,19 +1547,19 @@ class OsrmRemoteRouter extends RemoteRouter {
|
|
|
1329
1547
|
const legs = jsonItinerary.legs.map((jsonLeg) => {
|
|
1330
1548
|
var _a;
|
|
1331
1549
|
const legCoords = jsonLeg.steps.map((step) => step.geometry.coordinates.map(this.jsonToCoordinates)).flat().filter((coords, idx, arr) => idx === 0 || !arr[idx - 1].equals(coords));
|
|
1332
|
-
const
|
|
1550
|
+
const minStepsInfo = (_a = jsonLeg.steps) == null ? void 0 : _a.map(({ maneuver, name, distance, duration }) => {
|
|
1333
1551
|
const stepCoords = this.jsonToCoordinates(maneuver.location);
|
|
1334
1552
|
const distances = legCoords.map((coords) => coords.distanceTo(stepCoords));
|
|
1335
1553
|
const idStepCoordsInLeg = distances.indexOf(Math.min(...distances));
|
|
1336
1554
|
if (idStepCoordsInLeg < 0) {
|
|
1337
1555
|
throw new Error("Osrm Parser: Cannot find step coords in leg coordinates");
|
|
1338
1556
|
}
|
|
1339
|
-
return
|
|
1557
|
+
return {
|
|
1340
1558
|
coords: stepCoords,
|
|
1341
1559
|
name,
|
|
1342
1560
|
distance,
|
|
1343
1561
|
duration
|
|
1344
|
-
}
|
|
1562
|
+
};
|
|
1345
1563
|
});
|
|
1346
1564
|
return new Leg({
|
|
1347
1565
|
mode,
|
|
@@ -1353,7 +1571,7 @@ class OsrmRemoteRouter extends RemoteRouter {
|
|
|
1353
1571
|
to: {
|
|
1354
1572
|
coords: legCoords[legCoords.length - 1]
|
|
1355
1573
|
},
|
|
1356
|
-
|
|
1574
|
+
minStepsInfo
|
|
1357
1575
|
});
|
|
1358
1576
|
});
|
|
1359
1577
|
return new Itinerary({
|
|
@@ -1422,7 +1640,7 @@ class OtpRemoteRouter extends RemoteRouter {
|
|
|
1422
1640
|
for (const jsonLeg of jsonItinerary.legs) {
|
|
1423
1641
|
const legCoords = Polyline__default.default.decode(jsonLeg.legGeometry.points).map(([lat, lon]) => new geo.Coordinates(lat, lon));
|
|
1424
1642
|
let transportInfo;
|
|
1425
|
-
let
|
|
1643
|
+
let minStepsInfo;
|
|
1426
1644
|
if (isLegPT(jsonLeg)) {
|
|
1427
1645
|
transportInfo = {
|
|
1428
1646
|
name: jsonLeg.routeShortName,
|
|
@@ -1430,21 +1648,21 @@ class OtpRemoteRouter extends RemoteRouter {
|
|
|
1430
1648
|
routeTextColor: jsonLeg.routeTextColor,
|
|
1431
1649
|
directionName: jsonLeg.headsign
|
|
1432
1650
|
};
|
|
1433
|
-
|
|
1651
|
+
minStepsInfo = [{
|
|
1434
1652
|
coords: legCoords[0],
|
|
1435
1653
|
name: jsonLeg.headsign
|
|
1436
|
-
}
|
|
1654
|
+
}];
|
|
1437
1655
|
} else {
|
|
1438
|
-
|
|
1656
|
+
minStepsInfo = jsonLeg.steps.map((jsonStep) => {
|
|
1439
1657
|
const distances = legCoords.map((coords) => coords.distanceTo(jsonToCoordinates(jsonStep)));
|
|
1440
1658
|
const idStepCoordsInLeg = distances.indexOf(Math.min(...distances));
|
|
1441
1659
|
if (idStepCoordsInLeg < 0) {
|
|
1442
1660
|
throw new Error("OTP Parser: Cannot find closest step");
|
|
1443
1661
|
}
|
|
1444
|
-
return
|
|
1662
|
+
return {
|
|
1445
1663
|
coords: legCoords[idStepCoordsInLeg],
|
|
1446
1664
|
name: jsonStep.streetName
|
|
1447
|
-
}
|
|
1665
|
+
};
|
|
1448
1666
|
});
|
|
1449
1667
|
}
|
|
1450
1668
|
const leg = new Leg({
|
|
@@ -1462,7 +1680,7 @@ class OtpRemoteRouter extends RemoteRouter {
|
|
|
1462
1680
|
},
|
|
1463
1681
|
coords: legCoords,
|
|
1464
1682
|
transportInfo,
|
|
1465
|
-
|
|
1683
|
+
minStepsInfo
|
|
1466
1684
|
});
|
|
1467
1685
|
legs.push(leg);
|
|
1468
1686
|
}
|
|
@@ -1503,7 +1721,7 @@ class WemapMultiRemoteRouterPayload {
|
|
|
1503
1721
|
}
|
|
1504
1722
|
class WemapMultiRemoteRouter extends RemoteRouter {
|
|
1505
1723
|
get rname() {
|
|
1506
|
-
return "wemap-
|
|
1724
|
+
return "wemap-multi";
|
|
1507
1725
|
}
|
|
1508
1726
|
async getItineraries(endpointUrl, mode, waypoints, options) {
|
|
1509
1727
|
const payload = new WemapMultiRemoteRouterPayload(
|
|
@@ -1528,19 +1746,17 @@ class WemapMultiRemoteRouter extends RemoteRouter {
|
|
|
1528
1746
|
}
|
|
1529
1747
|
}
|
|
1530
1748
|
const WemapMultiRemoteRouter$1 = new WemapMultiRemoteRouter();
|
|
1749
|
+
const remoteRouters = [
|
|
1750
|
+
CitywayRemoteRouter$1,
|
|
1751
|
+
DeutscheBahnRemoteRouter$1,
|
|
1752
|
+
IdfmRemoteRouter$1,
|
|
1753
|
+
OsrmRemoteRouter$1,
|
|
1754
|
+
OtpRemoteRouter$1,
|
|
1755
|
+
WemapMultiRemoteRouter$1
|
|
1756
|
+
];
|
|
1531
1757
|
class RemoteRouterManager {
|
|
1532
|
-
constructor() {
|
|
1533
|
-
__publicField(this, "remoteRouters", [
|
|
1534
|
-
CitywayRemoteRouter$1,
|
|
1535
|
-
DeutscheBahnRemoteRouter$1,
|
|
1536
|
-
IdfmRemoteRouter$1,
|
|
1537
|
-
OsrmRemoteRouter$1,
|
|
1538
|
-
OtpRemoteRouter$1,
|
|
1539
|
-
WemapMultiRemoteRouter$1
|
|
1540
|
-
]);
|
|
1541
|
-
}
|
|
1542
1758
|
getRouterByName(name) {
|
|
1543
|
-
return
|
|
1759
|
+
return remoteRouters.find((remoteRouter) => remoteRouter.rname === name);
|
|
1544
1760
|
}
|
|
1545
1761
|
async getItineraries(name, endpointUrl, mode, waypoints, options) {
|
|
1546
1762
|
const router = this.getRouterByName(name);
|
|
@@ -1549,9 +1765,9 @@ class RemoteRouterManager {
|
|
|
1549
1765
|
}
|
|
1550
1766
|
return router.getItineraries(endpointUrl, mode, waypoints, options);
|
|
1551
1767
|
}
|
|
1552
|
-
async getItinerariesWithFallback(
|
|
1768
|
+
async getItinerariesWithFallback(remoteRouters2, mode, waypoints, options) {
|
|
1553
1769
|
let routerResponse;
|
|
1554
|
-
for (const { name, endpointUrl } of
|
|
1770
|
+
for (const { name, endpointUrl } of remoteRouters2) {
|
|
1555
1771
|
routerResponse = await this.getItineraries(name, endpointUrl, mode, waypoints, options);
|
|
1556
1772
|
if (routerResponse.itineraries.length) {
|
|
1557
1773
|
return routerResponse;
|
|
@@ -1559,7 +1775,7 @@ class RemoteRouterManager {
|
|
|
1559
1775
|
}
|
|
1560
1776
|
if (!routerResponse) {
|
|
1561
1777
|
routerResponse = new RouterResponse({
|
|
1562
|
-
routerName:
|
|
1778
|
+
routerName: remoteRouters2.map((rr) => rr.name),
|
|
1563
1779
|
from: waypoints[0],
|
|
1564
1780
|
to: waypoints[waypoints.length]
|
|
1565
1781
|
});
|
|
@@ -1574,7 +1790,7 @@ class WemapMultiRouter {
|
|
|
1574
1790
|
__publicField(this, "maps", []);
|
|
1575
1791
|
}
|
|
1576
1792
|
get rname() {
|
|
1577
|
-
return "wemap-
|
|
1793
|
+
return "wemap-multi";
|
|
1578
1794
|
}
|
|
1579
1795
|
addIOMap(customNetworkMap) {
|
|
1580
1796
|
this.maps.push(customNetworkMap);
|
|
@@ -1582,21 +1798,9 @@ class WemapMultiRouter {
|
|
|
1582
1798
|
removeIOMap(customNetworkMap) {
|
|
1583
1799
|
this.maps = this.maps.filter((map) => map !== customNetworkMap);
|
|
1584
1800
|
}
|
|
1585
|
-
|
|
1586
|
-
var _a;
|
|
1587
|
-
if (waypoints.length > 2) {
|
|
1588
|
-
Logger__default.default.warn(`WemapMultiRouter uses only the first 2 waypoints (asked ${waypoints.length})`);
|
|
1589
|
-
}
|
|
1590
|
-
const start = waypoints[0];
|
|
1591
|
-
const end = waypoints[1];
|
|
1592
|
-
const routerResponse = new RouterResponse({
|
|
1593
|
-
routerName: this.rname,
|
|
1594
|
-
from: start,
|
|
1595
|
-
to: end
|
|
1596
|
-
});
|
|
1597
|
-
const remoteRouters = ((_a = options.remoteRouters) == null ? void 0 : _a.filter(({ name }) => name !== WemapMultiRemoteRouter$1.rname)) || [];
|
|
1801
|
+
getIoMapsFromOptions(options) {
|
|
1598
1802
|
let ioMapsToTest = this.maps;
|
|
1599
|
-
const
|
|
1803
|
+
const targetMaps = options == null ? void 0 : options.targetMaps;
|
|
1600
1804
|
if (targetMaps) {
|
|
1601
1805
|
ioMapsToTest = this.maps.filter((map) => map.name && targetMaps.includes(map.name));
|
|
1602
1806
|
if (ioMapsToTest.length !== targetMaps.length) {
|
|
@@ -1607,9 +1811,55 @@ class WemapMultiRouter {
|
|
|
1607
1811
|
});
|
|
1608
1812
|
}
|
|
1609
1813
|
}
|
|
1814
|
+
return ioMapsToTest;
|
|
1815
|
+
}
|
|
1816
|
+
convertOptionsToWemapOsmOptions(options) {
|
|
1817
|
+
return !options || !("useStairs" in options) || options.useStairs ? WemapOsmRouter.DEFAULT_OPTIONS : WemapOsmRouter.WITHOUT_STAIRS_OPTIONS;
|
|
1818
|
+
}
|
|
1819
|
+
async getTrip(mode, waypoints, options = null) {
|
|
1820
|
+
const ioMapsToTest = this.getIoMapsFromOptions(options);
|
|
1821
|
+
if (waypoints.length < 2) {
|
|
1822
|
+
throw Error(`Cannot retrieve a trip itinerary. Two points or more are necessary`);
|
|
1823
|
+
}
|
|
1824
|
+
if (mode !== "WALK") {
|
|
1825
|
+
throw Error(`Cannot calculate trip itinerary for mode "${mode}". Only "WALK" is implemented.`);
|
|
1826
|
+
}
|
|
1827
|
+
const mapOfWaypoints = waypoints.reduce((map, waypoint) => {
|
|
1828
|
+
const mapOfThisWaypoint = ioMapsToTest.find((map2) => map2.isPointInside(waypoint));
|
|
1829
|
+
if (!mapOfThisWaypoint) {
|
|
1830
|
+
throw Error(`Cannot find a network for this trip waypoint (${waypoint.toString()}). Outdoor trips are not implemented.`);
|
|
1831
|
+
}
|
|
1832
|
+
if (map && mapOfThisWaypoint !== map) {
|
|
1833
|
+
throw Error(`Cannot handle this trip, because two waypoints are on different maps (${mapOfThisWaypoint} and ${mapOfWaypoints}). Multi-map trips are not implemented.`);
|
|
1834
|
+
}
|
|
1835
|
+
return mapOfThisWaypoint;
|
|
1836
|
+
}, null);
|
|
1837
|
+
const wemapOsmRouterOptions = this.convertOptionsToWemapOsmOptions(options);
|
|
1838
|
+
const tripItinerary = mapOfWaypoints.getTripInsideMap(waypoints, wemapOsmRouterOptions);
|
|
1839
|
+
return new RouterResponse({
|
|
1840
|
+
routerName: this.rname,
|
|
1841
|
+
from: tripItinerary.from,
|
|
1842
|
+
to: tripItinerary.to,
|
|
1843
|
+
itineraries: [tripItinerary]
|
|
1844
|
+
});
|
|
1845
|
+
}
|
|
1846
|
+
async getItineraries(mode, waypoints, options = null) {
|
|
1847
|
+
var _a;
|
|
1848
|
+
if (waypoints.length > 2) {
|
|
1849
|
+
Logger__default.default.warn(`WemapMultiRouter uses only the first 2 waypoints (asked ${waypoints.length})`);
|
|
1850
|
+
}
|
|
1851
|
+
const start = waypoints[0];
|
|
1852
|
+
const end = waypoints[1];
|
|
1853
|
+
const routerResponse = new RouterResponse({
|
|
1854
|
+
routerName: this.rname,
|
|
1855
|
+
from: start,
|
|
1856
|
+
to: end
|
|
1857
|
+
});
|
|
1858
|
+
const remoteRouters2 = ((_a = options == null ? void 0 : options.remoteRouters) == null ? void 0 : _a.filter(({ name }) => name !== WemapMultiRemoteRouter$1.rname)) || [];
|
|
1859
|
+
const ioMapsToTest = this.getIoMapsFromOptions(options);
|
|
1610
1860
|
if (!ioMapsToTest.length) {
|
|
1611
1861
|
try {
|
|
1612
|
-
return await RemoteRouterManager$1.getItinerariesWithFallback(
|
|
1862
|
+
return await RemoteRouterManager$1.getItinerariesWithFallback(remoteRouters2, mode, waypoints);
|
|
1613
1863
|
} catch (e) {
|
|
1614
1864
|
if (!isRoutingError(e)) {
|
|
1615
1865
|
throw e;
|
|
@@ -1620,7 +1870,7 @@ class WemapMultiRouter {
|
|
|
1620
1870
|
}
|
|
1621
1871
|
let ioMapItinerary;
|
|
1622
1872
|
const mapWithStart = ioMapsToTest.find((map) => map.isPointInside(start));
|
|
1623
|
-
const wemapOsmRouterOptions =
|
|
1873
|
+
const wemapOsmRouterOptions = this.convertOptionsToWemapOsmOptions(options);
|
|
1624
1874
|
if (mapWithStart && mapWithStart.isPointInside(end)) {
|
|
1625
1875
|
try {
|
|
1626
1876
|
ioMapItinerary = mapWithStart.getItineraryInsideMap(start, end, wemapOsmRouterOptions);
|
|
@@ -1639,7 +1889,7 @@ class WemapMultiRouter {
|
|
|
1639
1889
|
let remoteRouterResponse;
|
|
1640
1890
|
if (!mapWithStart && !mapWithEnd) {
|
|
1641
1891
|
try {
|
|
1642
|
-
return await RemoteRouterManager$1.getItinerariesWithFallback(
|
|
1892
|
+
return await RemoteRouterManager$1.getItinerariesWithFallback(remoteRouters2, mode, waypoints);
|
|
1643
1893
|
} catch (e) {
|
|
1644
1894
|
if (!isRoutingError(e)) {
|
|
1645
1895
|
throw e;
|
|
@@ -1657,7 +1907,7 @@ class WemapMultiRouter {
|
|
|
1657
1907
|
try {
|
|
1658
1908
|
ioMapItinerary = mapWithStart.getBestItineraryFromStartToEntryPoints(start, end, wemapOsmRouterOptions);
|
|
1659
1909
|
remoteRouterResponse = await RemoteRouterManager$1.getItinerariesWithFallback(
|
|
1660
|
-
|
|
1910
|
+
remoteRouters2,
|
|
1661
1911
|
mode,
|
|
1662
1912
|
[ioMapItinerary.to, end]
|
|
1663
1913
|
);
|
|
@@ -1668,7 +1918,7 @@ class WemapMultiRouter {
|
|
|
1668
1918
|
if (!isRoutingError(e)) {
|
|
1669
1919
|
throw e;
|
|
1670
1920
|
}
|
|
1671
|
-
routerResponse.error = `Tried to calculate an itinerary from "start" to "entrypoints" using wemap router on local map "${mapWithStart.name}" and an itinerary from "entrypoints" to "end" using remote routers (${
|
|
1921
|
+
routerResponse.error = `Tried to calculate an itinerary from "start" to "entrypoints" using wemap router on local map "${mapWithStart.name}" and an itinerary from "entrypoints" to "end" using remote routers (${remoteRouters2.map((r) => r.name).join(", ")}), but failed. Details: ${e.message}.`;
|
|
1672
1922
|
return routerResponse;
|
|
1673
1923
|
}
|
|
1674
1924
|
routerResponse.itineraries = remoteRouterResponse.itineraries.map(
|
|
@@ -1686,7 +1936,7 @@ class WemapMultiRouter {
|
|
|
1686
1936
|
try {
|
|
1687
1937
|
ioMapItinerary = mapWithEnd.getBestItineraryFromEntryPointsToEnd(start, end, wemapOsmRouterOptions);
|
|
1688
1938
|
remoteRouterResponse = await RemoteRouterManager$1.getItinerariesWithFallback(
|
|
1689
|
-
|
|
1939
|
+
remoteRouters2,
|
|
1690
1940
|
mode,
|
|
1691
1941
|
[start, ioMapItinerary.from]
|
|
1692
1942
|
);
|
|
@@ -1697,7 +1947,7 @@ class WemapMultiRouter {
|
|
|
1697
1947
|
if (!isRoutingError(e)) {
|
|
1698
1948
|
throw e;
|
|
1699
1949
|
}
|
|
1700
|
-
routerResponse.error = `Tried to calculate an itinerary from "start" to "entrypoints" using remote routers (${
|
|
1950
|
+
routerResponse.error = `Tried to calculate an itinerary from "start" to "entrypoints" using remote routers (${remoteRouters2.map((r) => r.name).join(", ")}) and an itinerary from "entrypoints" to "end" using wemap router on local map "${mapWithEnd.name}", but failed. Details: ${e.message}.`;
|
|
1701
1951
|
return routerResponse;
|
|
1702
1952
|
}
|
|
1703
1953
|
routerResponse.itineraries = remoteRouterResponse.itineraries.map(
|
|
@@ -1724,7 +1974,7 @@ class WemapMultiRouter {
|
|
|
1724
1974
|
ioMapItinerary1 = mapWithStart.getBestItineraryFromStartToEntryPoints(start, end, wemapOsmRouterOptions);
|
|
1725
1975
|
ioMapItinerary2 = mapWithEnd.getBestItineraryFromEntryPointsToEnd(start, end, wemapOsmRouterOptions);
|
|
1726
1976
|
remoteRouterResponse = await RemoteRouterManager$1.getItinerariesWithFallback(
|
|
1727
|
-
|
|
1977
|
+
remoteRouters2,
|
|
1728
1978
|
mode,
|
|
1729
1979
|
[ioMapItinerary1.to, ioMapItinerary2.from]
|
|
1730
1980
|
);
|
|
@@ -1735,7 +1985,7 @@ class WemapMultiRouter {
|
|
|
1735
1985
|
if (!isRoutingError(e)) {
|
|
1736
1986
|
throw e;
|
|
1737
1987
|
}
|
|
1738
|
-
routerResponse.error = `Tried to calculate an itinerary from "start" to "entrypoints1" using wemap router on local map "${mapWithStart.name}", an itinerary from "entrypoints1" to "entrypoints2" using remote routers (${
|
|
1988
|
+
routerResponse.error = `Tried to calculate an itinerary from "start" to "entrypoints1" using wemap router on local map "${mapWithStart.name}", an itinerary from "entrypoints1" to "entrypoints2" using remote routers (${remoteRouters2.map((r) => r.name).join(", ")}) and an itinerary from "entrypoints2" to "end" using wemap router on local map "${mapWithEnd.name}", but failed. Details: ${e.message}.`;
|
|
1739
1989
|
return routerResponse;
|
|
1740
1990
|
}
|
|
1741
1991
|
routerResponse.itineraries = remoteRouterResponse.itineraries.map(
|
|
@@ -1752,46 +2002,63 @@ class WemapMultiRouter {
|
|
|
1752
2002
|
}
|
|
1753
2003
|
}
|
|
1754
2004
|
class CustomNetworkMap {
|
|
1755
|
-
constructor(
|
|
2005
|
+
constructor(graph, entryPoints, bounds = null, name = null) {
|
|
1756
2006
|
__publicField(this, "name");
|
|
1757
|
-
__publicField(this, "
|
|
2007
|
+
__publicField(this, "graph");
|
|
1758
2008
|
__publicField(this, "router");
|
|
1759
2009
|
__publicField(this, "bounds");
|
|
1760
2010
|
__publicField(this, "entryPoints");
|
|
1761
2011
|
__publicField(this, "disabledWays", /* @__PURE__ */ new Set());
|
|
1762
2012
|
this.name = name;
|
|
1763
|
-
this.
|
|
1764
|
-
this.router = new WemapOsmRouter(
|
|
2013
|
+
this.graph = graph;
|
|
2014
|
+
this.router = new WemapOsmRouter(graph);
|
|
1765
2015
|
entryPoints.forEach((entryPoint) => {
|
|
1766
|
-
if (!
|
|
2016
|
+
if (!graph.vertices.includes(entryPoint)) {
|
|
1767
2017
|
throw new Error(`Cannot find entry point ${entryPoint.coords.toString()} in network "${name}"`);
|
|
1768
2018
|
}
|
|
1769
2019
|
});
|
|
1770
2020
|
this.entryPoints = entryPoints;
|
|
1771
2021
|
if (bounds) {
|
|
1772
|
-
this.bounds =
|
|
2022
|
+
this.bounds = bounds;
|
|
1773
2023
|
} else {
|
|
1774
|
-
const polygon = [
|
|
2024
|
+
const polygon = [graph.vertices.map((vertex) => [vertex.coords.lng, vertex.coords.lat])];
|
|
1775
2025
|
const convexHull = convexHullFn__default.default({ type: "polygon", coordinates: polygon });
|
|
1776
2026
|
if (!convexHull) {
|
|
1777
2027
|
throw new Error(`Cannot calculate convexHull of network "${name}"`);
|
|
1778
2028
|
}
|
|
1779
|
-
this.bounds =
|
|
2029
|
+
this.bounds = {
|
|
2030
|
+
type: "MultiPolygon",
|
|
2031
|
+
coordinates: [convexHull.geometry.coordinates]
|
|
2032
|
+
};
|
|
1780
2033
|
}
|
|
1781
2034
|
}
|
|
1782
2035
|
static fromOsmXml(osmXmlString, name = null) {
|
|
1783
2036
|
const osmModel = osm.OsmParser.parseOsmXmlString(osmXmlString);
|
|
1784
|
-
const
|
|
1785
|
-
const entryPoints =
|
|
2037
|
+
const graph = OsmGraph.fromOsmModel(osmModel);
|
|
2038
|
+
const entryPoints = graph.vertices.filter(({ data: { tags } }) => tags && tags["wemap:routing-io"]);
|
|
1786
2039
|
if (entryPoints.some((el) => el === null) || new Set(entryPoints).size !== entryPoints.length) {
|
|
1787
2040
|
throw new Error("Cannot parse wemap:routing-io correctly");
|
|
1788
2041
|
}
|
|
1789
|
-
const
|
|
1790
|
-
|
|
2042
|
+
const bounds = {
|
|
2043
|
+
type: "MultiPolygon",
|
|
2044
|
+
coordinates: []
|
|
2045
|
+
};
|
|
2046
|
+
osmModel.ways.filter(({ tags }) => tags["wemap:routing-bounds"]).forEach((way) => {
|
|
2047
|
+
bounds.coordinates.push([
|
|
2048
|
+
way.nodes.reduce((acc, node) => {
|
|
2049
|
+
acc.push([node.coords.lng, node.coords.lat]);
|
|
2050
|
+
return acc;
|
|
2051
|
+
}, [])
|
|
2052
|
+
]);
|
|
2053
|
+
});
|
|
2054
|
+
osmModel.relations.filter((rel) => rel.tags["wemap:routing-bounds"] && rel.isMultipolygon()).forEach((rel) => {
|
|
2055
|
+
const polygon = rel.getGeoJsonPolygon();
|
|
2056
|
+
polygon && bounds.coordinates.push(polygon.coordinates);
|
|
2057
|
+
});
|
|
2058
|
+
if (!bounds.coordinates.length) {
|
|
1791
2059
|
throw new Error('Search bounds is undefined. Please use OSM tag : "wemap:routing-bounds=yes"');
|
|
1792
2060
|
}
|
|
1793
|
-
|
|
1794
|
-
return new CustomNetworkMap(network, entryPoints, bounds, name);
|
|
2061
|
+
return new CustomNetworkMap(graph, entryPoints, bounds, name);
|
|
1795
2062
|
}
|
|
1796
2063
|
isPointInside(coordinates) {
|
|
1797
2064
|
return pointInPolygon__default.default([coordinates.lng, coordinates.lat], this.bounds);
|
|
@@ -1833,45 +2100,22 @@ class CustomNetworkMap {
|
|
|
1833
2100
|
getItineraryInsideMap(start, end, options) {
|
|
1834
2101
|
return this.router.getItinerary(start, end, options);
|
|
1835
2102
|
}
|
|
2103
|
+
getTripInsideMap(waypoints, options) {
|
|
2104
|
+
return this.router.getTripItinerary(waypoints, options);
|
|
2105
|
+
}
|
|
1836
2106
|
enableWay(osmId) {
|
|
1837
|
-
this.
|
|
1838
|
-
var _a;
|
|
1839
|
-
return ((_a = edge.builtFrom) == null ? void 0 : _a.id) === osmId;
|
|
1840
|
-
}).forEach((e) => this.router.disabledEdges.delete(e));
|
|
2107
|
+
this.graph.edges.filter((edge) => edge.data.id === osmId).forEach((e) => this.router.disabledEdges.delete(e));
|
|
1841
2108
|
this.disabledWays.delete(osmId);
|
|
1842
2109
|
}
|
|
1843
2110
|
disableWay(osmId) {
|
|
1844
|
-
this.
|
|
1845
|
-
var _a;
|
|
1846
|
-
return ((_a = edge.builtFrom) == null ? void 0 : _a.id) === osmId;
|
|
1847
|
-
}).forEach((e) => this.router.disabledEdges.add(e));
|
|
2111
|
+
this.graph.edges.filter((edge) => edge.data.id === osmId).forEach((e) => this.router.disabledEdges.add(e));
|
|
1848
2112
|
this.disabledWays.add(osmId);
|
|
1849
2113
|
}
|
|
1850
2114
|
}
|
|
1851
|
-
function getTurnInfoFromAngle(_angle) {
|
|
1852
|
-
let direction, directionExtra;
|
|
1853
|
-
const directionAngle = maths.rad2deg(maths.diffAngle(_angle, Math.PI));
|
|
1854
|
-
const directionAngleAbs = Math.abs(directionAngle);
|
|
1855
|
-
if (directionAngleAbs <= 20) {
|
|
1856
|
-
direction = "straight";
|
|
1857
|
-
} else {
|
|
1858
|
-
direction = directionAngle > 0 ? "left" : "right";
|
|
1859
|
-
if (directionAngleAbs < 55) {
|
|
1860
|
-
directionExtra = "slight";
|
|
1861
|
-
} else if (directionAngleAbs > 120) {
|
|
1862
|
-
directionExtra = "sharp";
|
|
1863
|
-
}
|
|
1864
|
-
}
|
|
1865
|
-
return { direction, directionExtra };
|
|
1866
|
-
}
|
|
1867
|
-
const WemapOsmRouterUtils = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
|
|
1868
|
-
__proto__: null,
|
|
1869
|
-
getTurnInfoFromAngle
|
|
1870
|
-
}, Symbol.toStringTag, { value: "Module" }));
|
|
1871
2115
|
class ItineraryInfoManager {
|
|
1872
2116
|
constructor(itinerary = null) {
|
|
1873
2117
|
__publicField(this, "_itinerary", null);
|
|
1874
|
-
__publicField(this, "
|
|
2118
|
+
__publicField(this, "_geoGraphProjectionHandler", null);
|
|
1875
2119
|
__publicField(this, "_steps", []);
|
|
1876
2120
|
__publicField(this, "_coordsNextStep", []);
|
|
1877
2121
|
__publicField(this, "_coordsPreviousStep", []);
|
|
@@ -1889,8 +2133,8 @@ class ItineraryInfoManager {
|
|
|
1889
2133
|
}
|
|
1890
2134
|
this._itinerary = itinerary;
|
|
1891
2135
|
this._steps = itinerary.steps;
|
|
1892
|
-
const
|
|
1893
|
-
this.
|
|
2136
|
+
const graph = itinerary.toGraph();
|
|
2137
|
+
this._geoGraphProjectionHandler = new geo.GeoGraphProjectionHandler(graph);
|
|
1894
2138
|
this._coordsNextStep = new Array(itinerary.coords.length);
|
|
1895
2139
|
this._coordsPreviousStep = new Array(itinerary.coords.length);
|
|
1896
2140
|
this._coordsDistanceTraveled = new Array(itinerary.coords.length);
|
|
@@ -1915,15 +2159,15 @@ class ItineraryInfoManager {
|
|
|
1915
2159
|
});
|
|
1916
2160
|
}
|
|
1917
2161
|
getInfo(position) {
|
|
1918
|
-
if (!this._itinerary || !this.
|
|
2162
|
+
if (!this._itinerary || !this._geoGraphProjectionHandler) {
|
|
1919
2163
|
return null;
|
|
1920
2164
|
}
|
|
1921
|
-
const projection = this.
|
|
2165
|
+
const projection = this._geoGraphProjectionHandler.getProjection(position);
|
|
1922
2166
|
if (!projection) {
|
|
1923
2167
|
return null;
|
|
1924
2168
|
}
|
|
1925
2169
|
let itineraryInfo = null;
|
|
1926
|
-
if (projection.nearestElement instanceof geo.
|
|
2170
|
+
if (projection.nearestElement instanceof geo.GeoGraphVertex) {
|
|
1927
2171
|
const idx = this._itinerary.coords.findIndex(
|
|
1928
2172
|
(coords) => projection.nearestElement.coords === coords
|
|
1929
2173
|
);
|
|
@@ -1942,14 +2186,14 @@ class ItineraryInfoManager {
|
|
|
1942
2186
|
traveledPercentage: traveledDistance / this._itinerary.distance,
|
|
1943
2187
|
remainingPercentage: remainingDistance / this._itinerary.distance
|
|
1944
2188
|
};
|
|
1945
|
-
} else if (projection.nearestElement instanceof geo.
|
|
1946
|
-
let firstNode = projection.nearestElement.
|
|
2189
|
+
} else if (projection.nearestElement instanceof geo.GeoGraphEdge) {
|
|
2190
|
+
let firstNode = projection.nearestElement.vertex1.coords;
|
|
1947
2191
|
let idx = this._itinerary.coords.findIndex((coords) => firstNode === coords);
|
|
1948
2192
|
if (idx === -1) {
|
|
1949
2193
|
throw new Error("ItineraryInfoManager: could not find projection in itinerary (Edge)");
|
|
1950
2194
|
}
|
|
1951
|
-
if (idx === this._itinerary.coords.length - 1 || this._itinerary.coords[idx + 1] !== projection.nearestElement.
|
|
1952
|
-
firstNode = projection.nearestElement.
|
|
2195
|
+
if (idx === this._itinerary.coords.length - 1 || this._itinerary.coords[idx + 1] !== projection.nearestElement.vertex2.coords) {
|
|
2196
|
+
firstNode = projection.nearestElement.vertex2.coords;
|
|
1953
2197
|
idx--;
|
|
1954
2198
|
}
|
|
1955
2199
|
const traveledDistance = this._coordsDistanceTraveled[idx] + projection.coords.distanceTo(firstNode);
|
|
@@ -1969,23 +2213,21 @@ class ItineraryInfoManager {
|
|
|
1969
2213
|
}
|
|
1970
2214
|
}
|
|
1971
2215
|
exports.CitywayRemoteRouter = CitywayRemoteRouter$1;
|
|
2216
|
+
exports.CustomNetworkMap = CustomNetworkMap;
|
|
1972
2217
|
exports.DeutscheBahnRemoteRouter = DeutscheBahnRemoteRouter$1;
|
|
1973
2218
|
exports.IdfmRemoteRouter = IdfmRemoteRouter$1;
|
|
1974
2219
|
exports.Itinerary = Itinerary;
|
|
1975
2220
|
exports.ItineraryInfoManager = ItineraryInfoManager;
|
|
1976
2221
|
exports.Leg = Leg;
|
|
2222
|
+
exports.OsmGraph = OsmGraph;
|
|
2223
|
+
exports.OsmRouter = WemapOsmRouter;
|
|
1977
2224
|
exports.OsrmRemoteRouter = OsrmRemoteRouter$1;
|
|
1978
2225
|
exports.OtpRemoteRouter = OtpRemoteRouter$1;
|
|
1979
2226
|
exports.RemoteRouterManager = RemoteRouterManager$1;
|
|
1980
2227
|
exports.RemoteRouterServerUnreachable = RemoteRouterServerUnreachable;
|
|
1981
2228
|
exports.RouterResponse = RouterResponse;
|
|
1982
|
-
exports.StepInfo = StepInfo;
|
|
1983
|
-
exports.WemapMetaRouterIOMap = CustomNetworkMap;
|
|
1984
2229
|
exports.WemapMultiRemoteRouter = WemapMultiRemoteRouter$1;
|
|
1985
2230
|
exports.WemapMultiRemoteRouterPayload = WemapMultiRemoteRouterPayload;
|
|
1986
2231
|
exports.WemapMultiRouter = WemapMultiRouter;
|
|
1987
|
-
exports.WemapOsmRouter = WemapOsmRouter;
|
|
1988
|
-
exports.WemapOsmRouterOptions = WemapOsmRouterOptions;
|
|
1989
|
-
exports.WemapOsmRouterUtils = WemapOsmRouterUtils;
|
|
1990
2232
|
exports.getDurationFromLength = getDurationFromLength;
|
|
1991
2233
|
//# sourceMappingURL=index.js.map
|