@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 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.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.0"
31
+ "@wemap/maths": "^4.0.3"
32
32
  },
33
- "gitHead": "8b72858590fc2ff33fbea4f090de8cd353a7445f"
33
+ "gitHead": "91a82028ddda32038999582da381d1d0d8acd091"
34
34
  }
@@ -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
- projection.projection = edge.node1.coords.clone();
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
- projection.projection = edge.node2.coords.clone();
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 = segmentProjection.clone();
222
+ MapMatching._assignLatLngLevel(segmentProjection, projection.projection);
203
223
  MapMatching._updateProjectionLevelFromEdge(edge, projection.projection);
204
224
  }
205
225
  }
206
226
  }
207
227
  }
208
228
 
209
- if (!projection.projection) {
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(7.5);
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 {Number[]} quaternion
16
- * @param {Number} time
17
- * @param {Number} accuracy
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 {Number[]}
30
+ * @returns {number[]}
31
31
  */
32
32
  get quaternion() {
33
33
  return this._quaternion;
34
34
  }
35
35
 
36
36
  /**
37
- * @param {Number[]} quaternion
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 {Number}
51
+ * @returns {number}
52
52
  */
53
53
  get time() {
54
54
  return this._time;
55
55
  }
56
56
 
57
57
  /**
58
- * @param {Number} time
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 {Number}
72
+ * @returns {number}
73
73
  */
74
74
  get accuracy() {
75
75
  return this._accuracy;
76
76
  }
77
77
 
78
78
  /**
79
- * @param {Number} accuracy
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
  }