Browse Source

StructureBoundingBox3D transform

dsehnal 4 years ago
parent
commit
02de871c59

+ 39 - 0
src/mol-plugin-state/transforms/representation.ts

@@ -36,6 +36,10 @@ import { DihedralParams, DihedralRepresentation } from '../../mol-repr/shape/loc
 import { ModelSymmetry } from '../../mol-model-formats/structure/property/symmetry';
 import { Clipping } from '../../mol-theme/clipping';
 import { ObjectKeys } from '../../mol-util/type-helpers';
+import { Mesh } from '../../mol-geo/geometry/mesh/mesh';
+import { getBoxMesh } from './shape';
+import { Shape } from '../../mol-model/shape';
+import { Box3D } from '../../mol-math/geometry';
 
 export { StructureRepresentation3D };
 export { ExplodeStructureRepresentation3D };
@@ -736,6 +740,41 @@ const ModelUnitcell3D = PluginStateTransform.BuiltIn({
     }
 });
 
+export { StructureBoundingBox3D };
+type StructureBoundingBox3D = typeof StructureBoundingBox3D
+const StructureBoundingBox3D = PluginStateTransform.BuiltIn({
+    name: 'structure-bounding-box-3d',
+    display: 'Bounding Box',
+    from: SO.Molecule.Structure,
+    to: SO.Shape.Representation3D,
+    params: {
+        radius: PD.Numeric(0.05, { min: 0.01, max: 4, step: 0.01 }, { isEssential: true }),
+        color: PD.Color(ColorNames.red, { isEssential: true }),
+        ...Mesh.Params,
+    }
+})({
+    canAutoUpdate() {
+        return true;
+    },
+    apply({ a, params }, plugin: PluginContext) {
+        return Task.create('Bounding Box', async ctx => {
+            const repr = ShapeRepresentation((_, data: { box: Box3D, radius: number, color: Color }, __, shape) => {
+                const mesh = getBoxMesh(data.box, data.radius, shape?.geometry);
+                return Shape.create('Bouding Box', data, mesh, () => data.color, () => 1, () => 'Bounding Box');
+            }, Mesh.Utils);
+            await repr.createOrUpdate(params, { box: a.data.boundary.box, radius: params.radius, color: params.color }).runInContext(ctx);
+            return new SO.Shape.Representation3D({ repr, source: a }, { label: `Bounding Box` });
+        });
+    },
+    update({ a, b, oldParams, newParams }, plugin: PluginContext) {
+        return Task.create('Bounding Box', async ctx => {
+            await b.data.repr.createOrUpdate(newParams, { box: a.data.boundary.box, radius: newParams.radius, color: newParams.color }).runInContext(ctx);
+            b.data.source = a;
+            return StateTransformer.UpdateResult.Updated;
+        });
+    }
+});
+
 export { StructureSelectionsDistance3D };
 type StructureSelectionsDistance3D = typeof StructureSelectionsDistance3D
 const StructureSelectionsDistance3D = PluginStateTransform.BuiltIn({

+ 22 - 18
src/mol-plugin-state/transforms/shape.ts

@@ -7,7 +7,7 @@
 import { Mesh } from '../../mol-geo/geometry/mesh/mesh';
 import { MeshBuilder } from '../../mol-geo/geometry/mesh/mesh-builder';
 import { BoxCage } from '../../mol-geo/primitive/box';
-import { Sphere3D } from '../../mol-math/geometry';
+import { Box3D, Sphere3D } from '../../mol-math/geometry';
 import { Mat4, Vec3 } from '../../mol-math/linear-algebra';
 import { Shape } from '../../mol-model/shape';
 import { Task } from '../../mol-task';
@@ -39,23 +39,7 @@ const BoxShape3D = PluginStateTransform.BuiltIn({
                 data: params,
                 params: Mesh.Params,
                 getShape: (_, data: typeof params) => {
-
-                    const diag = Vec3.sub(Vec3(), data.topRight, data.bottomLeft);
-                    const translateUnit = Mat4.fromTranslation(Mat4(), Vec3.create(0.5, 0.5, 0.5));
-                    const scale = Mat4.fromScaling(Mat4(), diag);
-                    const translate = Mat4.fromTranslation(Mat4(), data.bottomLeft);
-                    const transform = Mat4.mul3(Mat4(), translate, scale, translateUnit);
-
-                    // TODO: optimize
-                    const state = MeshBuilder.createState(256, 128);
-                    state.currentGroup = 1;
-                    MeshBuilder.addCage(state, transform, BoxCage(), data.radius, 2, 20);
-                    const mesh = MeshBuilder.getMesh(state);
-
-                    const center = Vec3.scaleAndAdd(Vec3(), data.bottomLeft, diag, 0.5);
-                    const radius = Vec3.distance(data.bottomLeft, center);
-                    mesh.setBoundingSphere(Sphere3D.create(center, radius));
-
+                    const mesh = getBoxMesh(Box3D.create(params.bottomLeft, params.topRight), params.radius);
                     return Shape.create('Box', data, mesh, () => data.color, () => 1, () => 'Box');
                 },
                 geometryUtils: Mesh.Utils
@@ -63,3 +47,23 @@ const BoxShape3D = PluginStateTransform.BuiltIn({
         });
     }
 });
+
+export function getBoxMesh(box: Box3D, radius: number, oldMesh?: Mesh) {
+    const diag = Vec3.sub(Vec3(), box.max, box.min);
+    const translateUnit = Mat4.fromTranslation(Mat4(), Vec3.create(0.5, 0.5, 0.5));
+    const scale = Mat4.fromScaling(Mat4(), diag);
+    const translate = Mat4.fromTranslation(Mat4(), box.min);
+    const transform = Mat4.mul3(Mat4(), translate, scale, translateUnit);
+
+    // TODO: optimize?
+    const state = MeshBuilder.createState(256, 128, oldMesh);
+    state.currentGroup = 1;
+    MeshBuilder.addCage(state, transform, BoxCage(), radius, 2, 20);
+    const mesh = MeshBuilder.getMesh(state);
+
+    const center = Vec3.scaleAndAdd(Vec3(), box.min, diag, 0.5);
+    const sphereRadius = Vec3.distance(box.min, center);
+    mesh.setBoundingSphere(Sphere3D.create(center, sphereRadius));
+
+    return mesh;
+}

+ 1 - 0
src/mol-plugin/spec.ts

@@ -93,6 +93,7 @@ export const DefaultPluginSpec = (): PluginSpec => ({
         PluginSpec.Action(StateTransforms.Representation.StructureSelectionsLabel3D),
         PluginSpec.Action(StateTransforms.Representation.StructureSelectionsOrientation3D),
         PluginSpec.Action(StateTransforms.Representation.ModelUnitcell3D),
+        PluginSpec.Action(StateTransforms.Representation.StructureBoundingBox3D),
         PluginSpec.Action(StateTransforms.Representation.ExplodeStructureRepresentation3D),
         PluginSpec.Action(StateTransforms.Representation.UnwindStructureAssemblyRepresentation3D),
         PluginSpec.Action(StateTransforms.Representation.OverpaintStructureRepresentation3DFromScript),