import Range from '../common/range'
import Point from '../common/point'
import Vector2 from '../common/vector2'
import Base from './base'
import AABB from './aabb'
import OBB from './obb'
/**
* Sphere box class.
*
*/
class Sphere extends Base {
get x () { return this._x }
set x (value) {
this._x = value
this._create()
}
get y () { return this._y }
set y (value) {
this._y = value
this._create()
}
get radius () { return this._radius }
set radius (value) {
this._radius = value
this._create()
}
/**
* The overall width range of this obb.
* @return {Range}
*/
get widthRange () { return this._widthRange }
/**
* The overall height range of this obb.
* @return {Range}
*/
get heightRange () { return this._heightRange }
/**
* Returns an sphere box object.
* @param {Number} [x=0] - The X coordinate of the upper-left corner of the sphere.
* @param {Number} [y=0] - The Y coordinate of the upper-left corner of the sphere.
* @param {Number} [radius=0] - The width of this obb.
*/
constructor (x = 0, y = 0, radius = 0) {
super()
this._x = x
this._y = y
this._radius = radius
this._create()
}
_create () {
this._widthRange = new Range(this.x - this.radius, this.x + this.radius)
this._heightRange = new Range(this.y - this.radius, this.y + this.radius)
}
/**
* Checks whether the point object given are contained within this sphere.
*
* @param {Point} point - The point object of test.
*/
pointCollision (point) {
return (point.x - this.x) ** 2 + (point.y - this.y) ** 2 <= this.radius ** 2
}
/**
* Checks whether the aabb object given are contained within this sphere.
*
* @param {AABB} aabb - The aabb object of test
*/
aabbCollision (aabb) {
let sCenterVector2 = new Vector2(this.x, this.y)
let sCenter2aCenter = sCenterVector2.sub(new Vector2(aabb.center.x, aabb.center.y)).abs()
let aabbPoint = aabb.points()[1]
let apCenterVector2 = new Vector2(aabbPoint.x, aabbPoint.y)
let aabbHalfLength = apCenterVector2.sub(new Vector2(aabb.center.x, aabb.center.y)).abs()
let sphereCenter2aabb = sCenter2aCenter.sub(aabbHalfLength).max(0)
return sphereCenter2aabb.dot() <= this.radius ** 2
}
/**
* Checks whether the obb object given are contained within this sphere.
*
* @param {OBB} obb - The obb object of test
*/
obbCollision (obb) {
let point = obb.axes.point(new Point(this.x, this.y))
let sphereCenter2obbCenter = (new Vector2(point.x, point.y)).sub(new Vector2(0, 0)).abs()
let obbHalfLength = new Vector2(obb.width / 2, obb.height / 2)
let sphereCenter2obb = sphereCenter2obbCenter.sub(obbHalfLength).max(0)
return sphereCenter2obb.dot() <= this.radius ** 2
}
/**
* Checks whether the sphere object given are contained within this sphere.
*
* @param {Sphere} sphere - The sphere object of test
*/
sphereCollision (sphere) {
return this.pointCollision(new Point(sphere.x, sphere.y))
}
/**
* Transforms this object into a new AABB object and returns.
*
* @return {AABB}
*/
sphere2aabb () {
return new AABB(this.x - this.radius, this.y - this.radius, this.radius * 2, this.radius * 2)
}
/**
* Transforms this object into a new OBB object and returns.
*
* @return {OBB}
*/
sphere2obb (angle = 0) {
return new OBB(this.x, this.y, this.radius * 2, this.radius * 2, angle)
}
}
export default Sphere