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