@wemap/providers 3.1.16 → 3.1.18

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
@@ -65,6 +65,6 @@
65
65
  "lint": "eslint --ext .js,.jsx --quiet src",
66
66
  "test": "mocha -r esm \"src/**/*.spec.js\""
67
67
  },
68
- "version": "3.1.16",
69
- "gitHead": "8238894f4e451bc5bf0b9e1ebaf32053c237e64c"
68
+ "version": "3.1.18",
69
+ "gitHead": "faa44f5a027616ce6b61be6bb90be996543e133c"
70
70
  }
@@ -129,27 +129,27 @@ class ProvidersInterface {
129
129
  }
130
130
 
131
131
  static get mapMatchingMaxDistance() {
132
- return AbsolutePosition.mapMatching.maxDistance;
132
+ return AbsolutePosition.mapMatchingMaxDistance;
133
133
  }
134
134
 
135
135
  static set mapMatchingMaxDistance(maxDistance) {
136
- AbsolutePosition.mapMatching.maxDistance = maxDistance;
136
+ AbsolutePosition.mapMatchingMaxDistance = maxDistance;
137
137
  }
138
138
 
139
139
  static get mapMatchingMinDistance() {
140
- return AbsolutePosition.mapMatching.minDistance;
140
+ return AbsolutePosition.mapMatchingMinDistance;
141
141
  }
142
142
 
143
143
  static set mapMatchingMinDistance(minDistance) {
144
- AbsolutePosition.mapMatching.minDistance = minDistance;
144
+ AbsolutePosition.mapMatchingMinDistance = minDistance;
145
145
  }
146
146
 
147
147
  static get mapMatchingMaxAngleBearing() {
148
- return AbsolutePosition.mapMatching.maxAngleBearing;
148
+ return AbsolutePosition.mapMatchingMaxAngleBearing;
149
149
  }
150
150
 
151
151
  static set mapMatchingMaxAngleBearing(maxAngleBearing) {
152
- AbsolutePosition.mapMatching.maxAngleBearing = maxAngleBearing;
152
+ AbsolutePosition.mapMatchingMaxAngleBearing = maxAngleBearing;
153
153
  }
154
154
  }
155
155
 
@@ -19,19 +19,21 @@ import ProvidersOptions from '../../../ProvidersOptions';
19
19
  const ACCURACY_NEW_POS_EPS_RATIO = 1.5;
20
20
  const ACCURACY_RELOC_RATIO = 2;
21
21
  const MM_MAX_ANGLE = deg2rad(20);
22
- const MM_MAX_DIST = 15;
23
- const MM_MIN_DIST = 1;
22
+ const MM_MAX_DIST = 30;
23
+ const MM_MIN_DIST = 0;
24
24
  const MM_MIN_TIME = 0.4;
25
25
 
