Source: boxes/aabb.js

boxes/aabb.js

import Range from '../common/range'
import Point from '../common/point'
import Base from './base'
import OBB from './obb'
import Sphere from './sphere'

/**
 * Axis-aligned bounding box class.
 *
 */
class AABB extends Base {
  get x () { return this._x }
  set x (value) {
    if (this._x !== value) {
      this._x = value
      this._create()
    }
  }

  get y () { return this._y }
  set y (value) {
    if (this._y !== value) {
      this._y = value
      this._create()
    }
  }

  get width () { return this._width }
  set width (value) {
    if (this._width !== value) {
      this._width = value
      this._create()
    }
  }

  get height () { return this._height }
  set height (value) {
    if (this._height !== value) {
      this._height = value
      this._create()
    }
  }

  /**
   * The overall width range of this aabb.
   * @return {Range}
   */
  get widthRange () { return this._widthRange }

  /**
   * The overall height range of this aabb.
   * @return {Range}
   */
  get heightRange () { return this._heightRange }

  /**
   * The center point of this aabb.
   * @return {Point}
   */
  get center () { return this._center }

  /**
   * Returns an axis-aligned bounding box object.
   * @param {Number} [x=0] - The X coordinate of the upper-left corner of the aabb.
   * @param {Number} [y=0] - The Y coordinate of the upper-left corner of the aabb.
   * @param {Number} [width=0] - The width of this aabb.
   * @param {Number} [height=0] - The height of this aabb.
   */
  constructor (x = 0, y = 0, width = 0, height = 0) {
    super()
    this._x = x
    this._y = y
    this._width = width
    this._height = height
    this._create()
  }

  _create () {
    this._widthRange = new Range(this.x, this.x + this.width)
    this._heightRange = new Range(this.y, this.y + this.height)
    this._center = new Point(this.x + this.width / 2, this.y + this.height / 2)
  }

  /**
   * Get an array of point objects that span the four vertices of this aabb.
   *
   * @return {Array<Point>}
   */
  points () {
    return [
      new Point(this.x, this.y),
      new Point(this.x + this.width, this.y),
      new Point(this.x, this.y + this.height),
      new Point(this.x + this.width, this.y + this.height)
    ]
  }

  /**
   * Checks whether the point object given are contained within this aabb.
   *
   * @param {Point} point - The point object of test.
   */
  pointCollision (point) {
    return this.widthRange.hit(point.x) && this.heightRange.hit(point.y)
  }

  /**
   * Checks whether the aabb object given are contained within this aabb.
   *
   * @param {AABB} aabb - The aabb object of test
   */
  aabbCollision (aabb) {
    let wRangeCollision = this.widthRange.collision(aabb.widthRange)
    let hRangeCollision = this.heightRange.collision(aabb.heightRange)
    return wRangeCollision && hRangeCollision
  }

  /**
   * Checks whether the obb object given are contained within this aabb.
   *
   * @param {OBB} obb - The obb object of test
   */
  obbCollision (obb) {
    return obb.obbCollision(this.aabb2obb)
  }

  /**
   * Checks whether the sphere object given are contained within this aabb.
   *
   * @param {Sphere} sphere - The sphere object of test
   */
  sphereCollision (sphere) {
    return sphere.aabbCollision(this)
  }

  /**
   * Transforms this object into a new OBB object and returns.
   *
   * @return {OBB}
   */
  aabb2obb () {
    return new OBB(this.center.x, this.center.y, this.width, this.height, 0)
  }

  /**
   * Transforms this object into a new Sphere object and returns.
   *
   * @return {Sphere}
   */
  aabb2sphere () {
    let radius = this.width > this.height ? this.width : this.height
    return new Sphere(this.center.x, this.center.y, radius)
  }
}

export default AABB