@wemap/geo 1.0.5 → 2.7.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/index.js +2 -0
- package/package.json +4 -3
- package/src/Constants.js +11 -1
- package/src/Utils.js +46 -0
- package/src/Utils.spec.js +39 -0
- package/src/coordinates/Level.js +1 -0
- package/src/coordinates/Level.spec.js +39 -30
- package/src/coordinates/WGS84.js +150 -134
- package/src/coordinates/WGS84.spec.js +268 -0
- package/src/coordinates/WGS84UserPosition.js +136 -23
- package/src/coordinates/WGS84UserPosition.spec.js +247 -0
- package/src/rotations/Attitude.js +56 -30
- package/src/rotations/Attitude.spec.js +82 -0
|
@@ -1,63 +1,89 @@
|
|
|
1
1
|
import {
|
|
2
|
-
Rotations,
|
|
2
|
+
Rotations, Quaternion, rad2deg, deg2rad
|
|
3
3
|
} from '@wemap/maths';
|
|
4
4
|
|
|
5
|
-
const rotxM90 = Quaternion.fromAxisAngle([1, 0, 0], -Math.PI / 2);
|
|
6
|
-
|
|
7
5
|
class Attitude {
|
|
8
6
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
headingDegreesV = null;
|
|
13
|
-
eulerAnglesV = null;
|
|
14
|
-
eulerAnglesDegreesV = null;
|
|
7
|
+
_quaternion = [1, 0, 0, 0];
|
|
8
|
+
_heading = null;
|
|
9
|
+
_eulerAngles = null;
|
|
15
10
|
|
|
16
11
|
constructor(quaternion) {
|
|
17
12
|
this.quaternion = quaternion;
|
|
18
13
|
}
|
|
19
14
|
|
|
15
|
+
static unitary() {
|
|
16
|
+
return new Attitude([1, 0, 0, 0]);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
get quaternion() {
|
|
20
|
+
return this._quaternion;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
set quaternion(quaternion) {
|
|
24
|
+
if (!Array.isArray(quaternion)
|
|
25
|
+
|| quaternion.length !== 4
|
|
26
|
+
|| Math.abs(1 - Quaternion.norm(quaternion)) > 1e-4) {
|
|
27
|
+
throw new Error('quaternion is not a unit quaternion');
|
|
28
|
+
}
|
|
29
|
+
this._quaternion = quaternion;
|
|
30
|
+
}
|
|
31
|
+
|
|
20
32
|
get eulerAngles() {
|
|
21
|
-
if (
|
|
22
|
-
this.
|
|
33
|
+
if (this._eulerAngles === null) {
|
|
34
|
+
this._eulerAngles = Rotations.quaternionToEulerZXY(this.quaternion);
|
|
23
35
|
}
|
|
24
|
-
return this.
|
|
36
|
+
return this._eulerAngles;
|
|
25
37
|
}
|
|
26
38
|
|
|
27
39
|
get eulerAnglesDegrees() {
|
|
28
|
-
|
|
29
|
-
this.eulerAnglesDegreesV = Rotations.quaternionToEulerZXYDegrees(this.quaternion);
|
|
30
|
-
}
|
|
31
|
-
return this.eulerAnglesDegreesV;
|
|
40
|
+
return this.eulerAngles.map(x => rad2deg(x));
|
|
32
41
|
}
|
|
33
42
|
|
|
34
43
|
get heading() {
|
|
35
|
-
if (
|
|
36
|
-
|
|
44
|
+
if (this._heading === null) {
|
|
45
|
+
let offset = 0;
|
|
46
|
+
if (global.window && global.window.orientation) {
|
|
47
|
+
offset = deg2rad(global.window.orientation);
|
|
48
|
+
}
|
|
49
|
+
this._heading = Rotations.getHeadingFromQuaternion(this.quaternion) + offset;
|
|
37
50
|
}
|
|
38
|
-
return this.
|
|
51
|
+
return this._heading;
|
|
39
52
|
}
|
|
40
53
|
|
|
41
54
|
get headingDegrees() {
|
|
42
|
-
|
|
43
|
-
this.headingDegreesV = MathUtils.rad2deg(Rotations.getHeadingFromQuaternion(this.quaternion)) + (window.orientation || 0);
|
|
44
|
-
}
|
|
45
|
-
return this.headingDegreesV;
|
|
55
|
+
return rad2deg(this.heading);
|
|
46
56
|
}
|
|
47
57
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
58
|
+
/**
|
|
59
|
+
* Compares two Attitude
|
|
60
|
+
* @param {Attitude} att1 attitude 1
|
|
61
|
+
* @param {Attitude} att2 attitude 2
|
|
62
|
+
*/
|
|
63
|
+
static equalsTo(att1, att2) {
|
|
64
|
+
|
|
65
|
+
// Handle null comparison
|
|
66
|
+
if (att1 === null && att1 === att2) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (!(att1 instanceof Attitude) || !(att2 instanceof Attitude)) {
|
|
71
|
+
return false;
|
|
51
72
|
}
|
|
52
|
-
|
|
73
|
+
|
|
74
|
+
return Quaternion.distance(att1.quaternion, att2.quaternion) < 1e-8;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
equalsTo(other) {
|
|
78
|
+
return Attitude.equalsTo(this, other);
|
|
53
79
|
}
|
|
54
80
|
|
|
55
|
-
|
|
81
|
+
toJson() {
|
|
56
82
|
return this.quaternion;
|
|
57
83
|
}
|
|
58
84
|
|
|
59
|
-
static
|
|
60
|
-
return new Attitude(
|
|
85
|
+
static fromJson(json) {
|
|
86
|
+
return new Attitude(json);
|
|
61
87
|
}
|
|
62
88
|
|
|
63
89
|
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import chai from 'chai';
|
|
2
|
+
import chaiAlmost from 'chai-almost';
|
|
3
|
+
|
|
4
|
+
import Attitude from './Attitude';
|
|
5
|
+
|
|
6
|
+
const expect = chai.expect;
|
|
7
|
+
chai.use(chaiAlmost());
|
|
8
|
+
|
|
9
|
+
describe('Attitude', () => {
|
|
10
|
+
|
|
11
|
+
it('creation', () => {
|
|
12
|
+
expect(() => new Attitude()).throw(Error);
|
|
13
|
+
expect(() => new Attitude(true)).throw(Error);
|
|
14
|
+
expect(() => new Attitude(false)).throw(Error);
|
|
15
|
+
expect(() => new Attitude([])).throw(Error);
|
|
16
|
+
expect(() => new Attitude([1])).throw(Error);
|
|
17
|
+
expect(() => new Attitude([1, 2, 3, 4])).throw(Error);
|
|
18
|
+
expect(() => new Attitude([1, 1, 1, 1])).throw(Error);
|
|
19
|
+
expect(() => new Attitude([0, 0, 0, 1])).not.throw(Error);
|
|
20
|
+
expect(() => new Attitude([0.5, 0.5, 0.5, 0.5])).not.throw(Error);
|
|
21
|
+
expect(() => new Attitude([Math.sqrt(2) / 2, Math.sqrt(2) / 2, 0, 0])).not.throw(Error);
|
|
22
|
+
expect(Attitude.unitary().quaternion).deep.equals([1, 0, 0, 0]);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it('eulerAngles', () => {
|
|
26
|
+
|
|
27
|
+
const attitude = new Attitude([1, 0, 0, 0]);
|
|
28
|
+
expect(attitude.eulerAngles).deep.equals([0, 0, 0]);
|
|
29
|
+
expect(attitude.eulerAngles).deep.equals([0, 0, 0]);
|
|
30
|
+
|
|
31
|
+
expect(new Attitude([0, 1, 0, 0]).eulerAngles).deep.equals([Math.PI, 0, Math.PI]);
|
|
32
|
+
expect(new Attitude([0, 0, 1, 0]).eulerAngles).deep.equals([0, 0, Math.PI]);
|
|
33
|
+
expect(new Attitude([0, 0, 0, 1]).eulerAngles).deep.equals([Math.PI, 0, 0]);
|
|
34
|
+
|
|
35
|
+
expect(new Attitude([1, 0, 0, 0]).eulerAnglesDegrees).deep.equals([0, 0, 0]);
|
|
36
|
+
expect(new Attitude([0, 0, 1, 0]).eulerAnglesDegrees).deep.equals([0, 0, 180]);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
it('heading', () => {
|
|
40
|
+
const attitude = new Attitude([1, 0, 0, 0]);
|
|
41
|
+
expect(attitude.heading).equals(0);
|
|
42
|
+
expect(attitude.heading).equals(0);
|
|
43
|
+
|
|
44
|
+
expect(new Attitude([Math.sqrt(2) / 2, Math.sqrt(2) / 2, 0, 0]).heading).equals(0);
|
|
45
|
+
expect(new Attitude([-0.5, 0.5, 0.5, 0.5]).heading).equals(Math.PI / 2);
|
|
46
|
+
|
|
47
|
+
const tmpWindow = global.window;
|
|
48
|
+
global.window = { orientation: 90 };
|
|
49
|
+
expect(new Attitude([1, 0, 0, 0]).heading).equals(Math.PI / 2);
|
|
50
|
+
expect(new Attitude([Math.sqrt(2) / 2, Math.sqrt(2) / 2, 0, 0]).heading).equals(Math.PI / 2);
|
|
51
|
+
expect(new Attitude([-0.5, 0.5, 0.5, 0.5]).heading).equals(Math.PI);
|
|
52
|
+
global.window = tmpWindow;
|
|
53
|
+
|
|
54
|
+
expect(new Attitude([-0.5, 0.5, 0.5, 0.5]).headingDegrees).equals(90);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('equalsTo', () => {
|
|
58
|
+
|
|
59
|
+
expect(Attitude.equalsTo(null, null)).true;
|
|
60
|
+
expect(Attitude.equalsTo(new Attitude([-0.5, 0.5, 0.5, 0.5]), new Attitude([1, 0, 0, 0]))).false;
|
|
61
|
+
expect(Attitude.equalsTo([-0.5, 0.5, 0.5, 0.5], new Attitude([1, 0, 0, 0]))).false;
|
|
62
|
+
expect(Attitude.equalsTo(new Attitude([1, 0, 0, 0]), [-0.5, 0.5, 0.5, 0.5])).false;
|
|
63
|
+
expect(new Attitude([1, 0, 0, 0]).equalsTo(new Attitude([1, 0, 0, 0]))).true;
|
|
64
|
+
expect(new Attitude([-0.5, 0.5, 0.5, 0.5]).equalsTo(new Attitude([-0.5, 0.5, 0.5, 0.5]))).true;
|
|
65
|
+
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
it('json', () => {
|
|
70
|
+
|
|
71
|
+
let attitude;
|
|
72
|
+
|
|
73
|
+
attitude = new Attitude([1, 0, 0, 0]);
|
|
74
|
+
expect(attitude.toJson()).deep.equals([1, 0, 0, 0]);
|
|
75
|
+
expect(attitude.equalsTo(Attitude.fromJson(attitude.toJson()))).true;
|
|
76
|
+
|
|
77
|
+
attitude = new Attitude([-0.5, 0.5, 0.5, 0.5]);
|
|
78
|
+
expect(attitude.toJson()).deep.equals([-0.5, 0.5, 0.5, 0.5]);
|
|
79
|
+
expect(attitude.equalsTo(Attitude.fromJson(attitude.toJson()))).true;
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
});
|