aboutsummaryrefslogtreecommitdiff
path: root/src/client/util/Transform.ts
blob: e9170ec365acf708990b8c98b03067c610324782 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
export class Transform {
    private _translateX: number = 0;
    private _translateY: number = 0;
    private _scale: number = 1;

    static Identity(): Transform {
        return new Transform(0, 0, 1);
    }

    get TranslateX(): number { return this._translateX; }
    get TranslateY(): number { return this._translateY; }
    get Scale(): number { return this._scale; }

    constructor(x: number, y: number, scale: number) {
        this._translateX = x;
        this._translateY = y;
        this._scale = scale;
    }

    translate = (x: number, y: number): this => {
        this._translateX += x;
        this._translateY += y;
        return this;
    }

    scale = (scale: number): this => {
        this._scale *= scale;
        this._translateX *= scale;
        this._translateY *= scale;
        return this;
    }

    scaleAbout = (scale: number, x: number, y: number): this => {
        this._translateX += x * this._scale - x * this._scale * scale;
        this._translateY += y * this._scale - y * this._scale * scale;
        this._scale *= scale;
        return this;
    }

    transform = (transform: Transform): this => {
        this._translateX = transform._translateX + transform._scale * this._translateX;
        this._translateY = transform._translateY + transform._scale * this._translateY;
        this._scale *= transform._scale;
        return this;
    }

    preTranslate = (x: number, y: number): this => {
        this._translateX += this._scale * x;
        this._translateY += this._scale * y;
        return this;
    }

    preScale = (scale: number): this => {
        this._scale *= scale;
        return this;
    }

    preTransform = (transform: Transform): this => {
        this._translateX += transform._translateX * this._scale;
        this._translateY += transform._translateY * this._scale;
        this._scale *= transform._scale;
        return this;
    }

    translated = (x: number, y: number): Transform => this.copy().translate(x, y);

    preTranslated = (x: number, y: number): Transform => this.copy().preTranslate(x, y);

    scaled = (scale: number): Transform => this.copy().scale(scale);

    scaledAbout = (scale: number, x: number, y: number): Transform => this.copy().scaleAbout(scale, x, y);

    preScaled = (scale: number): Transform => this.copy().preScale(scale);

    transformed = (transform: Transform): Transform => this.copy().transform(transform);

    preTransformed = (transform: Transform): Transform => this.copy().preTransform(transform);

    transformPoint = (x: number, y: number): [number, number] => {
        x *= this._scale;
        x += this._translateX;
        y *= this._scale;
        y += this._translateY;
        return [x, y];
    }

    transformDirection = (x: number, y: number): [number, number] => [x * this._scale, y * this._scale];

    transformBounds(x: number, y: number, width: number, height: number): { x: number, y: number, width: number, height: number } {
        [x, y] = this.transformPoint(x, y);
        [width, height] = this.transformDirection(width, height);
        return { x, y, width, height };
    }

    inverse = () => new Transform(-this._translateX / this._scale, -this._translateY / this._scale, 1 / this._scale);

    copy = () => new Transform(this._translateX, this._translateY, this._scale);

}