import { Vector3D } from './Vector3D'; export class Sphere { /** * */ public x: number; /** * */ public y: number; /** * */ public z: number; /** * */ public radius: number; /** * Create a Sphere with ABCD coefficients */ constructor(x: number = 0, y: number = 0, z: number = 0, radius: number = 0) { this.x = x; this.y = y; this.z = z; this.radius = radius; } public rayIntersection(position: Vector3D, direction: Vector3D, targetNormal: Vector3D): number { if (this.containsPoint(position)) return 0; const px: number = position.x - this.x, py: number = position.y - this.y, pz: number = position.z - this.z; const vx: number = direction.x, vy: number = direction.y, vz: number = direction.z; let rayEntryDistance: number; const a: number = vx * vx + vy * vy + vz * vz; const b: number = 2 * (px * vx + py * vy + pz * vz); const c: number = px * px + py * py + pz * pz - this.radius * this.radius; const det: number = b * b - 4 * a * c; if (det >= 0) { // ray goes through sphere const sqrtDet: number = Math.sqrt(det); rayEntryDistance = (-b - sqrtDet) / (2 * a); if (rayEntryDistance >= 0) { targetNormal.x = px + rayEntryDistance * vx; targetNormal.y = py + rayEntryDistance * vy; targetNormal.z = pz + rayEntryDistance * vz; targetNormal.normalize(); return rayEntryDistance; } } // ray misses sphere return -1; } public containsPoint(position: Vector3D): boolean { const px: number = position.x - this.x; const py: number = position.y - this.y; const pz: number = position.z - this.z; const distance: number = Math.sqrt(px * px + py * py + pz * pz); return distance <= this.radius; } /** * Copies all of sphere data from the source Sphere object into the calling * Sphere object. * * @param sourceSphere The Sphere object from which to copy the data. */ public copyFrom(sourceSphere: Sphere): void { this.x = sourceSphere.x; this.y = sourceSphere.y; this.z = sourceSphere.z; this.radius = sourceSphere.radius; } /** * Adds two spheres together to create a new Sphere object, by filling * in the horizontal, vertical and longitudinal space between the two spheres. * *
Note: The union() method ignores spheres with
* 0 as the height, width or depth value, such as: var
* box2:Sphere = new Sphere(300,300,300,50,50,0);