Przeglądaj źródła

move delocalizedTriplets code to unit.resonance

Alexander Rose 3 lat temu
rodzic
commit
b6e142f04c

+ 8 - 0
src/mol-model/structure/structure/unit.ts

@@ -25,6 +25,7 @@ import { Mat4, Vec3 } from '../../../mol-math/linear-algebra';
 import { IndexPairBonds } from '../../../mol-model-formats/structure/property/bonds/index-pair';
 import { ElementSetIntraBondCache } from './unit/bonds/element-set-intra-bond-cache';
 import { ModelSymmetry } from '../../../mol-model-formats/structure/property/symmetry';
+import { getResonance, UnitResonance } from './unit/resonance';
 
 /**
  * A building block of a structure that corresponds to an atomic or
@@ -282,6 +283,12 @@ namespace Unit {
             return this.props.rings;
         }
 
+        get resonance() {
+            if (this.props.resonance) return this.props.resonance;
+            this.props.resonance = getResonance(this);
+            return this.props.resonance;
+        }
+
         get polymerElements() {
             if (this.props.polymerElements) return this.props.polymerElements;
             this.props.polymerElements = getAtomicPolymerElements(this);
@@ -342,6 +349,7 @@ namespace Unit {
     interface AtomicProperties extends BaseProperties {
         bonds?: IntraUnitBonds
         rings?: UnitRings
+        resonance?: UnitResonance
         nucleotideElements?: SortedArray<ElementIndex>
         proteinElements?: SortedArray<ElementIndex>
         residueCount?: number

+ 65 - 0
src/mol-model/structure/structure/unit/resonance.ts

@@ -0,0 +1,65 @@
+/**
+ * Copyright (c) 2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ *
+ * @author Alexander Rose <alexander.rose@weirdbyte.de>
+ */
+
+import { sortedCantorPairing } from '../../../../mol-data/util';
+import { BondType } from '../../model/types';
+import { StructureElement } from '../element';
+import { Unit } from '../unit';
+
+export type UnitResonance = {
+    /**
+     * Lookup for triplets of atoms in delocalized bonds.
+     *
+     * Does not include triplets that are part of aromatic rings.
+     */
+    delocalizedTriplets: {
+        /** Return 3rd element in triplet or undefined if `a` and `b` are not part of a triplet */
+        getThirdElement: (a: StructureElement.UnitIndex, b: StructureElement.UnitIndex) => StructureElement.UnitIndex | undefined
+    }
+}
+
+export function getResonance(unit: Unit.Atomic) {
+    return {
+        delocalizedTriplets: getDelocalizedTriplets(unit)
+    };
+}
+
+function getDelocalizedTriplets(unit: Unit.Atomic) {
+    const bonds = unit.bonds;
+    const { b, edgeProps, offset } = bonds;
+    const { order: _order, flags: _flags } = edgeProps;
+    const { elementAromaticRingIndices } = unit.rings;
+
+    const map = new Map<number, StructureElement.UnitIndex>();
+
+    for (let i = 0 as StructureElement.UnitIndex; i < unit.elements.length; i++) {
+        if (elementAromaticRingIndices.has(i)) continue;
+
+        const count = offset[i + 1] - offset[i] + 1;
+        if (count < 2) continue;
+
+        const deloBonds: StructureElement.UnitIndex[] = [];
+        for (let t = offset[i], _t = offset[i + 1]; t < _t; t++) {
+            const f = _flags[t];
+            if (!BondType.is(f, BondType.Flag.Aromatic)) continue;
+
+            deloBonds.push(b[t]);
+        }
+
+        if (deloBonds.length >= 2) {
+            map.set(sortedCantorPairing(i, deloBonds[0]), deloBonds[1]);
+            for (let j = 1, jl = deloBonds.length; j < jl; j++) {
+                map.set(sortedCantorPairing(i, deloBonds[j]), deloBonds[0]);
+            }
+        }
+    }
+
+    return {
+        getThirdElement: (a: StructureElement.UnitIndex, b: StructureElement.UnitIndex) => {
+            return map.get(sortedCantorPairing(a, b));
+        }
+    };
+}

