@wemap/geo 0.4.0 → 1.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/index.js CHANGED
@@ -1,5 +1,4 @@
1
1
  import Constants from './src/Constants';
2
- import Utils from './src/Utils';
3
2
 
4
3
  import Attitude from './src/rotations/Attitude';
5
4
 
@@ -7,24 +6,10 @@ import Level from './src/coordinates/Level';
7
6
  import WGS84 from './src/coordinates/WGS84';
8
7
  import WGS84UserPosition from './src/coordinates/WGS84UserPosition';
9
8
 
10
- import Edge from './src/graph/Edge';
11
- import GraphRouter from './src/graph/GraphRouter';
12
- import Itinerary from './src/graph/Itinerary';
13
- import Network from './src/graph/Network';
14
- import Node from './src/graph/Node';
15
- import MapMatching from './src/graph/MapMatching';
16
-
17
9
  export {
18
10
  Attitude,
19
11
  Constants,
20
- Edge,
21
- GraphRouter,
22
- Itinerary,
23
12
  Level,
24
- MapMatching,
25
- Network,
26
- Node,
27
- Utils,
28
13
  WGS84,
29
14
  WGS84UserPosition
30
15
  };
package/package.json CHANGED
@@ -12,7 +12,7 @@
12
12
  "directory": "packages/geo"
13
13
  },
14
14
  "name": "@wemap/geo",
15
- "version": "0.4.0",
15
+ "version": "1.0.1",
16
16
  "bugs": {
17
17
  "url": "https://github.com/wemap/wemap-utils-js/issues"
18
18
  },
@@ -31,5 +31,5 @@
31
31
  "lodash.isnumber": "^3.0.3",
32
32
  "lodash.isstring": "^4.0.1"
33
33
  },
34
- "gitHead": "08d7d843add321d899aef07f9e2ec7739270dc70"
34
+ "gitHead": "f4d8fe98fff281533d884e0479894662c4dec9fe"
35
35
  }
@@ -96,11 +96,11 @@ class Level {
96
96
  }
97
97
 
98
98
  if (!second) {
99
- return first;
99
+ return null;
100
100
  }
101
101
 
102
102
  if (!first) {
103
- return second;
103
+ return null;
104
104
  }
105
105
 
