diff --git a/src/mol-repr/structure/visual/polymer-trace-mesh.ts b/src/mol-repr/structure/visual/polymer-trace-mesh.ts index 25a0aacf37310b7468b7c702dbb6ece1a97cd2f7..d7a5e39e5750156b45080691c9694589161be0c9 100644 --- a/src/mol-repr/structure/visual/polymer-trace-mesh.ts +++ b/src/mol-repr/structure/visual/polymer-trace-mesh.ts @@ -67,6 +67,9 @@ function createPolymerTraceMesh(ctx: VisualContext, unit: Unit, structure: Struc w2 *= aspectRatio / 2 } + const startCap = v.secStrucFirst || v.coarseBackboneFirst || v.first + const endCap = v.secStrucLast || v.coarseBackboneLast || v.last + if (isSheet) { const h0 = w0 * aspectRatio const h1 = w1 * aspectRatio @@ -78,7 +81,7 @@ function createPolymerTraceMesh(ctx: VisualContext, unit: Unit, structure: Struc if (radialSegments === 2) { addRibbon(builderState, curvePoints, normalVectors, binormalVectors, linearSegments, widthValues, heightValues, arrowHeight) } else { - addSheet(builderState, curvePoints, normalVectors, binormalVectors, linearSegments, widthValues, heightValues, arrowHeight, v.secStrucFirst, v.secStrucLast) + addSheet(builderState, curvePoints, normalVectors, binormalVectors, linearSegments, widthValues, heightValues, arrowHeight, startCap, endCap) } } else { let h0: number, h1: number, h2: number @@ -110,9 +113,9 @@ function createPolymerTraceMesh(ctx: VisualContext, unit: Unit, structure: Struc addRibbon(builderState, curvePoints, normalVectors, binormalVectors, linearSegments, widthValues, heightValues, 0) } } else if (radialSegments === 4) { - addSheet(builderState, curvePoints, normalVectors, binormalVectors, linearSegments, widthValues, heightValues, 0, v.secStrucFirst || v.coarseBackboneFirst, v.secStrucLast || v.coarseBackboneLast) + addSheet(builderState, curvePoints, normalVectors, binormalVectors, linearSegments, widthValues, heightValues, 0, startCap, endCap) } else { - addTube(builderState, curvePoints, normalVectors, binormalVectors, linearSegments, radialSegments, widthValues, heightValues, 1, v.secStrucFirst || v.coarseBackboneFirst, v.secStrucLast || v.coarseBackboneLast) + addTube(builderState, curvePoints, normalVectors, binormalVectors, linearSegments, radialSegments, widthValues, heightValues, 1, startCap, endCap) } } diff --git a/src/mol-repr/structure/visual/polymer-tube-mesh.ts b/src/mol-repr/structure/visual/polymer-tube-mesh.ts index b1025682576f17d664322e2d1d138bdd530c716f..c015f2053cbf19dd1e914debe75e95909d5eee86 100644 --- a/src/mol-repr/structure/visual/polymer-tube-mesh.ts +++ b/src/mol-repr/structure/visual/polymer-tube-mesh.ts @@ -52,6 +52,9 @@ function createPolymerTubeMesh(ctx: VisualContext, unit: Unit, structure: Struct interpolateCurveSegment(state, v, tension, shift) + const startCap = v.secStrucFirst || v.coarseBackboneFirst || v.first + const endCap = v.secStrucLast || v.coarseBackboneLast || v.last + let s0 = theme.size.size(v.centerPrev) * sizeFactor let s1 = theme.size.size(v.center) * sizeFactor let s2 = theme.size.size(v.centerNext) * sizeFactor @@ -61,9 +64,9 @@ function createPolymerTubeMesh(ctx: VisualContext, unit: Unit, structure: Struct if (radialSegments === 2) { addRibbon(builderState, curvePoints, normalVectors, binormalVectors, linearSegments, widthValues, heightValues, 0) } else if (radialSegments === 4) { - addSheet(builderState, curvePoints, normalVectors, binormalVectors, linearSegments, widthValues, heightValues, 0, v.secStrucFirst || v.coarseBackboneFirst, v.secStrucLast || v.coarseBackboneLast) + addSheet(builderState, curvePoints, normalVectors, binormalVectors, linearSegments, widthValues, heightValues, 0, startCap, endCap) } else { - addTube(builderState, curvePoints, normalVectors, binormalVectors, linearSegments, radialSegments, widthValues, heightValues, 1, v.first, v.last) + addTube(builderState, curvePoints, normalVectors, binormalVectors, linearSegments, radialSegments, widthValues, heightValues, 1, startCap, endCap) } ++i diff --git a/src/mol-repr/structure/visual/util/polymer/trace-iterator.ts b/src/mol-repr/structure/visual/util/polymer/trace-iterator.ts index 5c7b3b535de15bb94b680c1ed937543b44509a77..d75cf4bd36ac28a166a938fad48533a54da691de 100644 --- a/src/mol-repr/structure/visual/util/polymer/trace-iterator.ts +++ b/src/mol-repr/structure/visual/util/polymer/trace-iterator.ts @@ -64,6 +64,7 @@ function createPolymerTraceElement (unit: Unit): PolymerTraceElement { const enum AtomicPolymerTraceIteratorState { nextPolymer, nextResidue } +const tmpDir = Vec3() const tmpVecA = Vec3() const tmpVecB = Vec3() @@ -239,6 +240,35 @@ export class AtomicPolymerTraceIterator implements Iterator<PolymerTraceElement> this.setFromToVector(this.d23, residueIndexNext1) this.setFromToVector(this.d34, residueIndexNext2) + // extend termini + const f = 0.5 + if (residueIndex === residueIndexPrev1) { + Vec3.scale(tmpDir, Vec3.sub(tmpDir, this.p3, this.p4), f) + Vec3.add(this.p2, this.p3, tmpDir) + Vec3.add(this.p1, this.p2, tmpDir) + Vec3.add(this.p0, this.p1, tmpDir) + } else if (residueIndexPrev1 === residueIndexPrev2) { + Vec3.scale(tmpDir, Vec3.sub(tmpDir, this.p2, this.p3), f) + Vec3.add(this.p1, this.p2, tmpDir) + Vec3.add(this.p0, this.p1, tmpDir) + } else if (residueIndexPrev2 === residueIndexPrev3) { + Vec3.scale(tmpDir, Vec3.sub(tmpDir, this.p1, this.p2), f) + Vec3.add(this.p0, this.p1, tmpDir) + } + if (residueIndex === residueIndexNext1) { + Vec3.scale(tmpDir, Vec3.sub(tmpDir, this.p3, this.p2), f) + Vec3.add(this.p4, this.p3, tmpDir) + Vec3.add(this.p5, this.p4, tmpDir) + Vec3.add(this.p6, this.p5, tmpDir) + } else if (residueIndexNext1 === residueIndexNext2) { + Vec3.scale(tmpDir, Vec3.sub(tmpDir, this.p4, this.p3), f) + Vec3.add(this.p5, this.p4, tmpDir) + Vec3.add(this.p6, this.p5, tmpDir) + } else if (residueIndexNext2 === residueIndexNext3) { + Vec3.scale(tmpDir, Vec3.sub(tmpDir, this.p5, this.p4), f) + Vec3.add(this.p6, this.p5, tmpDir) + } + 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.p2, this.p2, this.p3, this.p4, residueIndex) @@ -313,7 +343,7 @@ export class CoarsePolymerTraceIterator implements Iterator<PolymerTraceElement> this.polymerSegment = this.polymerIt.move(); this.elementIndex = this.polymerSegment.start - if (this.elementIndex + 1 < this.polymerSegment.end) { + if (this.elementIndex < this.polymerSegment.end) { this.state = CoarsePolymerTraceIteratorState.nextElement break } @@ -321,8 +351,6 @@ export class CoarsePolymerTraceIterator implements Iterator<PolymerTraceElement> } if (this.state === CoarsePolymerTraceIteratorState.nextElement) { - this.elementIndex += 1 - const elementIndexPrev2 = this.getElementIndex(this.elementIndex - 2) const elementIndexPrev1 = this.getElementIndex(this.elementIndex - 1) const elementIndexNext1 = this.getElementIndex(this.elementIndex + 1) @@ -338,6 +366,25 @@ export class CoarsePolymerTraceIterator implements Iterator<PolymerTraceElement> this.pos(this.value.p3, elementIndexNext1) this.pos(this.value.p4, elementIndexNext2) + // extend termini + const f = 0.5 + if (this.elementIndex === elementIndexPrev1) { + Vec3.scale(tmpDir, Vec3.sub(tmpDir, this.value.p2, this.value.p3), f) + Vec3.add(this.value.p1, this.value.p2, tmpDir) + Vec3.add(this.value.p0, this.value.p1, tmpDir) + } else if (elementIndexPrev1 === elementIndexPrev2) { + Vec3.scale(tmpDir, Vec3.sub(tmpDir, this.value.p1, this.value.p2), f) + Vec3.add(this.value.p0, this.value.p1, tmpDir) + } + if (this.elementIndex === elementIndexNext1) { + Vec3.scale(tmpDir, Vec3.sub(tmpDir, this.value.p2, this.value.p1), f) + Vec3.add(this.value.p3, this.value.p2, tmpDir) + Vec3.add(this.value.p4, this.value.p3, tmpDir) + } else if (elementIndexNext1 === elementIndexNext2) { + Vec3.scale(tmpDir, Vec3.sub(tmpDir, this.value.p3, this.value.p2), f) + Vec3.add(this.value.p4, this.value.p3, tmpDir) + } + this.value.first = this.elementIndex === this.polymerSegment.start this.value.last = this.elementIndex === this.polymerSegment.end - 1 @@ -347,6 +394,7 @@ export class CoarsePolymerTraceIterator implements Iterator<PolymerTraceElement> } this.hasNext = this.elementIndex + 1 < this.polymerSegment.end || this.polymerIt.hasNext + this.elementIndex += 1 return this.value; }