Browse Source

hashCode for bonds to avoid re-creating repr

- TODO might be better solved with a unique id/version/identity check when unit bond can be reused
Alexander Rose 4 years ago
parent
commit
aaed0a9a63

+ 29 - 3
src/mol-math/graph/int-adjacency-graph.ts

@@ -1,11 +1,11 @@
 /**
- * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author David Sehnal <david.sehnal@gmail.com>
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-import { arrayPickIndices, cantorPairing } from '../../mol-data/util';
+import { arrayPickIndices, cantorPairing, hashFnv32a, hash1 } from '../../mol-data/util';
 import { LinkedIndex, SortedArray } from '../../mol-data/int';
 import { AssignableArrayLike } from '../../mol-util/type-helpers';
 
@@ -23,7 +23,8 @@ export interface IntAdjacencyGraph<VertexIndex extends number, EdgeProps extends
     readonly b: ArrayLike<VertexIndex>,
     readonly vertexCount: number,
     readonly edgeCount: number,
-    readonly edgeProps: Readonly<EdgeProps>
+    readonly edgeProps: Readonly<EdgeProps>,
+    readonly hashCode: number,
 
     /**
      * Get the edge index between i-th and j-th vertex.
@@ -52,6 +53,31 @@ export namespace IntAdjacencyGraph {
         readonly vertexCount: number;
         readonly edgeProps: EdgeProps;
 
+        private _hashCode = -1;
+        private computeHash() {
+            let hash = 23;
+            hash = (31 * hash + hashFnv32a(this.a)) | 0;
+            hash = (31 * hash + hashFnv32a(this.b)) | 0;
+            hash = (31 * hash + hashFnv32a(this.offset)) | 0;
+            for (const k in this.edgeProps) {
+                if (typeof this.edgeProps[k][0] === 'string') {
+                    // TODO
+                    hash = (31 * hash + this.edgeProps[k].length) | 0;
+                } else {
+                    hash = (31 * hash + hashFnv32a(this.edgeProps[k])) | 0;
+                }
+            }
+            hash = hash1(hash);
+            if (hash === -1) hash = 0;
+            this._hashCode = hash;
+            return hash;
+        }
+
+        get hashCode() {
+            if (this._hashCode !== -1) return this._hashCode;
+            return this.computeHash();
+        }
+
         getEdgeIndex(i: VertexIndex, j: VertexIndex): number {
             let a, b;
             if (i < j) {

+ 12 - 2
src/mol-repr/structure/visual/bond-intra-unit-cylinder.ts

@@ -13,7 +13,7 @@ import { Mesh } from '../../../mol-geo/geometry/mesh/mesh';
 import { Vec3 } from '../../../mol-math/linear-algebra';
 import { BitFlags, arrayEqual } from '../../../mol-util';
 import { createLinkCylinderMesh, LinkStyle } from './util/link';
-import { UnitsMeshParams, UnitsVisual, UnitsMeshVisual } from '../units-visual';
+import { UnitsMeshParams, UnitsVisual, UnitsMeshVisual, StructureGroup } from '../units-visual';
 import { VisualUpdateState } from '../../util';
 import { isHydrogen } from './util/common';
 import { BondType } from '../../../mol-model/structure/model/types';
@@ -114,7 +114,7 @@ export function IntraUnitBondCylinderVisual(materialId: number): UnitsVisual<Int
         createLocationIterator: BondIterator.fromGroup,
         getLoci: getIntraBondLoci,
         eachLocation: eachIntraBond,
-        setUpdateState: (state: VisualUpdateState, newProps: PD.Values<IntraUnitBondCylinderParams>, currentProps: PD.Values<IntraUnitBondCylinderParams>) => {
+        setUpdateState: (state: VisualUpdateState, newProps: PD.Values<IntraUnitBondCylinderParams>, currentProps: PD.Values<IntraUnitBondCylinderParams>, newTheme: Theme, currentTheme: Theme, newStructureGroup: StructureGroup, currentStructureGroup: StructureGroup) => {
             state.createGeometry = (
                 newProps.sizeFactor !== currentProps.sizeFactor ||
                 newProps.sizeAspectRatio !== currentProps.sizeAspectRatio ||
@@ -126,6 +126,16 @@ export function IntraUnitBondCylinderVisual(materialId: number): UnitsVisual<Int
                 !arrayEqual(newProps.includeTypes, currentProps.includeTypes) ||
                 !arrayEqual(newProps.excludeTypes, currentProps.excludeTypes)
             );
+
+            const newUnit = newStructureGroup.group.units[0];
+            const currentUnit = currentStructureGroup.group.units[0];
+            if (Unit.isAtomic(newUnit) && Unit.isAtomic(currentUnit)) {
+                if (newUnit.bonds.hashCode !== currentUnit.bonds.hashCode) {
+                    state.createGeometry = true;
+                    state.updateColor = true;
+                    state.updateSize = true;
+                }
+            }
         }
     }, materialId);
 }

+ 12 - 2
src/mol-repr/structure/visual/bond-intra-unit-line.ts

@@ -11,7 +11,7 @@ import { Theme } from '../../../mol-theme/theme';
 import { Vec3 } from '../../../mol-math/linear-algebra';
 import { BitFlags, arrayEqual } from '../../../mol-util';
 import { LinkStyle, createLinkLines } from './util/link';
-import { UnitsVisual, UnitsLinesParams, UnitsLinesVisual } from '../units-visual';
+import { UnitsVisual, UnitsLinesParams, UnitsLinesVisual, StructureGroup } from '../units-visual';
 import { VisualUpdateState } from '../../util';
 import { isHydrogen } from './util/common';
 import { BondType } from '../../../mol-model/structure/model/types';
@@ -111,7 +111,7 @@ export function IntraUnitBondLineVisual(materialId: number): UnitsVisual<IntraUn
         createLocationIterator: BondIterator.fromGroup,
         getLoci: getIntraBondLoci,
         eachLocation: eachIntraBond,
-        setUpdateState: (state: VisualUpdateState, newProps: PD.Values<IntraUnitBondLineParams>, currentProps: PD.Values<IntraUnitBondLineParams>) => {
+        setUpdateState: (state: VisualUpdateState, newProps: PD.Values<IntraUnitBondLineParams>, currentProps: PD.Values<IntraUnitBondLineParams>, newTheme: Theme, currentTheme: Theme, newStructureGroup: StructureGroup, currentStructureGroup: StructureGroup) => {
             state.createGeometry = (
                 newProps.sizeFactor !== currentProps.sizeFactor ||
                 newProps.linkScale !== currentProps.linkScale ||
@@ -120,6 +120,16 @@ export function IntraUnitBondLineVisual(materialId: number): UnitsVisual<IntraUn
                 !arrayEqual(newProps.includeTypes, currentProps.includeTypes) ||
                 !arrayEqual(newProps.excludeTypes, currentProps.excludeTypes)
             );
+
+            const newUnit = newStructureGroup.group.units[0];
+            const currentUnit = currentStructureGroup.group.units[0];
+            if (Unit.isAtomic(newUnit) && Unit.isAtomic(currentUnit)) {
+                if (newUnit.bonds.hashCode !== currentUnit.bonds.hashCode) {
+                    state.createGeometry = true;
+                    state.updateColor = true;
+                    state.updateSize = true;
+                }
+            }
         }
     }, materialId);
 }