Release package version 0.0.5
All checks were successful
CI / build (push) Successful in 28s

Update matrix 2d
This commit is contained in:
Andrey Kernichniy 2026-03-21 23:33:19 +07:00
parent 8c0e798bc7
commit b38fb6e7eb
4 changed files with 76 additions and 51 deletions

2
.gitignore vendored
View file

@ -30,4 +30,4 @@ yarn-error.log
.DS_Store .DS_Store
Thumbs.db Thumbs.db
playground/gxc-canvas-viewer/**/*.* playground/*/**/*.*

View file

@ -1,78 +1,103 @@
import { IPoint } from "../interfaces"; import { IPoint } from "../interfaces";
import { Point } from "./point"; 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 = [ const DEF_MATRIX: Matrix = [1, 0, 0, 0, 1, 0, 0, 0, 1];
[1, 0, 0],
[0, 1, 0],
[0, 0, 1],
];
export class Matrix2D { export class Matrix2D {
private _matrix: Matrix; 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) { constructor(matrix?: Matrix) {
this._matrix = matrix ?? DEF_MATRIX; this._matrix = matrix ?? DEF_MATRIX;
} }
clone(): Matrix2D { clone(): Matrix2D {
return new Matrix2D(this.getData()); return new Matrix2D([...this.getData()]);
} }
multiply(matrix: Matrix2D): Matrix2D { multiply(matrix: Matrix2D): Matrix2D {
const m = structuredClone(DEF_MATRIX); const a = this._matrix;
for (let i = 0; i < 3; i++) { const b = matrix.getData();
for (let j = 0; j < 3; j++) {
m[i][j] = 0; const m = DEF_MATRIX.slice() as Matrix;
for (let k = 0; k < 3; k++) {
m[i][j] += this._matrix[i][k] * matrix._matrix[k][j]; 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); return new Matrix2D(m);
} }
translate(x: number, y: number): Matrix2D { translate(x: number, y: number): Matrix2D {
const translationMatrix = new Matrix2D([ const translationMatrix = new Matrix2D([1, 0, x, 0, 1, y, 0, 0, 1]);
[1, 0, x],
[0, 1, y],
[0, 0, 1],
]);
return this.multiply(translationMatrix); return this.multiply(translationMatrix);
} }
rotate(angle: number): Matrix2D { rotate(angle: number): Matrix2D {
const cos = Math.cos(angle); const cos = Math.cos(angle);
const sin = Math.sin(angle); const sin = Math.sin(angle);
const rotationMatrix = new Matrix2D([ const rotationMatrix = new Matrix2D([cos, -sin, 0, sin, cos, 0, 0, 0, 1]);
[cos, -sin, 0],
[sin, cos, 0],
[0, 0, 1],
]);
return this.multiply(rotationMatrix); return this.multiply(rotationMatrix);
} }
scale(sx: number, sy: number): Matrix2D { scale(sx: number, sy: number): Matrix2D {
const scaleMatrix = new Matrix2D([ const scaleMatrix = new Matrix2D([sx, 0, 0, 0, sy, 0, 0, 0, 1]);
[sx, 0, 0],
[0, sy, 0],
[0, 0, 1],
]);
return this.multiply(scaleMatrix); return this.multiply(scaleMatrix);
} }
transformPoint(point: IPoint): Point { transformPoint(point: IPoint): Point {
const x = point.x; const x = point.x;
const y = point.y; const y = point.y;
const w = this._matrix[2][0] * x + this._matrix[2][1] * y + this._matrix[2][2]; const w = this.m20 * x + this.m21 * y + this.m22;
return new Point( return new Point((this.m00 * x + this.m01 * y + this.m02) / w, (this.m10 * x + this.m11 * y + this.m12) / w);
(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,
);
} }
getData(): Matrix { getData(): Matrix {
return structuredClone(this._matrix); return this._matrix;
} }
} }

View file

@ -31,20 +31,20 @@ export class Transform {
} }
static fromMatrix2D(matrix: Matrix2D): Transform { static fromMatrix2D(matrix: Matrix2D): Transform {
const m = matrix.getData(); const scaleX = Math.sqrt(matrix.m00 * matrix.m00 + matrix.m01 * matrix.m01);
const transform = new Transform(); const scaleY = Math.sqrt(matrix.m10 * matrix.m10 + matrix.m11 * matrix.m11);
// Извлечение масштаба const rotate = radToDeg(Math.atan2(matrix.m01, matrix.m00));
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 translateX = matrix.m02;
transform.rotate = radToDeg(Math.atan2(m[0][1], m[0][0])); const translateY = matrix.m12;
// Извлечение сдвига return new Transform({
transform.translateX = m[0][2]; scaleX,
transform.translateY = m[1][2]; scaleY,
rotate,
return transform; translateX,
translateY,
});
} }
} }

View file

@ -1,6 +1,6 @@
{ {
"name": "@gxc-solutions/math", "name": "@gxc-solutions/math",
"version": "0.0.4", "version": "0.0.5",
"main": "index.js", "main": "index.js",
"author": "GXC Solutions", "author": "GXC Solutions",
"publishConfig": { "publishConfig": {