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 ...@@ -52,7 +52,7 @@ function createPolymerTraceMesh(ctx: VisualContext, unit: Unit, structure: Struc
const isNucleicType = isNucleic(v.moleculeType) const isNucleicType = isNucleic(v.moleculeType)
const isSheet = SecondaryStructureType.is(v.secStrucType, SecondaryStructureType.Flag.Beta) const isSheet = SecondaryStructureType.is(v.secStrucType, SecondaryStructureType.Flag.Beta)
const isHelix = SecondaryStructureType.is(v.secStrucType, SecondaryStructureType.Flag.Helix) 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 const shift = isNucleicType ? 0.3 : 0.5
interpolateCurveSegment(state, v, tension, shift) 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> * @author Alexander Rose <alexander.rose@weirdbyte.de>
*/ */
...@@ -19,6 +19,7 @@ export interface CurveSegmentState { ...@@ -19,6 +19,7 @@ export interface CurveSegmentState {
} }
export interface CurveSegmentControls { export interface CurveSegmentControls {
secStrucFirst: boolean, secStrucLast: boolean
p0: Vec3, p1: Vec3, p2: Vec3, p3: Vec3, p4: Vec3, p0: Vec3, p1: Vec3, p2: Vec3, p3: Vec3, p4: Vec3,
d12: Vec3, d23: Vec3 d12: Vec3, d23: Vec3
} }
...@@ -48,20 +49,25 @@ const curvePoint = Vec3.zero() ...@@ -48,20 +49,25 @@ const curvePoint = Vec3.zero()
export function interpolatePointsAndTangents(state: CurveSegmentState, controls: CurveSegmentControls, tension: number, shift: number) { export function interpolatePointsAndTangents(state: CurveSegmentState, controls: CurveSegmentControls, tension: number, shift: number) {
const { curvePoints, tangentVectors, linearSegments } = state 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 shift1 = 1 - shift
const tensionBeg = secStrucFirst ? 0.5 : tension
const tensionEnd = secStrucLast ? 0.5 : tension
for (let j = 0; j <= linearSegments; ++j) { for (let j = 0; j <= linearSegments; ++j) {
const t = j * 1.0 / linearSegments; const t = j * 1.0 / linearSegments;
if (t < shift1) { if (t < shift1) {
Vec3.spline(curvePoint, p0, p1, p2, p3, t + shift, tension) const te = lerp(tensionBeg, tension, t)
Vec3.spline(tanA, p0, p1, p2, p3, t + shift + 0.01, tension) Vec3.spline(curvePoint, p0, p1, p2, p3, t + shift, te)
Vec3.spline(tanB, p0, p1, p2, p3, t + shift - 0.01, tension) 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 { } else {
Vec3.spline(curvePoint, p1, p2, p3, p4, t - shift1, tension) const te = lerp(tension, tensionEnd, t)
Vec3.spline(tanA, p1, p2, p3, p4, t - shift1 + 0.01, tension) Vec3.spline(curvePoint, p1, p2, p3, p4, t - shift1, te)
Vec3.spline(tanB, p1, p2, p3, p4, t - shift1 - 0.01, tension) 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.toArray(curvePoint, curvePoints, j * 3)
Vec3.normalize(tangentVec, Vec3.sub(tangentVec, tanA, tanB)) Vec3.normalize(tangentVec, Vec3.sub(tangentVec, tanA, tanB))
...@@ -69,17 +75,15 @@ export function interpolatePointsAndTangents(state: CurveSegmentState, controls: ...@@ -69,17 +75,15 @@ export function interpolatePointsAndTangents(state: CurveSegmentState, controls:
} }
} }
const tmpNormal = Vec3.zero() const tmpNormal = Vec3()
const tangentVec = Vec3.zero() const tangentVec = Vec3()
const normalVec = Vec3.zero() const normalVec = Vec3()
const binormalVec = Vec3.zero() const binormalVec = Vec3()
const prevNormal = Vec3.zero() const prevNormal = Vec3()
const firstControlPoint = Vec3.zero() const firstTangentVec = Vec3()
const lastControlPoint = Vec3.zero() const lastTangentVec = Vec3()
const firstTangentVec = Vec3.zero() const firstNormalVec = Vec3()
const lastTangentVec = Vec3.zero() const lastNormalVec = Vec3()
const firstNormalVec = Vec3.zero()
const lastNormalVec = Vec3.zero()
/** /**
* Populate normalVectors by interpolating from firstDirection to lastDirection with * Populate normalVectors by interpolating from firstDirection to lastDirection with
...@@ -91,13 +95,11 @@ export function interpolateNormals(state: CurveSegmentState, controls: CurveSegm ...@@ -91,13 +95,11 @@ export function interpolateNormals(state: CurveSegmentState, controls: CurveSegm
const n = curvePoints.length / 3 const n = curvePoints.length / 3
Vec3.fromArray(firstControlPoint, curvePoints, 0)
Vec3.fromArray(lastControlPoint, curvePoints, (n - 1) * 3)
Vec3.fromArray(firstTangentVec, tangentVectors, 0) 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(firstNormalVec, firstTangentVec, firstDirection)
Vec3.orthogonalize(lastNormalVec, lastTangentVec, Vec3.sub(tmpNormal, lastControlPoint, lastDirection)) Vec3.orthogonalize(lastNormalVec, lastTangentVec, lastDirection)
if (Vec3.dot(firstNormalVec, lastNormalVec) < 0) { if (Vec3.dot(firstNormalVec, lastNormalVec) < 0) {
Vec3.scale(lastNormalVec, lastNormalVec, -1) Vec3.scale(lastNormalVec, lastNormalVec, -1)
......
...@@ -57,13 +57,16 @@ function createPolymerTraceElement (unit: Unit): PolymerTraceElement { ...@@ -57,13 +57,16 @@ function createPolymerTraceElement (unit: Unit): PolymerTraceElement {
moleculeType: MoleculeType.unknown, moleculeType: MoleculeType.unknown,
coarseBackboneFirst: false, coarseBackboneLast: false, coarseBackboneFirst: false, coarseBackboneLast: false,
isCoarseBackbone: false, isCoarseBackbone: false,
p0: Vec3.zero(), p1: Vec3.zero(), p2: Vec3.zero(), p3: Vec3.zero(), p4: Vec3.zero(), p0: Vec3(), p1: Vec3(), p2: Vec3(), p3: Vec3(), p4: Vec3(),
d12: Vec3.create(1, 0, 0), d23: Vec3.create(1, 0, 0), d12: Vec3(), d23: Vec3()
} }
} }
const enum AtomicPolymerTraceIteratorState { nextPolymer, nextResidue } const enum AtomicPolymerTraceIteratorState { nextPolymer, nextResidue }
const tmpVecA = Vec3()
const tmpVecB = Vec3()
export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement> { export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement> {
private value: PolymerTraceElement private value: PolymerTraceElement
private polymerIt: SortedRanges.Iterator<ElementIndex, ResidueIndex> private polymerIt: SortedRanges.Iterator<ElementIndex, ResidueIndex>
...@@ -83,22 +86,23 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement> ...@@ -83,22 +86,23 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement>
private state: AtomicPolymerTraceIteratorState = AtomicPolymerTraceIteratorState.nextPolymer private state: AtomicPolymerTraceIteratorState = AtomicPolymerTraceIteratorState.nextPolymer
private residueAtomSegments: Segmentation<ElementIndex, ResidueIndex> private residueAtomSegments: Segmentation<ElementIndex, ResidueIndex>
private traceElementIndex: ArrayLike<ElementIndex> private traceElementIndex: ArrayLike<ElementIndex>
private directionElementIndex: ArrayLike<ElementIndex | -1> private directionFromElementIndex: ArrayLike<ElementIndex | -1>
private directionToElementIndex: ArrayLike<ElementIndex | -1>
private moleculeType: ArrayLike<MoleculeType> private moleculeType: ArrayLike<MoleculeType>
private atomicConformation: AtomicConformation private atomicConformation: AtomicConformation
private p0 = Vec3.zero(); private p0 = Vec3()
private p1 = Vec3.zero(); private p1 = Vec3()
private p2 = Vec3.zero(); private p2 = Vec3()
private p3 = Vec3.zero(); private p3 = Vec3()
private p4 = Vec3.zero(); private p4 = Vec3()
private p5 = Vec3.zero(); private p5 = Vec3()
private p6 = Vec3.zero(); private p6 = Vec3()
// private v01 = Vec3.zero(); private d01 = Vec3()
private v12 = Vec3.create(1, 0, 0); private d12 = Vec3()
private v23 = Vec3.create(1, 0, 0); private d23 = Vec3()
// private v34 = Vec3.zero(); private d34 = Vec3()
hasNext: boolean = false; hasNext: boolean = false;
...@@ -148,6 +152,20 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement> ...@@ -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() { move() {
const { residueIt, polymerIt, value } = this const { residueIt, polymerIt, value } = this
...@@ -161,7 +179,7 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement> ...@@ -161,7 +179,7 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement>
this.currSecStrucType = SecStrucTypeNA this.currSecStrucType = SecStrucTypeNA
this.nextSecStrucType = this.getSecStruc(this.residueSegmentMin) this.nextSecStrucType = this.getSecStruc(this.residueSegmentMin)
this.currCoarseBackbone = false this.currCoarseBackbone = false
this.nextCoarseBackbone = this.directionElementIndex[this.residueSegmentMin] === -1 this.nextCoarseBackbone = this.directionFromElementIndex[this.residueSegmentMin] === -1 || this.directionToElementIndex[this.residueSegmentMin] === -1
break break
} }
} }
...@@ -175,7 +193,7 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement> ...@@ -175,7 +193,7 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement>
this.prevCoarseBackbone = this.currCoarseBackbone this.prevCoarseBackbone = this.currCoarseBackbone
this.currCoarseBackbone = this.nextCoarseBackbone 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.secStrucType = this.currSecStrucType
value.secStrucFirst = this.prevSecStrucType !== this.currSecStrucType value.secStrucFirst = this.prevSecStrucType !== this.currSecStrucType
...@@ -205,7 +223,9 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement> ...@@ -205,7 +223,9 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement>
this.pos(this.p4, this.traceElementIndex[residueIndexNext1]) this.pos(this.p4, this.traceElementIndex[residueIndexNext1])
this.pos(this.p5, this.traceElementIndex[residueIndexNext2]) 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 { } else {
value.centerPrev.element = value.center.element value.centerPrev.element = value.center.element
value.center.element = value.centerNext.element value.center.element = value.centerNext.element
...@@ -217,12 +237,14 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement> ...@@ -217,12 +237,14 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement>
Vec3.copy(this.p4, this.p5) Vec3.copy(this.p4, this.p5)
Vec3.copy(this.p5, this.p6) 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] value.centerNext.element = this.traceElementIndex[residueIndexNext1]
this.pos(this.p6, this.traceElementIndex[residueIndexNext3]) this.pos(this.p6, this.traceElementIndex[residueIndexNext3])
this.pos(this.v23, this.directionElementIndex[residueIndex]) this.setFromToVector(this.d34, residueIndexNext2)
value.isCoarseBackbone = this.directionElementIndex[residueIndex] === -1 value.isCoarseBackbone = this.directionFromElementIndex[residueIndex] === -1 || this.directionToElementIndex[residueIndex] === -1
this.setControlPoint(value.p0, this.p0, this.p1, this.p2, residueIndexPrev2) this.setControlPoint(value.p0, this.p0, this.p1, this.p2, residueIndexPrev2)
this.setControlPoint(value.p1, this.p1, this.p2, this.p3, residueIndexPrev1) this.setControlPoint(value.p1, this.p1, this.p2, this.p3, residueIndexPrev1)
...@@ -230,8 +252,8 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement> ...@@ -230,8 +252,8 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement>
this.setControlPoint(value.p3, this.p3, this.p4, this.p5, residueIndexNext1) this.setControlPoint(value.p3, this.p3, this.p4, this.p5, residueIndexNext1)
this.setControlPoint(value.p4, this.p4, this.p5, this.p6, residueIndexNext2) this.setControlPoint(value.p4, this.p4, this.p5, this.p6, residueIndexNext2)
Vec3.copy(value.d12, this.v12) this.setDirection(value.d12, this.d01, this.d12, this.d23)
Vec3.copy(value.d23, this.v23) this.setDirection(value.d23, this.d12, this.d23, this.d34)
if (!residueIt.hasNext) { if (!residueIt.hasNext) {
this.state = AtomicPolymerTraceIteratorState.nextPolymer this.state = AtomicPolymerTraceIteratorState.nextPolymer
...@@ -247,7 +269,8 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement> ...@@ -247,7 +269,8 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement>
this.atomicConformation = unit.model.atomicConformation this.atomicConformation = unit.model.atomicConformation
this.residueAtomSegments = unit.model.atomicHierarchy.residueAtomSegments 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.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.moleculeType = unit.model.atomicHierarchy.derived.residue.moleculeType
this.cyclicPolymerMap = unit.model.atomicHierarchy.cyclicPolymerMap this.cyclicPolymerMap = unit.model.atomicHierarchy.cyclicPolymerMap
this.polymerIt = SortedRanges.transientSegments(getPolymerRanges(unit), unit.elements) 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