diff --git a/src/mol-geo/geometry/cylinders/cylinders-builder.ts b/src/mol-geo/geometry/cylinders/cylinders-builder.ts index d398e59621b32a7f7340adfb2895c0fa0b80b892..243ba71b087d97d6c4975c7430d3c75810c5584b 100644 --- a/src/mol-geo/geometry/cylinders/cylinders-builder.ts +++ b/src/mol-geo/geometry/cylinders/cylinders-builder.ts @@ -2,6 +2,7 @@ * Copyright (c) 2020 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author Alexander Rose <alexander.rose@weirdbyte.de> + * @author Gianluca Tomasello <giagitom@gmail.com> */ import { ChunkedArray } from '../../../mol-data/util'; @@ -43,16 +44,23 @@ export namespace CylindersBuilder { const addFixedCountDashes = (start: Vec3, end: Vec3, segmentCount: number, radiusScale: number, topCap: boolean, bottomCap: boolean, group: number) => { const d = Vec3.distance(start, end); + const isOdd = segmentCount % 2 !== 0; + segmentCount++; const s = Math.floor(segmentCount / 2); const step = 1 / segmentCount; + const offset = step / 2; Vec3.sub(tmpDir, end, start); for (let j = 0; j < s; ++j) { - const f = step * (j * 2 + 1); + const f = step * (j * 2 + 1) + offset; Vec3.setMagnitude(tmpDir, tmpDir, d * f); Vec3.add(tmpVecA, start, tmpDir); - Vec3.setMagnitude(tmpDir, tmpDir, d * step * ((j + 1) * 2)); - Vec3.add(tmpVecB, start, tmpDir); + if (isOdd && j === s - 1) { + Vec3.copy(tmpVecB, end); + } else { + Vec3.setMagnitude(tmpDir, tmpDir, d * (step * ((j + 1) * 2) + offset)); + Vec3.add(tmpVecB, start, tmpDir); + } add(tmpVecA[0], tmpVecA[1], tmpVecA[2], tmpVecB[0], tmpVecB[1], tmpVecB[2], radiusScale, topCap, bottomCap, group); } }; diff --git a/src/mol-repr/structure/visual/util/link.ts b/src/mol-repr/structure/visual/util/link.ts index dcfb3fa274748ca189bff62589cd1a6dcc0e0c7c..794a836abed2c45458ce07203e4f1129e5b70878 100644 --- a/src/mol-repr/structure/visual/util/link.ts +++ b/src/mol-repr/structure/visual/util/link.ts @@ -3,6 +3,7 @@ * * @author Alexander Rose <alexander.rose@weirdbyte.de> * @author Zhenyu Zhang <jump2cn@gmail.com> + * @author Gianluca Tomasello <giagitom@gmail.com> */ import { Vec3 } from '../../../../mol-math/linear-algebra'; @@ -25,7 +26,7 @@ export const LinkCylinderParams = { linkCap: PD.Boolean(false), aromaticScale: PD.Numeric(0.3, { min: 0, max: 1, step: 0.01 }), aromaticSpacing: PD.Numeric(1.5, { min: 0, max: 3, step: 0.01 }), - aromaticDashCount: PD.Numeric(2, { min: 2, max: 6, step: 2 }), + aromaticDashCount: PD.Numeric(2, { min: 1, max: 6, step: 1 }), dashCount: PD.Numeric(4, { min: 0, max: 10, step: 2 }), dashScale: PD.Numeric(0.8, { min: 0, max: 2, step: 0.1 }), dashCap: PD.Boolean(true), @@ -286,10 +287,6 @@ export function createLinkCylinderImpostors(ctx: VisualContext, linkBuilder: Lin // automatically adjust length for evenly spaced dashed cylinders const segmentCount = dashCount % 2 === 1 ? dashCount : dashCount + 1; - const lengthScale = 0.5 - (0.5 / 2 / segmentCount); - - const aromaticSegmentCount = aromaticDashCount + 1; - const aromaticLengthScale = 0.5 - (0.5 / 2 / aromaticSegmentCount); for (let edgeIndex = 0, _eI = linkCount; edgeIndex < _eI; ++edgeIndex) { if (ignore && ignore(edgeIndex)) continue; @@ -308,13 +305,11 @@ export function createLinkCylinderImpostors(ctx: VisualContext, linkBuilder: Lin v3scale(vm, v3add(vm, va, vb), 0.5); builder.add(va[0], va[1], va[2], vm[0], vm[1], vm[2], 1, linkCap, linkStub, edgeIndex); } else if (linkStyle === LinkStyle.Dashed) { + v3scale(vm, v3add(vm, va, vb), 0.5); if (segmentCount > 1) { - v3scale(tmpV12, v3sub(tmpV12, vb, va), lengthScale); - v3sub(vb, vb, tmpV12); - builder.addFixedCountDashes(va, vb, segmentCount, dashScale, dashCap, dashCap, edgeIndex); + builder.addFixedCountDashes(va, vm, segmentCount, dashScale, dashCap, dashCap, edgeIndex); } else { - v3scale(vm, v3add(vm, va, vb), 0.5); - builder.add(va[0], va[1], va[2], vm[0], vm[1], vm[2], dashScale, dashCap, dashCap, edgeIndex); + builder.add(va[0], va[1], va[2], vm[0], vm[1], vm[2], dashScale, dashCap, dashCap, colorModeFlag, edgeIndex); } } else if (linkStyle === LinkStyle.Double || linkStyle === LinkStyle.OffsetDouble || linkStyle === LinkStyle.Triple || linkStyle === LinkStyle.OffsetTriple || linkStyle === LinkStyle.Aromatic || linkStyle === LinkStyle.MirroredAromatic) { const order = (linkStyle === LinkStyle.Double || linkStyle === LinkStyle.OffsetDouble) ? 2 : @@ -330,22 +325,19 @@ export function createLinkCylinderImpostors(ctx: VisualContext, linkBuilder: Lin const aromaticOffset = linkRadius + aromaticScale * linkRadius + aromaticScale * linkRadius * aromaticSpacing; - v3scale(tmpV12, v3sub(tmpV12, vb, va), aromaticLengthScale); - v3sub(vb, vb, tmpV12); - - v3setMagnitude(tmpV12, v3sub(tmpV12, vb, va), linkRadius * 0.5); + v3setMagnitude(tmpV12, v3sub(tmpV12, vm, va), linkRadius * 0.5); v3add(va, va, tmpV12); v3setMagnitude(vShift, vShift, aromaticOffset); v3sub(va, va, vShift); - v3sub(vb, vb, vShift); - builder.addFixedCountDashes(va, vb, aromaticSegmentCount, aromaticScale, dashCap, dashCap, edgeIndex); + v3sub(vm, vm, vShift); + builder.addFixedCountDashes(va, vm, aromaticDashCount, aromaticScale, dashCap, dashCap, edgeIndex); if (linkStyle === LinkStyle.MirroredAromatic) { v3setMagnitude(vShift, vShift, aromaticOffset * 2); v3add(va, va, vShift); - v3add(vb, vb, vShift); - builder.addFixedCountDashes(va, vb, aromaticSegmentCount, aromaticScale, dashCap, dashCap, edgeIndex); + v3add(vm, vm, vShift); + builder.addFixedCountDashes(va, vm, aromaticDashCount, aromaticScale, dashCap, dashCap, edgeIndex); } } else if (linkStyle === LinkStyle.OffsetDouble || linkStyle === LinkStyle.OffsetTriple) { const multipleOffset = linkRadius + multiScale * linkRadius + linkScale * linkRadius * linkSpacing; @@ -353,7 +345,7 @@ export function createLinkCylinderImpostors(ctx: VisualContext, linkBuilder: Lin builder.add(va[0], va[1], va[2], vm[0], vm[1], vm[2], 1, linkCap, linkStub, edgeIndex); - v3setMagnitude(tmpV12, v3sub(tmpV12, va, vb), linkRadius / 1.5); + v3setMagnitude(tmpV12, v3sub(tmpV12, va, vm), linkRadius / 1.5); v3sub(va, va, tmpV12); if (order === 3) builder.add(va[0] + vShift[0], va[1] + vShift[1], va[2] + vShift[2], vm[0] + vShift[0], vm[1] + vShift[1], vm[2] + vShift[2], multiScale, linkCap, linkStub, edgeIndex); @@ -366,11 +358,11 @@ export function createLinkCylinderImpostors(ctx: VisualContext, linkBuilder: Lin builder.add(va[0] - vShift[0], va[1] - vShift[1], va[2] - vShift[2], vm[0] - vShift[0], vm[1] - vShift[1], vm[2] - vShift[2], multiScale, linkCap, linkStub, edgeIndex); } } else if (linkStyle === LinkStyle.Disk) { - v3scale(tmpV12, v3sub(tmpV12, vb, va), 0.475); + v3scale(tmpV12, v3sub(tmpV12, vm, va), 0.475); v3add(va, va, tmpV12); - v3sub(vb, vb, tmpV12); + v3sub(vm, vm, tmpV12); - builder.add(va[0], va[1], va[2], vb[0], vb[1], vb[2], 1, linkCap, linkStub, edgeIndex); + builder.add(va[0], va[1], va[2], vm[0], vm[1], vm[2], 1, linkCap, linkStub, edgeIndex); } } @@ -505,4 +497,4 @@ export function createLinkLines(ctx: VisualContext, linkBuilder: LinkBuilderProp } else { return { lines: l }; } -} \ No newline at end of file +}