@wemap/geo 7.1.0 → 7.2.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
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"directory": "packages/geo"
|
|
13
13
|
},
|
|
14
14
|
"name": "@wemap/geo",
|
|
15
|
-
"version": "7.1
|
|
15
|
+
"version": "7.2.1",
|
|
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": "
|
|
33
|
+
"gitHead": "64528ea2d1a6384ca0d33a794975960c38f25fe0"
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
262
|
-
|
|
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
|
-
|
|
301
|
-
|
|
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) {
|
package/src/graph/MapMatching.js
CHANGED
|
@@ -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
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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;
|
|
@@ -30,7 +30,7 @@ class NoRouteFoundError extends Error {
|
|
|
30
30
|
get message() {
|
|
31
31
|
let message = `No route found from ${this.startStr} to ${this.endStr}.`;
|
|
32
32
|
if (this.details) {
|
|
33
|
-
message += ` Details: ${this.details}
|
|
33
|
+
message += ` Details: ${this.details}`;
|
|
34
34
|
}
|
|
35
35
|
return message;
|
|
36
36
|
}
|