@wemap/geo 0.3.7 → 0.3.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/package.json
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"directory": "packages/geo"
|
|
13
13
|
},
|
|
14
14
|
"name": "@wemap/geo",
|
|
15
|
-
"version": "0.3.
|
|
15
|
+
"version": "0.3.9",
|
|
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": "
|
|
34
|
+
"gitHead": "84a60e64b0968bc45f0f76cc26c08e165dbe6985"
|
|
35
35
|
}
|
package/src/coordinates/Level.js
CHANGED
|
@@ -119,6 +119,20 @@ describe('Level', () => {
|
|
|
119
119
|
expect(Level.equalsTo(new Level(-1.5, 1).clone(), new Level(-1.5, 1))).true;
|
|
120
120
|
});
|
|
121
121
|
|
|
122
|
+
it('isInside', () => {
|
|
123
|
+
expect(new Level(0).isInside(0)).true;
|
|
124
|
+
expect(new Level(1).isInside(0)).false;
|
|
125
|
+
expect(new Level(-1).isInside(0)).false;
|
|
126
|
+
expect(new Level(0).isInside(1)).false;
|
|
127
|
+
expect(new Level(0).isInside(-1)).false;
|
|
128
|
+
expect(new Level(0, 2).isInside(0)).true;
|
|
129
|
+
expect(new Level(0, 2).isInside(1)).true;
|
|
130
|
+
expect(new Level(0, 2).isInside(-1)).false;
|
|
131
|
+
expect(new Level(2, 0).isInside(0)).true;
|
|
132
|
+
expect(new Level(2, 0).isInside(1)).true;
|
|
133
|
+
expect(new Level(2, 0).isInside(-1)).false;
|
|
134
|
+
});
|
|
135
|
+
|
|
122
136
|
it('intersect', () => {
|
|
123
137
|
expect(Level.intersect(null, null)).is.null;
|
|
124
138
|
|
|
@@ -138,6 +152,8 @@ describe('Level', () => {
|
|
|
138
152
|
expect(Level.equalsTo(Level.intersect(new Level(-3, -1), new Level(-1, 2)), new Level(-1)));
|
|
139
153
|
expect(Level.intersect(new Level(-3, -2), new Level(-1, 2))).is.null;
|
|
140
154
|
expect(Level.intersect(new Level(-1, 2), new Level(-3, -2))).is.null;
|
|
155
|
+
expect(Level.intersect(new Level(0), new Level(1, 2))).is.null;
|
|
156
|
+
expect(Level.intersect(new Level(1, 2), new Level(0))).is.null;
|
|
141
157
|
});
|
|
142
158
|
|
|
143
159
|
it('union', () => {
|
|
@@ -159,6 +175,8 @@ describe('Level', () => {
|
|
|
159
175
|
expect(Level.equalsTo(Level.union(new Level(-3, -1), new Level(-1, 2)), new Level(-3, 2)));
|
|
160
176
|
expect(Level.equalsTo(Level.union(new Level(-3, -2), new Level(-1, 2)), new Level(-3, 2)));
|
|
161
177
|
expect(Level.equalsTo(Level.union(new Level(-1, 2), new Level(-3, -2)), new Level(-3, 2)));
|
|
178
|
+
expect(Level.equalsTo(Level.union(new Level(0), new Level(1, 2)), new Level(0, 2)));
|
|
179
|
+
expect(Level.equalsTo(Level.union(new Level(1, 2), new Level(0)), new Level(0, 2)));
|
|
162
180
|
});
|
|
163
181
|
|
|
164
182
|
});
|
package/src/graph/MapMatching.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint-disable max-statements */
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
import isNumber from 'lodash.isnumber';
|
|
4
4
|
|
|
5
5
|
import { rad2deg } from '@wemap/maths';
|
|
@@ -35,7 +35,53 @@ class MapMatching {
|
|
|
35
35
|
this.network = network;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
/**
|
|
39
|
+
* Check if the specified edge and its nodes can be used for projection
|
|
40
|
+
* @returns an array of two elements.
|
|
41
|
+
* First is true if projection will be used on the specified edge, false otherwise.
|
|
42
|
+
* Second is true if projection will be used on the nodes of the specified edge, false otherwise.
|
|
43
|
+
*/
|
|
44
|
+
_shouldProjectOnEdgeAndNodes(edge, location, useBearing, useMultiLevelSegments, acceptEdgeFn) {
|
|
45
|
+
|
|
46
|
+
if (!acceptEdgeFn(edge)) {
|
|
47
|
+
// if edge selection is not verified
|
|
48
|
+
return [false, false];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
if (location.level && !location.level.intersect(edge.level)
|
|
52
|
+
|| !location.level && edge.level) {
|
|
53
|
+
// if location level is defined and do not intersect targeted level
|
|
54
|
+
return [false, false];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ignore MultiLevelSegments if option used
|
|
58
|
+
const checkEdge = !(!useMultiLevelSegments && edge.level && edge.level.isRange);
|
|
59
|
+
|
|
60
|
+
if (useBearing) {
|
|
61
|
+
// if mapmatching bearing is enabled do not use nodes matching
|
|
62
|
+
if (checkEdge) {
|
|
63
|
+
// condition for optimisation
|
|
64
|
+
const edgeBearing = rad2deg(edge.bearing);
|
|
65
|
+
const diffAngle = MapMatching.diffAngle90(edgeBearing, location.bearing);
|
|
66
|
+
if (diffAngle > this._maxAngleBearing) {
|
|
67
|
+
// Do not try to project if angle is greater than the threshold
|
|
68
|
+
return [false, false];
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return [checkEdge, false];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return [checkEdge, true];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
static _updateProjectionLevelFromEdge = (_edge, _projection) => {
|
|
78
|
+
if (_edge.level) {
|
|
79
|
+
_projection.level = _edge.level.clone();
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
getProjection(location, useDistance = false, useBearing = false,
|
|
84
|
+
useMultiLevelSegments = true, acceptEdgeFn = () => true) {
|
|
39
85
|
|
|
40
86
|
if (!this.network) {
|
|
41
87
|
return null;
|
|
@@ -49,70 +95,52 @@ class MapMatching {
|
|
|
49
95
|
return null;
|
|
50
96
|
}
|
|
51
97
|
|
|
52
|
-
const updateProjectionLevelFromEdge = (_edge, _projection) => {
|
|
53
|
-
if (_edge.level) {
|
|
54
|
-
_projection.level = _edge.level.clone();
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
|
|
58
98
|
const projection = {};
|
|
59
99
|
projection.origin = location;
|
|
60
100
|
projection.distanceFromNearestElement = Number.MAX_VALUE;
|
|
61
101
|
|
|
102
|
+
const isProjectionBetter = (distanceOfNewProjection) => {
|
|
103
|
+
return distanceOfNewProjection < projection.distanceFromNearestElement
|
|
104
|
+
&& (!useDistance || distanceOfNewProjection <= this._maxDistance);
|
|
105
|
+
};
|
|
106
|
+
|
|
62
107
|
for (let i = 0; i < this.network.edges.length; i++) {
|
|
63
108
|
const edge = this.network.edges[i];
|
|
64
109
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
110
|
+
const [checkEdge, checkNodes] = this._shouldProjectOnEdgeAndNodes(
|
|
111
|
+
edge, location, useBearing, useMultiLevelSegments, acceptEdgeFn);
|
|
68
112
|
|
|
69
|
-
if (
|
|
70
|
-
continue;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
if (location.level && !location.level.intersect(edge.level)
|
|
74
|
-
|| !location.level && edge.level) {
|
|
75
|
-
continue;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (useBearing) {
|
|
79
|
-
const edgeBearing = rad2deg(edge.bearing);
|
|
80
|
-
const diffAngle = MapMatching.diffAngle90(edgeBearing, location.bearing);
|
|
81
|
-
if (diffAngle > this._maxAngleBearing) {
|
|
82
|
-
continue;
|
|
83
|
-
}
|
|
84
|
-
} else {
|
|
113
|
+
if (checkNodes) {
|
|
85
114
|
// Check node 1
|
|
86
115
|
const distNode1 = location.distanceTo(edge.node1.coords);
|
|
87
|
-
if (distNode1
|
|
88
|
-
&& (!useDistance || distNode1 <= this._maxDistance)) {
|
|
116
|
+
if (isProjectionBetter(distNode1)) {
|
|
89
117
|
projection.distanceFromNearestElement = distNode1;
|
|
90
118
|
projection.nearestElement = edge.node1;
|
|
91
119
|
projection.projection = edge.node1.coords.clone();
|
|
92
|
-
|
|
120
|
+
MapMatching._updateProjectionLevelFromEdge(edge, projection.projection);
|
|
93
121
|
}
|
|
94
122
|
|
|
95
123
|
// Check node 2
|
|
96
124
|
const distNode2 = location.distanceTo(edge.node2.coords);
|
|
97
|
-
if (distNode2
|
|
98
|
-
&& (!useDistance || distNode2 <= this._maxDistance)) {
|
|
125
|
+
if (isProjectionBetter(distNode2)) {
|
|
99
126
|
projection.distanceFromNearestElement = distNode2;
|
|
100
127
|
projection.nearestElement = edge.node2;
|
|
101
128
|
projection.projection = edge.node2.coords.clone();
|
|
102
|
-
|
|
129
|
+
MapMatching._updateProjectionLevelFromEdge(edge, projection.projection);
|
|
103
130
|
}
|
|
104
131
|
}
|
|
105
132
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
133
|
+
if (checkEdge) {
|
|
134
|
+
// Check edge
|
|
135
|
+
const segmentProjection = location.getProjection(edge);
|
|
136
|
+
if (segmentProjection) {
|
|
137
|
+
const distEdge = location.distanceTo(segmentProjection);
|
|
138
|
+
if (isProjectionBetter(distEdge)) {
|
|
139
|
+
projection.distanceFromNearestElement = distEdge;
|
|
140
|
+
projection.nearestElement = edge;
|
|
141
|
+
projection.projection = segmentProjection.clone();
|
|
142
|
+
MapMatching._updateProjectionLevelFromEdge(edge, projection.projection);
|
|
143
|
+
}
|
|
116
144
|
}
|
|
117
145
|
}
|
|
118
146
|
}
|
|
@@ -34,10 +34,6 @@ describe('MapMatching', () => {
|
|
|
34
34
|
it('matching node levels', () => {
|
|
35
35
|
let currentPosition, projection;
|
|
36
36
|
|
|
37
|
-
/**
|
|
38
|
-
* Projection on Nodes
|
|
39
|
-
*/
|
|
40
|
-
|
|
41
37
|
currentPosition = new WGS84(43.6091773, 3.8842584, null, null);
|
|
42
38
|
projection = mapMatching.getProjection(currentPosition);
|
|
43
39
|
expect(projection).is.null;
|
|
@@ -57,10 +53,6 @@ describe('MapMatching', () => {
|
|
|
57
53
|
it('matching edge levels', () => {
|
|
58
54
|
let currentPosition, projection;
|
|
59
55
|
|
|
60
|
-
/**
|
|
61
|
-
* Projection on Edges
|
|
62
|
-
*/
|
|
63
|
-
|
|
64
56
|
currentPosition = new WGS84(43.6092811, 3.8842406, null, null);
|
|
65
57
|
projection = mapMatching.getProjection(currentPosition);
|
|
66
58
|
expect(projection).is.null;
|
|
@@ -80,10 +72,6 @@ describe('MapMatching', () => {
|
|
|
80
72
|
it('matching stairs nodes levels', () => {
|
|
81
73
|
let currentPosition, projection;
|
|
82
74
|
|
|
83
|
-
/**
|
|
84
|
-
* Projection on Edges
|
|
85
|
-
*/
|
|
86
|
-
|
|
87
75
|
currentPosition = new WGS84(43.6093691, 3.8842057, null, null);
|
|
88
76
|
projection = mapMatching.getProjection(currentPosition);
|
|
89
77
|
expect(projection).is.null;
|
|
@@ -103,10 +91,6 @@ describe('MapMatching', () => {
|
|
|
103
91
|
it('matching stairs edge levels', () => {
|
|
104
92
|
let currentPosition, projection;
|
|
105
93
|
|
|
106
|
-
/**
|
|
107
|
-
* Projection on Edges
|
|
108
|
-
*/
|
|
109
|
-
|
|
110
94
|
currentPosition = new WGS84(43.6093476, 3.8841978, null, null);
|
|
111
95
|
projection = mapMatching.getProjection(currentPosition);
|
|
112
96
|
expect(projection).is.null;
|
|
@@ -125,4 +109,25 @@ describe('MapMatching', () => {
|
|
|
125
109
|
|
|
126
110
|
});
|
|
127
111
|
|
|
112
|
+
it('useMultiLevelSegments', () => {
|
|
113
|
+
let currentPosition, projection;
|
|
114
|
+
|
|
115
|
+
// On Nodes
|
|
116
|
+
|
|
117
|
+
currentPosition = new WGS84(43.6093691, 3.8842057, null, new Level(0));
|
|
118
|
+
projection = mapMatching.getProjection(currentPosition, true, false, false);
|
|
119
|
+
expect(projection).is.null;
|
|
120
|
+
|
|
121
|
+
// Next two are complex cases and not yet handled by our system
|
|
122
|
+
|
|
123
|
+
// currentPosition = new WGS84(43.6093691, 3.8842057, null, new Level(1));
|
|
124
|
+
// projection = mapMatching.getProjection(currentPosition, true, false, false);
|
|
125
|
+
// expect(projection.nearestElement).equals(nodes[14]);
|
|
126
|
+
|
|
127
|
+
// currentPosition = new WGS84(43.6093691, 3.8842057, null, new Level(2));
|
|
128
|
+
// projection = mapMatching.getProjection(currentPosition, true, false, false);
|
|
129
|
+
// expect(projection.nearestElement).equals(nodes[11]);
|
|
130
|
+
|
|
131
|
+
});
|
|
132
|
+
|
|
128
133
|
});
|