@rocon/balcan 0.0.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/dist/core/bitmap.balcan.d.ts +4 -0
- package/dist/core/bitmap.balcan.js +22 -0
- package/dist/core/core.balcan.d.ts +73 -0
- package/dist/core/core.balcan.js +136 -0
- package/dist/core/geo.balcan.d.ts +109 -0
- package/dist/core/geo.balcan.js +255 -0
- package/dist/core/math.balcan.d.ts +35 -0
- package/dist/core/math.balcan.js +90 -0
- package/dist/core/ts-matrix/Matrix.d.ts +111 -0
- package/dist/core/ts-matrix/Matrix.js +243 -0
- package/dist/core/ts-matrix/Quat.d.ts +168 -0
- package/dist/core/ts-matrix/Quat.js +435 -0
- package/dist/core/ts-matrix/Vector.d.ts +145 -0
- package/dist/core/ts-matrix/Vector.js +252 -0
- package/dist/core/ts-matrix/constants.d.ts +1 -0
- package/dist/core/ts-matrix/constants.js +1 -0
- package/dist/core/ts-matrix/ts-matrix.d.ts +3 -0
- package/dist/core/ts-matrix/ts-matrix.js +31 -0
- package/dist/core/types.balcan.d.ts +93 -0
- package/dist/core/types.balcan.js +1 -0
- package/dist/core/util.balcan.d.ts +23 -0
- package/dist/core/util.balcan.js +71 -0
- package/dist/core/viewport.balcan.d.ts +27 -0
- package/dist/core/viewport.balcan.js +60 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +3 -0
- package/dist/mixin/mixin.d.ts +7 -0
- package/dist/mixin/mixin.js +7 -0
- package/dist/mixin/mixin.type.d.ts +2 -0
- package/dist/mixin/mixin.type.js +1 -0
- package/dist/staffs/image.staff.d.ts +27 -0
- package/dist/staffs/image.staff.js +74 -0
- package/dist/staffs/index.d.ts +3 -0
- package/dist/staffs/index.js +3 -0
- package/dist/staffs/wheelZoom.staff.d.ts +21 -0
- package/dist/staffs/wheelZoom.staff.js +45 -0
- package/dist/staffs/windowResizeObserver.staff.d.ts +8 -0
- package/dist/staffs/windowResizeObserver.staff.js +17 -0
- package/dist/types/geometry.d.ts +68 -0
- package/dist/types/index.d.ts +1 -0
- package/package.json +39 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
export var math;
|
|
2
|
+
(function (math) {
|
|
3
|
+
function average(...values) {
|
|
4
|
+
if (values.length === 0)
|
|
5
|
+
return 0;
|
|
6
|
+
return values.reduce((acc, cur) => acc + cur, 0) / values.length;
|
|
7
|
+
}
|
|
8
|
+
math.average = average;
|
|
9
|
+
/** degree -> radian */
|
|
10
|
+
function radian(deg, opt) {
|
|
11
|
+
const parsedDeg = typeof deg === 'string' ? parseFloat(deg) : Number(deg);
|
|
12
|
+
const semi = opt?.invertY ? -180 : 180;
|
|
13
|
+
const rad = (parsedDeg * Math.PI) / semi;
|
|
14
|
+
if (opt?.toFixed) {
|
|
15
|
+
return parseFloat(rad.toFixed(opt.toFixed));
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
return rad;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
math.radian = radian;
|
|
22
|
+
/** radian -> degree */
|
|
23
|
+
function degree(rad, opt) {
|
|
24
|
+
const parsedRad = typeof rad === 'string' ? parseFloat(rad) : Number(rad);
|
|
25
|
+
const semi = opt?.invertY ? -180 : 180;
|
|
26
|
+
const degree = (parsedRad * semi) / Math.PI;
|
|
27
|
+
if (opt?.toFixed) {
|
|
28
|
+
return parseFloat(degree.toFixed(opt.toFixed));
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
return degree;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
math.degree = degree;
|
|
35
|
+
/** 주어진 각도를 -180 ~ 180 범위로 좁힌다 */
|
|
36
|
+
function normalizeAngle(degree) {
|
|
37
|
+
const mod = degree % 360;
|
|
38
|
+
if (mod <= -180)
|
|
39
|
+
return mod + 360;
|
|
40
|
+
if (mod > 180)
|
|
41
|
+
return mod - 360;
|
|
42
|
+
else
|
|
43
|
+
return mod;
|
|
44
|
+
}
|
|
45
|
+
math.normalizeAngle = normalizeAngle;
|
|
46
|
+
/** 위치 간 거리를 구한다, 위치는 Vector와 Position 타입을 사용할 수 있다 */
|
|
47
|
+
function vectorDistance(p1, p2) {
|
|
48
|
+
const v1 = vector2d(p1);
|
|
49
|
+
const v2 = vector2d(p2);
|
|
50
|
+
const dx = v2.x - v1.x;
|
|
51
|
+
const dy = v2.y - v1.y;
|
|
52
|
+
return Math.sqrt(dx * dx + dy * dy);
|
|
53
|
+
}
|
|
54
|
+
math.vectorDistance = vectorDistance;
|
|
55
|
+
/** 두 점을 잇는 직선의 기울기를 구한다 */
|
|
56
|
+
function vectorSlope(params) {
|
|
57
|
+
const { point1, point2, outputUnit = 'radian' } = params;
|
|
58
|
+
let angle = 0;
|
|
59
|
+
const v1 = vector2d(point1);
|
|
60
|
+
const v2 = vector2d(point2);
|
|
61
|
+
angle = Math.atan2(v2.y - v1.y, v2.x - v1.x);
|
|
62
|
+
if (outputUnit === 'degree')
|
|
63
|
+
return degree(angle);
|
|
64
|
+
else
|
|
65
|
+
return angle;
|
|
66
|
+
}
|
|
67
|
+
math.vectorSlope = vectorSlope;
|
|
68
|
+
/** 벡터 덧셈 */
|
|
69
|
+
function vectorAdd(v1, v2) {
|
|
70
|
+
const r = { x: v1.x + v2.x, y: v1.y + v2.y };
|
|
71
|
+
if ('theta' in v1 && 'theta' in v2)
|
|
72
|
+
return { ...r, theta: v1.theta + v2.theta };
|
|
73
|
+
else
|
|
74
|
+
return r;
|
|
75
|
+
}
|
|
76
|
+
math.vectorAdd = vectorAdd;
|
|
77
|
+
/** 벡터 내적 */
|
|
78
|
+
function vectorDot(v1, v2) {
|
|
79
|
+
return v1.x * v2.x + v1.y * v2.y;
|
|
80
|
+
}
|
|
81
|
+
math.vectorDot = vectorDot;
|
|
82
|
+
/** position like 자료형을 vector2d 로 변환함 */
|
|
83
|
+
function vector2d(point) {
|
|
84
|
+
if ('stagex' in point)
|
|
85
|
+
return { x: point.stagex, y: point.stagey };
|
|
86
|
+
else
|
|
87
|
+
return { x: point.x, y: point.y };
|
|
88
|
+
}
|
|
89
|
+
math.vector2d = vector2d;
|
|
90
|
+
})(math || (math = {}));
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import Vector from './Vector';
|
|
2
|
+
export default class Matrix {
|
|
3
|
+
/** Number of rows of the matrix */
|
|
4
|
+
private _rows;
|
|
5
|
+
/** Number of columns of the matrix */
|
|
6
|
+
private _columns;
|
|
7
|
+
/** Values of the matrix as a two dimensional array */
|
|
8
|
+
private _values;
|
|
9
|
+
constructor(rows: number, columns: number, values?: number[][]);
|
|
10
|
+
get rows(): number;
|
|
11
|
+
get columns(): number;
|
|
12
|
+
get values(): number[][];
|
|
13
|
+
/**
|
|
14
|
+
* Set values into the matrix.
|
|
15
|
+
* If the parameters matrix is to wide, the values are cropped to the current matrix size.
|
|
16
|
+
* It the parameters matrix is to small, remaining cells will be filled with 0.
|
|
17
|
+
* @param newValues Arrays of new values.
|
|
18
|
+
*/
|
|
19
|
+
set values(newValues: number[][]);
|
|
20
|
+
/**
|
|
21
|
+
* Get a matrix value, from its position
|
|
22
|
+
* @param row Matrix line, from 0 to `rows`
|
|
23
|
+
* @param col Matric column, from 0 to `columns`
|
|
24
|
+
*/
|
|
25
|
+
at(row: number, col: number): number;
|
|
26
|
+
/**
|
|
27
|
+
* Sets all matrix values to 0
|
|
28
|
+
*/
|
|
29
|
+
reset(): void;
|
|
30
|
+
/**
|
|
31
|
+
* Add an new column to the matrix, filled with 0
|
|
32
|
+
*/
|
|
33
|
+
addAColumn(): Matrix;
|
|
34
|
+
/**
|
|
35
|
+
* Add an new row to the matrix, filled with 0
|
|
36
|
+
*/
|
|
37
|
+
addARow(): Matrix;
|
|
38
|
+
/**
|
|
39
|
+
* Check if two matrix are equals, value by value
|
|
40
|
+
* @param mat The matrix against to check equality
|
|
41
|
+
*/
|
|
42
|
+
equals(mat: Matrix): boolean;
|
|
43
|
+
/**
|
|
44
|
+
* Sets the matrix as an identity matrix
|
|
45
|
+
*/
|
|
46
|
+
setAsIdentity(): this;
|
|
47
|
+
/**
|
|
48
|
+
* Gets an identity matrix (1 on diagonal)
|
|
49
|
+
* @param dimension Dimension of the squared matrix
|
|
50
|
+
*/
|
|
51
|
+
static identity(dimension: number): Matrix;
|
|
52
|
+
/**
|
|
53
|
+
* Computes the product with another matrix
|
|
54
|
+
* @param mat The second operand matrix
|
|
55
|
+
* @throws Error if matrixA.columns != matrixB.rows
|
|
56
|
+
* @return A new Matrix, result of the multiplication
|
|
57
|
+
*/
|
|
58
|
+
multiply(mat: Matrix): Matrix;
|
|
59
|
+
/**
|
|
60
|
+
* Computes the product with a vector
|
|
61
|
+
* @param vec The vector to multiply with
|
|
62
|
+
* @throws Error if matrix.columns != vector.rows
|
|
63
|
+
* @return A new Vector, result of the multiplication
|
|
64
|
+
*/
|
|
65
|
+
multiplyVector(vec: Vector): Vector;
|
|
66
|
+
/**
|
|
67
|
+
* Get the position, from its matrix value
|
|
68
|
+
* @param value The value to search
|
|
69
|
+
* @return The position of the value, or -1 if not found
|
|
70
|
+
*/
|
|
71
|
+
indexOf(value: number): [number, number];
|
|
72
|
+
/**
|
|
73
|
+
* Computes the maximum value of the matrix
|
|
74
|
+
* @return The maximum value
|
|
75
|
+
*/
|
|
76
|
+
max(): number;
|
|
77
|
+
/**
|
|
78
|
+
* Computes the minimum value of the matrix
|
|
79
|
+
* @return The minimum value
|
|
80
|
+
* @throws Error if the matrix is empty
|
|
81
|
+
*/
|
|
82
|
+
min(): number;
|
|
83
|
+
/**
|
|
84
|
+
* Rounds all matrix values to the nearest integer
|
|
85
|
+
* @return A new matrix with the rounded values
|
|
86
|
+
*/
|
|
87
|
+
round(): Matrix;
|
|
88
|
+
/**
|
|
89
|
+
* Computes the determinant of the matrix
|
|
90
|
+
* @throws Error if the matrix is not squared
|
|
91
|
+
*/
|
|
92
|
+
determinant(): number;
|
|
93
|
+
/**
|
|
94
|
+
* Gets a cofactor matrix
|
|
95
|
+
* @param row The row to omit in the matrix
|
|
96
|
+
* @param col The column to omit in the matrix
|
|
97
|
+
* @return The cofactor matrix sized (r-1)x(c-1)
|
|
98
|
+
*/
|
|
99
|
+
getCofactor(row: number, col: number): Matrix;
|
|
100
|
+
/**
|
|
101
|
+
* Computes a transposed the matrix
|
|
102
|
+
* @return A new matrix sized (columns) x (rows)
|
|
103
|
+
*/
|
|
104
|
+
transpose(): Matrix;
|
|
105
|
+
/**
|
|
106
|
+
* Computes the inversed matrix
|
|
107
|
+
* @return A new matrix inversed
|
|
108
|
+
*/
|
|
109
|
+
inverse(): Matrix;
|
|
110
|
+
toString(): string;
|
|
111
|
+
}
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import Vector from './Vector';
|
|
2
|
+
export default class Matrix {
|
|
3
|
+
/** Number of rows of the matrix */
|
|
4
|
+
_rows;
|
|
5
|
+
/** Number of columns of the matrix */
|
|
6
|
+
_columns;
|
|
7
|
+
/** Values of the matrix as a two dimensional array */
|
|
8
|
+
_values;
|
|
9
|
+
constructor(rows, columns, values) {
|
|
10
|
+
this._rows = Math.max(rows, 1);
|
|
11
|
+
this._columns = Math.max(columns, 1);
|
|
12
|
+
// Create matrix filled with 0 by default
|
|
13
|
+
this._values = new Array(this._rows)
|
|
14
|
+
.fill([])
|
|
15
|
+
.map(() => new Array(this._columns).fill(0));
|
|
16
|
+
if (values) {
|
|
17
|
+
this.values = values;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
get rows() {
|
|
21
|
+
return this._rows;
|
|
22
|
+
}
|
|
23
|
+
get columns() {
|
|
24
|
+
return this._columns;
|
|
25
|
+
}
|
|
26
|
+
get values() {
|
|
27
|
+
return this._values;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Set values into the matrix.
|
|
31
|
+
* If the parameters matrix is to wide, the values are cropped to the current matrix size.
|
|
32
|
+
* It the parameters matrix is to small, remaining cells will be filled with 0.
|
|
33
|
+
* @param newValues Arrays of new values.
|
|
34
|
+
*/
|
|
35
|
+
set values(newValues) {
|
|
36
|
+
const minRow = Math.min(newValues.length, this.rows);
|
|
37
|
+
const minCol = Math.min(newValues[0].length, this.columns);
|
|
38
|
+
for (let r = 0; r < minRow; r++) {
|
|
39
|
+
for (let c = 0; c < minCol; c++) {
|
|
40
|
+
this.values[r][c] = newValues[r][c];
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get a matrix value, from its position
|
|
46
|
+
* @param row Matrix line, from 0 to `rows`
|
|
47
|
+
* @param col Matric column, from 0 to `columns`
|
|
48
|
+
*/
|
|
49
|
+
at(row, col) {
|
|
50
|
+
return this.values[row][col];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Sets all matrix values to 0
|
|
54
|
+
*/
|
|
55
|
+
reset() {
|
|
56
|
+
this.values = this.values.map((row) => row.map(() => 0));
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Add an new column to the matrix, filled with 0
|
|
60
|
+
*/
|
|
61
|
+
addAColumn() {
|
|
62
|
+
return new Matrix(this.rows, this.columns + 1, this.values);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Add an new row to the matrix, filled with 0
|
|
66
|
+
*/
|
|
67
|
+
addARow() {
|
|
68
|
+
return new Matrix(this.rows + 1, this.columns, this.values);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Check if two matrix are equals, value by value
|
|
72
|
+
* @param mat The matrix against to check equality
|
|
73
|
+
*/
|
|
74
|
+
equals(mat) {
|
|
75
|
+
// Reduce on rows -> reduce on columns -> if a value != then false!
|
|
76
|
+
return (this.rows === mat.rows &&
|
|
77
|
+
this.columns === mat.columns &&
|
|
78
|
+
this.values.reduce(
|
|
79
|
+
// Rows
|
|
80
|
+
(eql, row, i) => eql &&
|
|
81
|
+
row.reduce(
|
|
82
|
+
// Columns (real values)
|
|
83
|
+
(eql2, val, j) => eql2 && mat.at(i, j) === val, eql), true));
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Sets the matrix as an identity matrix
|
|
87
|
+
*/
|
|
88
|
+
setAsIdentity() {
|
|
89
|
+
if (this.rows !== this.columns)
|
|
90
|
+
throw new Error("Dimension error! The matrix isn't squared!");
|
|
91
|
+
this.values.forEach((row, i) => {
|
|
92
|
+
row.forEach((c, j) => {
|
|
93
|
+
this.values[i][j] = i === j ? 1 : 0;
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
return this;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Gets an identity matrix (1 on diagonal)
|
|
100
|
+
* @param dimension Dimension of the squared matrix
|
|
101
|
+
*/
|
|
102
|
+
static identity(dimension) {
|
|
103
|
+
if (dimension < 1)
|
|
104
|
+
throw Error('Dimension error! Matrix dimension must be positive.');
|
|
105
|
+
return new Matrix(dimension, dimension).setAsIdentity();
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Computes the product with another matrix
|
|
109
|
+
* @param mat The second operand matrix
|
|
110
|
+
* @throws Error if matrixA.columns != matrixB.rows
|
|
111
|
+
* @return A new Matrix, result of the multiplication
|
|
112
|
+
*/
|
|
113
|
+
multiply(mat) {
|
|
114
|
+
if (this.columns !== mat.rows)
|
|
115
|
+
throw new Error("Dimension error! The operand matrix must have the same number of rows as 'this' matrix columns!");
|
|
116
|
+
const resMatrix = new Matrix(this.rows, mat.columns);
|
|
117
|
+
resMatrix.values = resMatrix.values.map((row, i) => {
|
|
118
|
+
return row.map((val, j) => {
|
|
119
|
+
return this.values[i].reduce((sum, elm, k) => sum + elm * mat.at(k, j), 0);
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
return resMatrix;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Computes the product with a vector
|
|
126
|
+
* @param vec The vector to multiply with
|
|
127
|
+
* @throws Error if matrix.columns != vector.rows
|
|
128
|
+
* @return A new Vector, result of the multiplication
|
|
129
|
+
*/
|
|
130
|
+
multiplyVector(vec) {
|
|
131
|
+
if (this.columns !== vec.rows)
|
|
132
|
+
throw new Error('Dimension error! The vector must have the same number of elements as the matrix columns!');
|
|
133
|
+
const resultValues = this.values.map((row) => {
|
|
134
|
+
return row.reduce((sum, element, index) => sum + element * vec.at(index), 0);
|
|
135
|
+
});
|
|
136
|
+
return new Vector(resultValues);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Get the position, from its matrix value
|
|
140
|
+
* @param value The value to search
|
|
141
|
+
* @return The position of the value, or -1 if not found
|
|
142
|
+
*/
|
|
143
|
+
indexOf(value) {
|
|
144
|
+
for (let i = 0; i < this.rows; i++) {
|
|
145
|
+
for (let j = 0; j < this.columns; j++) {
|
|
146
|
+
if (this.values[i][j] === value)
|
|
147
|
+
return [i, j];
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return [-1, -1];
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Computes the maximum value of the matrix
|
|
154
|
+
* @return The maximum value
|
|
155
|
+
*/
|
|
156
|
+
max() {
|
|
157
|
+
return this.values.reduce((max, row) => Math.max(max, ...row), -Infinity);
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Computes the minimum value of the matrix
|
|
161
|
+
* @return The minimum value
|
|
162
|
+
* @throws Error if the matrix is empty
|
|
163
|
+
*/
|
|
164
|
+
min() {
|
|
165
|
+
return this.values.reduce((min, row) => Math.min(min, ...row), Infinity);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Rounds all matrix values to the nearest integer
|
|
169
|
+
* @return A new matrix with the rounded values
|
|
170
|
+
*/
|
|
171
|
+
round() {
|
|
172
|
+
return new Matrix(this.rows, this.columns, this.values.map((row) => row.map((val) => Math.round(val))));
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Computes the determinant of the matrix
|
|
176
|
+
* @throws Error if the matrix is not squared
|
|
177
|
+
*/
|
|
178
|
+
determinant() {
|
|
179
|
+
if (this.rows !== this.columns)
|
|
180
|
+
throw new Error("Dimension error! The matrix isn't squared!");
|
|
181
|
+
if (this.rows === this.columns && this.columns === 1) {
|
|
182
|
+
return this.values[0][0];
|
|
183
|
+
}
|
|
184
|
+
let det = 0;
|
|
185
|
+
let sign = 1;
|
|
186
|
+
if (this.rows === 2) {
|
|
187
|
+
det =
|
|
188
|
+
this.values[0][0] * this.values[1][1] -
|
|
189
|
+
this.values[1][0] * this.values[0][1];
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
for (let i = 0; i < this.rows; i++) {
|
|
193
|
+
const minor = this.getCofactor(0, i);
|
|
194
|
+
det += sign * this.at(0, i) * minor.determinant();
|
|
195
|
+
sign = -sign;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return det;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Gets a cofactor matrix
|
|
202
|
+
* @param row The row to omit in the matrix
|
|
203
|
+
* @param col The column to omit in the matrix
|
|
204
|
+
* @return The cofactor matrix sized (r-1)x(c-1)
|
|
205
|
+
*/
|
|
206
|
+
getCofactor(row, col) {
|
|
207
|
+
return new Matrix(this.rows - 1, this.columns - 1, this.values
|
|
208
|
+
.filter((v, i) => i !== row) // Remove the unnecessary row
|
|
209
|
+
.map((c) => c.filter((v, i) => i !== col)));
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Computes a transposed the matrix
|
|
213
|
+
* @return A new matrix sized (columns) x (rows)
|
|
214
|
+
*/
|
|
215
|
+
transpose() {
|
|
216
|
+
return new Matrix(this.columns, this.rows, new Array(this.columns)
|
|
217
|
+
.fill([])
|
|
218
|
+
.map((row, i) => new Array(this.rows).fill(0).map((c, j) => this.at(j, i))));
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Computes the inversed matrix
|
|
222
|
+
* @return A new matrix inversed
|
|
223
|
+
*/
|
|
224
|
+
inverse() {
|
|
225
|
+
if (this.rows !== this.columns)
|
|
226
|
+
throw new Error("Dimension error! The matrix isn't squared!");
|
|
227
|
+
const det = this.determinant();
|
|
228
|
+
if (det === 0)
|
|
229
|
+
throw new Error("Determinant is 0, can't compute inverse.");
|
|
230
|
+
// Get cofactor matrix: i.e. for each matrix value, get the cofactor's determinant
|
|
231
|
+
const cofactorMatrix = new Matrix(this.rows, this.columns, this.values.map((row, i) => row.map((val, j) => {
|
|
232
|
+
const sign = Math.pow(-1, i + j);
|
|
233
|
+
return sign * this.getCofactor(i, j).determinant();
|
|
234
|
+
})));
|
|
235
|
+
// Transpose it
|
|
236
|
+
const transposedCofactor = cofactorMatrix.transpose();
|
|
237
|
+
// Compute inverse of transposed / determinant on each value
|
|
238
|
+
return new Matrix(this.rows, this.columns, this.values.map((row, i) => row.map((val, j) => transposedCofactor.at(i, j) / det)));
|
|
239
|
+
}
|
|
240
|
+
toString() {
|
|
241
|
+
return `[${this.values.map((row) => `[${row.join(', ')}]`).join(',\n')}]`;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import type Vector from './Vector';
|
|
2
|
+
/**
|
|
3
|
+
* Class representing a Quaternion for 3D rotations
|
|
4
|
+
*/
|
|
5
|
+
export default class Quat {
|
|
6
|
+
/** Values of the quaternion as [x, y, z, w] */
|
|
7
|
+
private _values;
|
|
8
|
+
constructor(values?: [number, number, number, number]);
|
|
9
|
+
get values(): number[];
|
|
10
|
+
/**
|
|
11
|
+
* Set values into the quaternion.
|
|
12
|
+
* @param newValues Array of new values [x, y, z, w].
|
|
13
|
+
*/
|
|
14
|
+
set values(newValues: number[]);
|
|
15
|
+
get x(): number;
|
|
16
|
+
set x(value: number);
|
|
17
|
+
get y(): number;
|
|
18
|
+
set y(value: number);
|
|
19
|
+
get z(): number;
|
|
20
|
+
set z(value: number);
|
|
21
|
+
get w(): number;
|
|
22
|
+
set w(value: number);
|
|
23
|
+
get xy(): [number, number];
|
|
24
|
+
set xy(values: [number, number]);
|
|
25
|
+
get xyz(): [number, number, number];
|
|
26
|
+
set xyz(values: [number, number, number]);
|
|
27
|
+
get xyzw(): [number, number, number, number];
|
|
28
|
+
set xyzw(values: [number, number, number, number]);
|
|
29
|
+
/**
|
|
30
|
+
* Get an identity quaternion (rotation by 0 degrees)
|
|
31
|
+
* @return A new identity quaternion
|
|
32
|
+
*/
|
|
33
|
+
static identity(): Quat;
|
|
34
|
+
/**
|
|
35
|
+
* Get a quaternion value at a specific index
|
|
36
|
+
* @param index Index from 0 to 3
|
|
37
|
+
* @return The value at the specified index
|
|
38
|
+
*/
|
|
39
|
+
at(index: number): number;
|
|
40
|
+
/**
|
|
41
|
+
* Reset all quaternion values to 0
|
|
42
|
+
*/
|
|
43
|
+
reset(): void;
|
|
44
|
+
/**
|
|
45
|
+
* Copy the quaternion to another quaternion
|
|
46
|
+
* @param dest Destination quaternion (optional)
|
|
47
|
+
* @return The destination quaternion
|
|
48
|
+
*/
|
|
49
|
+
copy(dest?: Quat): Quat;
|
|
50
|
+
/**
|
|
51
|
+
* Calculate the roll angle (rotation around x-axis)
|
|
52
|
+
* @return Roll angle in radians
|
|
53
|
+
*/
|
|
54
|
+
roll(): number;
|
|
55
|
+
/**
|
|
56
|
+
* Calculate the pitch angle (rotation around y-axis)
|
|
57
|
+
* @return Pitch angle in radians
|
|
58
|
+
*/
|
|
59
|
+
pitch(): number;
|
|
60
|
+
/**
|
|
61
|
+
* Calculate the yaw angle (rotation around z-axis)
|
|
62
|
+
* @return Yaw angle in radians
|
|
63
|
+
*/
|
|
64
|
+
yaw(): number;
|
|
65
|
+
/**
|
|
66
|
+
* Check if two quaternions are equal within a threshold
|
|
67
|
+
* @param quat The quaternion to compare against
|
|
68
|
+
* @param threshold The threshold for comparison (default: EPSILON)
|
|
69
|
+
* @return True if quaternions are equal within threshold
|
|
70
|
+
*/
|
|
71
|
+
equals(quat: Quat, threshold?: number): boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Set the quaternion as an identity quaternion
|
|
74
|
+
* @return This quaternion for method chaining
|
|
75
|
+
*/
|
|
76
|
+
setIdentity(): Quat;
|
|
77
|
+
/**
|
|
78
|
+
* Calculate the w component based on x, y, z components
|
|
79
|
+
* @return This quaternion for method chaining
|
|
80
|
+
*/
|
|
81
|
+
calculateW(): Quat;
|
|
82
|
+
/**
|
|
83
|
+
* Compute the inverse of the quaternion
|
|
84
|
+
* @return This quaternion for method chaining
|
|
85
|
+
*/
|
|
86
|
+
inverse(): Quat;
|
|
87
|
+
/**
|
|
88
|
+
* Compute the conjugate of the quaternion
|
|
89
|
+
* @return This quaternion for method chaining
|
|
90
|
+
*/
|
|
91
|
+
conjugate(): Quat;
|
|
92
|
+
/**
|
|
93
|
+
* Calculate the length (magnitude) of the quaternion
|
|
94
|
+
* @return The length of the quaternion
|
|
95
|
+
*/
|
|
96
|
+
length(): number;
|
|
97
|
+
/**
|
|
98
|
+
* Normalize the quaternion to unit length
|
|
99
|
+
* @param dest Destination quaternion (optional)
|
|
100
|
+
* @return The normalized quaternion
|
|
101
|
+
*/
|
|
102
|
+
normalize(dest?: Quat): Quat;
|
|
103
|
+
/**
|
|
104
|
+
* Add another quaternion to this quaternion
|
|
105
|
+
* @param other The quaternion to add
|
|
106
|
+
* @return This quaternion for method chaining
|
|
107
|
+
*/
|
|
108
|
+
add(other: Quat): Quat;
|
|
109
|
+
/**
|
|
110
|
+
* Multiply this quaternion by another quaternion
|
|
111
|
+
* @param other The quaternion to multiply with
|
|
112
|
+
* @return This quaternion for method chaining
|
|
113
|
+
*/
|
|
114
|
+
multiply(other: Quat): Quat;
|
|
115
|
+
/**
|
|
116
|
+
* Calculate the dot product of two quaternions
|
|
117
|
+
* @param q1 First quaternion
|
|
118
|
+
* @param q2 Second quaternion
|
|
119
|
+
* @return The dot product
|
|
120
|
+
*/
|
|
121
|
+
static dot(q1: Quat, q2: Quat): number;
|
|
122
|
+
/**
|
|
123
|
+
* Calculate the sum of two quaternions
|
|
124
|
+
* @param q1 First quaternion
|
|
125
|
+
* @param q2 Second quaternion
|
|
126
|
+
* @return A new quaternion with the sum
|
|
127
|
+
*/
|
|
128
|
+
static sum(q1: Quat, q2: Quat): Quat;
|
|
129
|
+
/**
|
|
130
|
+
* Calculate the product of two quaternions
|
|
131
|
+
* @param q1 First quaternion
|
|
132
|
+
* @param q2 Second quaternion
|
|
133
|
+
* @return A new quaternion with the product
|
|
134
|
+
*/
|
|
135
|
+
static product(q1: Quat, q2: Quat): Quat;
|
|
136
|
+
/**
|
|
137
|
+
* Calculate the cross product of two quaternions
|
|
138
|
+
* @param q1 First quaternion
|
|
139
|
+
* @param q2 Second quaternion
|
|
140
|
+
* @return A new quaternion with the cross product
|
|
141
|
+
*/
|
|
142
|
+
static cross(q1: Quat, q2: Quat): Quat;
|
|
143
|
+
/**
|
|
144
|
+
* Spherical linear interpolation between two quaternions with short path
|
|
145
|
+
* @param q1 First quaternion
|
|
146
|
+
* @param q2 Second quaternion
|
|
147
|
+
* @param time Interpolation parameter (0 to 1)
|
|
148
|
+
* @return A new interpolated quaternion
|
|
149
|
+
*/
|
|
150
|
+
static shortMix(q1: Quat, q2: Quat, time: number): Quat;
|
|
151
|
+
/**
|
|
152
|
+
* Spherical linear interpolation between two quaternions
|
|
153
|
+
* @param q1 First quaternion
|
|
154
|
+
* @param q2 Second quaternion
|
|
155
|
+
* @param time Interpolation parameter (0 to 1)
|
|
156
|
+
* @return A new interpolated quaternion
|
|
157
|
+
*/
|
|
158
|
+
static mix(q1: Quat, q2: Quat, time: number): Quat;
|
|
159
|
+
/**
|
|
160
|
+
* Create a quaternion from an axis and angle
|
|
161
|
+
* @param axis The rotation axis as a 3D vector
|
|
162
|
+
* @param angle The rotation angle in radians
|
|
163
|
+
* @return A new quaternion representing the rotation
|
|
164
|
+
* @throws Error if the axis vector is not 3D
|
|
165
|
+
*/
|
|
166
|
+
static fromAxisAngle(axis: Vector, angle: number): Quat;
|
|
167
|
+
toString(): string;
|
|
168
|
+
}
|