@wemap/geo 4.0.0 → 4.0.3
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 +1 -0
- package/package.json +3 -3
- package/src/graph/MapMatching.js +33 -9
- package/src/graph/MapMatching.spec.js +1 -1
- package/src/graph/Projection.js +21 -0
- package/src/graph/Step.js +10 -0
- package/src/rotations/Attitude.js +32 -9
package/index.js
CHANGED
|
@@ -20,6 +20,7 @@ export { default as Itinerary } from './src/graph/Itinerary.js';
|
|
|
20
20
|
export { default as Network } from './src/graph/Network.js';
|
|
21
21
|
export { default as Node } from './src/graph/Node.js';
|
|
22
22
|
export { default as MapMatching } from './src/graph/MapMatching.js';
|
|
23
|
+
export { default as Projection } from './src/graph/Projection.js';
|
|
23
24
|
export { default as Step } from './src/graph/Step.js';
|
|
24
25
|
export * as GraphUtils from './src/graph/Utils.js';
|
|
25
26
|
export { default as NoRouteFoundError } from './src/graph/NoRouteFoundError.js';
|
package/package.json
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"directory": "packages/geo"
|
|
13
13
|
},
|
|
14
14
|
"name": "@wemap/geo",
|
|
15
|
-
"version": "4.0.
|
|
15
|
+
"version": "4.0.3",
|
|
16
16
|
"bugs": {
|
|
17
17
|
"url": "https://github.com/wemap/wemap-modules-js/issues"
|
|
18
18
|
},
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"license": "ISC",
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@wemap/logger": "^4.0.0",
|
|
31
|
-
"@wemap/maths": "^4.0.
|
|
31
|
+
"@wemap/maths": "^4.0.3"
|
|
32
32
|
},
|
|
33
|
-
"gitHead": "
|
|
33
|
+
"gitHead": "91a82028ddda32038999582da381d1d0d8acd091"
|
|
34
34
|
}
|
package/src/graph/MapMatching.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable complexity */
|
|
1
2
|
/* eslint-disable max-statements */
|
|
2
3
|
import { diffAngleLines } from '@wemap/maths';
|
|
3
4
|
|
|
@@ -6,6 +7,7 @@ import Coordinates from '../coordinates/Coordinates.js';
|
|
|
6
7
|
import Level from '../coordinates/Level.js';
|
|
7
8
|
|
|
8
9
|
import Network from './Network.js';
|
|
10
|
+
import Projection from './Projection.js';
|
|
9
11
|
|
|
10
12
|
class MapMatching {
|
|
11
13
|
|
|
@@ -104,8 +106,7 @@ class MapMatching {
|
|
|
104
106
|
// if mapmatching bearing is enabled do not use nodes matching
|
|
105
107
|
if (checkEdge) {
|
|
106
108
|
// condition for optimisation
|
|
107
|
-
const diffAngle = diffAngleLines(
|
|
108
|
-
edge.bearing, location.bearing);
|
|
109
|
+
const diffAngle = diffAngleLines(edge.bearing, location.bearing);
|
|
109
110
|
if (diffAngle > this._maxAngleBearing) {
|
|
110
111
|
// Do not try to project if angle is greater than the threshold
|
|
111
112
|
checkEdge = false;
|
|
@@ -118,6 +119,21 @@ class MapMatching {
|
|
|
118
119
|
return [checkEdge, checkNode1, checkNode2];
|
|
119
120
|
}
|
|
120
121
|
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* @param {Coordinates} fromCoordinates
|
|
125
|
+
* @param {Coordinates} toCoordinates
|
|
126
|
+
*/
|
|
127
|
+
static _assignLatLngLevel(fromCoordinates, toCoordinates) {
|
|
128
|
+
toCoordinates.lat = fromCoordinates.lat;
|
|
129
|
+
toCoordinates.lng = fromCoordinates.lng;
|
|
130
|
+
toCoordinates.level = fromCoordinates.level;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* @param {Edge} _edge
|
|
135
|
+
* @param {Coordinates} _projection
|
|
136
|
+
*/
|
|
121
137
|
static _updateProjectionLevelFromEdge = (_edge, _projection) => {
|
|
122
138
|
if (_edge.level) {
|
|
123
139
|
_projection.level = _edge.level.clone();
|
|
@@ -130,6 +146,7 @@ class MapMatching {
|
|
|
130
146
|
* @param {boolean} useBearing
|
|
131
147
|
* @param {boolean} useMultiLevelSegments
|
|
132
148
|
* @param {function} acceptEdgeFn
|
|
149
|
+
* @returns {Projection}
|
|
133
150
|
*/
|
|
134
151
|
getProjection(location, useDistance = false, useBearing = false,
|
|
135
152
|
useMultiLevelSegments = true, acceptEdgeFn = () => true) {
|
|
@@ -146,9 +163,10 @@ class MapMatching {
|
|
|
146
163
|
return null;
|
|
147
164
|
}
|
|
148
165
|
|
|
149
|
-
const projection =
|
|
166
|
+
const projection = new Projection();
|
|
150
167
|
projection.origin = location;
|
|
151
168
|
projection.distanceFromNearestElement = Number.MAX_VALUE;
|
|
169
|
+
projection.projection = location.clone();
|
|
152
170
|
|
|
153
171
|
const isProjectionBetter = (distanceOfNewProjection) => {
|
|
154
172
|
return distanceOfNewProjection < projection.distanceFromNearestElement
|
|
@@ -167,10 +185,11 @@ class MapMatching {
|
|
|
167
185
|
if (isProjectionBetter(distNode1) || distNode1 <= Constants.EPS_MM) {
|
|
168
186
|
projection.distanceFromNearestElement = distNode1;
|
|
169
187
|
projection.nearestElement = edge.node1;
|
|
170
|
-
|
|
188
|
+
MapMatching._assignLatLngLevel(edge.node1.coords, projection.projection);
|
|
171
189
|
MapMatching._updateProjectionLevelFromEdge(edge, projection.projection);
|
|
172
190
|
|
|
173
|
-
if (distNode1 <= Constants.EPS_MM
|
|
191
|
+
if (distNode1 <= Constants.EPS_MM
|
|
192
|
+
&& location.level === edge.node1.coords.level) {
|
|
174
193
|
break;
|
|
175
194
|
}
|
|
176
195
|
}
|
|
@@ -183,10 +202,11 @@ class MapMatching {
|
|
|
183
202
|
|
|
184
203
|
projection.distanceFromNearestElement = distNode2;
|
|
185
204
|
projection.nearestElement = edge.node2;
|
|
186
|
-
|
|
205
|
+
MapMatching._assignLatLngLevel(edge.node2.coords, projection.projection);
|
|
187
206
|
MapMatching._updateProjectionLevelFromEdge(edge, projection.projection);
|
|
188
207
|
|
|
189
|
-
if (distNode2 <= Constants.EPS_MM
|
|
208
|
+
if (distNode2 <= Constants.EPS_MM
|
|
209
|
+
&& location.level === edge.node2.coords.level) {
|
|
190
210
|
break;
|
|
191
211
|
}
|
|
192
212
|
}
|
|
@@ -199,19 +219,23 @@ class MapMatching {
|
|
|
199
219
|
if (isProjectionBetter(distEdge)) {
|
|
200
220
|
projection.distanceFromNearestElement = distEdge;
|
|
201
221
|
projection.nearestElement = edge;
|
|
202
|
-
projection.projection
|
|
222
|
+
MapMatching._assignLatLngLevel(segmentProjection, projection.projection);
|
|
203
223
|
MapMatching._updateProjectionLevelFromEdge(edge, projection.projection);
|
|
204
224
|
}
|
|
205
225
|
}
|
|
206
226
|
}
|
|
207
227
|
}
|
|
208
228
|
|
|
209
|
-
|
|
229
|
+
|
|
230
|
+
if (!projection.nearestElement) {
|
|
210
231
|
return null;
|
|
211
232
|
}
|
|
212
233
|
|
|
234
|
+
projection.projection.accuracy += projection.distanceFromNearestElement;
|
|
235
|
+
|
|
213
236
|
return projection;
|
|
214
237
|
}
|
|
238
|
+
|
|
215
239
|
}
|
|
216
240
|
|
|
217
241
|
export default MapMatching;
|
|
@@ -85,7 +85,7 @@ describe('MapMatching', () => {
|
|
|
85
85
|
const owMapMatching = new MapMatching(owNetwork);
|
|
86
86
|
result = owMapMatching.getProjection(new Coordinates(43.6092086, 3.8842598, 10));
|
|
87
87
|
expect(result).is.not.null;
|
|
88
|
-
expect(result.projection.alt).equals(
|
|
88
|
+
expect(result.projection.alt).equals(10);
|
|
89
89
|
});
|
|
90
90
|
|
|
91
91
|
it('with bearing', () => {
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import Coordinates from '../coordinates/Coordinates.js';
|
|
2
|
+
import Edge from './Edge.js';
|
|
3
|
+
import Node from './Node.js';
|
|
4
|
+
|
|
5
|
+
class Projection {
|
|
6
|
+
|
|
7
|
+
/** @type {Coordinates} */
|
|
8
|
+
origin;
|
|
9
|
+
|
|
10
|
+
/** @type {number} */
|
|
11
|
+
distanceFromNearestElement;
|
|
12
|
+
|
|
13
|
+
/** @type {Coordinates} */
|
|
14
|
+
projection;
|
|
15
|
+
|
|
16
|
+
/** @type {Node|Edge} */
|
|
17
|
+
nearestElement;
|
|
18
|
+
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default Projection;
|
package/src/graph/Step.js
CHANGED
|
@@ -36,6 +36,16 @@ class Step {
|
|
|
36
36
|
/** @type {number} */
|
|
37
37
|
_length = 0;
|
|
38
38
|
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* @param {object} obj
|
|
42
|
+
*/
|
|
43
|
+
constructor(obj) {
|
|
44
|
+
if (typeof obj === 'object') {
|
|
45
|
+
Object.assign(this, obj);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
39
49
|
/** @type {Node} */
|
|
40
50
|
get node() {
|
|
41
51
|
return this.nodes[0];
|
|
@@ -12,9 +12,9 @@ class Attitude {
|
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
14
|
*
|
|
15
|
-
* @param {
|
|
16
|
-
* @param {
|
|
17
|
-
* @param {
|
|
15
|
+
* @param {number[]} quaternion
|
|
16
|
+
* @param {number} time
|
|
17
|
+
* @param {number} accuracy
|
|
18
18
|
*/
|
|
19
19
|
constructor(quaternion, time, accuracy) {
|
|
20
20
|
this.quaternion = quaternion;
|
|
@@ -27,14 +27,14 @@ class Attitude {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
|
-
* @returns {
|
|
30
|
+
* @returns {number[]}
|
|
31
31
|
*/
|
|
32
32
|
get quaternion() {
|
|
33
33
|
return this._quaternion;
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
/**
|
|
37
|
-
* @param {
|
|
37
|
+
* @param {number[]} quaternion
|
|
38
38
|
*/
|
|
39
39
|
set quaternion(quaternion) {
|
|
40
40
|
if (!Array.isArray(quaternion)
|
|
@@ -48,14 +48,14 @@ class Attitude {
|
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
/**
|
|
51
|
-
* @returns {
|
|
51
|
+
* @returns {number}
|
|
52
52
|
*/
|
|
53
53
|
get time() {
|
|
54
54
|
return this._time;
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
/**
|
|
58
|
-
* @param {
|
|
58
|
+
* @param {number} time
|
|
59
59
|
*/
|
|
60
60
|
set time(time) {
|
|
61
61
|
if (typeof time === 'number') {
|
|
@@ -69,14 +69,14 @@ class Attitude {
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
/**
|
|
72
|
-
* @returns {
|
|
72
|
+
* @returns {number}
|
|
73
73
|
*/
|
|
74
74
|
get accuracy() {
|
|
75
75
|
return this._accuracy;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
/**
|
|
79
|
-
* @param {
|
|
79
|
+
* @param {number} accuracy
|
|
80
80
|
*/
|
|
81
81
|
set accuracy(accuracy) {
|
|
82
82
|
if (typeof accuracy === 'number' && accuracy >= 0 && accuracy <= Math.PI) {
|
|
@@ -89,6 +89,7 @@ class Attitude {
|
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
+
/** @type {number[]} */
|
|
92
93
|
get eulerAngles() {
|
|
93
94
|
if (this._eulerAngles === null) {
|
|
94
95
|
this._eulerAngles = Rotations.quaternionToEulerZXY(this.quaternion);
|
|
@@ -96,10 +97,12 @@ class Attitude {
|
|
|
96
97
|
return this._eulerAngles;
|
|
97
98
|
}
|
|
98
99
|
|
|
100
|
+
/** @type {number[]} */
|
|
99
101
|
get eulerAnglesDegrees() {
|
|
100
102
|
return this.eulerAngles.map(x => rad2deg(x));
|
|
101
103
|
}
|
|
102
104
|
|
|
105
|
+
/** @type {number} */
|
|
103
106
|
get heading() {
|
|
104
107
|
if (this._heading === null) {
|
|
105
108
|
let offset = 0;
|
|
@@ -111,6 +114,7 @@ class Attitude {
|
|
|
111
114
|
return this._heading;
|
|
112
115
|
}
|
|
113
116
|
|
|
117
|
+
/** @type {number} */
|
|
114
118
|
get headingDegrees() {
|
|
115
119
|
return rad2deg(this.heading);
|
|
116
120
|
}
|
|
@@ -124,6 +128,7 @@ class Attitude {
|
|
|
124
128
|
|
|
125
129
|
// Handle null comparison
|
|
126
130
|
if (att1 === null && att1 === att2) {
|
|
131
|
+
// TODO not sure to return true here.
|
|
127
132
|
return true;
|
|
128
133
|
}
|
|
129
134
|
|
|
@@ -131,21 +136,39 @@ class Attitude {
|
|
|
131
136
|
return false;
|
|
132
137
|
}
|
|
133
138
|
|
|
139
|
+
if (att1 === att2) {
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
|
|
134
143
|
return Quaternion.equalsTo(att1.quaternion, att2.quaternion);
|
|
135
144
|
}
|
|
136
145
|
|
|
146
|
+
/**
|
|
147
|
+
* @param {Attitude} other
|
|
148
|
+
* @returns {boolean}
|
|
149
|
+
*/
|
|
137
150
|
equalsTo(other) {
|
|
138
151
|
return Attitude.equalsTo(this, other);
|
|
139
152
|
}
|
|
140
153
|
|
|
154
|
+
/**
|
|
155
|
+
* @returns {object}
|
|
156
|
+
*/
|
|
141
157
|
toJson() {
|
|
142
158
|
return this.quaternion;
|
|
143
159
|
}
|
|
144
160
|
|
|
161
|
+
/**
|
|
162
|
+
* @param {object} json
|
|
163
|
+
* @returns {Attitude}
|
|
164
|
+
*/
|
|
145
165
|
static fromJson(json) {
|
|
146
166
|
return new Attitude(json);
|
|
147
167
|
}
|
|
148
168
|
|
|
169
|
+
/**
|
|
170
|
+
* @returns {Attitude}
|
|
171
|
+
*/
|
|
149
172
|
clone() {
|
|
150
173
|
return new Attitude(this.quaternion.slice(0), this.time, this.accuracy);
|
|
151
174
|
}
|