From ce0ff2fed8bcd312eae126a1ec4d125e45f03396 Mon Sep 17 00:00:00 2001
From: David Sehnal <david.sehnal@gmail.com>
Date: Thu, 29 Aug 2019 15:46:20 +0200
Subject: [PATCH] mol-model: optionally compute centroid based bounding sphere
 (disabled for now)

---
 src/mol-math/geometry/centroid-helper.ts      |  5 ++
 .../structure/structure/structure.ts          |  7 +++
 .../structure/structure/util/boundary.ts      | 49 ++++++++++++++++++-
 3 files changed, 59 insertions(+), 2 deletions(-)

diff --git a/src/mol-math/geometry/centroid-helper.ts b/src/mol-math/geometry/centroid-helper.ts
index 7387757fc..637e92483 100644
--- a/src/mol-math/geometry/centroid-helper.ts
+++ b/src/mol-math/geometry/centroid-helper.ts
@@ -5,6 +5,7 @@
  */
 
 import { Vec3 } from '../../mol-math/linear-algebra/3d';
+import { Sphere3D } from './primitives/sphere3d';
 
 export { CentroidHelper }
 
@@ -35,6 +36,10 @@ class CentroidHelper {
         if (d > this.radiusSq) this.radiusSq = d;
     }
 
+    getSphere(): Sphere3D {
+        return { center: Vec3.clone(this.center), radius: Math.sqrt(this.radiusSq) };
+    }
+
     constructor() {
 
     }
diff --git a/src/mol-model/structure/structure/structure.ts b/src/mol-model/structure/structure/structure.ts
index a88ab91f8..0cf0f2fe7 100644
--- a/src/mol-model/structure/structure/structure.ts
+++ b/src/mol-model/structure/structure/structure.ts
@@ -221,6 +221,13 @@ class Structure {
             || (this._props.uniqueAtomicResidueIndices = getUniqueAtomicResidueIndices(this));
     }
 
+    get isAtomic() {
+        for (const u of this.units) {
+            if (u.kind !== Unit.Kind.Atomic) return false;
+        }
+        return true;
+    }
+
     /**
      * Provides mapping for serial element indices accross all units.
      *
diff --git a/src/mol-model/structure/structure/util/boundary.ts b/src/mol-model/structure/structure/util/boundary.ts
index 1b9026a6a..98e7e0968 100644
--- a/src/mol-model/structure/structure/util/boundary.ts
+++ b/src/mol-model/structure/structure/util/boundary.ts
@@ -9,15 +9,60 @@ import { Box3D, Sphere3D } from '../../../../mol-math/geometry';
 import { BoundaryHelper } from '../../../../mol-math/geometry/boundary-helper';
 import { Vec3 } from '../../../../mol-math/linear-algebra';
 import Structure from '../structure';
+import { CentroidHelper } from '../../../../mol-math/geometry/centroid-helper';
 
 export type Boundary = { box: Box3D, sphere: Sphere3D }
 
-const tmpBox = Box3D.empty()
-const tmpSphere = Sphere3D.zero()
+const tmpBox = Box3D.empty();
+const tmpSphere = Sphere3D.zero();
+const tmpVec = Vec3.zero();
 
 const boundaryHelper = new BoundaryHelper();
+const centroidHelper = new CentroidHelper();
+
+// TODO: show this be enabled? does not solve problem with "renderable bounding spheres"
+const CENTROID_COMPUTATION_THRESHOLD = -1;
 
 export function computeStructureBoundary(s: Structure): Boundary {
+    if (s.elementCount <= CENTROID_COMPUTATION_THRESHOLD && s.isAtomic) return computeStructureBoundaryFromElements(s);
+    return computeStructureBoundaryFromUnits(s);
+}
+
+function computeStructureBoundaryFromElements(s: Structure): Boundary {
+    centroidHelper.reset();
+
+    const min = Vec3.create(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE)
+    const max = Vec3.create(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE)
+
+    const v = tmpVec;
+    for (const unit of s.units) {
+        const { x, y, z } = unit.conformation;
+        const elements = unit.elements;
+        for (let j = 0, _j = elements.length; j < _j; j++) {
+            const e = elements[j];
+            Vec3.set(v, x(e), y(e), z(e));
+            centroidHelper.includeStep(v);
+            Vec3.min(min, min, v);
+            Vec3.max(max, max, v);
+        };
+    }
+
+    centroidHelper.finishedIncludeStep();
+
+    for (const unit of s.units) {
+        const { x, y, z } = unit.conformation;
+        const elements = unit.elements;
+        for (let j = 0, _j = elements.length; j < _j; j++) {
+            const e = elements[j];
+            Vec3.set(v, x(e), y(e), z(e));
+            centroidHelper.radiusStep(v);
+        };
+    }
+
+    return { box: { min, max }, sphere: centroidHelper.getSphere() };
+}
+
+function computeStructureBoundaryFromUnits(s: Structure): Boundary {
     const min = Vec3.create(Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE)
     const max = Vec3.create(-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE)
 
-- 
GitLab