@pirireis/webglobeplugins 0.8.15-alpha → 0.8.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/Math/plane.ts ADDED
@@ -0,0 +1,167 @@
1
+ import { Vector3D } from './vector3d';
2
+ import { WORLD_RADIUS_MERCATOR } from "./constants";
3
+ import { Radians, Meter } from './types';
4
+ import { Ray } from './ray';
5
+
6
+
7
+ const VEC_EPSILON = 1e-8;
8
+
9
+ const _0vector = /*@__PURE__*/ new Vector3D(0, 0, 0);
10
+
11
+
12
+
13
+ export class Plane {
14
+ public normal: Vector3D;
15
+ public constant: number; // negative distance from the origin to the plane along the normal vector
16
+
17
+
18
+
19
+
20
+ constructor(normal: Vector3D, constant: number) {
21
+ this.normal = normal.normalize();
22
+ this.constant = constant;
23
+ }
24
+
25
+
26
+ set(normal: Vector3D, constant: number): Plane {
27
+ this.normal.copy(normal);
28
+ this.constant = constant;
29
+ return this;
30
+ }
31
+
32
+
33
+
34
+ copy(plane: Plane): Plane {
35
+ this.normal.copy(plane.normal);
36
+ this.constant = plane.constant;
37
+ return this;
38
+ }
39
+
40
+
41
+
42
+ clone(): Plane {
43
+ return new Plane(this.normal.clone(), this.constant);
44
+ }
45
+
46
+
47
+
48
+ distanceToPoint(point: Vector3D): number {
49
+ return this.normal.dot(point) - this.constant;
50
+ }
51
+
52
+
53
+
54
+ projectPoint(point: Vector3D): Vector3D {
55
+ const distance = this.distanceToPoint(point);
56
+ return point.subtract(_0vector.copy(this.normal).scale(distance));
57
+ }
58
+
59
+
60
+
61
+ equals(other: Plane): boolean { // assumes normals are normalized
62
+ return this.normal.equals(other.normal) && Math.abs(this.constant - other.constant) < VEC_EPSILON;
63
+ }
64
+
65
+
66
+ equalsReverseOriantation(other: Plane): boolean { // assumes normals are normalized
67
+ _0vector.copy(this.normal).negate();
68
+ return _0vector.equals(other.normal) && Math.abs(this.constant + other.constant) < VEC_EPSILON;
69
+ }
70
+
71
+
72
+
73
+
74
+ setFromNormalAndPoint(normal: Vector3D, point: Vector3D): Plane {
75
+ this.normal.copy(normal);
76
+ this.constant = point.dot(normal);
77
+ return this;
78
+ }
79
+
80
+
81
+
82
+
83
+ static fromNormalAndCoplanarPoint(normal: Vector3D, point: Vector3D): Plane {
84
+ return new Plane(normal, -point.dot(normal));
85
+ }
86
+
87
+
88
+
89
+ setFromPoints(p1: Vector3D, p2: Vector3D, p3: Vector3D): Plane {
90
+ this.normal = p2.clone().subtract(p1).cross(p3.subtract(p1)).normalize();
91
+ this.constant = p1.dot(this.normal);
92
+ return this;
93
+ }
94
+
95
+
96
+
97
+
98
+ static fromPoints(p1: Vector3D, p2: Vector3D, p3: Vector3D): Plane {
99
+ const normal = p2.subtract(p1).cross(p3.subtract(p1)).normalize();
100
+ const constant = p1.dot(normal);
101
+ return new Plane(normal, constant);
102
+ }
103
+
104
+
105
+
106
+
107
+ static fromGlobeLookInfo(centerLongitude: Radians, centerLatitude: Radians, distance: Meter, target: Plane): boolean {
108
+ const radiansAngle = Math.PI * distance / WORLD_RADIUS_MERCATOR;
109
+ target.normal.setFromLonLat(centerLongitude, centerLatitude).normalize();
110
+ target.constant = - Math.cos(radiansAngle);
111
+ return true;
112
+ }
113
+
114
+
115
+
116
+ intersectionPlane(other: Plane): { origin: Vector3D, direction: Vector3D } | Plane | null {
117
+ if (this.normal.equals(other.normal)) {
118
+ if (Math.abs(this.constant - other.constant) < VEC_EPSILON) {
119
+ console.log('same orientation', this, other);
120
+ return this.clone(); // planes are equal
121
+ }
122
+ console.log('same orientation null', this, other);
123
+ return null; // planes are parallel and not equal
124
+ }
125
+ // opposite orientation
126
+ if (_0vector.copy(this.normal).negate().equals(other.normal)) {
127
+ if (Math.abs(this.constant + other.constant) < VEC_EPSILON) {
128
+ console.log('opposite orientation', this, other);
129
+ return this.clone(); // planes are equal
130
+ }
131
+ console.log('opposite orientation null', this, other);
132
+ return null; // planes are parallel and not equal
133
+ }
134
+
135
+
136
+ const nA = this.normal;
137
+ const nB = other.normal;
138
+ const dA = this.constant;
139
+ const dB = other.constant;
140
+
141
+ const direction = nA.clone().cross(nB).normalize();
142
+
143
+ // find a point on the line of intersection
144
+ const denomXY = nA.x * nB.y - nA.y * nB.x;
145
+
146
+ if (Math.abs(denomXY) > VEC_EPSILON) {
147
+ const x = (dA * nB.y - dB * nA.y) / denomXY;
148
+ const y = (dB * nA.x - dA * nB.x) / denomXY;
149
+ return { origin: new Vector3D(x, y, 0), direction };
150
+ }
151
+ const denomXZ = nA.x * nB.z - nA.z * nB.x;
152
+ if (Math.abs(denomXZ) > VEC_EPSILON) {
153
+ const x = (dA * nB.z - dB * nA.z) / denomXZ;
154
+ const z = (dB * nA.x - dA * nB.x) / denomXZ;
155
+ return { origin: new Vector3D(x, 0, z), direction };
156
+ }
157
+ const denomYZ = nA.y * nB.z - nA.z * nB.y;
158
+ if (Math.abs(denomYZ) > VEC_EPSILON) {
159
+ const y = (dA * nB.z - dB * nA.z) / denomYZ;
160
+ const z = (dB * nA.y - dA * nB.y) / denomYZ;
161
+ return { origin: new Vector3D(0, y, z), direction };
162
+ }
163
+ console.log('intersectionPlane null', this, other);
164
+ return null; // planes are parallel and not equal
165
+ }
166
+
167
+ }
@@ -0,0 +1,159 @@
1
+ import { Radians, Vector3D } from './types'
2
+
3
+
4
+ export class Quaternion {
5
+ x: number;
6
+ y: number;
7
+ z: number;
8
+ w: number;
9
+
10
+
11
+
12
+ constructor(x: number = 0, y: number = 0, z: number = 0, w: number = 1) {
13
+ this.x = x;
14
+ this.y = y;
15
+ this.z = z;
16
+ this.w = w;
17
+ }
18
+
19
+
20
+
21
+ set(x: number, y: number, z: number, w: number): Quaternion {
22
+ this.x = x;
23
+ this.y = y;
24
+ this.z = z;
25
+ this.w = w;
26
+ return this;
27
+ }
28
+
29
+
30
+
31
+ multiply(other: Quaternion): Quaternion {
32
+ const x = this.x * other.w + this.w * other.x + this.y * other.z - this.z * other.y;
33
+ const y = this.y * other.w + this.w * other.y + this.z * other.x - this.x * other.z;
34
+ const z = this.z * other.w + this.w * other.z + this.x * other.y - this.y * other.x;
35
+ const w = this.w * other.w - this.x * other.x - this.y * other.y - this.z * other.z;
36
+ return this.set(x, y, z, w);
37
+ }
38
+
39
+
40
+
41
+ length(): number {
42
+ return Math.sqrt(this.x ** 2 + this.y ** 2 + this.z ** 2 + this.w ** 2);
43
+ }
44
+
45
+
46
+
47
+ normalize(): Quaternion {
48
+ const len = this.length();
49
+ if (len > 0) {
50
+ this.x /= len;
51
+ this.y /= len;
52
+ this.z /= len;
53
+ this.w /= len;
54
+ }
55
+ return this;
56
+ }
57
+
58
+
59
+
60
+ copy(other: Quaternion): Quaternion {
61
+ this.x = other.x;
62
+ this.y = other.y;
63
+ this.z = other.z;
64
+ this.w = other.w;
65
+ return this;
66
+ }
67
+
68
+
69
+
70
+ clone(): Quaternion {
71
+ return new Quaternion(this.x, this.y, this.z, this.w);
72
+ }
73
+
74
+
75
+
76
+ setFromUnitVectors(vFrom: Vector3D, vTo: Vector3D): Quaternion {
77
+ const d = vFrom.dot(vTo) + 1;
78
+ if (d < 0.000001) {
79
+ if (Math.abs(vFrom.x) > Math.abs(vFrom.z)) {
80
+ this.set(-vFrom.y, vFrom.x, 0, 0);
81
+ } else {
82
+ this.set(0, -vFrom.z, vFrom.y, 0);
83
+ }
84
+ }
85
+ else {
86
+ this.set(
87
+ vFrom.y * vTo.z - vFrom.z * vTo.y,
88
+ vFrom.z * vTo.x - vFrom.x * vTo.z,
89
+ vFrom.x * vTo.y - vFrom.y * vTo.x,
90
+ d
91
+ )
92
+ }
93
+ return this;
94
+ }
95
+
96
+
97
+
98
+ static fromUnitVectors(vFrom: Vector3D, vTo: Vector3D): Quaternion {
99
+ return new Quaternion().setFromUnitVectors(vFrom, vTo);
100
+ }
101
+
102
+
103
+
104
+ setFromAxisAngle(axis: Vector3D, angle: Radians): Quaternion {
105
+ const halfAngle = angle / 2;
106
+ const s = Math.sin(halfAngle);
107
+ const len = axis.length() || 1;
108
+ this.x = axis.x * s / len;
109
+ this.y = axis.y * s / len;
110
+ this.z = axis.z * s / len;
111
+ this.w = Math.cos(halfAngle);
112
+ return this;
113
+ }
114
+
115
+
116
+
117
+ static fromAxisAngle(axis: Vector3D, angle: Radians): Quaternion {
118
+ return new Quaternion().setFromAxisAngle(axis, angle);
119
+ }
120
+
121
+
122
+
123
+ rotatePoint(point: Vector3D, out: Vector3D) {
124
+ const x = point.x;
125
+ const y = point.y;
126
+ const z = point.z;
127
+
128
+ const qx = this.x;
129
+ const qy = this.y;
130
+ const qz = this.z;
131
+ const qw = this.w;
132
+
133
+ const ix = qw * x + qy * z - qz * y;
134
+ const iy = qw * y + qz * x - qx * z;
135
+ const iz = qw * z + qx * y - qy * x;
136
+ const iw = -qx * x - qy * y - qz * z;
137
+
138
+ out.x = ix * qw + iw * -qx + iy * -qz - iz * -qy;
139
+ out.y = iy * qw + iw * -qy + iz * -qx - ix * -qz;
140
+ out.z = iz * qw + iw * -qz + ix * -qy - iy * -qx;
141
+
142
+ return out;
143
+
144
+ }
145
+
146
+
147
+ toMatrix4x4(): number[] {
148
+ const x = this.x, y = this.y, z = this.z, w = this.w;
149
+ const xx = x * x, yy = y * y, zz = z * z, xy = x * y, xz = x * z, yz = y * z, wx = w * x, wy = w * y, wz = w * z;
150
+ return [
151
+ 1 - 2 * (yy + zz), 2 * (xy - wz), 2 * (xz + wy), 0,
152
+ 2 * (xy + wz), 1 - 2 * (xx + zz), 2 * (yz - wx), 0,
153
+ 2 * (xz - wy), 2 * (yz + wx), 1 - 2 * (xx + yy), 0,
154
+ 0, 0, 0, 1
155
+ ];
156
+ }
157
+
158
+
159
+ }
package/Math/ray.ts ADDED
@@ -0,0 +1,101 @@
1
+ import { Vector3D } from './vector3d';
2
+ import { Plane } from './plane';
3
+
4
+
5
+ const _0vector = /*@__PURE__*/ new Vector3D(0, 0, 0);
6
+ const _1vector = /*@__PURE__*/ new Vector3D(0, 0, 0);
7
+ const _3vector = /*@__PURE__*/ new Vector3D(0, 0, 0);
8
+ export class Ray {
9
+
10
+ origin: Vector3D;
11
+ direction: Vector3D;
12
+
13
+ constructor(origin: Vector3D, direction: Vector3D) {
14
+ this.origin = origin;
15
+ this.direction = direction.normalize();
16
+ }
17
+
18
+ copy(ray: Ray): Ray {
19
+ this.origin.copy(ray.origin);
20
+ this.direction.copy(ray.direction);
21
+ return this;
22
+ }
23
+
24
+ clone(): Ray {
25
+ return new Ray(this.origin.clone(), this.direction.clone());
26
+ }
27
+
28
+
29
+ at(distance: number, out: Vector3D): Vector3D {
30
+ return out.copy(this.direction).multiplyByScaler(distance).add(this.origin);
31
+ }
32
+
33
+
34
+ set(origin: Vector3D, direction: Vector3D): Ray {
35
+ this.origin.copy(origin);
36
+ this.direction.copy(direction).normalize();
37
+ return this;
38
+ }
39
+
40
+ intersectionSphere(sphereOrigin: Vector3D, sphereRadius: number): [Vector3D, Vector3D] | null {
41
+
42
+ const l = this.direction.clone().normalize();
43
+ const s = this.origin.clone().subtract(sphereOrigin);
44
+ const b = l.dot(s);
45
+
46
+ const c = s.dot(s) - sphereRadius * sphereRadius;
47
+ const d = b * b - c;
48
+
49
+ if (d < 0) {
50
+ return null; // no intersection
51
+ } else {
52
+ const x = Math.sqrt(d);
53
+ const t1 = -b - x;
54
+ const t2 = -b + x;
55
+ // l and s are used as output vectors
56
+ return [this.at(t1, l), this.at(t2, s)];
57
+ }
58
+ }
59
+
60
+
61
+ contains(point: Vector3D): boolean {
62
+ const x = this.origin.x - point.x;
63
+ const y = this.origin.y - point.y;
64
+ const z = this.origin.z - point.z;
65
+ const distance = Math.sqrt(x * x + y * y + z * z);
66
+ if (distance < 0.0001) {
67
+ return true; // point is very close to the origin
68
+ }
69
+ return Math.abs(_0vector.set(x / distance, y / distance, z / distance).dot(this.direction)) > 0.9999; // point direction towards origin
70
+ // is very close to the ray direction
71
+ }
72
+
73
+ // TODO: Applay this approach to other static methods on other Math classes.
74
+ static fromTwoPlanes(planeA: Plane, planeB: Plane, target: Ray | null = null): Ray | null {
75
+ const intersection = planeA.intersectionPlane(planeB);
76
+ if (intersection === null || intersection instanceof Plane) {
77
+ return null; // planes are parallel
78
+ }
79
+ if (target === null) {
80
+ target = new Ray(intersection.origin, intersection.direction);
81
+ }
82
+ else {
83
+ target.set(intersection.origin, intersection.direction);
84
+ }
85
+ return target;
86
+ }
87
+
88
+
89
+ static fromTwoPoints(pointA: Vector3D, pointB: Vector3D, target: Ray | null = null): Ray {
90
+ if (target === null) {
91
+ target = new Ray(pointA, pointB.clone().subtract(pointA).normalize());
92
+ } else {
93
+ target.set(pointA, pointB.clone().subtract(pointA).normalize());
94
+ }
95
+ return target;
96
+ }
97
+
98
+ }
99
+
100
+
101
+
@@ -0,0 +1,10 @@
1
+
2
+ There is an arc on a unit sphere. The sphere center is at the origin. The arc is represented with start and points.
3
+
4
+ And there is a plane the intersects with the same sphere. Represented with vector and distance from origin.
5
+
6
+ I want to know the relative position of points to the plane. If they are at the same direction with the plane vector or not.
7
+
8
+ If two points are on the same side of the plane. If so, do they closer to origin then plane or not.
9
+
10
+ If two points are on different side of the plane, I want to know the intersection point of arc and plane.
package/Math/types.ts ADDED
@@ -0,0 +1,36 @@
1
+ export type Radians = number;
2
+ export type Degrees = number;
3
+ export type Meter = number;
4
+
5
+ interface Vector3D {
6
+ x: number;
7
+ y: number;
8
+ z: number;
9
+ dot(other: Vector3D): number;
10
+ cross(other: Vector3D): Vector3D;
11
+ lerp(other: Vector3D, t: number): Vector3D;
12
+ scale(scalar: number): Vector3D;
13
+ applyQuaternion(q: Quaternion): Vector3D;
14
+ normalize(): Vector3D;
15
+ clone(): Vector3D;
16
+ copy(other: Vector3D): Vector3D;
17
+ set(x: number, y: number, z: number): Vector3D;
18
+ add(other: Vector3D): Vector3D;
19
+ subtract(other: Vector3D): Vector3D;
20
+ negate(): Vector3D;
21
+ length(): number;
22
+ multiplyByScaler(scalar: number): Vector3D;
23
+ divideByScaler(scalar: number): Vector3D;
24
+ }
25
+
26
+ interface Quaternion {
27
+ x: number;
28
+ y: number;
29
+ z: number;
30
+ w: number;
31
+ }
32
+
33
+ export {
34
+ Vector3D,
35
+ Quaternion
36
+ }
package/Math/utils.js ADDED
@@ -0,0 +1,3 @@
1
+ import { Vector3D } from "./vector3d";
2
+ import { Quaternion } from "./quaternion";
3
+
@@ -0,0 +1,230 @@
1
+ import { Vector3D as IVector3D, Radians } from "./types";
2
+ import { Quaternion } from "./quaternion";
3
+
4
+
5
+
6
+ export class Vector3D implements IVector3D {
7
+ x: number;
8
+ y: number;
9
+ z: number;
10
+
11
+
12
+ constructor(x: number = 0, y: number = 0, z: number = 0) {
13
+ this.x = x;
14
+ this.y = y;
15
+ this.z = z;
16
+ }
17
+
18
+
19
+
20
+ normalize(): Vector3D {
21
+ this.divideByScaler(this.length() || 1);
22
+ return this;
23
+ }
24
+
25
+
26
+
27
+ dot(other: Vector3D) {
28
+ return this.x * other.x + this.y * other.y + this.z * other.z;
29
+ }
30
+
31
+
32
+
33
+ equals(other: Vector3D, epsilon: number = 0.0000001): boolean {
34
+ // TODO: consider coppying other in case is true to avoid difference accumulation.
35
+ return Math.abs(this.x - other.x) < epsilon &&
36
+ Math.abs(this.y - other.y) < epsilon &&
37
+ Math.abs(this.z - other.z) < epsilon;
38
+ }
39
+
40
+
41
+
42
+
43
+ static crossVectors(a: Vector3D, b: Vector3D, c: Vector3D = new Vector3D): Vector3D {
44
+ const x = a.y * b.z - a.z * b.y;
45
+ const y = a.z * b.x - a.x * b.z;
46
+ const z = a.x * b.y - a.y * b.x;
47
+
48
+ c.set(x, y, z);
49
+
50
+ return c;
51
+ }
52
+
53
+
54
+
55
+ cross(other: Vector3D): Vector3D {
56
+ return Vector3D.crossVectors(this, other, this);
57
+ }
58
+
59
+
60
+
61
+ lerpVectors(a: Vector3D, b: Vector3D, t: number): Vector3D {
62
+ this.x = a.x + (b.x - a.x) * t;
63
+ this.y = a.y + (b.y - a.y) * t;
64
+ this.z = a.z + (b.z - a.z) * t;
65
+
66
+ return this;
67
+ }
68
+
69
+
70
+
71
+ lerp(other: Vector3D, t: number): Vector3D {
72
+ return this.lerpVectors(this, other, t);
73
+ }
74
+
75
+
76
+
77
+ scale(scalar: number): Vector3D {
78
+ this.x *= scalar;
79
+ this.y *= scalar;
80
+ this.z *= scalar;
81
+
82
+ return this;
83
+ }
84
+
85
+ dotProduct(other: Vector3D): number {
86
+ return this.x * other.x + this.y * other.y + this.z * other.z;
87
+ }
88
+
89
+
90
+ dotDivide(other: Vector3D): number {
91
+ return this.x / other.x + this.y / other.y + this.z / other.z;
92
+ }
93
+
94
+
95
+ add(other: Vector3D): Vector3D {
96
+ this.x += other.x;
97
+ this.y += other.y;
98
+ this.z += other.z;
99
+
100
+ return this;
101
+ }
102
+
103
+
104
+
105
+ negate(): Vector3D {
106
+ this.x = -this.x;
107
+ this.y = -this.y;
108
+ this.z = -this.z;
109
+
110
+ return this;
111
+ }
112
+
113
+
114
+
115
+ length(): number {
116
+ return Math.sqrt(this.x ** 2 + this.y ** 2 + this.z ** 2);
117
+ }
118
+
119
+
120
+
121
+ subtract(other: Vector3D): Vector3D {
122
+ this.x -= other.x;
123
+ this.y -= other.y;
124
+ this.z -= other.z;
125
+
126
+ return this;
127
+ }
128
+
129
+
130
+
131
+ applyQuaternion(q: Quaternion): Vector3D {
132
+ const x = this.x, y = this.y, z = this.z;
133
+ const qx = q.x, qy = q.y, qz = q.z, qw = q.w;
134
+ // calculate quat * vector
135
+ const ix = qw * x + qy * z - qz * y;
136
+ const iy = qw * y + qz * x - qx * z;
137
+ const iz = qw * z + qx * y - qy * x;
138
+ const iw = -qx * x - qy * y - qz * z;
139
+ // calculate result * inverse quat
140
+ this.x = ix * qw + iw * -qx + iy * -qz - iz * -qy;
141
+ this.y = iy * qw + iw * -qy + iz * -qx - ix * -qz;
142
+ this.z = iz * qw + iw * -qz + ix * -qy - iy * -qx;
143
+ return this;
144
+ }
145
+
146
+
147
+
148
+ multiplyByScaler(scalar: number): Vector3D {
149
+ this.x *= scalar;
150
+ this.y *= scalar;
151
+ this.z *= scalar;
152
+
153
+ return this;
154
+ };
155
+
156
+
157
+
158
+ divideByScaler(scalar: number): Vector3D {
159
+ this.x /= scalar;
160
+ this.y /= scalar;
161
+ this.z /= scalar;
162
+
163
+ return this;
164
+ }
165
+
166
+
167
+
168
+ copy(other: Vector3D): Vector3D {
169
+ this.x = other.x;
170
+ this.y = other.y;
171
+ this.z = other.z;
172
+
173
+ return this
174
+ }
175
+
176
+
177
+
178
+ set(x: number, y: number, z: number): Vector3D {
179
+ this.x = x;
180
+ this.y = y;
181
+ this.z = z;
182
+
183
+ return this
184
+ }
185
+
186
+
187
+
188
+ clone(): Vector3D {
189
+ return new Vector3D(this.x, this.y, this.z);
190
+ }
191
+
192
+
193
+
194
+ randomUnit(): Vector3D {
195
+ const x = Math.random() * 2 - 1;
196
+ const y = Math.random() * 2 - 1;
197
+ const z = Math.random() * 2 - 1;
198
+
199
+ return this.set(x, y, z).normalize();
200
+ }
201
+
202
+
203
+
204
+ setFromLonLat(lon: Radians, lat: Radians): Vector3D {
205
+ const x = Math.cos(lat) * Math.cos(lon);
206
+ const y = Math.cos(lat) * Math.sin(lon);
207
+ const z = Math.sin(lat);
208
+
209
+ return this.set(x, y, z);
210
+ }
211
+
212
+
213
+
214
+
215
+ toLonLat(): { lon: Radians, lat: Radians } {
216
+ const len = this.length();
217
+ const x = this.x / len;
218
+ const y = this.y / len;
219
+ const z = this.z / len;
220
+ const lon = Math.atan2(y, x);
221
+ const lat = Math.asin(z);
222
+
223
+ return { lon, lat };
224
+ }
225
+
226
+
227
+ static fromLonLatRadians(lon: Radians, lat: Radians): Vector3D {
228
+ return new Vector3D().setFromLonLat(lon, lat);
229
+ }
230
+ }
package/jest.config.js ADDED
@@ -0,0 +1,6 @@
1
+ module.exports = {
2
+ preset: 'ts-jest',
3
+ testEnvironment: 'node',
4
+ testMatch: ['**/tests/**/*.test.ts'],
5
+ moduleFileExtensions: ['ts', 'js'],
6
+ }