@wemap/routers 12.10.8 → 12.10.9
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/helpers/InstructionManager.d.ts +20 -0
- package/dist/helpers/InstructionManagerV1.d.ts +7 -0
- package/{index.ts → dist/index.d.ts} +1 -11
- package/dist/index.js +1 -5099
- package/dist/index.js.map +1 -1
- package/dist/src/ItineraryInfoManager.d.ts +31 -0
- package/dist/src/RoutingError.d.ts +24 -0
- package/{src/StatusCode.ts → dist/src/StatusCode.d.ts} +2 -3
- package/dist/src/Utils.d.ts +6 -0
- package/dist/src/graph/Edge.d.ts +32 -0
- package/dist/src/graph/Graph.d.ts +40 -0
- package/dist/src/graph/GraphProjection.d.ts +11 -0
- package/dist/src/graph/GraphProjectionOptions.d.ts +7 -0
- package/dist/src/graph/GraphRoute.d.ts +19 -0
- package/dist/src/graph/GraphRouter.d.ts +20 -0
- package/dist/src/graph/GraphRouterEngine.d.ts +77 -0
- package/{src/graph/GraphRouterOptions.ts → dist/src/graph/GraphRouterOptions.d.ts} +5 -7
- package/dist/src/graph/GraphRouterOptionsBuilder.d.ts +20 -0
- package/dist/src/graph/NoRouteFoundError.d.ts +12 -0
- package/dist/src/graph/Vertex.d.ts +19 -0
- package/dist/src/model/Itinerary.d.ts +81 -0
- package/dist/src/model/Leg.d.ts +66 -0
- package/dist/src/model/LevelChange.d.ts +7 -0
- package/dist/src/model/RouterRequest.d.ts +40 -0
- package/dist/src/model/Step.d.ts +42 -0
- package/dist/src/model/StepExtra.d.ts +3 -0
- package/dist/src/model/StepsBuilder.d.ts +16 -0
- package/dist/src/model/TransitMode.d.ts +5 -0
- package/{src/model/TravelMode.ts → dist/src/model/TravelMode.d.ts} +1 -2
- package/dist/src/model/generateSteps.d.ts +0 -0
- package/{src/remote/RemoteRouter.ts → dist/src/remote/RemoteRouter.d.ts} +2 -7
- package/dist/src/remote/RemoteRouterManager.d.ts +731 -0
- package/dist/src/remote/RemoteRouterUtils.d.ts +6 -0
- package/dist/src/remote/cityway/CitywayRemoteRouter.d.ts +109 -0
- package/dist/src/remote/deutsche-bahn/DeutscheBahnRemoteRouter.d.ts +31 -0
- package/dist/src/remote/geovelo/GeoveloRemoteRouter.d.ts +106 -0
- package/dist/src/remote/idfm/IdfmRemoteRouter.d.ts +123 -0
- package/dist/src/remote/navitia/NavitiaRemoteRouter.d.ts +34 -0
- package/dist/src/remote/navitia/types.d.ts +87 -0
- package/dist/src/remote/osrm/OsrmRemoteRouter.d.ts +70 -0
- package/dist/src/remote/otp/OtpRemoteRouter.d.ts +69 -0
- package/dist/src/remote/wemap-multi/WemapMultiRemoteRouter.d.ts +19 -0
- package/dist/src/types.d.ts +31 -0
- package/dist/src/wemap-multi/CustomGraphMap.d.ts +56 -0
- package/dist/src/wemap-multi/CustomGraphMapTester.d.ts +39 -0
- package/dist/src/wemap-multi/WemapMultiRouter.d.ts +14 -0
- package/dist/src/wemap-osm/OsmGraphUtils.d.ts +11 -0
- package/dist/tests/CommonTest.d.ts +8 -0
- package/package.json +11 -8
- package/assets/biocbon-bergere-rdc-network.osm +0 -163
- package/assets/bureaux-wemap-montpellier-network.osm +0 -174
- package/assets/components.osm +0 -146
- package/assets/elevator-models-4.osm +0 -89
- package/assets/elevator-models.osm +0 -354
- package/assets/exit-graph.osm +0 -25
- package/assets/gare-de-lest-network-pp-bounds.osm +0 -1613
- package/assets/gare-de-lyon-extract.osm +0 -174
- package/assets/geovelo-montpellier.json +0 -1144
- package/assets/horizontal-elevator.osm +0 -12
- package/assets/itinerary-deutsche-bahn-1.json +0 -368
- package/assets/itinerary-grenoble-otp-1.json +0 -1536
- package/assets/itinerary-grenoble-otp-2.json +0 -1092
- package/assets/itinerary-info-two-points-proj.osm +0 -39
- package/assets/itinerary-info-two-points.osm +0 -24
- package/assets/itinerary-lehavre-cityway-1.json +0 -6799
- package/assets/itinerary-lehavre-cityway-2.json +0 -2133
- package/assets/itinerary-lehavre-cityway-3.json +0 -12577
- package/assets/itinerary-lehavre-cityway-4.json +0 -1451
- package/assets/itinerary-lehavre-cityway-5.json +0 -5925
- package/assets/itinerary-lemans-navitia.json +0 -7768
- package/assets/itinerary-montpellier-osrm-3.json +0 -185
- package/assets/itinerary-montpellier-outdoor-without-steps.json +0 -110
- package/assets/itinerary-montpellier-outdoor.json +0 -513
- package/assets/itinerary-paris-idfm-2.json +0 -1838
- package/assets/itinerary-paris-idfm.json +0 -27727
- package/assets/itinerary-step-not-on-path-osrm.json +0 -457
- package/assets/itinerary-with-duplicate-nodes.json +0 -110
- package/assets/network-conveying-backward.osm +0 -74
- package/assets/network-elevator.osm +0 -48
- package/assets/network-escalators.osm +0 -50
- package/assets/network-simple.osm +0 -27
- package/assets/network-steps-same-level.osm +0 -283
- package/assets/network-with-modifiers.osm +0 -39
- package/assets/one-way.osm +0 -46
- package/assets/report-map-1.osm +0 -36
- package/assets/report-map-2.osm +0 -29
- package/assets/report-map-3.osm +0 -15
- package/assets/rr-wemap-multi-indoor-outdoor-indoor.json +0 -1352
- package/assets/rr-wemap-multi-indoor-outdoor.json +0 -145
- package/assets/rr-wemap-multi-multi-level.json +0 -262
- package/assets/rr-wemap-multi-outdoor-indoor.json +0 -145
- package/assets/rr-wemap-multi-outdoor-outdoor.json +0 -207
- package/assets/rr-wemap-multi-remote-indoor-indoor.json +0 -155
- package/assets/rr-wemap-multi-remote-indoor-outdoor-indoor.json +0 -668
- package/assets/rr-wemap-multi-remote-indoor-outdoor.json +0 -154
- package/assets/rr-wemap-multi-remote-outdoor-indoor.json +0 -179
- package/assets/rr-wemap-multi-remote-outdoor-outdoor.json +0 -109
- package/assets/stairs-and-exit.osm +0 -47
- package/helpers/InstructionManager.ts +0 -184
- package/helpers/InstructionManagerV1.ts +0 -95
- package/src/ItineraryInfoManager.spec.ts +0 -183
- package/src/ItineraryInfoManager.ts +0 -181
- package/src/RoutingError.ts +0 -60
- package/src/Utils.ts +0 -8
- package/src/graph/Edge.spec.ts +0 -32
- package/src/graph/Edge.ts +0 -64
- package/src/graph/Graph.spec.ts +0 -509
- package/src/graph/Graph.ts +0 -272
- package/src/graph/GraphProjection.ts +0 -15
- package/src/graph/GraphProjectionOptions.ts +0 -8
- package/src/graph/GraphRoute.spec.ts +0 -15
- package/src/graph/GraphRoute.ts +0 -43
- package/src/graph/GraphRouter.spec.ts +0 -317
- package/src/graph/GraphRouter.ts +0 -229
- package/src/graph/GraphRouterEngine.ts +0 -248
- package/src/graph/GraphRouterOptionsBuilder.ts +0 -98
- package/src/graph/NoRouteFoundError.ts +0 -39
- package/src/graph/Vertex.spec.ts +0 -42
- package/src/graph/Vertex.ts +0 -45
- package/src/model/Itinerary.spec.ts +0 -134
- package/src/model/Itinerary.ts +0 -370
- package/src/model/Leg.spec.ts +0 -107
- package/src/model/Leg.ts +0 -224
- package/src/model/LevelChange.spec.ts +0 -50
- package/src/model/LevelChange.ts +0 -14
- package/src/model/RouterRequest.ts +0 -33
- package/src/model/Step.spec.ts +0 -99
- package/src/model/Step.ts +0 -90
- package/src/model/StepExtra.ts +0 -1
- package/src/model/StepsBuilder.ts +0 -242
- package/src/model/TransitMode.spec.ts +0 -31
- package/src/model/TransitMode.ts +0 -28
- package/src/model/generateSteps.ts +0 -102
- package/src/remote/RemoteRouterManager.spec.ts +0 -178
- package/src/remote/RemoteRouterManager.ts +0 -72
- package/src/remote/RemoteRouterUtils.ts +0 -25
- package/src/remote/cityway/CitywayRemoteRouter.spec.ts +0 -122
- package/src/remote/cityway/CitywayRemoteRouter.ts +0 -435
- package/src/remote/deutsche-bahn/DeutscheBahnRemoteRouter.spec.ts +0 -52
- package/src/remote/deutsche-bahn/DeutscheBahnRemoteRouter.ts +0 -85
- package/src/remote/geovelo/GeoveloRemoteRouter.spec.ts +0 -54
- package/src/remote/geovelo/GeoveloRemoteRouter.ts +0 -293
- package/src/remote/idfm/IdfmRemoteRouter.spec.ts +0 -102
- package/src/remote/idfm/IdfmRemoteRouter.ts +0 -523
- package/src/remote/navitia/NavitiaRemoteRouter.spec.ts +0 -116
- package/src/remote/navitia/NavitiaRemoteRouter.ts +0 -445
- package/src/remote/navitia/types.ts +0 -73
- package/src/remote/osrm/OsrmRemoteRouter.spec.ts +0 -127
- package/src/remote/osrm/OsrmRemoteRouter.ts +0 -303
- package/src/remote/otp/OtpRemoteRouter.spec.ts +0 -103
- package/src/remote/otp/OtpRemoteRouter.ts +0 -223
- package/src/remote/wemap-multi/WemapMultiRemoteRouter.spec.ts +0 -103
- package/src/remote/wemap-multi/WemapMultiRemoteRouter.ts +0 -56
- package/src/types.ts +0 -32
- package/src/wemap-multi/CustomGraphMap.spec.ts +0 -40
- package/src/wemap-multi/CustomGraphMap.ts +0 -213
- package/src/wemap-multi/CustomGraphMapTester.spec.ts +0 -48
- package/src/wemap-multi/CustomGraphMapTester.ts +0 -90
- package/src/wemap-multi/WemapMultiRouter.spec.ts +0 -138
- package/src/wemap-multi/WemapMultiRouter.ts +0 -329
- package/src/wemap-osm/OsmGraphUtils.spec.ts +0 -165
- package/src/wemap-osm/OsmGraphUtils.ts +0 -173
- package/src/wemap-osm/OsmRouter.elevators.spec.ts +0 -106
- package/src/wemap-osm/OsmRouter.spec.ts +0 -292
- package/tests/CommonTest.ts +0 -78
- package/tsconfig.json +0 -3
- package/vite.config.ts +0 -4
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import chai from 'chai';
|
|
2
|
-
import fs from 'fs';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import { fileURLToPath } from 'url';
|
|
5
|
-
import fetchMock from 'fetch-mock';
|
|
6
|
-
|
|
7
|
-
import { Coordinates } from '@wemap/geo';
|
|
8
|
-
|
|
9
|
-
import WemapMultiRemoteRouter from './WemapMultiRemoteRouter.js';
|
|
10
|
-
import { verifyStepsCoherence } from '../../model/Itinerary.spec.js';
|
|
11
|
-
import { type RouterRequest } from '../../model/RouterRequest.js';
|
|
12
|
-
|
|
13
|
-
const { expect } = chai;
|
|
14
|
-
|
|
15
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
16
|
-
const assetsPath = path.resolve(__dirname, '../../../assets');
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
function mockFetchWithJsonAsset(assetName: string) {
|
|
20
|
-
fetchMock.restore();
|
|
21
|
-
fetchMock.mock('*', (() => {
|
|
22
|
-
const filePath = path.resolve(assetsPath, assetName);
|
|
23
|
-
const fileString = fs.readFileSync(filePath, 'utf8');
|
|
24
|
-
return JSON.parse(fileString);
|
|
25
|
-
})(),)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
describe('WemapMultiRemoteRouter', () => {
|
|
29
|
-
|
|
30
|
-
after(() => {
|
|
31
|
-
fetchMock.restore();
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
const endpointUrl = 'http://localhost:3001';
|
|
36
|
-
|
|
37
|
-
it('indoor to indoor', async () => {
|
|
38
|
-
mockFetchWithJsonAsset('rr-wemap-multi-remote-indoor-indoor.json');
|
|
39
|
-
|
|
40
|
-
const routerRequest: RouterRequest = {
|
|
41
|
-
origin: new Coordinates(48.8725992, 2.343431),
|
|
42
|
-
destination: new Coordinates(48.8725694, 2.3433),
|
|
43
|
-
travelMode: 'WALK'
|
|
44
|
-
}
|
|
45
|
-
const itineraries = await WemapMultiRemoteRouter.getItineraries(endpointUrl, routerRequest);
|
|
46
|
-
itineraries.forEach(verifyStepsCoherence);
|
|
47
|
-
expect(itineraries.length).equals(1);
|
|
48
|
-
expect(itineraries[0].coords.length).equals(6);
|
|
49
|
-
expect(itineraries[0].legs).not.empty;
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it('outdoor to outdoor', async () => {
|
|
53
|
-
mockFetchWithJsonAsset('rr-wemap-multi-remote-outdoor-outdoor.json');
|
|
54
|
-
const routerRequest: RouterRequest = {
|
|
55
|
-
origin: new Coordinates(48.8726513, 2.343449),
|
|
56
|
-
destination: new Coordinates(48.8726397, 2.3431657),
|
|
57
|
-
travelMode: 'WALK'
|
|
58
|
-
}
|
|
59
|
-
const itineraries = await WemapMultiRemoteRouter.getItineraries(endpointUrl, routerRequest);
|
|
60
|
-
itineraries.forEach(verifyStepsCoherence);
|
|
61
|
-
expect(itineraries[0].coords.length).equals(4);
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it('outdoor to indoor', async () => {
|
|
65
|
-
mockFetchWithJsonAsset('rr-wemap-multi-remote-outdoor-indoor.json');
|
|
66
|
-
const routerRequest: RouterRequest = {
|
|
67
|
-
origin: new Coordinates(48.8726085, 2.3434289),
|
|
68
|
-
destination: new Coordinates(48.8725694, 2.3433),
|
|
69
|
-
travelMode: 'WALK'
|
|
70
|
-
}
|
|
71
|
-
const itineraries = await WemapMultiRemoteRouter.getItineraries(endpointUrl, routerRequest);
|
|
72
|
-
|
|
73
|
-
itineraries.forEach(verifyStepsCoherence);
|
|
74
|
-
expect(itineraries[0].coords.length).equals(6);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it('indoor to outdoor', async () => {
|
|
78
|
-
mockFetchWithJsonAsset('rr-wemap-multi-remote-indoor-outdoor.json');
|
|
79
|
-
const routerRequest: RouterRequest = {
|
|
80
|
-
origin: new Coordinates(48.8725992, 2.343431),
|
|
81
|
-
destination: new Coordinates(48.8726513, 2.343449),
|
|
82
|
-
travelMode: 'WALK'
|
|
83
|
-
}
|
|
84
|
-
const itineraries = await WemapMultiRemoteRouter.getItineraries(endpointUrl, routerRequest);
|
|
85
|
-
|
|
86
|
-
itineraries.forEach(verifyStepsCoherence);
|
|
87
|
-
expect(itineraries[0].coords.length).equals(6);
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
it('indoor to outdoor to indoor', async () => {
|
|
91
|
-
mockFetchWithJsonAsset('rr-wemap-multi-remote-indoor-outdoor-indoor.json');
|
|
92
|
-
const routerRequest: RouterRequest = {
|
|
93
|
-
origin: new Coordinates(48.8725992, 2.343431),
|
|
94
|
-
destination: new Coordinates(48.8772962, 2.3584458, null, 0),
|
|
95
|
-
travelMode: 'WALK'
|
|
96
|
-
}
|
|
97
|
-
const itineraries = await WemapMultiRemoteRouter.getItineraries(endpointUrl, routerRequest);
|
|
98
|
-
|
|
99
|
-
itineraries.forEach(verifyStepsCoherence);
|
|
100
|
-
expect(itineraries[0].coords.length).equals(77);
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
});
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { Coordinates } from '@wemap/geo';
|
|
2
|
-
|
|
3
|
-
import RemoteRouter from '../RemoteRouter.js';
|
|
4
|
-
import { RouterRequest } from '../../model/RouterRequest.js';
|
|
5
|
-
import Itinerary from '../../model/Itinerary.js';
|
|
6
|
-
import { RemoteRoutingError } from '../../RoutingError.js';
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
type WemapRouterRequest = Omit<RouterRequest, 'origin' | 'destination' | 'waypoints'> & {
|
|
10
|
-
mapId?: number,
|
|
11
|
-
origin: Coordinates | number | string
|
|
12
|
-
destination: Coordinates | number | string
|
|
13
|
-
waypoints?: (Coordinates | number | string)[]
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Singleton.
|
|
18
|
-
*/
|
|
19
|
-
class WemapMultiRemoteRouter extends RemoteRouter {
|
|
20
|
-
|
|
21
|
-
get rname() { return 'wemap-multi' as const; }
|
|
22
|
-
|
|
23
|
-
async getItineraries(endpointUrl: string, routerRequest: WemapRouterRequest) {
|
|
24
|
-
const { origin, destination, waypoints } = routerRequest;
|
|
25
|
-
const payload = {
|
|
26
|
-
...routerRequest,
|
|
27
|
-
origin: origin instanceof Coordinates ? origin.toJson() : origin,
|
|
28
|
-
destination: destination instanceof Coordinates ? destination.toJson() : destination,
|
|
29
|
-
...(waypoints && {waypoints: waypoints.map(w => w instanceof Coordinates ? w.toJson() : w)})
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
const res = await (fetch(endpointUrl, {
|
|
33
|
-
method: 'POST',
|
|
34
|
-
headers: {
|
|
35
|
-
'Accept': 'application/json',
|
|
36
|
-
'Content-Type': 'application/json'
|
|
37
|
-
},
|
|
38
|
-
body: JSON.stringify(payload)
|
|
39
|
-
}).catch(() => {
|
|
40
|
-
throw RemoteRoutingError.unreachableServer(this.rname, endpointUrl);
|
|
41
|
-
}));
|
|
42
|
-
|
|
43
|
-
const jsonResponse = await res.json().catch(() => {
|
|
44
|
-
throw RemoteRoutingError.responseNotParsing(this.rname, endpointUrl);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
if (jsonResponse.error) {
|
|
48
|
-
throw RemoteRoutingError.notFound(this.rname, jsonResponse.error)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
return (jsonResponse.itineraries || []).map(Itinerary.fromJson) as Itinerary[];
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export default new WemapMultiRemoteRouter();
|
package/src/types.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { type CoordinatesCompressedJson } from '@wemap/geo';
|
|
2
|
-
import { type EdgeProperties } from './graph/Edge.js';
|
|
3
|
-
import { VertexProperties } from './graph/Vertex.js';
|
|
4
|
-
|
|
5
|
-
export type GraphVertexJson = {
|
|
6
|
-
id: number,
|
|
7
|
-
coords: CoordinatesCompressedJson
|
|
8
|
-
properties?: VertexProperties
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export type GraphEdgeJson = {
|
|
12
|
-
id: number,
|
|
13
|
-
vertex1Idx: number,
|
|
14
|
-
vertex2Idx: number,
|
|
15
|
-
properties?: EdgeProperties
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export type GeoGraphJson = {
|
|
19
|
-
vertices: GraphVertexJson[],
|
|
20
|
-
edges: GraphEdgeJson[]
|
|
21
|
-
};
|
|
22
|
-
|
|
23
|
-
export type CompressedGraphVertexJson = CoordinatesCompressedJson;
|
|
24
|
-
|
|
25
|
-
export type CompressedGeoGraphJson = {
|
|
26
|
-
vertices: CompressedGraphVertexJson[],
|
|
27
|
-
verticesIds: (string | number)[],
|
|
28
|
-
edges: (
|
|
29
|
-
[number, number] |
|
|
30
|
-
[number, number, EdgeProperties]
|
|
31
|
-
)[]
|
|
32
|
-
};
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import chai from 'chai';
|
|
2
|
-
import fs from 'fs';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import { fileURLToPath } from 'url';
|
|
5
|
-
|
|
6
|
-
import CustomGraphMap from './CustomGraphMap.js';
|
|
7
|
-
|
|
8
|
-
const { expect } = chai;
|
|
9
|
-
|
|
10
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
11
|
-
|
|
12
|
-
function getMapNameAndContents(assetName: string) {
|
|
13
|
-
const filePath = path.resolve(__dirname, '../../assets/' + assetName);
|
|
14
|
-
const osmXmlString = fs.readFileSync(filePath, 'utf8');
|
|
15
|
-
const mapName = path.parse(assetName).name;
|
|
16
|
-
return [mapName, osmXmlString];
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
describe('CustomGraphMap', () => {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
it('fromOsmXml - biocbon-bergere-rdc-network', async () => {
|
|
23
|
-
|
|
24
|
-
const [mapName, mapContents] = getMapNameAndContents('biocbon-bergere-rdc-network.osm');
|
|
25
|
-
const customGraphMap = CustomGraphMap.fromOsmXml(mapContents, mapName)!;
|
|
26
|
-
expect(customGraphMap.entryPoints.length).equal(1);
|
|
27
|
-
expect(customGraphMap.graph.edges).is.not.empty;
|
|
28
|
-
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it('fromOsmXml - gare-de-lest-network-pp-bounds', async () => {
|
|
32
|
-
|
|
33
|
-
const [mapName, mapContents] = getMapNameAndContents('gare-de-lest-network-pp-bounds.osm');
|
|
34
|
-
const customGraphMap = CustomGraphMap.fromOsmXml(mapContents, mapName)!;
|
|
35
|
-
expect(customGraphMap.entryPoints.length).equal(4);
|
|
36
|
-
expect(customGraphMap.graph.edges).is.not.empty;
|
|
37
|
-
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
});
|
|
@@ -1,213 +0,0 @@
|
|
|
1
|
-
import pointInPolygon from '@turf/boolean-point-in-polygon';
|
|
2
|
-
import convexHullFn from '@turf/convex';
|
|
3
|
-
import { Position, MultiPolygon } from '@turf/helpers';
|
|
4
|
-
|
|
5
|
-
import { Coordinates, Level } from '@wemap/geo';
|
|
6
|
-
import { OsmNode, OsmParser } from '@wemap/osm';
|
|
7
|
-
|
|
8
|
-
import Graph from '../graph/Graph.js';
|
|
9
|
-
import GraphRouter from '../graph/GraphRouter.js';
|
|
10
|
-
import { GraphRouterOptions } from '../graph/GraphRouterOptions.js';
|
|
11
|
-
import Vertex from '../graph/Vertex.js';
|
|
12
|
-
import OsmGraphUtils from '../wemap-osm/OsmGraphUtils.js';
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
export type ParsingErrors = {
|
|
16
|
-
couldNotParseFile?: string,
|
|
17
|
-
routingIoNotFound: OsmNode[],
|
|
18
|
-
routingBoundsNotFound: boolean
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export default class CustomGraphMap {
|
|
22
|
-
|
|
23
|
-
name: string | null;
|
|
24
|
-
graph: Graph;
|
|
25
|
-
router: GraphRouter;
|
|
26
|
-
bounds: MultiPolygon;
|
|
27
|
-
entryPoints: Vertex[];
|
|
28
|
-
|
|
29
|
-
constructor(
|
|
30
|
-
graph: Graph,
|
|
31
|
-
entryPoints: Vertex[],
|
|
32
|
-
bounds: MultiPolygon | null = null,
|
|
33
|
-
name: string | null = null) {
|
|
34
|
-
|
|
35
|
-
this.name = name;
|
|
36
|
-
this.graph = graph;
|
|
37
|
-
this.router = new GraphRouter(graph);
|
|
38
|
-
|
|
39
|
-
// Entry points
|
|
40
|
-
entryPoints.forEach(entryPoint => {
|
|
41
|
-
if (!graph.vertices.includes(entryPoint)) {
|
|
42
|
-
throw new Error(`Cannot find entry point ${entryPoint.coords.toString()} in graph "${name}"`);
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
this.entryPoints = entryPoints;
|
|
46
|
-
|
|
47
|
-
// Bounds
|
|
48
|
-
if (bounds) {
|
|
49
|
-
this.bounds = bounds;
|
|
50
|
-
} else {
|
|
51
|
-
const polygon = [graph.vertices.map(vertex => [vertex.coords.lng, vertex.coords.lat] as Position)];
|
|
52
|
-
const convexHull = convexHullFn({ type: 'polygon', coordinates: polygon });
|
|
53
|
-
if (!convexHull) {
|
|
54
|
-
throw new Error(`Cannot calculate convexHull of graph "${name}"`);
|
|
55
|
-
}
|
|
56
|
-
this.bounds = {
|
|
57
|
-
type: 'MultiPolygon',
|
|
58
|
-
coordinates: [convexHull.geometry.coordinates]
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
static fromOsmXml(
|
|
64
|
-
osmXmlString: string,
|
|
65
|
-
name: string | null = null,
|
|
66
|
-
callbackErrors?: (errors: ParsingErrors) => void
|
|
67
|
-
) {
|
|
68
|
-
const errors: ParsingErrors = {
|
|
69
|
-
routingIoNotFound: [],
|
|
70
|
-
routingBoundsNotFound: false
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
let osmModel;
|
|
74
|
-
try {
|
|
75
|
-
osmModel = OsmParser.parseOsmXmlString(osmXmlString);
|
|
76
|
-
} catch (e) {
|
|
77
|
-
errors.couldNotParseFile = e instanceof Error ? e.message : "Unknown error";
|
|
78
|
-
callbackErrors?.(errors);
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
let verticesMapping: [nodeId: number, vertex: Vertex][] = []
|
|
82
|
-
const graph = OsmGraphUtils.createGraphFromOsmModel(osmModel, OsmGraphUtils.DEFAULT_WAY_SELECTOR, vm => (verticesMapping = vm));
|
|
83
|
-
|
|
84
|
-
const entryPointsOsmNodes = osmModel.nodes.filter(node => node.tags['wemap:routing-io']);
|
|
85
|
-
const entryPointsToCheck = entryPointsOsmNodes.map(node => {
|
|
86
|
-
const vertex = verticesMapping.find(v => v[0] === node.id)?.[1]
|
|
87
|
-
if (!vertex) { errors.routingIoNotFound.push(node); }
|
|
88
|
-
return vertex || null;
|
|
89
|
-
});
|
|
90
|
-
const entryPoints = entryPointsToCheck.filter(it => it !== null) as Vertex[];
|
|
91
|
-
entryPoints.forEach(v => graph.exitVertices.add(v));
|
|
92
|
-
|
|
93
|
-
const bounds: MultiPolygon = {
|
|
94
|
-
type: 'MultiPolygon',
|
|
95
|
-
coordinates: []
|
|
96
|
-
};
|
|
97
|
-
osmModel.ways
|
|
98
|
-
.filter(({ tags }) => tags['wemap:routing-bounds'])
|
|
99
|
-
.forEach(way => {
|
|
100
|
-
bounds.coordinates.push([way.nodes.reduce((acc, node) => {
|
|
101
|
-
acc.push([node.coords.lng, node.coords.lat]);
|
|
102
|
-
return acc;
|
|
103
|
-
}, [] as Position[])
|
|
104
|
-
]);
|
|
105
|
-
});
|
|
106
|
-
osmModel.relations
|
|
107
|
-
.filter(rel => rel.tags['wemap:routing-bounds'] && rel.isMultipolygon())
|
|
108
|
-
.forEach(rel => {
|
|
109
|
-
const polygon = rel.getGeoJsonPolygon();
|
|
110
|
-
polygon && bounds.coordinates.push(polygon.coordinates);
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
if (!bounds.coordinates.length) {
|
|
114
|
-
errors.routingBoundsNotFound = true;
|
|
115
|
-
}
|
|
116
|
-
callbackErrors?.(errors);
|
|
117
|
-
return new CustomGraphMap(graph, entryPoints, bounds, name);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
isPointInside(coordinates: Coordinates) {
|
|
121
|
-
return pointInPolygon([coordinates.lng, coordinates.lat], this.bounds);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Get the list of entry points sorted by the lowest distance between:
|
|
126
|
-
* start -> entry point -> end
|
|
127
|
-
* (as the crow flies)
|
|
128
|
-
*
|
|
129
|
-
*/
|
|
130
|
-
getOrderedEntryPointsSortedByDistance(start: Coordinates, end: Coordinates) {
|
|
131
|
-
const entryPointsCopy = [...this.entryPoints];
|
|
132
|
-
const levelDiffFactor = 50; // in meters
|
|
133
|
-
return entryPointsCopy.sort((ep1, ep2) => {
|
|
134
|
-
|
|
135
|
-
const distance2D = Number(ep1.coords.distanceTo(start)) + ep1.coords.distanceTo(end)
|
|
136
|
-
- (ep2.coords.distanceTo(start) + ep2.coords.distanceTo(end))
|
|
137
|
-
|
|
138
|
-
const levelDiffEp1Start = Math.abs(Level.diff(start.level, ep1.coords.level) || 0);
|
|
139
|
-
const levelDiffEp1End = Math.abs(Level.diff(end.level, ep1.coords.level) || 0);
|
|
140
|
-
const levelDiffEp2Start = Math.abs(Level.diff(start.level, ep2.coords.level) || 0);
|
|
141
|
-
const levelDiffEp2End = Math.abs(Level.diff(end.level, ep2.coords.level) || 0);
|
|
142
|
-
const levelDiff = levelDiffEp1Start + levelDiffEp1End - (levelDiffEp2Start + levelDiffEp2End);
|
|
143
|
-
|
|
144
|
-
return distance2D + levelDiff * levelDiffFactor;
|
|
145
|
-
});
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Get the best itinerary from any entry point to an end coordinates.
|
|
150
|
-
*
|
|
151
|
-
* The algorithm works as following:
|
|
152
|
-
* 1 - Entry points are sorted using distance (as the crow flies) between start - entry point - end
|
|
153
|
-
* 2 - Try to calculate an itinerary from the first entry point to the end coordinates.
|
|
154
|
-
* 3 - If an itinerary is found, it is returned. Otherwise it tries from the next entry point.
|
|
155
|
-
*
|
|
156
|
-
* /!\ start is only used to sort the entry points (step 1).
|
|
157
|
-
*
|
|
158
|
-
*/
|
|
159
|
-
getBestRouteFromEntryPointsToDestination(start: Coordinates, end: Coordinates, options: GraphRouterOptions) {
|
|
160
|
-
// TODO: use multiple-destinations algorithm
|
|
161
|
-
const sortedEntryPoints = this.getOrderedEntryPointsSortedByDistance(start, end);
|
|
162
|
-
for (const entryPoint of sortedEntryPoints) {
|
|
163
|
-
const route = this.router.calculateShortestPath(entryPoint.coords, end, options).route();
|
|
164
|
-
if (route.hasRoute) {
|
|
165
|
-
return route;
|
|
166
|
-
}
|
|
167
|
-
// no route found
|
|
168
|
-
}
|
|
169
|
-
return null;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* Get the best itinerary from start coordinates to any entry point.
|
|
175
|
-
*
|
|
176
|
-
* The algorithm works as following:
|
|
177
|
-
* 1 - Entry points are sorted using distance (as the crow flies) between start - entry point - end
|
|
178
|
-
* 2 - Try to calculate an itinerary from the start coordinates to the first entry point.
|
|
179
|
-
* 3 - If an itinerary is found, it is returned. Otherwise it tries to the next entry point.
|
|
180
|
-
*
|
|
181
|
-
* /!\ end is only used to sort the entry points (step 1).
|
|
182
|
-
*
|
|
183
|
-
*/
|
|
184
|
-
getBestRouteFromOriginToEntryPoints(start: Coordinates, end: Coordinates, options: GraphRouterOptions) {
|
|
185
|
-
// TODO: use multiple-destinations algorithm
|
|
186
|
-
const sortedEntryPoints = this.getOrderedEntryPointsSortedByDistance(start, end);
|
|
187
|
-
for (const entryPoint of sortedEntryPoints) {
|
|
188
|
-
const route = this.router.calculateShortestPath(start, entryPoint.coords, options).route();
|
|
189
|
-
if (route.hasRoute) {
|
|
190
|
-
return route;
|
|
191
|
-
}
|
|
192
|
-
// no route found
|
|
193
|
-
}
|
|
194
|
-
return null;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
getRouteInsideMap(start: Coordinates, end: Coordinates, options: GraphRouterOptions) {
|
|
198
|
-
// Call the Wemap router to get the shortest path
|
|
199
|
-
const route = this.router.calculateShortestPath(start, end, options).route();
|
|
200
|
-
return route.hasRoute ? route : null;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
getTripInsideMap(waypoints: Coordinates[], options: GraphRouterOptions) {
|
|
204
|
-
// Call the Wemap router to get the shortest trip itinerary
|
|
205
|
-
return this.router.getShortestTrip(waypoints, options);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
getRoutesMultipleDestinationsInsideMap(start: Coordinates, ends: Coordinates[], options: GraphRouterOptions) {
|
|
209
|
-
// Call the Wemap router to get the shortest path for all the input destinations
|
|
210
|
-
return this.router.calculateShortestPathToMultipleDestinations(start, ends, options);
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import chai from 'chai';
|
|
2
|
-
import fs from 'fs';
|
|
3
|
-
import path from 'path';
|
|
4
|
-
import { fileURLToPath } from 'url';
|
|
5
|
-
|
|
6
|
-
import CustomGraphMapTester from './CustomGraphMapTester.js';
|
|
7
|
-
|
|
8
|
-
const { expect } = chai;
|
|
9
|
-
|
|
10
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
11
|
-
|
|
12
|
-
function createReport(fileName: string) {
|
|
13
|
-
const filePath = path.resolve(__dirname, '../../assets/' + fileName);
|
|
14
|
-
const osmXmlString = fs.readFileSync(filePath, 'utf8');
|
|
15
|
-
return CustomGraphMapTester.createReport(osmXmlString);
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
describe('CustomGraphMapTester', () => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
it('multiple-graph-components', async () => {
|
|
22
|
-
|
|
23
|
-
const report = createReport('report-map-1.osm');
|
|
24
|
-
expect(report.errors.length).equal(1);
|
|
25
|
-
expect(report.errors[0].type).equal('multiple-graph-components');
|
|
26
|
-
expect(report.errors[0].data.length).equal(2);
|
|
27
|
-
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it('routing-io-not-on-graph', async () => {
|
|
31
|
-
|
|
32
|
-
const report = createReport('report-map-2.osm');
|
|
33
|
-
expect(report.errors.length).equal(1);
|
|
34
|
-
expect(report.errors[0].type).equal('routing-io-not-on-graph');
|
|
35
|
-
expect(report.errors[0].data.length).equal(1);
|
|
36
|
-
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
it('routing-bounds-not-found', async () => {
|
|
40
|
-
|
|
41
|
-
const report = createReport('report-map-3.osm');
|
|
42
|
-
expect(report.errors.length).equal(1);
|
|
43
|
-
expect(report.errors[0].type).equal('routing-bounds-not-found');
|
|
44
|
-
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
});
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
import { OsmNode } from '@wemap/osm';
|
|
3
|
-
|
|
4
|
-
import CustomGraphMap, { type ParsingErrors } from './CustomGraphMap.js';
|
|
5
|
-
import Vertex from '../graph/Vertex.js';
|
|
6
|
-
|
|
7
|
-
export type Report = {
|
|
8
|
-
customGraphMap?: CustomGraphMap,
|
|
9
|
-
errors: Error[],
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export type Error = CouldNotParseFileError
|
|
13
|
-
| MultipleGraphComponentsError
|
|
14
|
-
| RoutingBoundsNotFoundError
|
|
15
|
-
| RoutingIoNotOnGraphError;
|
|
16
|
-
|
|
17
|
-
export type CouldNotParseFileError = {
|
|
18
|
-
type: 'could-not-parse-file',
|
|
19
|
-
details: string | undefined
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export type MultipleGraphComponentsError = {
|
|
23
|
-
type: 'multiple-graph-components',
|
|
24
|
-
data: Vertex[][]
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export type RoutingBoundsNotFoundError = {
|
|
28
|
-
type: 'routing-bounds-not-found'
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export type RoutingIoNotOnGraphError = {
|
|
32
|
-
type: 'routing-io-not-on-graph',
|
|
33
|
-
data: OsmNode[]
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export default class CustomGraphMapTester {
|
|
37
|
-
|
|
38
|
-
static createReport(osmXmlString: string): Report {
|
|
39
|
-
|
|
40
|
-
let customGraphMapErrors: ParsingErrors | undefined;
|
|
41
|
-
const customGraphMap = CustomGraphMap.fromOsmXml(osmXmlString, null, e => (customGraphMapErrors = e));
|
|
42
|
-
const errors: Error[] = [];
|
|
43
|
-
|
|
44
|
-
if (customGraphMapErrors?.couldNotParseFile || !customGraphMap) {
|
|
45
|
-
errors.push({
|
|
46
|
-
type: 'could-not-parse-file',
|
|
47
|
-
details: customGraphMapErrors?.couldNotParseFile
|
|
48
|
-
});
|
|
49
|
-
return { errors };
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
const components = customGraphMap.router.calculateComponents();
|
|
53
|
-
if (components.length > 1) {
|
|
54
|
-
errors.push({
|
|
55
|
-
type: 'multiple-graph-components',
|
|
56
|
-
data: components
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
if (customGraphMapErrors?.routingBoundsNotFound) {
|
|
60
|
-
errors.push({
|
|
61
|
-
type: 'routing-bounds-not-found'
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
if (customGraphMapErrors?.routingIoNotFound?.length) {
|
|
65
|
-
errors.push({
|
|
66
|
-
type: 'routing-io-not-on-graph',
|
|
67
|
-
data: customGraphMapErrors.routingIoNotFound
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
return { customGraphMap, errors };
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
static reportToJson(report: Report) {
|
|
75
|
-
return {
|
|
76
|
-
graph: report.customGraphMap?.graph?.toCompressedJson(),
|
|
77
|
-
errors: report.errors.map(error => {
|
|
78
|
-
if (error.type === 'multiple-graph-components') {
|
|
79
|
-
return { type: error.type, data: error.data.map(c => c.map(v => v.id)) };
|
|
80
|
-
}
|
|
81
|
-
if (error.type === 'routing-io-not-on-graph') {
|
|
82
|
-
return { type: error.type, data: error.data.map(v => v.id) };
|
|
83
|
-
}
|
|
84
|
-
return { type: error.type };
|
|
85
|
-
})
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
|