106
106
  if (first.isRange && !second.isRange) {
@@ -137,8 +137,8 @@ describe('Level', () => {
137
137
  expect(Level.intersect(null, null)).is.null;
138
138
 
139
139
  const level = new Level(1);
140
- expect(Level.intersect(level, null)).equals(level);
141
- expect(Level.intersect(null, level)).equals(level);
140
+ expect(Level.intersect(level, null)).equals(null);
141
+ expect(Level.intersect(null, level)).equals(null);
142
142
  expect(Level.intersect(level, level)).equals(level);
143
143
 
144
144
  expect(Level.equalsTo(Level.intersect(new Level(0, 1), new Level(1)), new Level(1)));
package/src/Utils.js DELETED
@@ -1,12 +0,0 @@
1
- class Utils {
2
-
3
- /**
4
- * Get route duration
5
- * @param {Number} speed in km/h
6
- */
7
- static getDurationFromLength(length, speed = 5) {
8
- return length / (speed * 1000 / 3600);
9
- }
10
- }
11
-
12
- export default Utils;
package/src/graph/Edge.js DELETED
@@ -1,73 +0,0 @@
1
- import Node from './Node';
2
-
3
- /**
4
- * An Edge is a segment composed of two Node
5
- * An edge is mostly issued from an OsmWay (data attribute), but this is not
6
- * always the case. For example, edges created by mapmatching.
7
- */
8
- class Edge {
9
-
10
- constructor(node1, node2, data, level) {
11
-
12
- if (!(node1 instanceof Node)) {
13
- throw new TypeError('node1 is not an instance of Node');
14
- }
15
-
16
- if (!(node2 instanceof Node)) {
17
- throw new TypeError('node2 is not an instance of Node');
18
- }
19
-
20
- this.node1 = node1;
21
- this.node2 = node2;
22
- this.data = data;
23
- this.level = level;
24
-
25
- this.node1.edges.push(this);
26
- this.node2.edges.push(this);
27
-
28
- this.computedSizeAndBearing = false;
29
- }
30
-
31
- /**
32
- * Get edge bearing from node1 to node2
33
- */
34
- get bearing() {
35
- if (!this.computedSizeAndBearing) {
36
- this.computeSizeAndBearing();
37
- }
38
- return this._bearing;
39
- }
40
-
41
- /**
42
- * get edge length
43
- */
44
- get length() {
45
- if (!this.computedSizeAndBearing) {
46
- this.computeSizeAndBearing();
47
- }
48
- return this._length;
49
- }
50
-
51
- computeSizeAndBearing() {
52
- this._length = this.node1.distanceTo(this.node2);
53
- this._bearing = this.node1.bearingTo(this.node2);
54
- this.computedSizedAndBearing = true;
55
- }
56
-
57
- equalsTo(other) {
58
-
59
- if (!(other instanceof Edge)) {
60
- return false;
61
- }
62
-
63
- return other.node1.equalsTo(this.node1) && other.node2.equalsTo(this.node2);
64
- }
65
-
66
- clone(node1, node2) {
67
- const edge = new Edge(node1, node2, this.data);
68
- edge.level = this.level;
69
- return edge;
70
- }
71
- }
72
-
73
- export default Edge;
@@ -1,260 +0,0 @@
1
- /* eslint-disable max-statements */
2
- /* eslint-disable complexity */
3
-
4
- import { WGS84 } from '@wemap/geo';
5
-
6
- import Edge from './Edge';
7
- import Itinerary from './Itinerary';
8
- import Node from './Node';
9
- import MapMatching from './MapMatching';
10
- import Utils from '../Utils';
11
-
12
- const DEFAULT_ACCEPT_EDGE_FN = () => true;
13
- const DEFAULT_ACCEPT_ONEWAY_FN = () => true;
14
- const DEFAULT_WEIGHT_FN = edge => Utils.getDurationFromLength(edge.length);
15
-
16
- class GraphRouter {
17
-
18
- constructor(network, mapMatchingMaxDistance = 50) {
19
- this.network = network;
20
- this.mapMatching = new MapMatching(network);
21
- this.mapMatching.maxDistance = mapMatchingMaxDistance;
22
- }
23
-
24
- getShortestPath(
25
- _start,
26
- _end,
27
- _acceptEdgeFn,
28
- _weightFn,
29
- _acceptOneWayFn) {
30
-
31
- const acceptEdgeFn = _acceptEdgeFn || DEFAULT_ACCEPT_EDGE_FN;
32
- const weightFn = _weightFn || DEFAULT_WEIGHT_FN;
33
- const acceptOneWayFn = _acceptOneWayFn || DEFAULT_ACCEPT_ONEWAY_FN;
34
-
35
- let start;
36
- let startNodeCreated;
37
-
38
- if (_start instanceof Node) {
39
- start = _start;
40
- } else if (_start instanceof WGS84) {
41
- const node = this.network.getNodeByCoords(_start);
42
- if (node) {
43
- start = node;
44
- } else {
45
- const proj = this.mapMatching.getProjection(_start, true, false, false, acceptEdgeFn);
46
- if (proj && proj.nearestElement instanceof Node) {
47
- start = proj.nearestElement;
48
- } else if (proj && proj.nearestElement instanceof Edge) {
49
- startNodeCreated = this.createNodeInsideEdge(
50
- proj.nearestElement,
51
- proj.projection
52
- );
53
- start = startNodeCreated;
54
- }
55
- }
56
- }
57
-
58
- if (!start) {
59
- throw new Error('Cannot provide path because no starting point has been found');
60
- }
61
-
62
- let end;
63
- let endNodeCreated;
64
-
65
- if (_end instanceof Node) {
66
- end = _end;
67
- } else if (_end instanceof WGS84) {
68
- const node = this.network.getNodeByCoords(_end);
69
- if (node) {
70
- end = node;
71
- } else {
72
- const proj = this.mapMatching.getProjection(_end, true, false, false, acceptEdgeFn);
73
- if (proj && proj.nearestElement instanceof Node) {
74
- end = proj.nearestElement;
75
- } else if (proj && proj.nearestElement instanceof Edge) {
76
- endNodeCreated = this.createNodeInsideEdge(
77
- proj.nearestElement,
78
- proj.projection
79
- );
80
- end = endNodeCreated;
81
- }
82
- }
83
- }
84
-
85
- if (!end) {
86
- if (startNodeCreated) {
87
- this.removeNodeFromPreviouslyCreatedEdge(startNodeCreated);
88
- }
89
- throw new Error('Cannot provide path because no end point has been found');
90
- }
91
-
92
- const path = this.getShortestPathInternal(start, end,
93
- acceptEdgeFn, weightFn, acceptOneWayFn);
94
-
95
- let route;
96
- if (path && path.length !== 0) {
97
- route = Itinerary.fromNetworkNodes(path, _start, _end);
98
- }
99
-
100
- if (endNodeCreated) {
101
- this.removeNodeFromPreviouslyCreatedEdge(endNodeCreated);
102
- }
103
-
104
- if (startNodeCreated) {
105
- this.removeNodeFromPreviouslyCreatedEdge(startNodeCreated);
106
- }
107
-
108
- return route;
109
- }
110
-
111
- createNodeInsideEdge(edge, point) {
112
- const a = edge.node1;
113
- const b = edge.node2;
114
-
115
- const m = new Node(point);
116
- m.coords.level = edge.level;
117
-
118
- const u = new Edge(a, m);
119
- u.level = edge.level;
120
- u.data = edge.data;
121
-
122
- const v = new Edge(b, m);
123
- v.level = edge.level;
124
- v.data = edge.data;
125
-
126
- a.edges = a.edges.filter(_edge => _edge !== edge);
127
- b.edges = b.edges.filter(_edge => _edge !== edge);
128
-
129
- this.network.nodes.push(m);
130
- this.network.edges.push(u, v);
131
-
132
- this.network.edges = this.network.edges.filter(
133
- _edge => _edge !== edge
134
- );
135
-
136
- return m;
137
- }
138
-
139
- removeNodeFromPreviouslyCreatedEdge(_node) {
140
- const u = _node.edges[0];
141
- const v = _node.edges[1];
142
-
143
- u.node1.edges = u.node1.edges.filter(edge => edge !== u);
144
- v.node1.edges = v.node1.edges.filter(edge => edge !== v);
145
-
146
- const oldEdge = new Edge(u.node1, v.node1);
147
- oldEdge.data = u.data;
148
- oldEdge.level = u.level;
149
- this.network.edges.push(oldEdge);
150
-
151
- this.network.nodes = this.network.nodes.filter(node => node !== _node);
152
- this.network.edges = this.network.edges.filter(
153
- edge => edge !== u && edge !== v
154
- );
155
- }
156
-
157
- getShortestPathInternal(start, end, acceptEdgeFn, weightFn, acceptOneWayFn) {
158
- const distanceMap = {},
159
- checking = {},
160
- vertexList = {},
161
- vertexNodes = {},
162
- parentVertices = {},
163
- path = [];
164
- let vertexId = 1;
165
-
166
- // Initially, we assume each vertex is unreachable
167
- this.network.nodes.forEach(vertex => {
168
-
169
- // Generate Unique Router Id
170
- vertex.uniqueRouterId = vertexId;
171
- vertexNodes[vertexId] = vertex;
172
-
173
- distanceMap[vertexId] = Infinity;
174
- checking[vertexId] = null;
175
- vertexList[vertexId] = true;
176
-
177
- vertexId++;
178
- });
179
-
180
- // The cost from the starting vertex to the starting vertex is 0
181
- distanceMap[start.uniqueRouterId] = 0;
182
-
183
- // check each vertex
184
- while (Object.keys(vertexList).length > 0) {
185
- const current = Number(
186
- Object.keys(vertexList).reduce((_checking, vertex) => {
187
- return distanceMap[_checking] > distanceMap[vertex]
188
- ? vertex
189
- : _checking;
190
- }, Object.keys(vertexList)[0])
191
- );
192
-
193
- // all the vertices accessible from current vertex
194
- this.network.edges
195
- .filter(edge => {
196
-
197
- if (!acceptEdgeFn(edge)) {
198
- return false;
199
- }
200
-
201
- const from = edge.node1.uniqueRouterId,
202
- to = edge.node2.uniqueRouterId;
203
- // are these vertices joined?
204
- return from === current || to === current;
205
- })
206
- // for each vertex we can reach
207
- .forEach(edge => {
208
- let to, from, reversed = false;
209
- // determine the direction of travel
210
- if (edge.node1.uniqueRouterId === current) {
211
- to = edge.node2.uniqueRouterId;
212
- from = edge.node1.uniqueRouterId;
213
- } else {
214
- to = edge.node1.uniqueRouterId;
215
- from = edge.node2.uniqueRouterId;
216
- reversed = true;
217
- }
218
-
219
- if (!acceptOneWayFn(edge, reversed)) {
220
- return;
221
- }
222
-
223
- // distance is how far we travelled to reach the
224
- // current vertex, plus cost of travel the next(to)
225
- const distance = distanceMap[current] + weightFn(edge);
226
-
227
- // if we have found a cheaper path
228
- // update the hash of costs
229
- // and record which vertex we came from
230
- if (distanceMap[to] > distance) {
231
- distanceMap[to] = distance;
232
- checking[to] = current;
233
- parentVertices[to] = from;
234
- }
235
- });
236
-
237
- // remove vertex so we don't revisit it
238
- delete vertexList[current];
239
- }
240
-
241
- // now we have the most efficient paths for all vertices
242
- // build the path for the user specified vertex(end)
243
- let endId = end.uniqueRouterId;
244
- while (parentVertices[endId]) {
245
- path.unshift(vertexNodes[endId]);
246
- endId = parentVertices[endId];
247
- }
248
- if (path.length !== 0) {
249
- path.unshift(start);
250
- }
251
-
252
- // Remove Unique Router Id
253
- this.network.nodes.forEach(vertex => {
254
- delete vertex.uniqueRouterId;
255
- });
256
-
257
- return path;
258
- }
259
- }
260
- export default GraphRouter;
@@ -1,159 +0,0 @@
1
- import { expect } from 'chai';
2
-
3
- import WGS84 from '../coordinates/WGS84';
4
- import GraphRouter from './GraphRouter';
5
- import Node from './Node';
6
- import Edge from './Edge';
7
-
8
- import {
9
- network, nodes, itineraryStart, itineraryEnd, routingOptions
10
- } from '../../tests/CommonTest';
11
- import Network from './Network';
12
-
13
-
14
- const {
15
- acceptEdgeWithoutStairsFn, weightFn, acceptOneWayFn
16
- } = routingOptions;
17
-
18
- describe('GraphRouter', () => {
19
-
20
- const router = new GraphRouter(network);
21
- let itinerary;
22
-
23
- it('network did not change', () => {
24
- const nodesBefore = network.nodes.slice(0);
25
- const edgesBefore = network.edges.slice(0);
26
-
27
- itinerary = router.getShortestPath(itineraryStart, itineraryEnd, null, weightFn);
28
-
29
- const isEdgeInArray = (edgeArray, edge) => edgeArray.find(_edge =>
30
- edge.node1 === _edge.node1
31
- && edge.node2 === _edge.node2
32
- && edge.level === _edge.level
33
- && edge.data === _edge.data
34
- );
35
- const areEdgeArrayEquals = (edgeArray1, edgeArray2) => {
36
- if (edgeArray1.length !== edgeArray2.length) {
37
- return false;
38
- }
39
- for (let j = 0; j < edgeArray1.length; j++) {
40
- if (!isEdgeInArray(edgeArray2, edgeArray1[j])) {
41
- return false;
42
- }
43
- }
44
- for (let j = 0; j < edgeArray2.length; j++) {
45
- if (!isEdgeInArray(edgeArray1, edgeArray2[j])) {
46
- return false;
47
- }
48
- }
49
- return true;
50
- };
51
-
52
- expect(network.nodes.length).equals(nodesBefore.length);
53
- for (let i = 0; i < nodesBefore.length; i++) {
54
- const node = network.nodes[i];
55
- const nodeBefore = nodesBefore[i];
56
- expect(nodeBefore).equals(node);
57
- expect(areEdgeArrayEquals(node.edges, nodeBefore.edges)).true;
58
- }
59
-
60
- expect(areEdgeArrayEquals(network.edges, edgesBefore)).true;
61
- });
62
-
63
- it('router returns shortest path', () => {
64
-
65
- expect(itinerary.nodes.length).equal(11);
66
-
67
- for (let i = 1; i <= 10; i++) {
68
- expect(itinerary.nodes[i]).equal(nodes[i + 6]);
69
- }
70
-
71
- });
72
- });
73
-
74
-
75
- describe('GraphRouter - Itinerary without stairs', () => {
76
-
77
- const router = new GraphRouter(network);
78
- const itinerary = router.getShortestPath(
79
- itineraryStart,
80
- itineraryEnd,
81
- acceptEdgeWithoutStairsFn,
82
- weightFn
83
- );
84
- const itineraryWithoutRestriction = router.getShortestPath(
85
- itineraryStart,
86
- itineraryEnd,
87
- null,
88
- weightFn
89
- );
90
-
91
- it('no stairs found', () => {
92
- expect(itinerary).is.not.undefined;
93
- expect(itinerary.edges.some(node => node.data && node.data.stairs)).false;
94
-
95
- expect(itineraryWithoutRestriction).is.not.undefined;
96
- expect(itineraryWithoutRestriction.edges.some(node => node.data && node.data.stairs)).true;
97
- });
98
- });
99
-
100
-
101
- describe('GraphRouter - Itinerary one way', () => {
102
-
103
- const owNodes = [
104
- new Node(new WGS84(43.6094442, 3.8842049), { name: 'p0' }),
105
- new Node(new WGS84(43.6094286, 3.8842011), { name: 'p1' }),
106
- new Node(new WGS84(43.6094058, 3.8841955), { name: 'p2' }),
107
- new Node(new WGS84(43.6093893, 3.8841914), { name: 'p3' }),
108
- new Node(new WGS84(43.6094256, 3.8842247), { name: 'p4' }),
109
- new Node(new WGS84(43.6094028, 3.8842191), { name: 'p5' })
110
- ];
111
-
112
- const owEdges = [
113
- new Edge(owNodes[0], owNodes[1], { name: 'e0' }),
114
- new Edge(owNodes[1], owNodes[2], { name: 'e1', oneWay: true }),
115
- new Edge(owNodes[2], owNodes[3], { name: 'e2' }),
116
- new Edge(owNodes[1], owNodes[4], { name: 'e3' }),
117
- new Edge(owNodes[4], owNodes[5], { name: 'e4' }),
118
- new Edge(owNodes[5], owNodes[2], { name: 'e5' })
119
- ];
120
- const owNetwork = new Network(owNodes, owEdges);
121
- const owRouter = new GraphRouter(owNetwork);
122
-
123
- const start = new WGS84(43.6094542, 3.8842072);
124
- const end = new WGS84(43.6093792, 3.8841889);
125
-
126
- const itinerary = owRouter.getShortestPath(
127
- start,
128
- end,
129
- null,
130
- weightFn,
131
- acceptOneWayFn
132
- );
133
-
134
- const itineraryOtherWay = owRouter.getShortestPath(
135
- end,
136
- start,
137
- null,
138
- weightFn,
139
- acceptOneWayFn
140
- );
141
-
142
- it('do not use oneway segments', () => {
143
-
144
- expect(itinerary).is.not.undefined;
145
- expect(itinerary.nodes[0]).equals(owNodes[0]);
146
- expect(itinerary.nodes[1]).equals(owNodes[1]);
147
- expect(itinerary.nodes[2]).equals(owNodes[2]);
148
- expect(itinerary.nodes[3]).equals(owNodes[3]);
149
-
150
- expect(itineraryOtherWay).is.not.undefined;
151
- expect(itineraryOtherWay.nodes[0]).equals(owNodes[3]);
152
- expect(itineraryOtherWay.nodes[1]).equals(owNodes[2]);
153
- expect(itineraryOtherWay.nodes[2]).equals(owNodes[5]);
154
- expect(itineraryOtherWay.nodes[3]).equals(owNodes[4]);
155
- expect(itineraryOtherWay.nodes[4]).equals(owNodes[1]);
156
- expect(itineraryOtherWay.nodes[5]).equals(owNodes[0]);
157
-
158
- });
159
- });