26
26
  class AbsolutePositionProvider extends MetaProvider {
27
27
 
28
28
  lastMMAttempt = -Infinity;
29
+ lastEventBearing = null;
29
30
 
30
31
  constructor() {
31
32
  super();
32
33
  this.mapMatching = new MapMatching();
33
34
  this.mapMatching.maxDistance = MM_MAX_DIST;
34
35
  this.mapMatching.maxAngleBearing = MM_MAX_ANGLE;
36
+ this._mapMatchingMinDistance = MM_MIN_DIST;
35
37
  }
36
38
 
37
39
  /**
@@ -93,22 +95,47 @@ class AbsolutePositionProvider extends MetaProvider {
93
95
  }
94
96
 
95
97
  onAbsolutePosition(newPositionEvent, canContainLevel = true) {
96
- if (this.lastEvent) {
98
+ let newPosition = newPositionEvent.data;
97
99
 
98
- const newPosition = newPositionEvent.data;
99
- const lastPosition = this.lastEvent.data;
100
+ if (!this._useNewAbsolutePosition(newPosition)) {
101
+ return;
102
+ }
100
103
 
101
- if (newPosition.distanceTo(lastPosition) < newPosition.accuracy * ACCURACY_NEW_POS_EPS_RATIO
102
- && newPosition.accuracy > lastPosition.accuracy / ACCURACY_RELOC_RATIO) {
103
- return;
104
+ if (this.lastEvent && !canContainLevel) {
105
+ newPosition.level = this.lastEvent.data.level;
106
+ }
107
+
108
+ if (this.lastEventBearing !== null) {
109
+ newPosition.bearing = this.lastEventBearing;
110
+ }
111
+
112
+ if (this._shouldHandleMapMatching()) {
113
+
114
+ let projectedPosition = null;
115
+
116
+ // Firstly, if lastEvent bearing is known, try to use map-matching with bearing
117
+ if (newPosition.bearing !== null) {
118
+ projectedPosition = this._calcMapMatchingPosition(newPosition, true);
104
119
  }
105
120
 
106
- if (!canContainLevel) {
107
- newPosition.level = lastPosition.level;
121
+ // Secondly, if map-matching with bearing did not work, try MM on nodes (without bearing).
122
+ if (!projectedPosition) {
123
+ projectedPosition = this._calcMapMatchingPosition(newPosition, false);
108
124
  }
125
+
126
+ if (projectedPosition) {
127
+ newPosition = projectedPosition;
128
+ }
129
+ } else {
130
+ newPosition = newPosition.clone();
109
131
  }
110
132
 
111
- this.notify(newPositionEvent.clone());
133
+ this.notify(this.createEvent(
134
+ EventType.AbsolutePosition,
135
+ newPosition,
136
+ newPositionEvent
137
+ ));
138
+
112
139
  }
113
140
 
114
141
  /**
@@ -116,45 +143,78 @@ class AbsolutePositionProvider extends MetaProvider {
116
143
  */
117
144
  onAbsolutePositionFromRel(newPositionEvent) {
118
145
 
119
- /**
120
- * If map matching is not used or not set, raw position is returned
121
- */
122
- if (!ProvidersOptions.useMapMatching
123
- || !this.mapMatching.network
124
- || newPositionEvent.data.time - this.lastMMAttempt < MM_MIN_TIME) {
125
- this.notify(newPositionEvent.clone());
126
- return;
127
- }
128
- this.lastMMAttempt = newPositionEvent.data.time;
146
+ let newPosition = newPositionEvent.data;
129
147
 
130
- const newPosition = newPositionEvent.data;
131
- const projection = this.mapMatching.getProjection(newPosition, true, true);
132
- if (!projection || !projection.projection) {
133
- // If no projection has been found, returns the position without map-matching
134
- this.notify(newPositionEvent.clone());
135
- return;
136
- }
148
+ this.lastEventBearing = newPosition.bearing;
137
149
 
138
- const projectedPosition = newPosition.clone();
150
+ if (this._shouldHandleMapMatching()
151
+ && newPositionEvent.data.time - this.lastMMAttempt > MM_MIN_TIME) {
139
152
 
140
- // Anyway, the projected level is used for new position
141
- projectedPosition.level = projection.projection.level;
153
+ // Firstly, try map matching with bearing
154
+ const projectedPosition = this._calcMapMatchingPosition(newPosition, true);
155
+ if (projectedPosition) {
156
+ newPosition = projectedPosition;
157
+ }
158
+ // map matching without bearing is not used to allow user to leave the network.
142
159
 
143
- // Do not use projection if it too close from itinerary,
144
- // this allows left/right movements (ie with ArCore)
145
- if (projection.distanceFromNearestElement > MM_MIN_DIST) {
146
- projectedPosition.lat = projection.projection.lat;
147
- projectedPosition.lng = projection.projection.lng;
160
+ this.lastMMAttempt = newPositionEvent.data.time;
161
+ } else {
162
+ newPosition = newPosition.clone();
148
163
  }
149
164
 
150
165
  this.notify(this.createEvent(
151
166
  EventType.AbsolutePosition,
152
- projectedPosition,
167
+ newPosition,
153
168
  newPositionEvent
154
169
  ));
170
+ }
171
+
172
+ _useNewAbsolutePosition(newPosition) {
173
+
174
+ if (!this.lastEvent) {
175
+ return true;
176
+ }
177
+
178
+ const lastPosition = this.lastEvent.data;
179
+
180
+ if (newPosition.accuracy <= newPosition.distanceTo(lastPosition) / ACCURACY_NEW_POS_EPS_RATIO) {
181
+ return true;
182
+ }
183
+
184
+ if (newPosition.accuracy <= lastPosition.accuracy / ACCURACY_RELOC_RATIO) {
185
+ return true;
186
+ }
187
+
188
+ return false;
155
189
 
156
190
  }
157
191
 
192
+ _shouldHandleMapMatching() {
193
+ return ProvidersOptions.useMapMatching && this.mapMatching.network;
194
+ }
195
+
196
+ _calcMapMatchingPosition(position, useBearing = true) {
197
+
198
+ const projection = this.mapMatching.getProjection(position, true, useBearing);
199
+ if (!projection || !projection.projection) {
200
+ return null;
201
+ }
202
+
203
+ // Do not use projection if it too close from itinerary,
204
+ // this allows left/right movements (ie with ArCore)
205
+ if (projection.distanceFromNearestElement < this._mapMatchingMinDistance) {
206
+ return null;
207
+ }
208
+
209
+ // Do not user projection.projection directly, because position has some specific properties like bearing
210
+ const projectedPosition = position.clone();
211
+ projectedPosition.lat = projection.projection.lat;
212
+ projectedPosition.lng = projection.projection.lng;
213
+ projectedPosition.level = projection.projection.level;
214
+
215
+ return projectedPosition;
216
+ }
217
+
158
218
  /**
159
219
  * @override
160
220
  * @param {UserPosition | Network} data
@@ -174,12 +234,60 @@ class AbsolutePositionProvider extends MetaProvider {
174
234
  ));
175
235
  } else if (data instanceof Network || eventType === EventType.Network) {
176
236
  this.mapMatching.network = data;
237
+
238
+ if (this._shouldHandleMapMatching() && this.lastEvent) {
239
+
240
+ const position = this.lastEvent.data;
241
+ let projectedPosition = null;
242
+
243
+ // Firstly, if lastEvent bearing is known, try to use map-matching with bearing
244
+ if (position.bearing !== null) {
245
+ projectedPosition = this._calcMapMatchingPosition(position, true);
246
+ }
247
+
248
+ // Secondly, if map-matching with bearing did not work, try MM on nodes (without bearing).
249
+ if (!projectedPosition) {
250
+ projectedPosition = this._calcMapMatchingPosition(position, false);
251
+ }
252
+
253
+ if (projectedPosition) {
254
+ this.notify(this.createEvent(
255
+ EventType.AbsolutePosition,
256
+ projectedPosition,
257
+ this.lastEvent
258
+ ));
259
+ }
260
+ }
261
+
177
262
  } else {
178
263
  throw new Error('Unknown feed object');
179
264
  }
180
265
 
181
266
  }
182
267
 
268
+ get mapMatchingMaxDistance() {
269
+ return this.mapMatching.maxDistance;
270
+ }
271
+
272
+ set mapMatchingMaxDistance(maxDistance) {
273
+ this.mapMatching.maxDistance = maxDistance;
274
+ }
275
+
276
+ get mapMatchingMinDistance() {
277
+ return this._mapMatchingMinDistance;
278
+ }
279
+
280
+ set mapMatchingMinDistance(minDistance) {
281
+ this._mapMatchingMinDistance = minDistance;
282
+ }
283
+
284
+ get mapMatchingMaxAngleBearing() {
285
+ return this.mapMatching.maxAngleBearing;
286
+ }
287
+
288
+ set mapMatchingMaxAngleBearing(maxAngleBearing) {
289
+ this.mapMatching.maxAngleBearing = maxAngleBearing;
290
+ }
183
291
  }
184
292
 
185
293
  export default AbsolutePositionProvider;