summaryrefslogtreecommitdiff
path: root/web/src/math/Rect.ts
blob: f52a2f7b7cabcec7bee7516505f038bff3d7ed18 (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
100
101
102
103
104
import Coord from "./Coord";

/** A rectangle on a grid whose origin is in the top left. */
export default class Rect {
  private readonly _topLeft: Coord;
  private readonly _width: number;
  private readonly _height: number;

  constructor(
    topLeftX: number,
    topLeftY: number,
    width: number,
    height: number,
  ) {
    this._topLeft = new Coord(topLeftX, topLeftY);
    this._width = width;
    this._height = height;
  }

  /** Width of this rectangle. */
  get width(): number {
    return this._width;
  }

  /** Height of this rectangle. */
  get height(): number {
    return this._height;
  }

  /** Coord of the top-left point of this rectangle. */
  get topLeft(): Coord {
    return this._topLeft;
  }

  /** Coord of the bottom-right point of this rectangle. */
  get bottomRight(): Coord {
    return new Coord(
      this._topLeft.x + this._width,
      this._topLeft.y + this._height,
    );
  }

  get center(): Coord {
    return new Coord(
      this.topLeft.x + (this.bottomRight.x - this.topLeft.x) / 2,
      this.topLeft.y + (this.bottomRight.y - this.topLeft.y) / 2,
    );
  }

  /** Determine if this rectangle contains the point at `coord`. */
  containsCoord(coord: Coord): boolean {
    return (
      this.topLeft.x <= coord.x &&
      coord.x <= this.bottomRight.x &&
      this.topLeft.y <= coord.y &&
      coord.y <= this.bottomRight.y
    );
  }

  verticallyContainsCoord(coord: Coord): boolean {
    return this.topLeft.y <= coord.y && coord.y <= this.bottomRight.y;
  }

  horizontallyContainsCoord(coord: Coord): boolean {
    return this.topLeft.x <= coord.x && coord.x <= this.bottomRight.x;
  }

  extend(other: Rect): Rect {
    const topLeftX = Math.min(
      this.topLeft.x,
      this.bottomRight.x,
      other.topLeft.x,
      other.bottomRight.x,
    );

    const topLeftY = Math.min(
      this.topLeft.y,
      this.bottomRight.y,
      other.topLeft.y,
      other.bottomRight.y,
    );

    const bottomRightX = Math.max(
      this.topLeft.x,
      this.bottomRight.x,
      other.topLeft.x,
      other.bottomRight.x,
    );

    const bottomRightY = Math.max(
      this.topLeft.y,
      this.bottomRight.y,
      other.topLeft.y,
      other.bottomRight.y,
    );

    return new Rect(
      topLeftX,
      topLeftY,
      bottomRightX - topLeftX,
      bottomRightY - topLeftY,
    );
  }
}