From 4091d9d8e1c69709236278bd642187d7b36ed53c Mon Sep 17 00:00:00 2001
From: Alexander Rose <alex.rose@rcsb.org>
Date: Wed, 29 Aug 2018 18:06:28 -0700
Subject: [PATCH] added transform methods to Box3D and Sphere3D

---
 src/mol-math/geometry/primitives/box3d.ts    | 55 ++++++++++++++++----
 src/mol-math/geometry/primitives/sphere3d.ts | 15 ++++--
 src/mol-math/linear-algebra/3d/mat4.ts       |  7 +++
 3 files changed, 62 insertions(+), 15 deletions(-)

diff --git a/src/mol-math/geometry/primitives/box3d.ts b/src/mol-math/geometry/primitives/box3d.ts
index 6d0b5bd5f..8b48c524a 100644
--- a/src/mol-math/geometry/primitives/box3d.ts
+++ b/src/mol-math/geometry/primitives/box3d.ts
@@ -2,9 +2,10 @@
  * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author David Sehnal <david.sehnal@gmail.com>
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-import { Vec3 } from '../../linear-algebra'
+import { Vec3, Mat4 } from '../../linear-algebra'
 import { PositionData } from '../common'
 import { OrderedSet } from 'mol-data/int';
 
@@ -12,10 +13,11 @@ interface Box3D { min: Vec3, max: Vec3 }
 
 namespace Box3D {
     export function create(min: Vec3, max: Vec3): Box3D { return { min, max }; }
+    export function empty(): Box3D { return { min: Vec3.zero(), max: Vec3.zero() }; }
 
     export function computeBounding(data: PositionData): Box3D {
-        const min = [Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE];
-        const max = [-Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE];
+        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 { x, y, z, indices } = data;
         for (let t = 0, _t = OrderedSet.size(indices); t < _t; t++) {
@@ -27,18 +29,49 @@ namespace Box3D {
             max[1] = Math.max(y[i], max[1]);
             max[2] = Math.max(z[i], max[2]);
         }
-        return { min: Vec3.create(min[0], min[1], min[2]), max: Vec3.create(max[0], max[1], max[2]) }
+        return { min, max }
     }
 
-    export function size(box: Box3D) {
-        return Vec3.sub(Vec3.zero(), box.max, box.min);
+    /** Get size of the box */
+    export function size(size: Vec3, box: Box3D): Vec3 {
+        return Vec3.sub(size, box.max, box.min);
     }
 
-    export function expand(box: Box3D, delta: Vec3): Box3D {
-        return {
-            min: Vec3.sub(Vec3.zero(), box.min, delta),
-            max: Vec3.add(Vec3.zero(), box.max, delta)
-        }
+    export function setEmpty(box: Box3D): Box3D {
+        Vec3.set(box.min, Number.MAX_VALUE, Number.MAX_VALUE, Number.MAX_VALUE)
+        Vec3.set(box.max, -Number.MAX_VALUE, -Number.MAX_VALUE, -Number.MAX_VALUE)
+        return box
+    }
+
+    /** Add point to box */
+    export function add(box: Box3D, point: Vec3): Box3D {
+        Vec3.min(box.min, box.min, point)
+        Vec3.max(box.max, box.max, point)
+        return box
+    }
+
+    /** Expand box by delta */
+    export function expand(out: Box3D, box: Box3D, delta: Vec3): Box3D {
+        Vec3.sub(out.min, box.min, delta)
+        Vec3.add(out.max, box.max, delta)
+        return out
+    }
+
+    const tmpTransformV = Vec3.zero()
+    /** Transform box with a Mat4 */
+    export function transform(out: Box3D, box: Box3D, m: Mat4): Box3D {
+        const [ minX, minY, minZ ] = box.min
+        const [ maxX, maxY, maxZ ] = box.max
+        setEmpty(out)
+        add(out, Vec3.transformMat4(tmpTransformV, Vec3.set(tmpTransformV, minX, minY, minZ), m))
+        add(out, Vec3.transformMat4(tmpTransformV, Vec3.set(tmpTransformV, minX, minY, maxZ), m))
+        add(out, Vec3.transformMat4(tmpTransformV, Vec3.set(tmpTransformV, minX, maxY, minZ), m))
+        add(out, Vec3.transformMat4(tmpTransformV, Vec3.set(tmpTransformV, minX, maxY, maxZ), m))
+        add(out, Vec3.transformMat4(tmpTransformV, Vec3.set(tmpTransformV, maxX, minY, minZ), m))
+        add(out, Vec3.transformMat4(tmpTransformV, Vec3.set(tmpTransformV, maxX, minY, maxZ), m))
+        add(out, Vec3.transformMat4(tmpTransformV, Vec3.set(tmpTransformV, maxX, maxY, minZ), m))
+        add(out, Vec3.transformMat4(tmpTransformV, Vec3.set(tmpTransformV, maxX, maxY, maxZ), m))
+        return out
     }
 }
 
diff --git a/src/mol-math/geometry/primitives/sphere3d.ts b/src/mol-math/geometry/primitives/sphere3d.ts
index 2132583d8..c38e9275a 100644
--- a/src/mol-math/geometry/primitives/sphere3d.ts
+++ b/src/mol-math/geometry/primitives/sphere3d.ts
@@ -2,18 +2,18 @@
  * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author David Sehnal <david.sehnal@gmail.com>
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-import { Vec3 } from '../../linear-algebra'
+import { Vec3, Mat4 } from '../../linear-algebra'
 import { PositionData } from '../common'
 import { OrderedSet } from 'mol-data/int';
 
 interface Sphere3D { center: Vec3, radius: number }
 
 namespace Sphere3D {
-    export function create(center: Vec3, radius: number): Sphere3D {
-        return { center, radius };
-    }
+    export function create(center: Vec3, radius: number): Sphere3D { return { center, radius }; }
+    export function zero(): Sphere3D { return { center: Vec3.zero(), radius: 0 }; }
 
     export function computeBounding(data: PositionData): Sphere3D {
         const { x, y, z, indices } = data;
@@ -43,6 +43,13 @@ namespace Sphere3D {
 
         return { center: Vec3.create(cx, cy, cz), radius: Math.sqrt(radiusSq) };
     }
+
+    /** Transform sphere with a Mat4 */
+    export function transform(out: Sphere3D, sphere: Sphere3D, m: Mat4): Sphere3D {
+        Vec3.transformMat4(out.center, sphere.center, m)
+        out.radius = sphere.radius * Mat4.getMaxScaleOnAxis(m)
+        return out
+    }
 }
 
 export { Sphere3D }
\ No newline at end of file
diff --git a/src/mol-math/linear-algebra/3d/mat4.ts b/src/mol-math/linear-algebra/3d/mat4.ts
index ddc230eb5..442f8e392 100644
--- a/src/mol-math/linear-algebra/3d/mat4.ts
+++ b/src/mol-math/linear-algebra/3d/mat4.ts
@@ -873,6 +873,13 @@ namespace Mat4 {
         return out;
     }
 
+    export function getMaxScaleOnAxis(m: Mat4) {
+        const scaleXSq = m[0] * m[0] + m[1] * m[1] + m[2] * m[2]
+        const scaleYSq = m[4] * m[4] + m[5] * m[5] + m[6] * m[6]
+        const scaleZSq = m[8] * m[8] + m[9] * m[9] + m[10] * m[10]
+        return Math.sqrt(Math.max(scaleXSq, scaleYSq, scaleZSq))
+    }
+
     /** Rotation matrix for 90deg around x-axis */
     export const rotX90: ReadonlyMat4 = Mat4.fromRotation(Mat4.identity(), degToRad(90), Vec3.create(1, 0, 0))
     /** Rotation matrix for 180deg around x-axis */
-- 
GitLab