Переглянути джерело

Merge branch 'master' of https://github.com/molstar/molstar into lighting

Alexander Rose 3 роки тому
батько
коміт
fdc006f833

+ 2 - 0
CHANGELOG.md

@@ -6,6 +6,8 @@ Note that since we don't clearly distinguish between a public and private interf
 
 ## [Unreleased]
 
+- Fix: allow atoms in aromatic rings to do hydrogen bonds
+
 ## [v2.4.0] - 2021-11-25
 
 - Fix secondary-structure property handling

+ 17 - 9
src/mol-geo/geometry/mesh/builder/tube.ts

@@ -6,7 +6,7 @@
  */
 
 import { Vec3 } from '../../../../mol-math/linear-algebra';
-import { ChunkedArray } from '../../../../mol-data/util';
+import { cantorPairing, ChunkedArray } from '../../../../mol-data/util';
 import { MeshBuilder } from '../mesh-builder';
 
 const normalVector = Vec3();
@@ -37,18 +37,20 @@ const v3unitX = Vec3.unitX;
 const caAdd3 = ChunkedArray.add3;
 
 const CosSinCache = new Map<number, { cos: number[], sin: number[] }>();
-function getCosSin(radialSegments: number) {
-    if (!CosSinCache.has(radialSegments)) {
+function getCosSin(radialSegments: number, shift: boolean) {
+    const offset = shift ? 1 : 0;
+    const hash = cantorPairing(radialSegments, offset);
+    if (!CosSinCache.has(hash)) {
         const cos: number[] = [];
         const sin: number[] = [];
         for (let j = 0; j < radialSegments; ++j) {
-            const t = 2 * Math.PI * j / radialSegments;
+            const t = (j * 2 + offset) / radialSegments * Math.PI;
             cos[j] = Math.cos(t);
             sin[j] = Math.sin(t);
         }
-        CosSinCache.set(radialSegments, { cos, sin });
+        CosSinCache.set(hash, { cos, sin });
     }
-    return CosSinCache.get(radialSegments)!;
+    return CosSinCache.get(hash)!;
 }
 
 export function addTube(state: MeshBuilder.State, controlPoints: ArrayLike<number>, normalVectors: ArrayLike<number>, binormalVectors: ArrayLike<number>, linearSegments: number, radialSegments: number, widthValues: ArrayLike<number>, heightValues: ArrayLike<number>, startCap: boolean, endCap: boolean, crossSection: 'elliptical' | 'rounded') {
@@ -56,9 +58,9 @@ export function addTube(state: MeshBuilder.State, controlPoints: ArrayLike<numbe
 
     let vertexCount = vertices.elementCount;
 
-    const { cos, sin } = getCosSin(radialSegments);
+    const { cos, sin } = getCosSin(radialSegments, crossSection === 'rounded');
 
-    const q1 = radialSegments / 4;
+    const q1 = Math.round(radialSegments / 4);
     const q3 = q1 * 3;
 
     for (let i = 0; i <= linearSegments; ++i) {
@@ -78,7 +80,13 @@ export function addTube(state: MeshBuilder.State, controlPoints: ArrayLike<numbe
                     ? (j < q1 || j >= q3) ? height - width : -height + width
                     : (j >= q1 && j < q3) ? -height + width : height - width;
                 v3scaleAndAdd(surfacePoint, surfacePoint, u, h);
-                add2AndScale2(normalVector, u, v, cos[j], sin[j]);
+                if (j === q1 || j === q1 - 1) {
+                    add2AndScale2(normalVector, u, v, 0, 1);
+                } else if (j === q3 || j === q3 - 1) {
+                    add2AndScale2(normalVector, u, v, 0, -1);
+                } else {
+                    add2AndScale2(normalVector, u, v, cos[j], sin[j]);
+                }
             } else {
                 add3AndScale2(surfacePoint, u, v, controlPoint, height * cos[j], width * sin[j]);
                 add2AndScale2(normalVector, u, v, width * cos[j], height * sin[j]);

+ 1 - 7
src/mol-model-props/computed/interactions/hydrogen-bonds.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2019-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2019-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  * @author Fred Ludlow <Fred.Ludlow@astx.com>
@@ -68,11 +68,8 @@ function addUnitHydrogenDonors(structure: Structure, unit: Unit.Atomic, builder:
     const { totalH } = getUnitValenceModel(structure, unit);
     const { elements } = unit;
     const { x, y, z } = unit.model.atomicConformation;
-    const { elementAromaticRingIndices } = unit.rings;
 
     for (let i = 0 as StructureElement.UnitIndex, il = elements.length; i < il; ++i) {
-        if (elementAromaticRingIndices.has(i)) continue;
-
         const element = typeSymbol(unit, i);
         if ((
             // include both nitrogen atoms in histidine due to
@@ -134,15 +131,12 @@ function addUnitHydrogenAcceptors(structure: Structure, unit: Unit.Atomic, build
     const { charge, implicitH, idealGeometry } = getUnitValenceModel(structure, unit);
     const { elements } = unit;
     const { x, y, z } = unit.model.atomicConformation;
-    const { elementAromaticRingIndices } = unit.rings;
 
     const add = (i: StructureElement.UnitIndex) => {
         builder.add(FeatureType.HydrogenAcceptor, FeatureGroup.None, x[elements[i]], y[elements[i]], z[elements[i]], i);
     };
 
     for (let i = 0 as StructureElement.UnitIndex, il = elements.length; i < il; ++i) {
-        if (elementAromaticRingIndices.has(i)) continue;
-
         const element = typeSymbol(unit, i);
         if (element === Elements.O) {
             // Basically assume all oxygen atoms are acceptors!