| import {EPS10} from '../math'; |
| import {Sphere} from "../bv/Sphere"; |
| import {Vec3} from './Vec3'; |
| |
| |
| |
| |
| |
| |
| |
| |
| export class Line3 { |
| |
| |
| |
| |
| |
| |
| public p0: Vec3; |
| |
| |
| |
| |
| |
| |
| public p1: Vec3; |
| |
| constructor(p0?: Vec3, p1?: Vec3) { |
| this.p0 = p0 || new Vec3(); |
| this.p1 = p1 || new Vec3(); |
| } |
| |
| public getMagnitude(): number { |
| return this.p0.distance(this.p1); |
| } |
| |
| public getSphereIntersection(sphere: Sphere): [Vec3] | [Vec3, Vec3] | [] { |
| let p0 = this.p0, |
| p1 = this.p1; |
| |
| let cx = sphere.center.x, |
| cy = sphere.center.y, |
| cz = sphere.center.z; |
| |
| let px = p0.x, |
| py = p0.y, |
| pz = p0.z; |
| |
| let vx = p1.x - px, |
| vy = p1.y - py, |
| vz = p1.z - pz; |
| |
| let A = vx * vx + vy * vy + vz * vz, |
| B = 2.0 * (px * vx + py * vy + pz * vz - vx * cx - vy * cy - vz * cz), |
| C = px * px - 2 * px * cx + cx * cx + py * py - 2 * py * cy + cy * cy + |
| pz * pz - 2 * pz * cz + cz * cz - sphere.radius * sphere.radius; |
| let D = B * B - 4 * A * C; |
| |
| if (D < 0) { |
| |
| return []; |
| } |
| |
| let t1 = (-B - Math.sqrt(D)) / (2.0 * A); |
| |
| let solution1 = new Vec3( |
| p0.x * (1 - t1) + t1 * p1.x, |
| p0.y * (1 - t1) + t1 * p1.y, |
| p0.z * (1 - t1) + t1 * p1.z |
| ); |
| |
| if (D == 0) { |
| return [solution1]; |
| } |
| |
| let t2 = (-B + Math.sqrt(D)) / (2.0 * A); |
| let solution2 = new Vec3( |
| p0.x * (1 - t2) + t2 * p1.x, |
| p0.y * (1 - t2) + t2 * p1.y, |
| p0.z * (1 - t2) + t2 * p1.z); |
| |
| |
| if (Math.abs(t1 - 0.5) < Math.abs(t2 - 0.5)) { |
| return [solution1, solution2]; |
| } |
| |
| return [solution2, solution1]; |
| } |
| |
| public intersects(line: Line3, res: Vec3, res2?: Vec3): boolean { |
| |
| let p13 = this.p0.sub(line.p0), |
| p43 = line.p1.sub(line.p0); |
| |
| if (Math.abs(p43.x) < EPS10 && Math.abs(p43.y) < EPS10 && Math.abs(p43.z) < EPS10) { |
| return false; |
| } |
| |
| let p21 = this.p1.sub(this.p0); |
| |
| if (Math.abs(p21.x) < EPS10 && Math.abs(p21.y) < EPS10 && Math.abs(p21.z) < EPS10) { |
| return false; |
| } |
| |
| let d1343 = p13.x * p43.x + p13.y * p43.y + p13.z * p43.z, |
| d4321 = p43.x * p21.x + p43.y * p21.y + p43.z * p21.z, |
| d1321 = p13.x * p21.x + p13.y * p21.y + p13.z * p21.z, |
| d4343 = p43.x * p43.x + p43.y * p43.y + p43.z * p43.z, |
| d2121 = p21.x * p21.x + p21.y * p21.y + p21.z * p21.z; |
| |
| let denom = d2121 * d4343 - d4321 * d4321; |
| |
| if (Math.abs(denom) < EPS10) { |
| return false; |
| } |
| |
| let numer = d1343 * d4321 - d1321 * d4343; |
| |
| let mua = numer / denom; |
| |
| res.x = this.p0.x + mua * p21.x; |
| res.y = this.p0.y + mua * p21.y; |
| res.z = this.p0.z + mua * p21.z; |
| |
| if (res2) { |
| |
| let mub = (d1343 + d4321 * mua) / d4343; |
| |
| res2.x = line.p0.x + mub * p43.x; |
| res2.y = line.p0.y + mub * p43.y; |
| res2.z = line.p0.z + mub * p43.z; |
| } |
| |
| return true; |
| } |
| |
| public getNearestDistancePoint(point: Vec3, res: Vec3): boolean { |
| |
| let p0 = this.p0, |
| p1 = this.p1; |
| |
| let mag = this.getMagnitude(); |
| |
| let u = |
| ( |
| ((point.x - p0.x) * (p1.x - p0.x)) + |
| ((point.y - p0.y) * (p1.y - p0.y)) + |
| ((point.z - p0.z) * (p1.z - p0.z)) |
| ) / |
| (mag * mag); |
| |
| res.x = p0.x + u * (p1.x - p0.x); |
| res.y = p0.y + u * (p1.y - p0.y); |
| res.z = p0.z + u * (p1.z - p0.z); |
| |
| if (u < 0.0 || u > 1.0) { |
| return false; |
| } |
| |
| return true; |
| } |
| } |