+ 5 - 9
src/mol-repr/structure/visual/bond-intra-unit-cylinder.ts

@@ -16,7 +16,7 @@ import { createLinkCylinderImpostors, createLinkCylinderMesh, LinkBuilderProps,
 import { UnitsMeshParams, UnitsVisual, UnitsMeshVisual, UnitsCylindersParams, UnitsCylindersVisual } from '../units-visual';
 import { VisualUpdateState } from '../../util';
 import { BondType } from '../../../mol-model/structure/model/types';
-import { BondCylinderParams, BondIterator, eachIntraBond, getDelocalizedTriplets, getIntraBondLoci, ignoreBondType, makeIntraBondIgnoreTest } from './util/bond';
+import { BondCylinderParams, BondIterator, eachIntraBond, getIntraBondLoci, ignoreBondType, makeIntraBondIgnoreTest } from './util/bond';
 import { Sphere3D } from '../../../mol-math/geometry';
 import { IntAdjacencyGraph } from '../../../mol-math/graph';
 import { WebGLContext } from '../../../mol-gl/webgl/context';
@@ -79,19 +79,15 @@ function getIntraUnitBondCylinderBuilderProps(unit: Unit.Atomic, structure: Stru
     };
 
     const { elementRingIndices, elementAromaticRingIndices } = unit.rings;
-    const deloTriplets = aromaticBonds ? getDelocalizedTriplets(unit) : undefined;
+    const deloTriplets = aromaticBonds ? unit.resonance.delocalizedTriplets : undefined;
 
     return {
         linkCount: edgeCount * 2,
         referencePosition: (edgeIndex: number) => {
             let aI = a[edgeIndex], bI = b[edgeIndex];
 
-            if (deloTriplets) {
-                const rI = deloTriplets.get(aI, bI);
-                if (rI !== undefined) {
-                    return pos(elements[rI], vRef);
-                }
-            }
+            const rI = deloTriplets?.getThirdElement(aI, bI);
+            if (rI !== undefined) return pos(elements[rI], vRef);
 
             if (aI > bI) [aI, bI] = [bI, aI];
             if (offset[aI + 1] - offset[aI] === 1) [aI, bI] = [bI, aI];
@@ -153,7 +149,7 @@ function getIntraUnitBondCylinderBuilderProps(unit: Unit.Atomic, structure: Stru
                 if (isBondType(f, BondType.Flag.Aromatic) || (arCount && !ignoreComputedAromatic)) {
                     if (arCount === 2) {
                         return LinkStyle.MirroredAromatic;
-                    } else if (arCount === 1 || deloTriplets?.get(aI, bI)) {
+                    } else if (arCount === 1 || deloTriplets?.getThirdElement(aI, bI)) {
                         return LinkStyle.Aromatic;
                     } else {
                         // case for bonds between two aromatic rings

+ 5 - 9
src/mol-repr/structure/visual/bond-intra-unit-line.ts

@@ -14,7 +14,7 @@ import { LinkStyle, createLinkLines, LinkBuilderProps } from './util/link';
 import { UnitsVisual, UnitsLinesParams, UnitsLinesVisual } from '../units-visual';
 import { VisualUpdateState } from '../../util';
 import { BondType } from '../../../mol-model/structure/model/types';
-import { BondIterator, BondLineParams, getIntraBondLoci, eachIntraBond, makeIntraBondIgnoreTest, ignoreBondType, getDelocalizedTriplets } from './util/bond';
+import { BondIterator, BondLineParams, getIntraBondLoci, eachIntraBond, makeIntraBondIgnoreTest, ignoreBondType } from './util/bond';
 import { Sphere3D } from '../../../mol-math/geometry';
 import { Lines } from '../../../mol-geo/geometry/lines/lines';
 import { IntAdjacencyGraph } from '../../../mol-math/graph';
@@ -52,19 +52,15 @@ function createIntraUnitBondLines(ctx: VisualContext, unit: Unit, structure: Str
     const pos = unit.conformation.invariantPosition;
 
     const { elementRingIndices, elementAromaticRingIndices } = unit.rings;
-    const deloTriplets = aromaticBonds ? getDelocalizedTriplets(unit) : undefined;
+    const deloTriplets = aromaticBonds ? unit.resonance.delocalizedTriplets : undefined;
 
     const builderProps: LinkBuilderProps = {
         linkCount: edgeCount * 2,
         referencePosition: (edgeIndex: number) => {
             let aI = a[edgeIndex], bI = b[edgeIndex];
 
-            if (deloTriplets) {
-                const rI = deloTriplets.get(aI, bI);
-                if (rI !== undefined) {
-                    return pos(elements[rI], vRef);
-                }
-            }
+            const rI = deloTriplets?.getThirdElement(aI, bI);
+            if (rI !== undefined) return pos(elements[rI], vRef);
 
             if (aI > bI) [aI, bI] = [bI, aI];
             if (offset[aI + 1] - offset[aI] === 1) [aI, bI] = [bI, aI];
@@ -114,7 +110,7 @@ function createIntraUnitBondLines(ctx: VisualContext, unit: Unit, structure: Str
                 if (isBondType(f, BondType.Flag.Aromatic) || (arCount && !ignoreComputedAromatic)) {
                     if (arCount === 2) {
                         return LinkStyle.MirroredAromatic;
-                    } else if (arCount === 1 || deloTriplets?.get(aI, bI)) {
+                    } else if (arCount === 1 || deloTriplets?.getThirdElement(aI, bI)) {
                         return LinkStyle.Aromatic;
                     } else {
                         // case for bonds between two aromatic rings

+ 0 - 46
src/mol-repr/structure/visual/util/bond.ts

@@ -14,7 +14,6 @@ import { PickingId } from '../../../../mol-geo/geometry/picking';
 import { EmptyLoci, Loci } from '../../../../mol-model/loci';
 import { Interval, OrderedSet, SortedArray } from '../../../../mol-data/int';
 import { isH, isHydrogen, StructureGroup } from './common';
-import { sortedCantorPairing } from '../../../../mol-data/util';
 
 export const BondParams = {
     includeTypes: PD.MultiSelect(ObjectKeys(BondType.Names), PD.objectToOptions(BondType.Names)),
@@ -266,48 +265,3 @@ export function eachInterBond(loci: Loci, structure: Structure, apply: (interval
     }
     return changed;
 }
-
-//
-
-/**
- * Get a lookup for triplets of atoms in delocalized bonds.
- *
- * Does not include triplets that are part of aromatic rings
- */
-export function getDelocalizedTriplets(unit: Unit.Atomic) {
-    const bonds = unit.bonds;
-    const { b, edgeProps, offset } = bonds;
-    const { order: _order, flags: _flags } = edgeProps;
-    const { elementAromaticRingIndices } = unit.rings;
-
-    const map = new Map<number, StructureElement.UnitIndex>();
-
-    for (let i = 0 as StructureElement.UnitIndex; i < unit.elements.length; i++) {
-        if (elementAromaticRingIndices.has(i)) continue;
-
-        const count = offset[i + 1] - offset[i] + 1;
-        if (count < 2) continue;
-
-        const deloBonds: StructureElement.UnitIndex[] = [];
-        for (let t = offset[i], _t = offset[i + 1]; t < _t; t++) {
-            const f = _flags[t];
-            if (!BondType.is(f, BondType.Flag.Aromatic)) continue;
-
-            deloBonds.push(b[t]);
-        }
-
-        if (deloBonds.length >= 2) {
-            map.set(sortedCantorPairing(i, deloBonds[0]), deloBonds[1]);
-            for (let j = 1, jl = deloBonds.length; j < jl; j++) {
-                map.set(sortedCantorPairing(i, deloBonds[j]), deloBonds[0]);
-            }
-        }
-    }
-
-    return {
-        /** Return 3rd element in triplet or undefined if `a` and `b` are not part of a triplet */
-        get: (a: StructureElement.UnitIndex, b: StructureElement.UnitIndex) => {
-            return map.get(sortedCantorPairing(a, b));
-        }
-    };
-}