Browse Source

mol-math: IntAdjacencyGraph.areEqual, remove hashCode

David Sehnal 4 years ago
parent
commit
bdde2cea31

+ 31 - 27
src/mol-math/graph/int-adjacency-graph.ts

@@ -5,7 +5,7 @@
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
 
-import { arrayPickIndices, cantorPairing, hashFnv32a, hash1 } from '../../mol-data/util';
+import { arrayPickIndices, cantorPairing } from '../../mol-data/util';
 import { LinkedIndex, SortedArray } from '../../mol-data/int';
 import { AssignableArrayLike } from '../../mol-util/type-helpers';
 
@@ -23,8 +23,7 @@ export interface IntAdjacencyGraph<VertexIndex extends number, EdgeProps extends
     readonly b: ArrayLike<VertexIndex>,
     readonly vertexCount: number,
     readonly edgeCount: number,
-    readonly edgeProps: Readonly<EdgeProps>,
-    readonly hashCode: number,
+    readonly edgeProps: Readonly<EdgeProps>
 
     /**
      * Get the edge index between i-th and j-th vertex.
@@ -49,35 +48,40 @@ export interface IntAdjacencyGraph<VertexIndex extends number, EdgeProps extends
 export namespace IntAdjacencyGraph {
     export type EdgePropsBase = { [name: string]: ArrayLike<any> }
 
-    class IntGraphImpl<VertexIndex extends number, EdgeProps extends IntAdjacencyGraph.EdgePropsBase> implements IntAdjacencyGraph<VertexIndex, EdgeProps> {
-        readonly vertexCount: number;
-        readonly edgeProps: EdgeProps;
+    export function areEqual<I extends number, P extends IntAdjacencyGraph.EdgePropsBase>(a: IntAdjacencyGraph<I, P>, b: IntAdjacencyGraph<I, P>) {
+        if (a.vertexCount !== b.vertexCount || a.edgeCount !== b.edgeCount) return false;
 
-        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;
+        const { a: aa, b: ab, offset: ao } = a;
+        const { a: ba, b: bb, offset: bo } = b;
+
+        for (let i = 0, _i = a.a.length; i < _i; i++) {
+            if (aa[i] !== ba[i]) return false;
         }
 
-        get hashCode() {
-            if (this._hashCode !== -1) return this._hashCode;
-            return this.computeHash();
+        for (let i = 0, _i = a.b.length; i < _i; i++) {
+            if (ab[i] !== bb[i]) return false;
         }
 
+        for (let i = 0, _i = a.offset.length; i < _i; i++) {
+            if (ao[i] !== bo[i]) return false;
+        }
+
+        for (const k of Object.keys(a.edgeProps)) {
+            const pa = a.edgeProps[k], pb = b.edgeProps[k];
+            if (!pb) return false;
+
+            for (let i = 0, _i = pa.length; i < _i; i++) {
+                if (pa[i] !== pb[i]) return false;
+            }
+        }
+
+        return true;
+    }
+
+    class IntGraphImpl<VertexIndex extends number, EdgeProps extends IntAdjacencyGraph.EdgePropsBase> implements IntAdjacencyGraph<VertexIndex, EdgeProps> {
+        readonly vertexCount: number;
+        readonly edgeProps: EdgeProps;
+
         getEdgeIndex(i: VertexIndex, j: VertexIndex): number {
             let a, b;
             if (i < j) {

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

@@ -19,6 +19,7 @@ import { isHydrogen } from './util/common';
 import { BondType } from '../../../mol-model/structure/model/types';
 import { ignoreBondType, BondCylinderParams, BondIterator, eachIntraBond, getIntraBondLoci } from './util/bond';
 import { Sphere3D } from '../../../mol-math/geometry';
+import { IntAdjacencyGraph } from '../../../mol-math/graph';
 
 function createIntraUnitBondCylinderMesh(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: PD.Values<IntraUnitBondCylinderParams>, mesh?: Mesh) {
     if (!Unit.isAtomic(unit)) return Mesh.createEmpty(mesh);
@@ -130,7 +131,7 @@ export function IntraUnitBondCylinderVisual(materialId: number): UnitsVisual<Int
             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) {
+                if (!IntAdjacencyGraph.areEqual(newUnit.bonds, currentUnit.bonds)) {
                     state.createGeometry = true;
                     state.updateColor = true;
                     state.updateSize = true;

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

@@ -18,6 +18,7 @@ import { BondType } from '../../../mol-model/structure/model/types';
 import { ignoreBondType, BondIterator, BondLineParams, getIntraBondLoci, eachIntraBond } from './util/bond';
 import { Sphere3D } from '../../../mol-math/geometry';
 import { Lines } from '../../../mol-geo/geometry/lines/lines';
+import { IntAdjacencyGraph } from '../../../mol-math/graph';
 
 function createIntraUnitBondLines(ctx: VisualContext, unit: Unit, structure: Structure, theme: Theme, props: PD.Values<IntraUnitBondLineParams>, lines?: Lines) {
     if (!Unit.isAtomic(unit)) return Lines.createEmpty(lines);
@@ -124,7 +125,7 @@ export function IntraUnitBondLineVisual(materialId: number): UnitsVisual<IntraUn
             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) {
+                if (!IntAdjacencyGraph.areEqual(newUnit.bonds, currentUnit.bonds)) {
                     state.createGeometry = true;
                     state.updateColor = true;
                     state.updateSize = true;