diff --git a/src/mol-math/geometry/symmetry-operator.ts b/src/mol-math/geometry/symmetry-operator.ts index 890472d04e189235c56476dfe9af7f93746da1ef..aa575c77289110a74d22d197f439c239c0c37ec0 100644 --- a/src/mol-math/geometry/symmetry-operator.ts +++ b/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 { diff --git a/src/mol-model/structure/structure/structure.ts b/src/mol-model/structure/structure/structure.ts index 32fc551caafadeeca2b6c04f66fc33bb1a12a685..7113f640bb74a5d5d72bc73fc10227c84e0959ca 100644 --- a/src/mol-model/structure/structure/structure.ts +++ b/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; } diff --git a/src/mol-model/structure/structure/unit.ts b/src/mol-model/structure/structure/unit.ts index 8ec99349308a246bf74320c2b517233d85999e8b..3bb205123d1961beddc044f7add9ab6ea7b3bc6c 100644 --- a/src/mol-model/structure/structure/unit.ts +++ b/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; }