@wemap/geo 7.0.0 → 7.2.0

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": "7.0.0",
15
+ "version": "7.2.0",
16
16
  "bugs": {
17
17
  "url": "https://github.com/wemap/wemap-modules-js/issues"
18
18
  },
@@ -30,5 +30,5 @@
30
30
  "@wemap/logger": "^7.0.0",
31
31
  "@wemap/maths": "^7.0.0"
32
32
  },
33
- "gitHead": "cfd70d1f998599c53689c1b1996a517247f04dce"
33
+ "gitHead": "a4a796c2870c6b1182a0c69fe753bc4012faf0c1"
34
34
  }
@@ -18,8 +18,29 @@ import Level from './Level.js';
18
18
  */
19
19
  class Coordinates {
20
20
 
21
+ /** @type {Number} */
22
+ _lat;
23
+
24
+ /** @type {Number} */
25
+ _lng;
26
+
27
+ /** @type {Number|null} */
28
+ _alt = null;
29
+
30
+ /** @type {Level|null} */
31
+ _level = null;
32
+
33
+ /** @type {[Number, Number, Number]|null} */
34
+ _ecef;
35
+
21
36
  autoWrap = true;
22
37
 
38
+ /**
39
+ * @param {Number} lat
40
+ * @param {Number} lng
41
+ * @param {Number|null} alt
42
+ * @param {Level|null} level
43
+ */
23
44
  constructor(lat, lng, alt, level) {
24
45
  this.lat = lat;
25
46
  this.lng = lng;
@@ -28,23 +49,28 @@ class Coordinates {
28
49
  this._ecef = null;
29
50
  }
30
51
 
52
+ /** @type {Number} */
31
53
  get lat() {
32
54
  return this._lat;
33
55
  }
34
56
 
57
+ /** @type {Number} */
35
58
  get latitude() {
36
59
  return this._lat;
37
60
  }
38
61
 
62
+ /** @type {Number} */
39
63
  get lng() {
40
64
  return this._lng;
41
65
  }
42
66
 
67
+ /** @type {Number} */
43
68
  get longitude() {
44
69
  return this._lng;
45
70
  }
46
71
 
47
72
  /**
73
+ * @type {Number|null}
48
74
  * alt does not denote the altitude of a point but its height from
49
75
  * the "level" field (if defined) or from the ground
50
76
  */
@@ -52,10 +78,12 @@ class Coordinates {
52
78
  return this._alt;
53
79
  }
54
80
 
81
+ /** @type {Level|null} */
55
82
  get level() {
56
83
  return this._level;
57
84
  }
58
85
 
86
+ /** @type {Number} */
59
87
  set lat(lat) {
60
88
  if (typeof lat === 'number' && Math.abs(lat) <= 90) {
61
89
  this._lat = lat;
@@ -65,10 +93,12 @@ class Coordinates {
65
93
  this._ecef = null;
66
94
  }
67
95
 
68
- set latitude(lat) {
96
+ /** @type {Number} */
97
+ set latitude(_) {
69
98
  throw new Error('Please use Coordinate#lat setter instead of Coordinate#latitude');
70
99
  }
71
100
 
101
+ /** @type {Number} */
72
102
  set lng(lng) {
73
103
  if (typeof lng === 'number') {
74
104
  this._lng = lng;
@@ -81,10 +111,12 @@ class Coordinates {
81
111
  this._ecef = null;
82
112
  }
83
113
 
84
- set longitude(lng) {
114
+ /** @type {Number} */
115
+ set longitude(_) {
85
116
  throw new Error('Please use Coordinate#lng setter instead of Coordinate#longitude');
86
117
  }
87
118
 
119
+ /** @type {Number|null} */
88
120
  set alt(alt) {
89
121
  if (typeof alt === 'number') {
90
122
  this._alt = alt;
@@ -97,6 +129,7 @@ class Coordinates {
97
129
  this._ecef = null;
98
130
  }
99
131
 
132
+ /** @type {Level|null} */
100
133
  set level(level) {
101
134
  if (level instanceof Level) {
102
135
  this._level = level;
@@ -108,6 +141,10 @@ class Coordinates {
108
141
  }
109
142
  }
110
143
 
144
+ /**
145
+ * Deep clone coordinates
146
+ * @returns {!Coordinates}
147
+ */
111
148
  clone() {
112
149
  const output = new Coordinates(this.lat, this.lng, this.alt);
113
150
  if (this.level) {
@@ -148,17 +185,35 @@ class Coordinates {
148
185
  && Level.equalsTo(pos1.level, pos2.level);
149
186
  }
150
187
 
188
+ /**
189
+ * @param {Coordinates} other
190
+ * @returns {!Boolean}
191
+ */
151
192
  equalsTo(other) {
152
193
  return Coordinates.equalsTo(this, other);
153
194
  }
154
195
 
196
+ /**
197
+ * @param {!Number} distance
198
+ * @param {!Number} bearing
199
+ * @param {?Number} elevation
200
+ * @returns {!Coordinates}
201
+ * @throws {Error} if elevation is defined and point altitude is not defined
202
+ */
155
203
  destinationPoint(distance, bearing, elevation) {
156
204
  const newPoint = this.clone();
157
205
  newPoint.move(distance, bearing, elevation);
158
206
  return newPoint;
159
207
  }
160
208
 
161
- // Source: http://www.movable-type.co.uk/scripts/latlong.html#destPoint
209
+ /**
210
+ * Source: http://www.movable-type.co.uk/scripts/latlong.html#destPoint
211
+ * @param {!Number} distance
212
+ * @param {!Number} bearing
213
+ * @param {?Number} elevation
214
+ * @returns {!Coordinates}
215
+ * @throws {Error} if elevation is defined and point altitude is not defined
216
+ */
162
217
  move(distance, bearing, elevation) {
163
218
 
164
219
  const dR = distance / Constants.R_MAJOR;
@@ -187,7 +242,6 @@ class Coordinates {
187
242
  this.alt += elevation;
188
243
  }
189
244
 
190
-
191
245
  return this;
192
246
  }
193
247
 
@@ -222,10 +276,19 @@ class Coordinates {
222
276
  return Constants.R_MAJOR * cosn;
223
277
  }
224
278
 
279
+ /**
280
+ * @param {!Coordinates} point1
281
+ * @param {!Coordinates} point2
282
+ * @returns {!Number}
283
+ */
225
284
  static distanceBetween(point1, point2) {
226
285
  return point1.distanceTo(point2);
227
286
  }
228
287
 
288
+ /**
289
+ * @param {!Coordinates} location2
290
+ * @returns {!Number}
291
+ */
229
292
  bearingTo(location2) {
230
293
  const lat1 = deg2rad(this.lat);
231
294
  const lat2 = deg2rad(location2.lat);
@@ -235,6 +298,11 @@ class Coordinates {
235
298
  Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(diffLng));
236
299
  }
237
300
 
301
+ /**
302
+ * @param {!Coordinates} point1
303
+ * @param {!Coordinates} point2
304
+ * @returns {!Number}
305
+ */
238
306
  static bearingTo(point1, point2) {
239
307
  return point1.bearingTo(point2);
240
308
  }
@@ -246,20 +314,25 @@ class Coordinates {
246
314
  * as a sphere instead of an ellipse
247
315
  */
248
316
 
317
+ /** @type {![Number, Number, Number, Number]} */
249
318
  get enuToEcefRotation() {
250
319
  const rot1 = Quaternion.fromAxisAngle([0, 0, 1], Math.PI / 2 + deg2rad(this.lng));
251
320
  const rot2 = Quaternion.fromAxisAngle([1, 0, 0], Math.PI / 2 - deg2rad(this.lat));
252
321
  return Quaternion.multiply(rot1, rot2);
253
322
  }
254
323
 
324
+ /** @type {![Number, Number, Number, Number]} */
255
325
  get ecefToEnuRotation() {
256
326
  const rot1 = Quaternion.fromAxisAngle([1, 0, 0], deg2rad(this.lat) - Math.PI / 2);
257
327
  const rot2 = Quaternion.fromAxisAngle([0, 0, 1], -deg2rad(this.lng) - Math.PI / 2);
258
328
  return Quaternion.multiply(rot1, rot2);
259
329
  }
260
330
 
261
- // https://gist.github.com/klucar/1536194
262
- // Adapted for spherical formula
331
+ /**
332
+ * https://gist.github.com/klucar/1536194
333
+ * Adapted for spherical formula
334
+ * @type {![Number, Number, Number]}
335
+ */
263
336
  get ecef() {
264
337
 
265
338
  if (!this._ecef) {
@@ -277,6 +350,10 @@ class Coordinates {
277
350
  return this._ecef;
278
351
  }
279
352
 
353
+ /**
354
+ * @param {![Number, Number, Number]} ecef
355
+ * @returns {!Coordinates}
356
+ */
280
357
  static fromECEF(ecef) {
281
358
 
282
359
  const x = ecef[0];
@@ -297,8 +374,13 @@ class Coordinates {
297
374
  }
298
375
 
299
376
 
300
- // https://stackoverflow.com/questions/1299567/how-to-calculate-distance-from-a-point-to-a-line-segment-on-a-sphere
301
- // Adapted to ECEF
377
+ /**
378
+ * https://stackoverflow.com/questions/1299567/how-to-calculate-distance-from-a-point-to-a-line-segment-on-a-sphere
379
+ * Adapted to ECEF
380
+ * @param {!Coordinates} p1
381
+ * @param {!Coordinates} p2
382
+ * @returns {Coordinates|null}
383
+ */
302
384
  getSegmentProjection(p1, p2) {
303
385
 
304
386
  const a = Vector3.normalize(p1.ecef);
@@ -338,6 +420,9 @@ class Coordinates {
338
420
  * Input / Output
339
421
  */
340
422
 
423
+ /**
424
+ * @returns {!String}
425
+ */
341
426
  toString() {
342
427
  let str = '[' + this._lat.toFixed(7) + ', ' + this._lng.toFixed(7);
343
428
  if (this._alt !== null) {
@@ -350,6 +435,9 @@ class Coordinates {
350
435
  return str;
351
436
  }
352
437
 
438
+ /**
439
+ * @returns {!Object}
440
+ */
353
441
  toJson() {
354
442
  const output = {
355
443
  lat: this.lat,
@@ -364,10 +452,17 @@ class Coordinates {
364
452
  return output;
365
453
  }
366
454
 
455
+ /**
456
+ * @param {!Object} json
457
+ * @returns {!Coordinates}
458
+ */
367
459
  static fromJson(json) {
368
460
  return new Coordinates(json.lat, json.lng, json.alt, Level.fromString(json.level));
369
461
  }
370
462
 
463
+ /**
464
+ * @returns {!Object}
465
+ */
371
466
  toCompressedJson() {
372
467
  const output = [this.lat, this.lng];
373
468
  if (this.alt !== null || this.level !== null) {
@@ -379,6 +474,10 @@ class Coordinates {
379
474
  return output;
380
475
  }
381
476
 
477
+ /**
478
+ * @param {!Object} json
479
+ * @returns {!Coordinates}
480
+ */
382
481
  static fromCompressedJson(json) {
383
482
  const coords = new Coordinates(json[0], json[1]);
384
483
  if (json.length > 2) {
@@ -102,11 +102,11 @@ class MapMatching {
102
102
  checkEdge = false;
103
103
  }
104
104
 
105
- if (!Level.equalsTo(location.level, edge.node1.coords.level) && !edge.node1.io) {
105
+ if (!Level.equalsTo(location.level, edge.node1.coords.level) && !(edge.node1.io && !location.level)) {
106
106
  checkNode1 = false;
107
107
  }
108
108
 
109
- if (!Level.equalsTo(location.level, edge.node2.coords.level) && !edge.node2.io) {
109
+ if (!Level.equalsTo(location.level, edge.node2.coords.level) && !(edge.node2.io && !location.level)) {
110
110
  checkNode2 = false;
111
111
  }
112
112
 
@@ -48,6 +48,10 @@ class GraphRouter {
48
48
 
49
49
  const createdNodes = [];
50
50
 
51
+ /**
52
+ * @param {GraphNode|Coordinates} point
53
+ * @returns {GraphNode}
54
+ */
51
55
  const retrieveOrCreateNearestNode = point => {
52
56
  if (point instanceof GraphNode) {
53
57
  return point;
@@ -60,10 +64,13 @@ class GraphRouter {
60
64
 
61
65
  const proj = this._mapMatching.getProjection(point, true, false, false, acceptEdgeFn);
62
66
  if (!proj) {
63
- throw new NoRouteFoundError(start, end,
64
- `Point ${point.toString()} is too far from the network `
65
- + `> ${this._mapMatching.maxDistance.toFixed(0)} meters`
66
- );
67
+ let message = `Point ${point.toString()} is too far from the network `
68
+ + `> ${this._mapMatching.maxDistance.toFixed(0)} meters.`;
69
+ if (point.level) {
70
+ message += ' If it is a multi-level map, please verify if you have'
71
+ + ` a network at level ${point.level.toString()}.`;
72
+ }
73
+ throw new NoRouteFoundError(start, end, message);
67
74
  }
68
75
  if (proj.nearestElement instanceof GraphNode) {
69
76
  return proj.nearestElement;