diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 0000000000000000000000000000000000000000..66b79079c93dc16fb531d184ab087fd311607b28
--- /dev/null
+++ b/.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": [
+		
+	]
+}
\ No newline at end of file
diff --git a/src/mol-math/linear-algebra/3d/quat.ts b/src/mol-math/linear-algebra/3d/quat.ts
index 2642c145c4b437c92f35a76d86177c9c0c3ff04d..569dc63735aae842b58d80837d1e3721c8fc9e81 100644
--- a/src/mol-math/linear-algebra/3d/quat.ts
+++ b/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
\ No newline at end of file
diff --git a/src/mol-math/linear-algebra/3d/vec2.ts b/src/mol-math/linear-algebra/3d/vec2.ts
index 3a5785dcffcf41bef5268369fc4ee6014c5c17a3..d1bd980551e856fc5f5e0c699636146776a7eac1 100644
--- a/src/mol-math/linear-algebra/3d/vec2.ts
+++ b/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
\ No newline at end of file
diff --git a/src/mol-math/linear-algebra/3d/vec3.ts b/src/mol-math/linear-algebra/3d/vec3.ts
index a8bae39359b0be356ffce17e05559bf11a693280..b50d947b165eb1a9cb7b887b520a9cac304f7b19 100644
--- a/src/mol-math/linear-algebra/3d/vec3.ts
+++ b/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)}]`;
     }
 }
 
diff --git a/src/mol-math/linear-algebra/3d/vec4.ts b/src/mol-math/linear-algebra/3d/vec4.ts
index 80672cf6e9cd84d77f09d92e93517410a9c3dd46..753356f0c80ef3650fc3f108404a782a87b447f4 100644
--- a/src/mol-math/linear-algebra/3d/vec4.ts
+++ b/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
\ No newline at end of file
diff --git a/src/mol-model/structure/model/properties/atomic/hierarchy.ts b/src/mol-model/structure/model/properties/atomic/hierarchy.ts
index 0854b3b13fa485b18a100648b271f93ebf317da1..1c12b0be4b5b549f0106350851a60ded5ad2aee6 100644
--- a/src/mol-model/structure/model/properties/atomic/hierarchy.ts
+++ b/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>
     }
 }
diff --git a/src/mol-model/structure/model/properties/utils/atomic-derived.ts b/src/mol-model/structure/model/properties/utils/atomic-derived.ts
index 67f3a8a10bc30b3dacc1601e4457925d07056582..11706d5ada50c1cab3eb8459e681e444d347908d 100644
--- a/src/mol-model/structure/model/properties/utils/atomic-derived.ts
+++ b/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>,
         }
     }
diff --git a/src/mol-model/structure/model/types.ts b/src/mol-model/structure/model/types.ts
index 89eaf3b4a058e2957e804f517599dcd4c6e4bb70..a41c0d419dd1bd495b362444be3c97104dd3b3d7 100644
--- a/src/mol-model/structure/model/types.ts
+++ b/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'])
diff --git a/src/mol-repr/structure/visual/polymer-trace-mesh.ts b/src/mol-repr/structure/visual/polymer-trace-mesh.ts
index 16793765b52f454f5123e5a972128dcd30bf43ae..4c94290bbc7b2f920e05ce61bc1e47e6600f8fa4 100644
--- a/src/mol-repr/structure/visual/polymer-trace-mesh.ts
+++ b/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)
diff --git a/src/mol-repr/structure/visual/util/polymer/curve-segment.ts b/src/mol-repr/structure/visual/util/polymer/curve-segment.ts
index b096422dcab5a3eab1771bd0c61475c14c9a1eaf..ebb7aaf3d2a5ab65d1f7e6c1f8e7472801bd2dfb 100644
--- a/src/mol-repr/structure/visual/util/polymer/curve-segment.ts
+++ b/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)
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 c731071615a795d4c00b7c34ef8ee104eaadbefb..c510f7c3b61ea818b3561948d2156aa23dc60c41 100644
--- a/src/mol-repr/structure/visual/util/polymer/trace-iterator.ts
+++ b/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)