import { Matrix3 } from './Matrix3.js'; import { Vector3 } from './Vector3.js'; const _vector1 = /*@__PURE__*/ new Vector3(); const _vector2 = /*@__PURE__*/ new Vector3(); const _normalMatrix = /*@__PURE__*/ new Matrix3(); class Plane { constructor(normal = new Vector3(1, 0, 0), constant = 0) { // normal is assumed to be normalized this.normal = normal; this.constant = constant; } set(normal, constant) { this.normal.copy(normal); this.constant = constant; return this; } setComponents(x, y, z, w) { this.normal.set(x, y, z); this.constant = w; return this; } setFromNormalAndCoplanarPoint(normal, point) { this.normal.copy(normal); this.constant = -point.dot(this.normal); return this; } setFromCoplanarPoints(a, b, c) { const normal = _vector1.subVectors(c, b).cross(_vector2.subVectors(a, b)).normalize(); // Q: should an error be thrown if normal is zero (e.g. degenerate plane)? this.setFromNormalAndCoplanarPoint(normal, a); return this; } copy(plane) { this.normal.copy(plane.normal); this.constant = plane.constant; return this; } normalize() { // Note: will lead to a divide by zero if the plane is invalid. const inverseNormalLength = 1.0 / this.normal.length(); this.normal.multiplyScalar(inverseNormalLength); this.constant *= inverseNormalLength; return this; } negate() { this.constant *= -1; this.normal.negate(); return this; } distanceToPoint(point) { return this.normal.dot(point) + this.constant; } distanceToSphere(sphere) { return this.distanceToPoint(sphere.center) - sphere.radius; } projectPoint(point, target) { return target.copy(this.normal).multiplyScalar(-this.distanceToPoint(point)).add(point); } intersectLine(line, target) { const direction = line.delta(_vector1); const denominator = this.normal.dot(direction); if (denominator === 0) { // line is coplanar, return origin if (this.distanceToPoint(line.start) === 0) { return target.copy(line.start); } // Unsure if this is the correct method to handle this case. return null; } const t = -(line.start.dot(this.normal) + this.constant) / denominator; if (t < 0 || t > 1) { return null; } return target.copy(direction).multiplyScalar(t).add(line.start); } intersectsLine(line) { // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it. const startSign = this.distanceToPoint(line.start); const endSign = this.distanceToPoint(line.end); return (startSign < 0 && endSign > 0) || (endSign < 0 && startSign > 0); } intersectsBox(box) { return box.intersectsPlane(this); } intersectsSphere(sphere) { return sphere.intersectsPlane(this); } coplanarPoint(target) { return target.copy(this.normal).multiplyScalar(-this.constant); } applyMatrix4(matrix, optionalNormalMatrix) { const normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix(matrix); const referencePoint = this.coplanarPoint(_vector1).applyMatrix4(matrix); const normal = this.normal.applyMatrix3(normalMatrix).normalize(); this.constant = -referencePoint.dot(normal); return this; } translate(offset) { this.constant -= offset.dot(this.normal); return this; } equals(plane) { return plane.normal.equals(this.normal) && plane.constant === this.constant; } clone() { return new this.constructor().copy(this); } } Plane.prototype.isPlane = true; export { Plane };