Browse Source

Add "radius" property to conformation

David Sehnal 6 years ago
parent
commit
51ef3f3650

+ 6 - 3
src/mol-math/geometry/symmetry-operator.ts

@@ -54,16 +54,17 @@ namespace SymmetryOperator {
         readonly position: CoordinateMapper,
         x(index: number): number,
         y(index: number): number,
-        z(index: number): number
+        z(index: number): number,
+        r(index: number): number
     }
 
     export interface Coordinates { x: ArrayLike<number>, y: ArrayLike<number>, z: ArrayLike<number> }
 
-    export function createMapping(operator: SymmetryOperator, coords: Coordinates): ArrayMapping {
+    export function createMapping(operator: SymmetryOperator, coords: Coordinates, radius: ((index: number) => number) | undefined): ArrayMapping {
         const invariantPosition = SymmetryOperator.createCoordinateMapper(SymmetryOperator.Default, coords);
         const position = operator.isIdentity ? invariantPosition : SymmetryOperator.createCoordinateMapper(operator, coords);
         const { x, y, z } = createProjections(operator, coords);
-        return { operator, invariantPosition, position, x, y, z };
+        return { operator, invariantPosition, position, x, y, z, r: radius ? radius : _zeroRadius };
     }
 
     export function createCoordinateMapper(t: SymmetryOperator, coords: Coordinates): CoordinateMapper {
@@ -74,6 +75,8 @@ namespace SymmetryOperator {
 
 export { SymmetryOperator }
 
+function _zeroRadius(i: number) { return 0; }
+
 interface Projections { x(index: number): number, y(index: number): number, z(index: number): number }
 
 function createProjections(t: SymmetryOperator, coords: SymmetryOperator.Coordinates): Projections {

+ 12 - 45
src/mol-model/structure/structure/structure.ts

@@ -324,22 +324,12 @@ namespace Structure {
     }
 
     const distVec = Vec3.zero();
-    function atomicOrGaussianDistance(u: Unit.Atomic | Unit.Gaussians, p: Vec3, r: number) {
-        const { elements, conformation } = u;
+    function unitElementMinDistance(unit: Unit, p: Vec3, eRadius: number) {
+        const { elements, conformation: { position, r } } = unit, dV = distVec;
         let minD = Number.MAX_VALUE;
         for (let i = 0, _i = elements.length; i < _i; i++) {
-            const d = Vec3.distance(p, conformation.position(elements[i], distVec)) - r;
-            if (d < minD) minD = d;
-        }
-        return minD;
-    }
-
-    function sphereDistance(u: Unit.Spheres, p: Vec3, r: number) {
-        const { elements, conformation } = u;
-        const radius = u.coarseConformation.radius;
-        let minD = Number.MAX_VALUE;
-        for (let i = 0, _i = elements.length; i < _i; i++) {
-            const d = Vec3.distance(p, conformation.position(elements[i], distVec)) - r - radius[elements[i]];
+            const e = elements[i];
+            const d = Vec3.distance(p, position(e, dV)) - eRadius - r(e);
             if (d < minD) minD = d;
         }
         return minD;
@@ -347,19 +337,10 @@ namespace Structure {
 
     export function minDistanceToPoint(s: Structure, point: Vec3, radius: number) {
         const { units } = s;
-        let minD = Number.MAX_VALUE, d = 0;
+        let minD = Number.MAX_VALUE;
         for (let i = 0, _i = units.length; i < _i; i++) {
             const unit = units[i];
-            switch (unit.kind) {
-                case Unit.Kind.Atomic:
-                // TODO: assign radius to gaussian elements?
-                case Unit.Kind.Gaussians:
-                    d = atomicOrGaussianDistance(unit, point, radius);
-                    break;
-                case Unit.Kind.Spheres:
-                    d = sphereDistance(unit, point, radius);
-                    break;
-            }
+            const d = unitElementMinDistance(unit, point, radius);
             if (d < minD) minD = d;
         }
         return minD;
@@ -370,30 +351,16 @@ namespace Structure {
         if (a.elementCount === 0 || b.elementCount === 0) return 0;
 
         const { units } = a;
-        let minD = Number.MAX_VALUE, d = 0;
+        let minD = Number.MAX_VALUE;
 
         for (let i = 0, _i = units.length; i < _i; i++) {
             const unit = units[i];
-            const { elements, conformation } = unit;
-
-            switch (unit.kind) {
-                case Unit.Kind.Atomic:
-                // TODO: assign radius to gaussian elements?
-                case Unit.Kind.Gaussians:
-                    for (let i = 0, _i = elements.length; i < _i; i++) {
-                        const d = minDistanceToPoint(b, conformation.position(elements[i], distPivot), 0);
-                        if (d < minD) minD = d;
-                    }
-                    break;
-                case Unit.Kind.Spheres:
-                    const radius = unit.coarseConformation.radius;
-                    for (let i = 0, _i = elements.length; i < _i; i++) {
-                        const d = minDistanceToPoint(b, conformation.position(elements[i], distPivot), radius[elements[i]]);
-                        if (d < minD) minD = d;
-                    }
-                    break;
+            const { elements, conformation: { position, r } } = unit;
+            for (let i = 0, _i = elements.length; i < _i; i++) {
+                const e = elements[i];
+                const d = minDistanceToPoint(b, position(e, distPivot), r(e));
+                if (d < minD) minD = d;
             }
-            if (d < minD) minD = d;
         }
         return minD;
     }

+ 15 - 5
src/mol-model/structure/structure/unit.ts

@@ -29,9 +29,9 @@ namespace Unit {
 
     export function create(id: number, kind: Kind, model: Model, operator: SymmetryOperator, elements: StructureElement.Set): Unit {
         switch (kind) {
-            case Kind.Atomic: return new Atomic(id, unitIdFactory(), model, elements, SymmetryOperator.createMapping(operator, model.atomicConformation), AtomicProperties());
-            case Kind.Spheres: return createCoarse(id, unitIdFactory(), model, Kind.Spheres, elements, SymmetryOperator.createMapping(operator, model.coarseConformation.spheres));
-            case Kind.Gaussians: return createCoarse(id, unitIdFactory(), model, Kind.Gaussians, elements, SymmetryOperator.createMapping(operator, model.coarseConformation.gaussians));
+            case Kind.Atomic: return new Atomic(id, unitIdFactory(), model, elements, SymmetryOperator.createMapping(operator, model.atomicConformation, void 0), AtomicProperties());
+            case Kind.Spheres: return createCoarse(id, unitIdFactory(), model, Kind.Spheres, elements, SymmetryOperator.createMapping(operator, model.coarseConformation.spheres, getSphereRadiusFunc(model)));
+            case Kind.Gaussians: return createCoarse(id, unitIdFactory(), model, Kind.Gaussians, elements, SymmetryOperator.createMapping(operator, model.coarseConformation.gaussians, getGaussianRadiusFunc(model)));
         }
     }
 
@@ -64,6 +64,16 @@ namespace Unit {
         readonly lookup3d: Lookup3D
     }
 
+    function getSphereRadiusFunc(model: Model) {
+        const r = model.coarseConformation.spheres.radius;
+        return (i: number) => r[i];
+    }
+
+    function getGaussianRadiusFunc(model: Model) {
+        // TODO: compute radius for gaussians
+        return (i: number) => 0;
+    }
+
     const unitIdFactory = idFactory();
 
     // A bulding block of a structure that corresponds
@@ -95,7 +105,7 @@ namespace Unit {
 
         applyOperator(id: number, operator: SymmetryOperator, dontCompose = false): Unit {
             const op = dontCompose ? operator : SymmetryOperator.compose(this.conformation.operator, operator);
-            return new Atomic(id, this.invariantId, this.model, this.elements, SymmetryOperator.createMapping(op, this.model.atomicConformation), this.props);
+            return new Atomic(id, this.invariantId, this.model, this.elements, SymmetryOperator.createMapping(op, this.model.atomicConformation, this.conformation.r), this.props);
         }
 
         get lookup3d() {
@@ -163,7 +173,7 @@ namespace Unit {
 
         applyOperator(id: number, operator: SymmetryOperator, dontCompose = false): Unit {
             const op = dontCompose ? operator : SymmetryOperator.compose(this.conformation.operator, operator);
-            const ret = createCoarse(id, this.invariantId, this.model, this.kind, this.elements, SymmetryOperator.createMapping(op, this.getCoarseElements()));
+            const ret = createCoarse(id, this.invariantId, this.model, this.kind, this.elements, SymmetryOperator.createMapping(op, this.getCoarseElements(), this.conformation.r));
             (ret as Coarse<K, C>)._lookup3d = this._lookup3d;
             return ret;
         }