瀏覽代碼

fix marking of carbohydrate visuals

Alexander Rose 3 年之前
父節點
當前提交
1b79d34907

+ 1 - 0
CHANGELOG.md

@@ -14,6 +14,7 @@ Note that since we don't clearly distinguish between a public and private interf
 - Add Model Export extension
 - Bugfix: Automatically treat empty string as "non-present" value in BinaryCIF writer.
 - Fix coarse model support in entity-id color theme
+- Fix marking of carbohydrate visuals (whole chain could get marked instead of single residue)
 
 ## [v3.0.0-dev.10] - 2022-01-17
 

+ 8 - 3
src/mol-repr/structure/visual/carbohydrate-link-cylinder.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
@@ -101,6 +101,8 @@ function getLinkLoci(pickingId: PickingId, structure: Structure, id: number) {
     return EmptyLoci;
 }
 
+const __linkIndicesSet = new Set<number>();
+
 function eachCarbohydrateLink(loci: Loci, structure: Structure, apply: (interval: Interval) => boolean) {
     let changed = false;
     if (!StructureElement.Loci.is(loci)) return false;
@@ -110,11 +112,14 @@ function eachCarbohydrateLink(loci: Loci, structure: Structure, apply: (interval
     for (const { unit, indices } of loci.elements) {
         if (!Unit.isAtomic(unit)) continue;
 
+        __linkIndicesSet.clear();
         OrderedSet.forEach(indices, v => {
-            // TODO avoid duplicate calls to apply
             const linkIndices = getLinkIndices(unit, unit.elements[v]);
             for (let i = 0, il = linkIndices.length; i < il; ++i) {
-                if (apply(Interval.ofSingleton(linkIndices[i]))) changed = true;
+                if (!__linkIndicesSet.has(linkIndices[i])) {
+                    __linkIndicesSet.add(linkIndices[i]);
+                    if (apply(Interval.ofSingleton(linkIndices[i]))) changed = true;
+                }
             }
         });
     }

+ 10 - 5
src/mol-repr/structure/visual/carbohydrate-symbol-mesh.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
@@ -29,8 +29,8 @@ import { getAltResidueLociFromId } from './util/common';
 import { BaseGeometry } from '../../../mol-geo/geometry/base';
 
 const t = Mat4.identity();
-const sVec = Vec3.zero();
-const pd = Vec3.zero();
+const sVec = Vec3();
+const pd = Vec3();
 
 const SideFactor = 2 * 0.806; // 0.806 == Math.cos(Math.PI / 4)
 
@@ -212,6 +212,8 @@ function getCarbohydrateLoci(pickingId: PickingId, structure: Structure, id: num
     return EmptyLoci;
 }
 
+const __elementIndicesSet = new Set<number>();
+
 /** For each carbohydrate (usually a monosaccharide) when all its residue's elements are in a loci. */
 function eachCarbohydrate(loci: Loci, structure: Structure, apply: (interval: Interval) => boolean) {
     const { getElementIndices } = structure.carbohydrates;
@@ -222,11 +224,14 @@ function eachCarbohydrate(loci: Loci, structure: Structure, apply: (interval: In
     for (const { unit, indices } of loci.elements) {
         if (!Unit.isAtomic(unit)) continue;
 
+        __elementIndicesSet.clear();
         OrderedSet.forEach(indices, v => {
-            // TODO avoid duplicate calls to apply
             const elementIndices = getElementIndices(unit, unit.elements[v]);
             for (let i = 0, il = elementIndices.length; i < il; ++i) {
-                if (apply(Interval.ofSingleton(elementIndices[i] * 2))) changed = true;
+                if (!__elementIndicesSet.has(elementIndices[i])) {
+                    __elementIndicesSet.add(elementIndices[i]);
+                    if (apply(Interval.ofSingleton(elementIndices[i] * 2))) changed = true;
+                }
             }
         });
     }

+ 8 - 3
src/mol-repr/structure/visual/carbohydrate-terminal-link-cylinder.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
@@ -123,6 +123,8 @@ function getTerminalLinkLoci(pickingId: PickingId, structure: Structure, id: num
     return EmptyLoci;
 }
 
+const __linkIndicesSet = new Set<number>();
+
 function eachTerminalLink(loci: Loci, structure: Structure, apply: (interval: Interval) => boolean) {
     let changed = false;
     if (!StructureElement.Loci.is(loci)) return false;
@@ -132,11 +134,14 @@ function eachTerminalLink(loci: Loci, structure: Structure, apply: (interval: In
     for (const { unit, indices } of loci.elements) {
         if (!Unit.isAtomic(unit)) continue;
 
+        __linkIndicesSet.clear();
         OrderedSet.forEach(indices, v => {
-            // TODO avoid duplicate calls to apply
             const linkIndices = getTerminalLinkIndices(unit, unit.elements[v]);
             for (let i = 0, il = linkIndices.length; i < il; ++i) {
-                if (apply(Interval.ofSingleton(linkIndices[i]))) changed = true;
+                if (!__linkIndicesSet.has(linkIndices[i])) {
+                    __linkIndicesSet.add(linkIndices[i]);
+                    if (apply(Interval.ofSingleton(linkIndices[i]))) changed = true;
+                }
             }
         });
     }

+ 2 - 1
src/mol-repr/visual.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2022 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
@@ -88,6 +88,7 @@ namespace Visual {
         const currentStatus = markerStatus.ref.value as MarkerInfo['status'];
 
         if (!isEveryLoci(loci)) {
+            // assume that all interval are non-overlapping
             let intervalSize = 0;
             lociApply(loci, interval => {
                 intervalSize += Interval.size(interval);