|
@@ -0,0 +1,115 @@
|
|
|
+/**
|
|
|
+ * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
|
|
+ *
|
|
|
+ * @author David Sehnal <david.sehnal@gmail.com>
|
|
|
+ */
|
|
|
+
|
|
|
+import { Vec3 } from 'mol-math/linear-algebra/3d';
|
|
|
+import { Box3D } from './primitives/box3d';
|
|
|
+import { Sphere3D } from './primitives/sphere3d';
|
|
|
+
|
|
|
+export class BoundaryHelper {
|
|
|
+ private count = 0;
|
|
|
+ private extremes = [Vec3.zero(), Vec3.zero(), Vec3.zero(), Vec3.zero(), Vec3.zero(), Vec3.zero()];
|
|
|
+ private u = Vec3.zero();
|
|
|
+ private v = Vec3.zero();
|
|
|
+
|
|
|
+ tolerance = 0;
|
|
|
+ center: Vec3 = Vec3.zero();
|
|
|
+ radius = 0;
|
|
|
+
|
|
|
+ reset(tolerance: number) {
|
|
|
+ Vec3.set(this.center, 0, 0, 0);
|
|
|
+ for (let i = 0; i < 6; i++) {
|
|
|
+ const e = i % 2 === 0 ? Number.MAX_VALUE : -Number.MAX_VALUE;
|
|
|
+ this.extremes[i] = Vec3.create(e, e, e);
|
|
|
+ }
|
|
|
+ this.radius = 0;
|
|
|
+ this.count = 0;
|
|
|
+ this.tolerance = tolerance;
|
|
|
+ }
|
|
|
+
|
|
|
+ boundaryStep(p: Vec3, r: number) {
|
|
|
+ updateExtremeMin(0, this.extremes[0], p, r);
|
|
|
+ updateExtremeMax(0, this.extremes[1], p, r);
|
|
|
+
|
|
|
+ updateExtremeMin(1, this.extremes[2], p, r);
|
|
|
+ updateExtremeMax(1, this.extremes[3], p, r);
|
|
|
+
|
|
|
+ updateExtremeMin(2, this.extremes[4], p, r);
|
|
|
+ updateExtremeMax(2, this.extremes[5], p, r);
|
|
|
+ this.count++;
|
|
|
+ }
|
|
|
+
|
|
|
+ finishIncludeStep() {
|
|
|
+ if (this.count === 0) return;
|
|
|
+
|
|
|
+ let maxSpan = 0, mI = 0, mJ = 0;
|
|
|
+
|
|
|
+ for (let i = 0; i < 5; i++) {
|
|
|
+ for (let j = i + 1; j < 6; j++) {
|
|
|
+ const d = Vec3.squaredDistance(this.extremes[i], this.extremes[j]);
|
|
|
+ if (d > maxSpan) {
|
|
|
+ maxSpan = d;
|
|
|
+ mI = i;
|
|
|
+ mJ = j;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ Vec3.add(this.center, this.extremes[mI], this.extremes[mJ]);
|
|
|
+ Vec3.scale(this.center, this.center, 0.5);
|
|
|
+ this.radius = Vec3.distance(this.center, this.extremes[mI]);
|
|
|
+ }
|
|
|
+
|
|
|
+ extendStep(p: Vec3, r: number) {
|
|
|
+ const d = Vec3.distance(p, this.center);
|
|
|
+ if ((1 + this.tolerance) * this.radius >= r + d) return;
|
|
|
+
|
|
|
+ Vec3.sub(this.u, p, this.center);
|
|
|
+ Vec3.normalize(this.u, this.u);
|
|
|
+
|
|
|
+ Vec3.scale(this.v, this.u, -this.radius);
|
|
|
+ Vec3.add(this.v, this.v, this.center);
|
|
|
+ Vec3.scale(this.u, this.u, r + d);
|
|
|
+ Vec3.add(this.u, this.u, this.center);
|
|
|
+
|
|
|
+ Vec3.add(this.center, this.u, this.v);
|
|
|
+ Vec3.scale(this.center, this.center, 0.5);
|
|
|
+ this.radius = 0.5 * (r + d + this.radius);
|
|
|
+ }
|
|
|
+
|
|
|
+ getBox(): Box3D {
|
|
|
+ Vec3.copy(this.u, this.extremes[0]);
|
|
|
+ Vec3.copy(this.v, this.extremes[0]);
|
|
|
+
|
|
|
+ for (let i = 1; i < 6; i++) {
|
|
|
+ Vec3.min(this.u, this.u, this.extremes[i]);
|
|
|
+ Vec3.max(this.v, this.v, this.extremes[i]);
|
|
|
+ }
|
|
|
+
|
|
|
+ return { min: Vec3.clone(this.u), max: Vec3.clone(this.v) };
|
|
|
+ }
|
|
|
+
|
|
|
+ getSphere(): Sphere3D {
|
|
|
+ return { center: Vec3.clone(this.center), radius: this.radius };
|
|
|
+ }
|
|
|
+
|
|
|
+ constructor() {
|
|
|
+ this.reset(0);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function updateExtremeMin(d: number, e: Vec3, center: Vec3, r: number) {
|
|
|
+ if (center[d] - r < e[d]) {
|
|
|
+ Vec3.copy(e, center);
|
|
|
+ e[d] -= r;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function updateExtremeMax(d: number, e: Vec3, center: Vec3, r: number) {
|
|
|
+ if (center[d] + r > e[d]) {
|
|
|
+ Vec3.copy(e, center);
|
|
|
+ e[d] += r;
|
|
|
+ }
|
|
|
+}
|