Source: AABB.js

import { Vector } from "./Vector.js";
import { Line } from "./Line.js";

/** Class representing an Axis-Aligned Bounding Box. */
export class AABB {
  /**
   * Create an AABB using centre position, width, and height.
   * @param {number} x - The x value of the centre.
   * @param {number} y - The y value of the centre.
   * @param {number} width - The width measured from the centre.
   * @param {number} height - The height measured from the centre.
   */
  constructor(x, y, width, height) {
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
  }

  /**
   * Create an AABB from four corner [Vectors]{@link Vector}.
   * @param {Vector} topLeft
   * @param {Vector} topRight
   * @param {Vector} bottomRight
   * @param {Vector} bottomLeft
   * @returns {AABB} - A new AABB object.
   */
  static fromCorners(topLeft, topRight, bottomRight, bottomLeft) {
    const centre = new Vector(topRight.x - topLeft.x, bottomLeft.y - topLeft.y);

    const width = topRight.x - centre.x;
    const height = bottomRight.y - centre.y;

    return new AABB(centre.x, centre.y, width, height);
  }

  /**
   * Check if this AABB contains a {@link Vector}.
   * @param {Vector} point - The vector to check.
   * @returns {boolean}
   */
  contains(point) {
    return (
      point.x > this.x - this.width &&
      point.x < this.x + this.width &&
      point.y > this.y - this.height &&
      point.y < this.y + this.height
    );
  }

  /**
   * Check if this AABB intersects another AABB.
   * @param {AABB} range - The target AABB to check.
   * @returns {boolean}
   */
  intersects(range) {
    return !(
      range.x - range.width > this.x + this.width ||
      range.x + range.width < this.x - this.width ||
      range.y - range.height > this.y + this.height ||
      range.y + range.height < this.y - this.height
    );
  }

  /**
   * Create an array of [Lines]{@link Line} containing one line for each side of the AABB.
	 * @param {string} [options.stroke]
	 * @param {number} [options.strokeWidth]
   * @returns {Line[]} - An array of Lines that can be added
   * to a {@link Plot} using {@link Plot#add}.
   */
  lines(options = {}) {
    const topLeft = new Vector(this.x - this.width, this.y - this.height);
    const topRight = new Vector(this.x + this.width, this.y - this.height);
    const bottomLeft = new Vector(this.x - this.width, this.y + this.height);
    const bottomRight = new Vector(this.x + this.width, this.y + this.height);

    let lines = [];

    lines.push(
      new Line(topLeft, topRight, options),
      new Line(topRight, bottomRight, options),
      new Line(bottomRight, bottomLeft, options),
      new Line(bottomLeft, topLeft, options),
    );

    return lines;
  }
}