diff --git a/.gitignore b/.gitignore index 3503468..d94f532 100644 --- a/.gitignore +++ b/.gitignore @@ -30,4 +30,4 @@ yarn-error.log .DS_Store Thumbs.db -playground/gxc-canvas-viewer/**/*.* \ No newline at end of file +playground/*/**/*.* \ No newline at end of file diff --git a/lib/src/models/matrix-2d.ts b/lib/src/models/matrix-2d.ts index ef8f701..7ba3693 100644 --- a/lib/src/models/matrix-2d.ts +++ b/lib/src/models/matrix-2d.ts @@ -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; } } diff --git a/lib/src/models/transform.ts b/lib/src/models/transform.ts index 01755b8..f3b7808 100644 --- a/lib/src/models/transform.ts +++ b/lib/src/models/transform.ts @@ -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, + }); } } diff --git a/lib/src/package.json b/lib/src/package.json index 7ec9cfb..6249516 100644 --- a/lib/src/package.json +++ b/lib/src/package.json @@ -1,6 +1,6 @@ { "name": "@gxc-solutions/math", - "version": "0.0.4", + "version": "0.0.5", "main": "index.js", "author": "GXC Solutions", "publishConfig": {