diff --git a/src/mol-model-props/computed/interactions/contacts.ts b/src/mol-model-props/computed/interactions/contacts.ts index c7baeb299ee0961e394d18a8510432a5841aaeee..9c85398e1d6058d1d80a4361454d465462c5a1bf 100644 --- a/src/mol-model-props/computed/interactions/contacts.ts +++ b/src/mol-model-props/computed/interactions/contacts.ts @@ -65,9 +65,10 @@ function isMember(element: StructureElement.UnitIndex, info: Features.Info) { return false } -function setPosition(v: Vec3, info: Features.Info) { - Vec3.set(v, info.x[info.feature], info.y[info.feature], info.z[info.feature]) - Vec3.transformMat4(v, v, info.unit.conformation.operator.matrix) +function setPosition(out: Vec3, info: Features.Info) { + Vec3.set(out, info.x[info.feature], info.y[info.feature], info.z[info.feature]) + Vec3.transformMat4(out, out, info.unit.conformation.operator.matrix) + return out } const tmpVec = Vec3() diff --git a/src/mol-model-props/computed/interactions/features.ts b/src/mol-model-props/computed/interactions/features.ts index 9e40471421afe4f139c064bc194c18da0d6a0db1..9bf69761a79ab977636238509c77ba0a44e8cfa9 100644 --- a/src/mol-model-props/computed/interactions/features.ts +++ b/src/mol-model-props/computed/interactions/features.ts @@ -10,6 +10,7 @@ import { GridLookup3D } from '../../../mol-math/geometry'; import { OrderedSet, SortedArray } from '../../../mol-data/int'; import { FeatureGroup, FeatureType } from './common'; import { ValenceModelProvider } from '../valence-model'; +import { Vec3 } from '../../../mol-math/linear-algebra'; export { Features } @@ -40,6 +41,12 @@ namespace Features { /** Index into Features data arrays */ export type FeatureIndex = { readonly '@type': 'feature-index' } & number + export function setPosition(out: Vec3, unit: Unit, index: FeatureIndex, features: Features) { + Vec3.set(out, features.x[index], features.y[index], features.z[index]) + Vec3.transformMat4(out, out, unit.conformation.operator.matrix) + return out + } + /** maps unit elements to features, range for unit element i is offsets[i] to offsets[i + 1] */ export type ElementsIndex = { /** feature indices */ diff --git a/src/mol-model/loci.ts b/src/mol-model/loci.ts index c379ae8eef94ba3db53757e23657d41cd8ebe0e2..b3771c937c43dc87883f66196f5ddc23e4df2fbd 100644 --- a/src/mol-model/loci.ts +++ b/src/mol-model/loci.ts @@ -15,6 +15,7 @@ import { Structure } from './structure/structure'; import { PrincipalAxes } from '../mol-math/linear-algebra/matrix/principal-axes'; import { ParamDefinition } from '../mol-util/param-definition'; import { Interactions } from '../mol-model-props/computed/interactions/interactions'; +import { Features } from '../mol-model-props/computed/interactions/features'; /** A Loci that includes every loci */ export const EveryLoci = { kind: 'every-loci' as 'every-loci' } @@ -118,7 +119,7 @@ namespace Loci { return loci } - const sphereHelper = new CentroidHelper(), tempPos = Vec3.zero(); + const sphereHelper = new CentroidHelper(), tmpPos = Vec3.zero(); export function getBoundingSphere(loci: Loci, boundingSphere?: Sphere3D): Sphere3D | undefined { if (loci.kind === 'every-loci' || loci.kind === 'empty-loci') return void 0; @@ -129,24 +130,36 @@ namespace Loci { if (loci.kind === 'structure-loci') { return Sphere3D.copy(boundingSphere, loci.structure.boundary.sphere) } else if (loci.kind === 'element-loci') { - return StructureElement.Loci.getBoundary(loci).sphere; + return Sphere3D.copy(boundingSphere, StructureElement.Loci.getBoundary(loci).sphere); } else if (loci.kind === 'bond-loci') { for (const e of loci.bonds) { - e.aUnit.conformation.position(e.aUnit.elements[e.aIndex], tempPos); - sphereHelper.includeStep(tempPos); - e.bUnit.conformation.position(e.bUnit.elements[e.bIndex], tempPos); - sphereHelper.includeStep(tempPos); + e.aUnit.conformation.position(e.aUnit.elements[e.aIndex], tmpPos); + sphereHelper.includeStep(tmpPos); + e.bUnit.conformation.position(e.bUnit.elements[e.bIndex], tmpPos); + sphereHelper.includeStep(tmpPos); } sphereHelper.finishedIncludeStep(); for (const e of loci.bonds) { - e.aUnit.conformation.position(e.aUnit.elements[e.aIndex], tempPos); - sphereHelper.radiusStep(tempPos); - e.aUnit.conformation.position(e.bUnit.elements[e.bIndex], tempPos); - sphereHelper.radiusStep(tempPos); + e.aUnit.conformation.position(e.aUnit.elements[e.aIndex], tmpPos); + sphereHelper.radiusStep(tmpPos); + e.aUnit.conformation.position(e.bUnit.elements[e.bIndex], tmpPos); + sphereHelper.radiusStep(tmpPos); } } else if (loci.kind === 'interaction-loci') { - // TODO - // return Interactions.Loci.getBoundary(loci).sphere; + const { unitsFeatures } = loci.interactions + for (const e of loci.contacts) { + Features.setPosition(tmpPos, e.unitA, e.indexA, unitsFeatures.get(e.unitA.id)) + sphereHelper.includeStep(tmpPos) + Features.setPosition(tmpPos, e.unitB, e.indexB, unitsFeatures.get(e.unitB.id)) + sphereHelper.includeStep(tmpPos); + } + sphereHelper.finishedIncludeStep(); + for (const e of loci.contacts) { + Features.setPosition(tmpPos, e.unitA, e.indexA, unitsFeatures.get(e.unitA.id)) + sphereHelper.radiusStep(tmpPos) + Features.setPosition(tmpPos, e.unitB, e.indexB, unitsFeatures.get(e.unitB.id)) + sphereHelper.radiusStep(tmpPos); + } } else if (loci.kind === 'shape-loci') { // TODO return void 0;