@wemap/geo 11.0.0-alpha.0 → 11.0.0-alpha.10
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/package.json +11 -5
- package/src/Utils.ts +4 -4
- package/src/coordinates/BoundingBox.ts +17 -33
- package/src/graph/GraphEdge.ts +8 -8
- package/src/graph/GraphNode.spec.ts +5 -3
- package/src/graph/GraphNode.ts +12 -12
- package/src/graph/GraphProjection.ts +3 -3
- package/src/graph/GraphUtils.ts +5 -5
- package/src/graph/MapMatching.ts +7 -7
- package/src/graph/Network.spec.ts +5 -2
- package/src/graph/Network.ts +24 -25
- package/src/router/GraphItinerary.spec.ts +1 -1
- package/src/router/GraphItinerary.ts +11 -11
- package/src/router/GraphRouter.spec.ts +16 -16
- package/src/router/GraphRouter.ts +34 -34
- package/src/router/GraphRouterOptions.ts +3 -3
- package/tests/CommonTest.ts +8 -6
- package/dist/index.js +0 -1633
- package/dist/index.js.map +0 -1
|
@@ -15,18 +15,18 @@ import GraphRouterOptions from './GraphRouterOptions.js';
|
|
|
15
15
|
const { expect } = chai;
|
|
16
16
|
chai.use(chaiAlmost(1e-3));
|
|
17
17
|
|
|
18
|
-
const networkDidNotChange = <
|
|
19
|
-
networkAfter: Network<
|
|
20
|
-
nodesBefore: GraphNode<
|
|
21
|
-
edgesBefore: GraphEdge<
|
|
18
|
+
const networkDidNotChange = <N, E>(
|
|
19
|
+
networkAfter: Network<N, E>,
|
|
20
|
+
nodesBefore: GraphNode<N, E>[],
|
|
21
|
+
edgesBefore: GraphEdge<E, N>[]
|
|
22
22
|
) => {
|
|
23
23
|
|
|
24
|
-
const isEdgeInArray = (edgeArray: GraphEdge<
|
|
24
|
+
const isEdgeInArray = (edgeArray: GraphEdge<E, N>[], edge: GraphEdge<E, N>) => edgeArray.find(_edge =>
|
|
25
25
|
edge.node1 === _edge.node1
|
|
26
26
|
&& edge.node2 === _edge.node2
|
|
27
27
|
&& edge.level === _edge.level
|
|
28
28
|
);
|
|
29
|
-
const areEdgeArrayEquals = (edgeArray1: GraphEdge<
|
|
29
|
+
const areEdgeArrayEquals = (edgeArray1: GraphEdge<E, N>[], edgeArray2: GraphEdge<E, N>[]) => {
|
|
30
30
|
if (edgeArray1.length !== edgeArray2.length) {
|
|
31
31
|
return false;
|
|
32
32
|
}
|
|
@@ -54,11 +54,11 @@ const networkDidNotChange = <T>(
|
|
|
54
54
|
expect(areEdgeArrayEquals(networkAfter.edges, edgesBefore)).true;
|
|
55
55
|
};
|
|
56
56
|
|
|
57
|
-
const getShortestPath = <
|
|
58
|
-
_router: GraphRouter<
|
|
59
|
-
_start: GraphNode<
|
|
60
|
-
_end: GraphNode<
|
|
61
|
-
_options?: GraphRouterOptions<
|
|
57
|
+
const getShortestPath = <N, E>(
|
|
58
|
+
_router: GraphRouter<N, E>,
|
|
59
|
+
_start: GraphNode<N, E> | Coordinates,
|
|
60
|
+
_end: GraphNode<N, E> | Coordinates,
|
|
61
|
+
_options?: GraphRouterOptions<N, E>
|
|
62
62
|
) => {
|
|
63
63
|
const { _network: network } = _router;
|
|
64
64
|
const nodesBefore = network.nodes.slice(0);
|
|
@@ -74,7 +74,7 @@ const createModel = () => {
|
|
|
74
74
|
|
|
75
75
|
const b = (name: string): BuiltFrom_t => ({ name });
|
|
76
76
|
|
|
77
|
-
const nodes = [
|
|
77
|
+
const nodes: GraphNode<BuiltFrom_t, BuiltFrom_t>[] = [
|
|
78
78
|
new GraphNode(new Coordinates(43.6091194, 3.884099), b('p0')),
|
|
79
79
|
new GraphNode(new Coordinates(43.6093629, 3.8842777), b('p1')),
|
|
80
80
|
new GraphNode(new Coordinates(43.6092785, 3.8845052), b('p2')),
|
|
@@ -105,9 +105,9 @@ const createModel = () => {
|
|
|
105
105
|
|
|
106
106
|
const getNodesNames = (_itinerary: GraphItinerary<BuiltFrom_t>) => _itinerary.nodes.map(node => node.builtFrom?.name || null);
|
|
107
107
|
|
|
108
|
-
let itinerary: GraphItinerary<BuiltFrom_t>,
|
|
109
|
-
router: GraphRouter<BuiltFrom_t>,
|
|
110
|
-
options: GraphRouterOptions<BuiltFrom_t>;
|
|
108
|
+
let itinerary: GraphItinerary<BuiltFrom_t, BuiltFrom_t>,
|
|
109
|
+
router: GraphRouter<BuiltFrom_t, BuiltFrom_t>,
|
|
110
|
+
options: GraphRouterOptions<BuiltFrom_t, BuiltFrom_t>;
|
|
111
111
|
|
|
112
112
|
describe('GraphRouter', () => {
|
|
113
113
|
|
|
@@ -193,7 +193,7 @@ describe('GraphRouter - Itinerary without stairs', () => {
|
|
|
193
193
|
it('no stairs found', () => {
|
|
194
194
|
|
|
195
195
|
router = new GraphRouter(network);
|
|
196
|
-
options = new GraphRouterOptions();
|
|
196
|
+
options = new GraphRouterOptions<BuiltFrom_t, BuiltFrom_t>();
|
|
197
197
|
options.acceptEdgeFn = edge => !edge.builtFrom?.stairs;
|
|
198
198
|
|
|
199
199
|
itinerary = getShortestPath(router, start, end, options);
|
|
@@ -10,23 +10,23 @@ import NoRouteFoundError from './NoRouteFoundError.js';
|
|
|
10
10
|
import GraphRouterOptions from './GraphRouterOptions.js';
|
|
11
11
|
import GraphItinerary from './GraphItinerary.js';
|
|
12
12
|
|
|
13
|
-
type Vertex<
|
|
13
|
+
type Vertex<N, E> = GraphNode<N, E> & { uniqueRouterId: number };
|
|
14
14
|
|
|
15
|
-
class GraphRouter<
|
|
15
|
+
class GraphRouter<N, E> {
|
|
16
16
|
|
|
17
|
-
_mapMatching: MapMatching<
|
|
18
|
-
_network: Network<
|
|
19
|
-
disabledEdges: Set<GraphEdge<
|
|
17
|
+
_mapMatching: MapMatching<N, E>;
|
|
18
|
+
_network: Network<N, E>;
|
|
19
|
+
disabledEdges: Set<GraphEdge<E, N>> = new Set();
|
|
20
20
|
|
|
21
|
-
constructor(network: Network<
|
|
21
|
+
constructor(network: Network<N, E>) {
|
|
22
22
|
this._network = network;
|
|
23
23
|
this._mapMatching = new MapMatching(network);
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
getShortestPath(
|
|
27
|
-
start: GraphNode<
|
|
28
|
-
end: GraphNode<
|
|
29
|
-
options = new GraphRouterOptions<
|
|
27
|
+
start: GraphNode<N, E> | Coordinates,
|
|
28
|
+
end: GraphNode<N, E> | Coordinates,
|
|
29
|
+
options = new GraphRouterOptions<N, E>()
|
|
30
30
|
) {
|
|
31
31
|
|
|
32
32
|
if (!(start instanceof GraphNode) && !(start instanceof Coordinates)) {
|
|
@@ -40,10 +40,10 @@ class GraphRouter<T> {
|
|
|
40
40
|
const { acceptEdgeFn, weightEdgeFn, projectionMaxDistance } = options;
|
|
41
41
|
this._mapMatching.maxDistance = projectionMaxDistance;
|
|
42
42
|
|
|
43
|
-
const createdNodes: GraphNode<
|
|
43
|
+
const createdNodes: GraphNode<N, E>[] = [];
|
|
44
44
|
|
|
45
45
|
|
|
46
|
-
const retrieveOrCreateNearestNode = (point: GraphNode<
|
|
46
|
+
const retrieveOrCreateNearestNode = (point: GraphNode<N, E> | Coordinates) => {
|
|
47
47
|
if (point instanceof GraphNode) {
|
|
48
48
|
return point;
|
|
49
49
|
}
|
|
@@ -77,7 +77,7 @@ class GraphRouter<T> {
|
|
|
77
77
|
|
|
78
78
|
const removeCreatedNodes = () => {
|
|
79
79
|
while (createdNodes.length) {
|
|
80
|
-
this.removeNodeFromPreviouslyCreatedEdge(createdNodes.pop() as GraphNode<
|
|
80
|
+
this.removeNodeFromPreviouslyCreatedEdge(createdNodes.pop() as GraphNode<N, E>);
|
|
81
81
|
}
|
|
82
82
|
};
|
|
83
83
|
|
|
@@ -90,7 +90,7 @@ class GraphRouter<T> {
|
|
|
90
90
|
|
|
91
91
|
let graphItinerary;
|
|
92
92
|
if (startNode === endNode) {
|
|
93
|
-
graphItinerary = GraphItinerary.fromNetworkNodes<
|
|
93
|
+
graphItinerary = GraphItinerary.fromNetworkNodes<N, E>(
|
|
94
94
|
startCoords, endCoords, [startNode], []
|
|
95
95
|
);
|
|
96
96
|
} else {
|
|
@@ -117,11 +117,11 @@ class GraphRouter<T> {
|
|
|
117
117
|
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
-
createNodeInsideEdge(edge: GraphEdge<
|
|
120
|
+
createNodeInsideEdge(edge: GraphEdge<E, N>, point: Coordinates) {
|
|
121
121
|
const a = edge.node1;
|
|
122
122
|
const b = edge.node2;
|
|
123
123
|
|
|
124
|
-
const m = new GraphNode<
|
|
124
|
+
const m = new GraphNode<N, E>(point, null); // cannot use edge.builtFrom because of typing
|
|
125
125
|
m.coords.level = edge.level;
|
|
126
126
|
|
|
127
127
|
const u = edge.clone();
|
|
@@ -145,7 +145,7 @@ class GraphRouter<T> {
|
|
|
145
145
|
return m;
|
|
146
146
|
}
|
|
147
147
|
|
|
148
|
-
removeNodeFromPreviouslyCreatedEdge(_node: GraphNode<
|
|
148
|
+
removeNodeFromPreviouslyCreatedEdge(_node: GraphNode<N, E>) {
|
|
149
149
|
const u = _node.edges[0];
|
|
150
150
|
const v = _node.edges[1];
|
|
151
151
|
|
|
@@ -164,16 +164,16 @@ class GraphRouter<T> {
|
|
|
164
164
|
}
|
|
165
165
|
|
|
166
166
|
getShortestPathBetweenGraphNodes(
|
|
167
|
-
start: GraphNode<
|
|
168
|
-
end: GraphNode<
|
|
169
|
-
acceptEdgeFn: (edge: GraphEdge<
|
|
170
|
-
weightFn: (edge: GraphEdge<
|
|
167
|
+
start: GraphNode<N, E>,
|
|
168
|
+
end: GraphNode<N, E>,
|
|
169
|
+
acceptEdgeFn: (edge: GraphEdge<E, N>) => boolean,
|
|
170
|
+
weightFn: (edge: GraphEdge<E, N>) => number
|
|
171
171
|
) {
|
|
172
172
|
|
|
173
173
|
const distanceMap: { [key: number]: number } = {},
|
|
174
174
|
checking: { [key: number]: null | number } = {},
|
|
175
175
|
vertexList: { [key: number]: boolean } = {},
|
|
176
|
-
vertexNodes: { [key: number]: Vertex<
|
|
176
|
+
vertexNodes: { [key: number]: Vertex<N, E> } = {},
|
|
177
177
|
parentVertices: { [key: number]: number } = {},
|
|
178
178
|
path = [];
|
|
179
179
|
let vertexId = 1;
|
|
@@ -183,8 +183,8 @@ class GraphRouter<T> {
|
|
|
183
183
|
this._network.nodes.forEach(vertex => {
|
|
184
184
|
|
|
185
185
|
// Generate Unique Router Id
|
|
186
|
-
(vertex as Vertex<
|
|
187
|
-
vertexNodes[vertexId] = vertex as Vertex<
|
|
186
|
+
(vertex as Vertex<N, E>).uniqueRouterId = vertexId;
|
|
187
|
+
vertexNodes[vertexId] = vertex as Vertex<N, E>;
|
|
188
188
|
distanceMap[vertexId] = Infinity;
|
|
189
189
|
checking[vertexId] = null;
|
|
190
190
|
vertexList[vertexId] = true;
|
|
@@ -192,8 +192,8 @@ class GraphRouter<T> {
|
|
|
192
192
|
vertexId++;
|
|
193
193
|
});
|
|
194
194
|
|
|
195
|
-
const startVertex = Object.values(vertexNodes).find(vertex => start.equals(vertex)) as Vertex<
|
|
196
|
-
const endVertex = Object.values(vertexNodes).find(vertex => end.equals(vertex)) as Vertex<
|
|
195
|
+
const startVertex = Object.values(vertexNodes).find(vertex => start.equals(vertex)) as Vertex<N, E>;
|
|
196
|
+
const endVertex = Object.values(vertexNodes).find(vertex => end.equals(vertex)) as Vertex<N, E>;
|
|
197
197
|
|
|
198
198
|
// The cost from the starting vertex to the starting vertex is 0
|
|
199
199
|
distanceMap[startVertex.uniqueRouterId] = 0;
|
|
@@ -217,8 +217,8 @@ class GraphRouter<T> {
|
|
|
217
217
|
return false;
|
|
218
218
|
}
|
|
219
219
|
|
|
220
|
-
const from = (edge.node1 as Vertex<
|
|
221
|
-
to = (edge.node2 as Vertex<
|
|
220
|
+
const from = (edge.node1 as Vertex<N, E>).uniqueRouterId,
|
|
221
|
+
to = (edge.node2 as Vertex<N, E>).uniqueRouterId;
|
|
222
222
|
// are these vertices joined?
|
|
223
223
|
return from === current || to === current;
|
|
224
224
|
})
|
|
@@ -226,12 +226,12 @@ class GraphRouter<T> {
|
|
|
226
226
|
.forEach(edge => {
|
|
227
227
|
let to, from, reversed = false;
|
|
228
228
|
// determine the direction of travel
|
|
229
|
-
if ((edge.node1 as Vertex<
|
|
230
|
-
to = (edge.node2 as Vertex<
|
|
231
|
-
from = (edge.node1 as Vertex<
|
|
229
|
+
if ((edge.node1 as Vertex<N, E>).uniqueRouterId === current) {
|
|
230
|
+
to = (edge.node2 as Vertex<N, E>).uniqueRouterId;
|
|
231
|
+
from = (edge.node1 as Vertex<N, E>).uniqueRouterId;
|
|
232
232
|
} else {
|
|
233
|
-
to = (edge.node1 as Vertex<
|
|
234
|
-
from = (edge.node2 as Vertex<
|
|
233
|
+
to = (edge.node1 as Vertex<N, E>).uniqueRouterId;
|
|
234
|
+
from = (edge.node2 as Vertex<N, E>).uniqueRouterId;
|
|
235
235
|
reversed = true;
|
|
236
236
|
}
|
|
237
237
|
|
|
@@ -273,11 +273,11 @@ class GraphRouter<T> {
|
|
|
273
273
|
|
|
274
274
|
// Remove Unique Router Id
|
|
275
275
|
this._network.nodes.forEach(vertex => {
|
|
276
|
-
delete (vertex as GraphNode<
|
|
276
|
+
delete (vertex as GraphNode<N, E> & { uniqueRouterId?: number }).uniqueRouterId;
|
|
277
277
|
});
|
|
278
278
|
|
|
279
279
|
// This clone the itinerary and temporary nodes
|
|
280
|
-
return GraphItinerary.fromNetworkNodes<
|
|
280
|
+
return GraphItinerary.fromNetworkNodes<N, E>(start.coords, end.coords, path, edgesWeights);
|
|
281
281
|
}
|
|
282
282
|
}
|
|
283
283
|
export default GraphRouter;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import GraphEdge from '../graph/GraphEdge.js';
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
class GraphRouterOptions<
|
|
4
|
+
class GraphRouterOptions<N, E> {
|
|
5
5
|
|
|
6
6
|
/** in meters */
|
|
7
7
|
projectionMaxDistance = 50;
|
|
8
8
|
|
|
9
|
-
weightEdgeFn = (edge: GraphEdge<
|
|
10
|
-
acceptEdgeFn: (edge: GraphEdge<
|
|
9
|
+
weightEdgeFn = (edge: GraphEdge<E, N>) => edge.length;
|
|
10
|
+
acceptEdgeFn: (edge: GraphEdge<E, N>) => boolean = () => true;
|
|
11
11
|
|
|
12
12
|
}
|
|
13
13
|
|
package/tests/CommonTest.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable no-inline-comments */
|
|
2
1
|
import chai from 'chai';
|
|
3
2
|
|
|
4
3
|
import Coordinates from '../src/coordinates/Coordinates.js';
|
|
@@ -11,7 +10,10 @@ import Network from '../src/graph/Network.js';
|
|
|
11
10
|
|
|
12
11
|
const { expect } = chai;
|
|
13
12
|
|
|
14
|
-
|
|
13
|
+
type N = string;
|
|
14
|
+
type E = string;
|
|
15
|
+
|
|
16
|
+
const nodes: Node<N, E>[] = [
|
|
15
17
|
new Node(new Coordinates(43.6092404, 3.884099), 'p0'), // 0
|
|
16
18
|
new Node(new Coordinates(43.6091965, 3.8841285), 'p1'),
|
|
17
19
|
new Node(new Coordinates(43.6091888, 3.8841263), 'p2'),
|
|
@@ -39,7 +41,7 @@ const nodes = [
|
|
|
39
41
|
new Node(new Coordinates(43.6095624, 3.8845134), 'p23')
|
|
40
42
|
];
|
|
41
43
|
|
|
42
|
-
const n = (name: string) => (nodes.find(node => node.builtFrom === name) as GraphNode<
|
|
44
|
+
const n = (name: string) => (nodes.find(node => node.builtFrom === name) as GraphNode<N, E>);
|
|
43
45
|
|
|
44
46
|
const edges = [
|
|
45
47
|
new Edge(n('p1'), n('p2'), 2, 'e0'),
|
|
@@ -69,12 +71,12 @@ const edges = [
|
|
|
69
71
|
new Edge(n('p22'), n('p23'), null, 'e24')
|
|
70
72
|
];
|
|
71
73
|
|
|
72
|
-
const network = new Network<
|
|
74
|
+
const network = new Network<E, N>();
|
|
73
75
|
network.edges = edges;
|
|
74
76
|
network.nodes = nodes;
|
|
75
77
|
Node.generateNodesLevels(nodes);
|
|
76
78
|
|
|
77
|
-
function verifyCoherence
|
|
79
|
+
function verifyCoherence(_network: Network) {
|
|
78
80
|
|
|
79
81
|
_network.edges.forEach(edge => {
|
|
80
82
|
expect(edge.node1).not.equal(edge.node2);
|
|
@@ -82,7 +84,7 @@ function verifyCoherence<T>(_network: Network<T>) {
|
|
|
82
84
|
|
|
83
85
|
_network.nodes.forEach(node => {
|
|
84
86
|
node.edges.forEach(edge => {
|
|
85
|
-
expect(edge).satisfy((_edge: GraphEdge
|
|
87
|
+
expect(edge).satisfy((_edge: GraphEdge) => {
|
|
86
88
|
return _edge.node1 === node || _edge.node2 === node;
|
|
87
89
|
});
|
|
88
90
|
});
|