@wemap/providers 9.1.0 → 9.1.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/package.json CHANGED
@@ -9,13 +9,13 @@
9
9
  ],
10
10
  "dependencies": {
11
11
  "@wemap/camera": "^9.0.8",
12
- "@wemap/geo": "^9.0.6",
12
+ "@wemap/geo": "^9.1.1",
13
13
  "@wemap/geomagnetism": "^0.1.1",
14
14
  "@wemap/logger": "^9.0.0",
15
- "@wemap/map": "^9.0.6",
15
+ "@wemap/map": "^9.1.1",
16
16
  "@wemap/maths": "^9.0.0",
17
- "@wemap/osm": "^9.0.6",
18
- "@wemap/routers": "^9.0.6",
17
+ "@wemap/osm": "^9.1.1",
18
+ "@wemap/routers": "^9.1.1",
19
19
  "@wemap/utils": "^9.0.0"
20
20
  },
21
21
  "description": "A package using different geoloc systems",
@@ -42,6 +42,6 @@
42
42
  "url": "git+https://github.com/wemap/wemap-modules-js.git"
43
43
  },
44
44
  "type": "module",
45
- "version": "9.1.0",
46
- "gitHead": "af24605a74542ee339618c979f24da61e194f6f0"
45
+ "version": "9.1.1",
46
+ "gitHead": "bf6a54cf4f886ebac773549339ada8f98c0b7f7f"
47
47
  }
@@ -1,6 +1,6 @@
1
1
  /* eslint-disable max-statements */
2
2
  import {
3
- AbsoluteHeading, GraphEdge, MapMatching, Network, GraphProjection, UserPosition
3
+ AbsoluteHeading, GraphEdge, Level, MapMatching, Network, GraphProjection, UserPosition
4
4
  } from '@wemap/geo';
5
5
  import { deg2rad, diffAngle, diffAngleLines } from '@wemap/maths';
6
6
  import { Itinerary } from '@wemap/routers';
