src/Sphere.js
import { Box3 } from "./Box3.js";
import { Vector3 } from "./Vector3.js";
/**
* A box.
*
* @type {Box3}
* @private
*/
const box = new Box3();
/**
* A vector.
*
* @type {Vector3}
* @private
*/
const v = new Vector3();
/**
* A sphere.
*/
export class Sphere {
/**
* Constructs a new sphere.
*
* @param {Vector3} [center] - The center.
* @param {Number} [radius] - The radius.
*/
constructor(center = new Vector3(), radius = 0) {
/**
* The center.
*
* @type {Vector3}
*/
this.center = center;
/**
* The radius.
*
* @type {Number}
*/
this.radius = radius;
}
/**
* Sets the center and the radius.
*
* @param {Vector3} center - The center.
* @param {Number} radius - The radius.
* @return {Sphere} This sphere.
*/
set(center, radius) {
this.center.copy(center);
this.radius = radius;
return this;
}
/**
* Copies the given sphere.
*
* @param {Sphere} s - A sphere.
* @return {Sphere} This sphere.
*/
copy(s) {
this.center.copy(s.center);
this.radius = s.radius;
return this;
}
/**
* Clones this sphere.
*
* @return {Sphere} The cloned sphere.
*/
clone() {
return new this.constructor().copy(this);
}
/**
* Sets this sphere from points.
*
* @param {Vector3[]} points - The points.
* @param {Vector3} [center] - An optional center.
* @return {Sphere} This sphere.
*/
setFromPoints(points, center = box.setFromPoints(points).getCenter(this.center)) {
let maxRadiusSq = 0;
let i, l;
for(i = 0, l = points.length; i < l; ++i) {
maxRadiusSq = Math.max(maxRadiusSq, center.distanceToSquared(points[i]));
}
this.radius = Math.sqrt(maxRadiusSq);
return this;
}
/**
* Computes the bounding sphere of the given box.
*
* @param {Box3} box - A box.
* @return {Sphere} This pshere.
*/
setFromBox(box) {
box.getCenter(this.center);
this.radius = box.getSize(v).length() * 0.5;
return this;
}
/**
* Checks if this sphere is empty.
*
* @return {Boolean} Whether this sphere is empty.
*/
isEmpty() {
return (this.radius <= 0);
}
/**
* Translates this sphere.
*
* @param {Number} offset - An offset.
* @return {Sphere} This sphere.
*/
translate(offset) {
this.center.add(offset);
return this;
}
/**
* Clamps the given point to this sphere.
*
* @param {Vector3} p - A point.
* @param {Vector3} [target] - A target vector. If none is provided, a new one will be created.
* @return {Vector3} The clamped point.
*/
clampPoint(p, target = new Vector3()) {
const deltaLengthSq = this.center.distanceToSquared(p);
target.copy(p);
if(deltaLengthSq > (this.radius * this.radius)) {
target.sub(this.center).normalize();
target.multiplyScalar(this.radius).add(this.center);
}
return target;
}
/**
* Calculates the distance from this sphere to the given point.
*
* @param {Vector3} p - A point.
* @return {Number} The distance.
*/
distanceToPoint(p) {
return (p.distanceTo(this.center) - this.radius);
}
/**
* Checks if the given point lies inside this sphere.
*
* @param {Vector3} p - A point.
* @return {Boolean} Whether this sphere contains the point.
*/
containsPoint(p) {
return (p.distanceToSquared(this.center) <= (this.radius * this.radius));
}
/**
* Checks if the this sphere intersects with the given one.
*
* @param {Sphere} s - A sphere.
* @return {Boolean} Whether this sphere intersects with the given one.
*/
intersectsSphere(s) {
const radiusSum = this.radius + s.radius;
return s.center.distanceToSquared(this.center) <= (radiusSum * radiusSum);
}
/**
* Checks if the this sphere intersects with the given box.
*
* @param {Box3} b - A box.
* @return {Boolean} Whether this sphere intersects with the given box.
*/
intersectsBox(b) {
return b.intersectsSphere(this);
}
/**
* Checks if the this sphere intersects with the given plane.
*
* @param {Plane} p - A plane.
* @return {Boolean} Whether this sphere intersects with the given plane.
*/
intersectsPlane(p) {
return (Math.abs(p.distanceToPoint(this.center)) <= this.radius);
}
/**
* Checks if this sphere equals the given one.
*
* @param {Sphere} s - A sphere.
* @return {Boolean} Whether the spheres are equal.
*/
equals(s) {
return (s.center.equals(this.center) && (s.radius === this.radius));
}
}