Browse Source

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

Alexander Rose 5 years ago
parent
commit
a827e9a449

+ 14 - 0
.vscode/extensions.json

@@ -0,0 +1,14 @@
+{
+	// See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
+	// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
+
+	// List of extensions which should be recommended for users of this workspace.
+	"recommendations": [
+		"ms-vscode.vscode-typescript-tslint-plugin",
+		"slevesque.shader"
+	],
+	// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
+	"unwantedRecommendations": [
+		
+	]
+}

+ 4 - 0
src/mol-math/linear-algebra/3d/quat.ts

@@ -435,6 +435,10 @@ namespace Quat {
 
         return normalize(out, Quat.fromMat3(out, axesTmpMat));
     }
+
+    export function toString(a: Quat, precision?: number) {
+        return `[${a[0].toPrecision(precision)} ${a[1].toPrecision(precision)} ${a[2].toPrecision(precision)}  ${a[3].toPrecision(precision)}]`;
+    }
 }
 
 export default Quat

+ 4 - 0
src/mol-math/linear-algebra/3d/vec2.ts

@@ -166,6 +166,10 @@ namespace Vec2 {
     export function areEqual(a: Vec2, b: Vec2) {
         return a[0] === b[0] && a[1] === b[1];
     }
+
+    export function toString(a: Vec2, precision?: number) {
+        return `[${a[0].toPrecision(precision)} ${a[1].toPrecision(precision)}}]`;
+    }
 }
 
 export default Vec2

+ 11 - 3
src/mol-math/linear-algebra/3d/vec3.ts

@@ -19,7 +19,7 @@
 
 import Mat4 from './mat4';
 import { Quat, Mat3, EPSILON } from '../3d';
-import { spline as _spline, clamp } from '../../interpolate'
+import { spline as _spline, quadraticBezier as _quadraticBezier, clamp } from '../../interpolate'
 import { NumberArray } from '../../../mol-util/type-helpers';
 
 interface Vec3 extends Array<number> { [d: number]: number, '@type': 'vec3', length: 3 }
@@ -344,6 +344,14 @@ namespace Vec3 {
         return out;
     }
 
+    export function quadraticBezier(out: Vec3, a: Vec3, b: Vec3, c: Vec3, t: number) {
+        out[0] = _quadraticBezier(a[0], b[0], c[0], t);
+        out[1] = _quadraticBezier(a[1], b[1], c[1], t);
+        out[2] = _quadraticBezier(a[2], b[2], c[2], t);
+
+        return out;
+    }
+
     /**
      * Performs a spline interpolation with two control points and a tension parameter
      */
@@ -525,8 +533,8 @@ namespace Vec3 {
         return normalize(out, cross(out, triangleNormalTmpAB, triangleNormalTmpAC));
     }
 
-    export function toString(a: Vec3) {
-        return `[${a[0]} ${a[1]} ${a[2]}]`;
+    export function toString(a: Vec3, precision?: number) {
+        return `[${a[0].toPrecision(precision)} ${a[1].toPrecision(precision)} ${a[2].toPrecision(precision)}]`;
     }
 }
 

+ 4 - 0
src/mol-math/linear-algebra/3d/vec4.ts

@@ -225,6 +225,10 @@ namespace Vec4 {
                 Math.abs(a2 - b2) <= EPSILON.Value * Math.max(1.0, Math.abs(a2), Math.abs(b2)) &&
                 Math.abs(a3 - b3) <= EPSILON.Value * Math.max(1.0, Math.abs(a3), Math.abs(b3)));
     }
+
+    export function toString(a: Vec4, precision?: number) {
+        return `[${a[0].toPrecision(precision)} ${a[1].toPrecision(precision)} ${a[2].toPrecision(precision)}  ${a[3].toPrecision(precision)}]`;
+    }
 }
 
 export default Vec4

+ 3 - 2
src/mol-model/structure/model/properties/atomic/hierarchy.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2017-2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2017-2019 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>
@@ -113,7 +113,8 @@ export interface AtomicData {
 export interface AtomicDerivedData {
     readonly residue: {
         readonly traceElementIndex: ArrayLike<ElementIndex | -1>
-        readonly directionElementIndex: ArrayLike<ElementIndex | -1>
+        readonly directionFromElementIndex: ArrayLike<ElementIndex | -1>
+        readonly directionToElementIndex: ArrayLike<ElementIndex | -1>
         readonly moleculeType: ArrayLike<MoleculeType>
     }
 }

+ 9 - 4
src/mol-model/structure/model/properties/utils/atomic-derived.ts

@@ -15,7 +15,8 @@ export function getAtomicDerivedData(data: AtomicData, index: AtomicIndex, chemi
     const { label_comp_id, _rowCount: n } = data.residues
 
     const traceElementIndex = new Int32Array(n)
-    const directionElementIndex = new Int32Array(n)
+    const directionFromElementIndex = new Int32Array(n)
+    const directionToElementIndex = new Int32Array(n)
     const moleculeType = new Uint8Array(n)
 
     const moleculeTypeMap = new Map<string, MoleculeType>()
@@ -44,14 +45,18 @@ export function getAtomicDerivedData(data: AtomicData, index: AtomicIndex, chemi
         }
         traceElementIndex[i] = traceIndex
 
-        const directionAtomId = getAtomIdForAtomRole(molType, 'direction')
-        directionElementIndex[i] = index.findAtomsOnResidue(i as ResidueIndex, directionAtomId)
+        const directionFromAtomId = getAtomIdForAtomRole(molType, 'directionFrom')
+        directionFromElementIndex[i] = index.findAtomsOnResidue(i as ResidueIndex, directionFromAtomId)
+
+        const directionToAtomId = getAtomIdForAtomRole(molType, 'directionTo')
+        directionToElementIndex[i] = index.findAtomsOnResidue(i as ResidueIndex, directionToAtomId)
     }
 
     return {
         residue: {
             traceElementIndex: traceElementIndex as unknown as ArrayLike<ElementIndex | -1>,
-            directionElementIndex: directionElementIndex as unknown as ArrayLike<ElementIndex | -1>,
+            directionFromElementIndex: directionFromElementIndex as unknown as ArrayLike<ElementIndex | -1>,
+            directionToElementIndex: directionToElementIndex as unknown as ArrayLike<ElementIndex | -1>,
             moleculeType: moleculeType as unknown as ArrayLike<MoleculeType>,
         }
     }

+ 9 - 5
src/mol-model/structure/model/types.ts

@@ -59,33 +59,37 @@ export const enum MoleculeType {
     saccharide
 }
 
-export type AtomRole = 'trace' | 'direction' | 'backboneStart' | 'backboneEnd' | 'coarseBackbone'
+export type AtomRole = 'trace' | 'directionFrom' | 'directionTo' | 'backboneStart' | 'backboneEnd' | 'coarseBackbone'
 
 export const MoleculeTypeAtomRoleId: { [k: number]: { [k in AtomRole]: Set<string> } } = {
     [MoleculeType.protein]: {
         trace: new Set(['CA']),
-        direction: new Set(['O', 'OC1', 'O1', 'OX1', 'OXT']),
+        directionFrom: new Set(['C']),
+        directionTo: new Set(['O', 'OC1', 'O1', 'OX1', 'OXT']),
         backboneStart: new Set(['N']),
         backboneEnd: new Set(['C']),
         coarseBackbone: new Set(['CA', 'BB'])
     },
     [MoleculeType.RNA]: {
         trace: new Set(['C4\'', 'C4*']),
-        direction: new Set(['C3\'', 'C3*']),
+        directionFrom: new Set(['C4\'', 'C4*']),
+        directionTo: new Set(['C3\'', 'C3*']),
         backboneStart: new Set(['P']),
         backboneEnd: new Set(['O3\'', 'O3*']),
         coarseBackbone: new Set(['P'])
     },
     [MoleculeType.DNA]: {
         trace: new Set(['C3\'', 'C3*']),
-        direction: new Set(['C1\'', 'C1*']),
+        directionFrom: new Set(['C3\'', 'C3*']),
+        directionTo: new Set(['C1\'', 'C1*']),
         backboneStart: new Set(['P']),
         backboneEnd: new Set(['O3\'', 'O3*']),
         coarseBackbone: new Set(['P'])
     },
     [MoleculeType.PNA]: {
         trace: new Set(['N4\'', 'N4*']),
-        direction: new Set(['C7\'', 'C7*']),
+        directionFrom: new Set(['N4\'', 'N4*']),
+        directionTo: new Set(['C7\'', 'C7*']),
         backboneStart: new Set(['N1\'', 'N1*']),
         backboneEnd: new Set(['C\'', 'C*']),
         coarseBackbone: new Set(['P'])

+ 1 - 1
src/mol-repr/structure/visual/polymer-trace-mesh.ts

@@ -52,7 +52,7 @@ function createPolymerTraceMesh(ctx: VisualContext, unit: Unit, structure: Struc
         const isNucleicType = isNucleic(v.moleculeType)
         const isSheet = SecondaryStructureType.is(v.secStrucType, SecondaryStructureType.Flag.Beta)
         const isHelix = SecondaryStructureType.is(v.secStrucType, SecondaryStructureType.Flag.Helix)
-        const tension = isNucleicType ? 0.5 : 0.9
+        const tension = isHelix ? 0.9 : 0.5
         const shift = isNucleicType ? 0.3 : 0.5
 
         interpolateCurveSegment(state, v, tension, shift)

+ 26 - 24
src/mol-repr/structure/visual/util/polymer/curve-segment.ts

@@ -1,5 +1,5 @@
 /**
- * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
+ * Copyright (c) 2018-2019 mol* contributors, licensed under MIT, See LICENSE file for more info.
  *
  * @author Alexander Rose <alexander.rose@weirdbyte.de>
  */
@@ -19,6 +19,7 @@ export interface CurveSegmentState {
 }
 
 export interface CurveSegmentControls {
+    secStrucFirst: boolean, secStrucLast: boolean
     p0: Vec3, p1: Vec3, p2: Vec3, p3: Vec3, p4: Vec3,
     d12: Vec3, d23: Vec3
 }
@@ -48,20 +49,25 @@ const curvePoint = Vec3.zero()
 
 export function interpolatePointsAndTangents(state: CurveSegmentState, controls: CurveSegmentControls, tension: number, shift: number) {
     const { curvePoints, tangentVectors, linearSegments } = state
-    const { p0, p1, p2, p3, p4 } = controls
+    const { p0, p1, p2, p3, p4, secStrucFirst, secStrucLast } = controls
 
     const shift1 = 1 - shift
 
+    const tensionBeg = secStrucFirst ? 0.5 : tension
+    const tensionEnd = secStrucLast ? 0.5 : tension
+
     for (let j = 0; j <= linearSegments; ++j) {
         const t = j * 1.0 / linearSegments;
         if (t < shift1) {
-            Vec3.spline(curvePoint, p0, p1, p2, p3, t + shift, tension)
-            Vec3.spline(tanA, p0, p1, p2, p3, t + shift + 0.01, tension)
-            Vec3.spline(tanB, p0, p1, p2, p3, t + shift - 0.01, tension)
+            const te = lerp(tensionBeg, tension, t)
+            Vec3.spline(curvePoint, p0, p1, p2, p3, t + shift, te)
+            Vec3.spline(tanA, p0, p1, p2, p3, t + shift + 0.01, tensionBeg)
+            Vec3.spline(tanB, p0, p1, p2, p3, t + shift - 0.01, tensionBeg)
         } else {
-            Vec3.spline(curvePoint, p1, p2, p3, p4, t - shift1, tension)
-            Vec3.spline(tanA, p1, p2, p3, p4, t - shift1 + 0.01, tension)
-            Vec3.spline(tanB, p1, p2, p3, p4, t - shift1 - 0.01, tension)
+            const te = lerp(tension, tensionEnd, t)
+            Vec3.spline(curvePoint, p1, p2, p3, p4, t - shift1, te)
+            Vec3.spline(tanA, p1, p2, p3, p4, t - shift1 + 0.01, te)
+            Vec3.spline(tanB, p1, p2, p3, p4, t - shift1 - 0.01, te)
         }
         Vec3.toArray(curvePoint, curvePoints, j * 3)
         Vec3.normalize(tangentVec, Vec3.sub(tangentVec, tanA, tanB))
@@ -69,17 +75,15 @@ export function interpolatePointsAndTangents(state: CurveSegmentState, controls:
     }
 }
 
-const tmpNormal = Vec3.zero()
-const tangentVec = Vec3.zero()
-const normalVec = Vec3.zero()
-const binormalVec = Vec3.zero()
-const prevNormal = Vec3.zero()
-const firstControlPoint = Vec3.zero()
-const lastControlPoint = Vec3.zero()
-const firstTangentVec = Vec3.zero()
-const lastTangentVec = Vec3.zero()
-const firstNormalVec = Vec3.zero()
-const lastNormalVec = Vec3.zero()
+const tmpNormal = Vec3()
+const tangentVec = Vec3()
+const normalVec = Vec3()
+const binormalVec = Vec3()
+const prevNormal = Vec3()
+const firstTangentVec = Vec3()
+const lastTangentVec = Vec3()
+const firstNormalVec = Vec3()
+const lastNormalVec = Vec3()
 
 /**
  * Populate normalVectors by interpolating from firstDirection to lastDirection with
@@ -91,13 +95,11 @@ export function interpolateNormals(state: CurveSegmentState, controls: CurveSegm
 
     const n = curvePoints.length / 3
 
-    Vec3.fromArray(firstControlPoint, curvePoints, 0)
-    Vec3.fromArray(lastControlPoint, curvePoints, (n - 1) * 3)
     Vec3.fromArray(firstTangentVec, tangentVectors, 0)
-    Vec3.fromArray(lastTangentVec, tangentVectors,  (n - 1) * 3)
+    Vec3.fromArray(lastTangentVec, tangentVectors, (n - 1) * 3)
 
-    Vec3.orthogonalize(firstNormalVec, firstTangentVec, Vec3.sub(tmpNormal, firstControlPoint, firstDirection))
-    Vec3.orthogonalize(lastNormalVec, lastTangentVec, Vec3.sub(tmpNormal, lastControlPoint, lastDirection))
+    Vec3.orthogonalize(firstNormalVec, firstTangentVec, firstDirection)
+    Vec3.orthogonalize(lastNormalVec, lastTangentVec, lastDirection)
 
     if (Vec3.dot(firstNormalVec, lastNormalVec) < 0) {
         Vec3.scale(lastNormalVec, lastNormalVec, -1)

+ 47 - 24
src/mol-repr/structure/visual/util/polymer/trace-iterator.ts

@@ -57,13 +57,16 @@ function createPolymerTraceElement (unit: Unit): PolymerTraceElement {
         moleculeType: MoleculeType.unknown,
         coarseBackboneFirst: false, coarseBackboneLast: false,
         isCoarseBackbone: false,
-        p0: Vec3.zero(), p1: Vec3.zero(), p2: Vec3.zero(), p3: Vec3.zero(), p4: Vec3.zero(),
-        d12: Vec3.create(1, 0, 0), d23: Vec3.create(1, 0, 0),
+        p0: Vec3(), p1: Vec3(), p2: Vec3(), p3: Vec3(), p4: Vec3(),
+        d12: Vec3(), d23: Vec3()
     }
 }
 
 const enum AtomicPolymerTraceIteratorState { nextPolymer, nextResidue }
 
+const tmpVecA = Vec3()
+const tmpVecB = Vec3()
+
 export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement> {
     private value: PolymerTraceElement
     private polymerIt: SortedRanges.Iterator<ElementIndex, ResidueIndex>
@@ -83,22 +86,23 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement>
     private state: AtomicPolymerTraceIteratorState = AtomicPolymerTraceIteratorState.nextPolymer
     private residueAtomSegments: Segmentation<ElementIndex, ResidueIndex>
     private traceElementIndex: ArrayLike<ElementIndex>
-    private directionElementIndex: ArrayLike<ElementIndex | -1>
+    private directionFromElementIndex: ArrayLike<ElementIndex | -1>
+    private directionToElementIndex: ArrayLike<ElementIndex | -1>
     private moleculeType: ArrayLike<MoleculeType>
     private atomicConformation: AtomicConformation
 
-    private p0 = Vec3.zero();
-    private p1 = Vec3.zero();
-    private p2 = Vec3.zero();
-    private p3 = Vec3.zero();
-    private p4 = Vec3.zero();
-    private p5 = Vec3.zero();
-    private p6 = Vec3.zero();
+    private p0 = Vec3()
+    private p1 = Vec3()
+    private p2 = Vec3()
+    private p3 = Vec3()
+    private p4 = Vec3()
+    private p5 = Vec3()
+    private p6 = Vec3()
 
-    // private v01 = Vec3.zero();
-    private v12 = Vec3.create(1, 0, 0);
-    private v23 = Vec3.create(1, 0, 0);
-    // private v34 = Vec3.zero();
+    private d01 = Vec3()
+    private d12 = Vec3()
+    private d23 = Vec3()
+    private d34 = Vec3()
 
     hasNext: boolean = false;
 
@@ -148,6 +152,20 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement>
         }
     }
 
+    private setFromToVector(out: Vec3, residueIndex: ResidueIndex) {
+        this.pos(tmpVecA, this.directionFromElementIndex[residueIndex])
+        this.pos(tmpVecB, this.directionToElementIndex[residueIndex])
+        Vec3.sub(out, tmpVecB, tmpVecA)
+    }
+
+    private setDirection(out: Vec3, v1: Vec3, v2: Vec3, v3: Vec3) {
+        Vec3.copy(tmpVecA, v1)
+        Vec3.copy(tmpVecB, v3)
+        if (Vec3.dot(v2, tmpVecA) < 0) Vec3.scale(tmpVecA, tmpVecA, -1)
+        if (Vec3.dot(v2, tmpVecB) < 0) Vec3.scale(tmpVecB, tmpVecB, -1)
+        Vec3.scale(out, Vec3.add(out, tmpVecA, Vec3.add(out, tmpVecB, Vec3.add(out, v2, v2))), 1/4)
+    }
+
     move() {
         const { residueIt, polymerIt, value } = this
 
@@ -161,7 +179,7 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement>
                     this.currSecStrucType = SecStrucTypeNA
                     this.nextSecStrucType = this.getSecStruc(this.residueSegmentMin)
                     this.currCoarseBackbone = false
-                    this.nextCoarseBackbone = this.directionElementIndex[this.residueSegmentMin] === -1
+                    this.nextCoarseBackbone = this.directionFromElementIndex[this.residueSegmentMin] === -1 || this.directionToElementIndex[this.residueSegmentMin] === -1
                     break
                 }
             }
@@ -175,7 +193,7 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement>
 
             this.prevCoarseBackbone = this.currCoarseBackbone
             this.currCoarseBackbone = this.nextCoarseBackbone
-            this.nextCoarseBackbone = residueIt.hasNext ? this.directionElementIndex[residueIndex + 1] === -1 : false
+            this.nextCoarseBackbone = residueIt.hasNext ? (this.directionFromElementIndex[residueIndex + 1] === -1 || this.directionToElementIndex[residueIndex + 1] === -1) : false
 
             value.secStrucType = this.currSecStrucType
             value.secStrucFirst = this.prevSecStrucType !== this.currSecStrucType
@@ -205,7 +223,9 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement>
                 this.pos(this.p4, this.traceElementIndex[residueIndexNext1])
                 this.pos(this.p5, this.traceElementIndex[residueIndexNext2])
 
-                this.pos(this.v12, this.directionElementIndex[residueIndexPrev1])
+                this.setFromToVector(this.d01, residueIndexPrev1)
+                this.setFromToVector(this.d12, residueIndex)
+                this.setFromToVector(this.d23, residueIndexNext1)
             } else {
                 value.centerPrev.element = value.center.element
                 value.center.element = value.centerNext.element
@@ -217,12 +237,14 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement>
                 Vec3.copy(this.p4, this.p5)
                 Vec3.copy(this.p5, this.p6)
 
-                Vec3.copy(this.v12, this.v23)
+                Vec3.copy(this.d01, this.d12)
+                Vec3.copy(this.d12, this.d23)
+                Vec3.copy(this.d23, this.d34)
             }
             value.centerNext.element = this.traceElementIndex[residueIndexNext1]
-            this.pos(this.p6,  this.traceElementIndex[residueIndexNext3])
-            this.pos(this.v23, this.directionElementIndex[residueIndex])
-            value.isCoarseBackbone = this.directionElementIndex[residueIndex] === -1
+            this.pos(this.p6, this.traceElementIndex[residueIndexNext3])
+            this.setFromToVector(this.d34, residueIndexNext2)
+            value.isCoarseBackbone = this.directionFromElementIndex[residueIndex] === -1 || this.directionToElementIndex[residueIndex] === -1
 
             this.setControlPoint(value.p0, this.p0, this.p1, this.p2, residueIndexPrev2)
             this.setControlPoint(value.p1, this.p1, this.p2, this.p3, residueIndexPrev1)
@@ -230,8 +252,8 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement>
             this.setControlPoint(value.p3, this.p3, this.p4, this.p5, residueIndexNext1)
             this.setControlPoint(value.p4, this.p4, this.p5, this.p6, residueIndexNext2)
 
-            Vec3.copy(value.d12, this.v12)
-            Vec3.copy(value.d23, this.v23)
+            this.setDirection(value.d12, this.d01, this.d12, this.d23)
+            this.setDirection(value.d23, this.d12, this.d23, this.d34)
 
             if (!residueIt.hasNext) {
                 this.state = AtomicPolymerTraceIteratorState.nextPolymer
@@ -247,7 +269,8 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement>
         this.atomicConformation = unit.model.atomicConformation
         this.residueAtomSegments = unit.model.atomicHierarchy.residueAtomSegments
         this.traceElementIndex = unit.model.atomicHierarchy.derived.residue.traceElementIndex as ArrayLike<ElementIndex> // can assume it won't be -1 for polymer residues
-        this.directionElementIndex = unit.model.atomicHierarchy.derived.residue.directionElementIndex
+        this.directionFromElementIndex = unit.model.atomicHierarchy.derived.residue.directionFromElementIndex
+        this.directionToElementIndex = unit.model.atomicHierarchy.derived.residue.directionToElementIndex
         this.moleculeType = unit.model.atomicHierarchy.derived.residue.moleculeType
         this.cyclicPolymerMap = unit.model.atomicHierarchy.cyclicPolymerMap
         this.polymerIt = SortedRanges.transientSegments(getPolymerRanges(unit), unit.elements)