@@ -40,6 +40,9 @@ class MapMatchingHandler extends Provider {
40
40
  /** @type {number} in meters */
41
41
  static DEFAULT_MM_HUGE_JUMP_DISTANCE = 3;
42
42
 
43
+ /** @type {number} in meters */
44
+ static DEFAULT_DISABLE_MM_CLOSE_TO_A_TURN_DISTANCE = 2;
45
+
43
46
  /** @type {number} */
44
47
  static DEFAULT_MIN_STEPS_BETWEEN_ORIENTATION_MATCHING = 3;
45
48
 
@@ -67,6 +70,9 @@ class MapMatchingHandler extends Provider {
67
70
  /** @type {number} */
68
71
  _hugeJumpDistance = MapMatchingHandler.DEFAULT_MM_HUGE_JUMP_DISTANCE;
69
72
 
73
+ /** @type {number} */
74
+ _disableMMCloseToATurnDistance = MapMatchingHandler.DEFAULT_DISABLE_MM_CLOSE_TO_A_TURN_DISTANCE;
75
+
70
76
  /** @type {number} */
71
77
  _minStepsBetweenOrientationMatching = MapMatchingHandler.DEFAULT_MIN_STEPS_BETWEEN_ORIENTATION_MATCHING;
72
78
 
@@ -364,6 +370,13 @@ class MapMatchingHandler extends Provider {
364
370
  return true;
365
371
  }
366
372
 
373
+ // Detector to avoid map-matching close to network turns
374
+ if (this._disableMMCloseToATurnDistance > 0
375
+ && this._hasTurnInCircle(projection.projection, this._disableMMCloseToATurnDistance)) {
376
+ AbsolutePosition.notify(positionEvent);
377
+ return true;
378
+ }
379
+
367
380
  AbsolutePosition.notify(this.createEvent(
368
381
  EventType.AbsolutePosition,
369
382
  projection.projection,
@@ -464,6 +477,41 @@ class MapMatchingHandler extends Provider {
464
477
  );
465
478
  }
466
479
 
480
+ /**
481
+ * @param {GraphNode} node
482
+ * @returns {boolean}
483
+ */
484
+ _nodeHasTurn(node) {
485
+ const { edges } = node;
486
+ for (let i = 0; i < edges.length; i++) {
487
+ for (let j = i + 1; j < edges.length; j++) {
488
+ const angle = diffAngleLines(edges[i].bearing, edges[j].bearing);
489
+ if (angle > MapMatchingHandler.DEFAULT_MM_MAX_ANGLE) {
490
+ return true;
491
+ }
492
+ }
493
+ }
494
+ return false;
495
+ }
496
+
497
+ /**
498
+ * @param {Coordinates} center
499
+ * @param {number} radius
500
+ * @returns {boolean}
501
+ */
502
+ _hasTurnInCircle(center, radius) {
503
+ /** @type {Network} */
504
+ const network = this._mapMatching.network;
505
+ if (!network) {
506
+ return false;
507
+ }
508
+
509
+ return network.nodes.filter(node =>
510
+ node.coords.distanceTo(center) <= radius
511
+ && Level.intersect(node.coords.level, center.level)
512
+ ).some(this._nodeHasTurn);
513
+ }
514
+
467
515
  /**
468
516
  * @param {Projection} projection
469
517
  */
@@ -560,6 +608,14 @@ class MapMatchingHandler extends Provider {
560
608
  this._hugeJumpDistance = hugeJumpDistance;
561
609
  }
562
610
 
611
+ get disableMMCloseToATurnDistance() {
612
+ return this._disableMMCloseToATurnDistance;
613
+ }
614
+
615
+ set disableMMCloseToATurnDistance(disableMMCloseToATurnDistance) {
616
+ this._disableMMCloseToATurnDistance = disableMMCloseToATurnDistance;
617
+ }
618
+
563
619
  get useOrientationMatching() {
564
620
  return this._useOrientationMatching;
565
621
  }
@@ -0,0 +1,136 @@
1
+ /* eslint-disable max-statements */
2
+ import chai from 'chai';
3
+ import { Coordinates, Network } from '@wemap/geo';
4
+ import { deg2rad } from '@wemap/maths';
5
+ import { Itinerary } from '@wemap/routers';
6
+ import MMH from './MapMatchingHandler.js';
7
+
8
+
9
+ const { expect } = chai;
10
+
11
+ describe('MapMatchingHandler', () => {
12
+
13
+ const p0 = new Coordinates(0, 0, null, 0);
14
+ const p1 = p0.destinationPoint(5, 0);
15
+ const p2 = p1.destinationPoint(5, Math.PI / 2);
16
+ const p3 = p1.destinationPoint(10, 0);
17
+ const p4 = p0.destinationPoint(2, deg2rad(10));
18
+
19
+ const pos1 = p0.clone();
20
+ const pos2 = pos1.destinationPoint(3, 0);
21
+ const pos3 = pos2.destinationPoint(10, 0);
22
+
23
+ it('_hasTurnInCircle - itinerary', () => {
24
+
25
+ expect(MMH._hasTurnInCircle(pos1, Number.MAX_VALUE)).is.false;
26
+
27
+ // p4 -> p1 -> p2 is a turn
28
+ MMH.itinerary = Itinerary.fromOrderedCoordinates([p0, p4, p1, p2]);
29
+
30
+ expect(MMH._nodeHasTurn(MMH.network.getNodeByCoords(p0))).is.false;
31
+ expect(MMH._nodeHasTurn(MMH.network.getNodeByCoords(p1))).is.true;
32
+ expect(MMH._nodeHasTurn(MMH.network.getNodeByCoords(p2))).is.false;
33
+ expect(MMH._nodeHasTurn(MMH.network.getNodeByCoords(p4))).is.false;
34
+
35
+ expect(MMH._hasTurnInCircle(pos1, 1)).is.false;
36
+ expect(MMH._hasTurnInCircle(pos1, 3)).is.false;
37
+ expect(MMH._hasTurnInCircle(pos1, 10)).is.true;
38
+ expect(MMH._hasTurnInCircle(pos2, 1)).is.false;
39
+ expect(MMH._hasTurnInCircle(pos2, 3)).is.true;
40
+ expect(MMH._hasTurnInCircle(pos2, 10)).is.true;
41
+ expect(MMH._hasTurnInCircle(pos3, 1)).is.false;
42
+ expect(MMH._hasTurnInCircle(pos3, 3)).is.false;
43
+ expect(MMH._hasTurnInCircle(pos3, 10)).is.true;
44
+
45
+ // Straight line
46
+ MMH.itinerary = Itinerary.fromOrderedCoordinates([p0, p4, p1, p3]);
47
+
48
+ expect(MMH._nodeHasTurn(MMH.network.getNodeByCoords(p1))).is.false;
49
+ expect(MMH._nodeHasTurn(MMH.network.getNodeByCoords(p4))).is.false;
50
+
51
+ expect(MMH._hasTurnInCircle(pos1, 10)).is.false;
52
+ expect(MMH._hasTurnInCircle(pos2, 10)).is.false;
53
+ expect(MMH._hasTurnInCircle(pos3, 10)).is.false;
54
+
55
+ });
56
+
57
+
58
+ it('_hasTurnInCircle - network', () => {
59
+
60
+ // p1 has turns
61
+ MMH.network = Network.fromCoordinates([[p0, p4, p1], [p1, p2], [p3, p1]]);
62
+
63
+ expect(MMH._nodeHasTurn(MMH.network.getNodeByCoords(p1))).is.true;
64
+ expect(MMH._nodeHasTurn(MMH.network.getNodeByCoords(p4))).is.false;
65
+
66
+ expect(MMH._hasTurnInCircle(pos1, 1)).is.false;
67
+ expect(MMH._hasTurnInCircle(pos1, 3)).is.false;
68
+ expect(MMH._hasTurnInCircle(pos1, 10)).is.true;
69
+ expect(MMH._hasTurnInCircle(pos2, 1)).is.false;
70
+ expect(MMH._hasTurnInCircle(pos2, 3)).is.true;
71
+ expect(MMH._hasTurnInCircle(pos2, 10)).is.true;
72
+ expect(MMH._hasTurnInCircle(pos3, 1)).is.false;
73
+ expect(MMH._hasTurnInCircle(pos3, 3)).is.false;
74
+ expect(MMH._hasTurnInCircle(pos3, 10)).is.true;
75
+
76
+ });
77
+
78
+ const p10 = new Coordinates(0, 0, null, 1);
79
+ const p11 = p10.destinationPoint(5, 0);
80
+ const p12 = p11.destinationPoint(5, Math.PI / 2);
81
+ const p13 = p11.destinationPoint(10, 0);
82
+
83
+ const pos12 = p10.clone().destinationPoint(3, 0);
84
+ const pos012 = new Coordinates(0, 0, null, [0, 1]).destinationPoint(3, 0);
85
+
86
+ it('_hasTurnInCircle - multi-levels', () => {
87
+
88
+ // level 1 is a straight line
89
+ MMH.network = Network.fromCoordinates([
90
+ [p0, p4, p1], [p1, p2], [p3, p1],
91
+ [p10, p11, p13]
92
+ ]);
93
+
94
+ expect(MMH._nodeHasTurn(MMH.network.getNodeByCoords(p1))).is.true;
95
+ expect(MMH._nodeHasTurn(MMH.network.getNodeByCoords(p11))).is.false;
96
+
97
+ expect(MMH._hasTurnInCircle(pos2, 1)).is.false;
98
+ expect(MMH._hasTurnInCircle(pos2, 3)).is.true;
99
+ expect(MMH._hasTurnInCircle(pos2, 10)).is.true;
100
+ expect(MMH._hasTurnInCircle(pos12, 1)).is.false;
101
+ expect(MMH._hasTurnInCircle(pos12, 3)).is.false;
102
+ expect(MMH._hasTurnInCircle(pos12, 10)).is.false;
103
+ expect(MMH._hasTurnInCircle(pos012, 1)).is.false;
104
+ expect(MMH._hasTurnInCircle(pos012, 3)).is.true;
105
+ expect(MMH._hasTurnInCircle(pos012, 10)).is.true;
106
+
107
+ // Changing level
108
+ // straight line
109
+ MMH.network = Network.fromCoordinates([
110
+ [p0, p4, p11], [p11, p13]
111
+ ]);
112
+ expect(MMH._nodeHasTurn(MMH.network.getNodeByCoords(p4))).is.false;
113
+ expect(MMH._hasTurnInCircle(pos2, Number.MAX_VALUE)).is.false;
114
+ expect(MMH._hasTurnInCircle(pos12, Number.MAX_VALUE)).is.false;
115
+ expect(MMH._hasTurnInCircle(pos012, Number.MAX_VALUE)).is.false;
116
+
117
+ // Changing level
118
+ // turn in p11
119
+ MMH.network = Network.fromCoordinates([
120
+ [p0, p4, p11], [p11, p12], [p11, p13]
121
+ ]);
122
+
123
+ expect(MMH._nodeHasTurn(MMH.network.getNodeByCoords(p11))).is.true;
124
+ expect(MMH._hasTurnInCircle(pos2, 1)).is.false;
125
+ expect(MMH._hasTurnInCircle(pos2, 3)).is.false;
126
+ expect(MMH._hasTurnInCircle(pos2, 10)).is.false;
127
+ expect(MMH._hasTurnInCircle(pos12, 1)).is.false;
128
+ expect(MMH._hasTurnInCircle(pos12, 3)).is.true;
129
+ expect(MMH._hasTurnInCircle(pos12, 10)).is.true;
130
+ expect(MMH._hasTurnInCircle(pos012, 1)).is.false;
131
+ expect(MMH._hasTurnInCircle(pos012, 3)).is.true;
132
+ expect(MMH._hasTurnInCircle(pos012, 10)).is.true;
133
+
134
+ });
135
+
136
+ });