Skip to content
Snippets Groups Projects
Commit 9b3d2f39 authored by Alexander Rose's avatar Alexander Rose
Browse files

polymer-trace improvements

parent 14cf7cc1
No related branches found
No related tags found
No related merge requests found
......@@ -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)
......
/**
* 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)
......
......@@ -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)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment