generated from gxc-solutions/gxc-template-repo
Update matrix 2d
This commit is contained in:
parent
8c0e798bc7
commit
b38fb6e7eb
4 changed files with 76 additions and 51 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -30,4 +30,4 @@ yarn-error.log
|
|||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
playground/gxc-canvas-viewer/**/*.*
|
||||
playground/*/**/*.*
|
||||
|
|
@ -1,78 +1,103 @@
|
|||
import { IPoint } from "../interfaces";
|
||||
import { Point } from "./point";
|
||||
|
||||
export type Matrix = [[number, number, number], [number, number, number], [number, number, number]];
|
||||
export type Matrix = [number, number, number, number, number, number, number, number, number];
|
||||
|
||||
const DEF_MATRIX: Matrix = [
|
||||
[1, 0, 0],
|
||||
[0, 1, 0],
|
||||
[0, 0, 1],
|
||||
];
|
||||
const DEF_MATRIX: Matrix = [1, 0, 0, 0, 1, 0, 0, 0, 1];
|
||||
|
||||
export class Matrix2D {
|
||||
private _matrix: Matrix;
|
||||
|
||||
get m00() {
|
||||
return this._matrix[0];
|
||||
}
|
||||
|
||||
get m01() {
|
||||
return this._matrix[1];
|
||||
}
|
||||
|
||||
get m02() {
|
||||
return this._matrix[2];
|
||||
}
|
||||
|
||||
get m10() {
|
||||
return this._matrix[3];
|
||||
}
|
||||
|
||||
get m11() {
|
||||
return this._matrix[4];
|
||||
}
|
||||
|
||||
get m12() {
|
||||
return this._matrix[5];
|
||||
}
|
||||
|
||||
get m20() {
|
||||
return this._matrix[6];
|
||||
}
|
||||
|
||||
get m21() {
|
||||
return this._matrix[7];
|
||||
}
|
||||
|
||||
get m22() {
|
||||
return this._matrix[8];
|
||||
}
|
||||
|
||||
constructor(matrix?: Matrix) {
|
||||
this._matrix = matrix ?? DEF_MATRIX;
|
||||
}
|
||||
|
||||
clone(): Matrix2D {
|
||||
return new Matrix2D(this.getData());
|
||||
return new Matrix2D([...this.getData()]);
|
||||
}
|
||||
|
||||
multiply(matrix: Matrix2D): Matrix2D {
|
||||
const m = structuredClone(DEF_MATRIX);
|
||||
for (let i = 0; i < 3; i++) {
|
||||
for (let j = 0; j < 3; j++) {
|
||||
m[i][j] = 0;
|
||||
for (let k = 0; k < 3; k++) {
|
||||
m[i][j] += this._matrix[i][k] * matrix._matrix[k][j];
|
||||
}
|
||||
}
|
||||
}
|
||||
const a = this._matrix;
|
||||
const b = matrix.getData();
|
||||
|
||||
const m = DEF_MATRIX.slice() as Matrix;
|
||||
|
||||
m[0] = a[0] * b[0] + a[1] * b[3] + a[2] * b[6];
|
||||
m[1] = a[0] * b[1] + a[1] * b[4] + a[2] * b[7];
|
||||
m[2] = a[0] * b[2] + a[1] * b[5] + a[2] * b[8];
|
||||
|
||||
m[3] = a[3] * b[0] + a[4] * b[3] + a[5] * b[6];
|
||||
m[4] = a[3] * b[1] + a[4] * b[4] + a[5] * b[7];
|
||||
m[5] = a[3] * b[2] + a[4] * b[5] + a[5] * b[8];
|
||||
|
||||
m[6] = a[6] * b[0] + a[7] * b[3] + a[8] * b[6];
|
||||
m[7] = a[6] * b[1] + a[7] * b[4] + a[8] * b[7];
|
||||
m[8] = a[6] * b[2] + a[7] * b[5] + a[8] * b[8];
|
||||
|
||||
return new Matrix2D(m);
|
||||
}
|
||||
|
||||
translate(x: number, y: number): Matrix2D {
|
||||
const translationMatrix = new Matrix2D([
|
||||
[1, 0, x],
|
||||
[0, 1, y],
|
||||
[0, 0, 1],
|
||||
]);
|
||||
const translationMatrix = new Matrix2D([1, 0, x, 0, 1, y, 0, 0, 1]);
|
||||
return this.multiply(translationMatrix);
|
||||
}
|
||||
|
||||
rotate(angle: number): Matrix2D {
|
||||
const cos = Math.cos(angle);
|
||||
const sin = Math.sin(angle);
|
||||
const rotationMatrix = new Matrix2D([
|
||||
[cos, -sin, 0],
|
||||
[sin, cos, 0],
|
||||
[0, 0, 1],
|
||||
]);
|
||||
const rotationMatrix = new Matrix2D([cos, -sin, 0, sin, cos, 0, 0, 0, 1]);
|
||||
return this.multiply(rotationMatrix);
|
||||
}
|
||||
|
||||
scale(sx: number, sy: number): Matrix2D {
|
||||
const scaleMatrix = new Matrix2D([
|
||||
[sx, 0, 0],
|
||||
[0, sy, 0],
|
||||
[0, 0, 1],
|
||||
]);
|
||||
const scaleMatrix = new Matrix2D([sx, 0, 0, 0, sy, 0, 0, 0, 1]);
|
||||
return this.multiply(scaleMatrix);
|
||||
}
|
||||
|
||||
transformPoint(point: IPoint): Point {
|
||||
const x = point.x;
|
||||
const y = point.y;
|
||||
const w = this._matrix[2][0] * x + this._matrix[2][1] * y + this._matrix[2][2];
|
||||
return new Point(
|
||||
(this._matrix[0][0] * x + this._matrix[0][1] * y + this._matrix[0][2]) / w,
|
||||
(this._matrix[1][0] * x + this._matrix[1][1] * y + this._matrix[1][2]) / w,
|
||||
);
|
||||
const w = this.m20 * x + this.m21 * y + this.m22;
|
||||
return new Point((this.m00 * x + this.m01 * y + this.m02) / w, (this.m10 * x + this.m11 * y + this.m12) / w);
|
||||
}
|
||||
|
||||
getData(): Matrix {
|
||||
return structuredClone(this._matrix);
|
||||
return this._matrix;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,20 +31,20 @@ export class Transform {
|
|||
}
|
||||
|
||||
static fromMatrix2D(matrix: Matrix2D): Transform {
|
||||
const m = matrix.getData();
|
||||
const transform = new Transform();
|
||||
const scaleX = Math.sqrt(matrix.m00 * matrix.m00 + matrix.m01 * matrix.m01);
|
||||
const scaleY = Math.sqrt(matrix.m10 * matrix.m10 + matrix.m11 * matrix.m11);
|
||||
|
||||
// Извлечение масштаба
|
||||
transform.scaleX = Math.sqrt(m[0][0] * m[0][0] + m[0][1] * m[0][1]);
|
||||
transform.scaleY = Math.sqrt(m[1][0] * m[1][0] + m[1][1] * m[1][1]);
|
||||
const rotate = radToDeg(Math.atan2(matrix.m01, matrix.m00));
|
||||
|
||||
// Извлечение поворота
|
||||
transform.rotate = radToDeg(Math.atan2(m[0][1], m[0][0]));
|
||||
const translateX = matrix.m02;
|
||||
const translateY = matrix.m12;
|
||||
|
||||
// Извлечение сдвига
|
||||
transform.translateX = m[0][2];
|
||||
transform.translateY = m[1][2];
|
||||
|
||||
return transform;
|
||||
return new Transform({
|
||||
scaleX,
|
||||
scaleY,
|
||||
rotate,
|
||||
translateX,
|
||||
translateY,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@gxc-solutions/math",
|
||||
"version": "0.0.4",
|
||||
"version": "0.0.5",
|
||||
"main": "index.js",
|
||||
"author": "GXC Solutions",
|
||||
"publishConfig": {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue