diff --git a/CHANGELOG.md b/CHANGELOG.md index f03a5a2d5874c4ce96f7cc70dcdf04d14c57d73c..4f194ff293a17af9ab8df7dc6aebe8433a1bd2ae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,17 @@ Note that since we don't clearly distinguish between a public and private interf ## [Unreleased] +- Improve aromatic bond visuals (add ``aromaticScale``, ``aromaticSpacing``, ``aromaticDashCount`` params) +- [Breaking] Change ``adjustCylinderLength`` default to ``false`` (set to true for focus representation) +- Fix marker highlight color overriding select color + +## [v2.3.5] - 2021-10-19 + +- Fix sequence viewer for PDB files with COMPND record and multichain entities. +- Fix index pair bonds order assignment + +## [v2.3.4] - 2021-10-12 + - Fix pickScale not taken into account in line/point shader - Add pixel-scale, pick-scale & pick-padding GET params to Viewer app - Fix selecting bonds not adding their atoms in selection manager @@ -15,6 +26,7 @@ Note that since we don't clearly distinguish between a public and private interf - Add points & crosses visuals to Line representation - Add ``pickPadding`` config option (look around in case target pixel is empty) - Add ``multipleBonds`` param to bond visuals with options: off, symmetric, offset +- Fix ``argparse`` config in servers. ## [v2.3.3] - 2021-10-01 @@ -145,29 +157,22 @@ Note that since we don't clearly distinguish between a public and private interf - Fixed Measurements UI labels (#166) ## [v2.0.3] - 2021-04-09 -### Added -- Support for ``ColorTheme.palette`` designed for providing gradient-like coloring. -### Changed +- Add support for ``ColorTheme.palette`` designed for providing gradient-like coloring. - [Breaking] The ``zip`` function is now asynchronous and expects a ``RuntimeContext``. Also added ``Zip()`` returning a ``Task``. - [Breaking] Add ``CubeGridFormat`` in ``alpha-orbitals`` extension. ## [v2.0.2] - 2021-03-29 -### Added -- ``Canvas3D.getRenderObjects``. -- [WIP] Animate state interpolating, including model trajectories -### Changed +- Add ``Canvas3D.getRenderObjects``. +- [WIP] Animate state interpolating, including model trajectories - Recognise MSE, SEP, TPO, PTR and PCA as non-standard amino-acids. - -### Fixed -- VolumeFromDensityServerCif transform label - +- Fix VolumeFromDensityServerCif transform label ## [v2.0.1] - 2021-03-23 -### Fixed -- Exclude tsconfig.commonjs.tsbuildinfo from npm bundle +- Exclude tsconfig.commonjs.tsbuildinfo from npm bundle ## [v2.0.0] - 2021-03-23 + Too many changes to list as this is the start of the changelog... Notably, default exports are now forbidden. diff --git a/package-lock.json b/package-lock.json index 3127732315807c1fab22950b5e1c541b1db8ce50..c5ced1fd9ca1bdff83888b8b2206d48fee639edc 100644 Binary files a/package-lock.json and b/package-lock.json differ diff --git a/package.json b/package.json index 3c53a78f6e9e9461a946c9bbb97a08ee1ae2b1cf..311b2505203e9d7ff6fd83cad9709547bdeb0b80 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "molstar", - "version": "2.3.3", + "version": "2.3.5", "description": "A comprehensive macromolecular library.", "homepage": "https://github.com/molstar/molstar#readme", "repository": { diff --git a/src/mol-gl/shader/chunks/assign-material-color.glsl.ts b/src/mol-gl/shader/chunks/assign-material-color.glsl.ts index c147051ec483c6b642b3d0a3af4c4ad224b9634d..9d550b8f14277d2fd128601971edcc78cf9d9136 100644 --- a/src/mol-gl/shader/chunks/assign-material-color.glsl.ts +++ b/src/mol-gl/shader/chunks/assign-material-color.glsl.ts @@ -3,9 +3,8 @@ export const assign_material_color = ` #if defined(dMarkerType_uniform) float marker = uMarker; #elif defined(dMarkerType_groupInstance) - float marker = vMarker; + float marker = floor(vMarker * 255.0 + 0.5); // rounding required to work on some cards on win #endif - marker = floor(marker * 255.0 + 0.5); // rounding required to work on some cards on win #endif #if defined(dRenderVariant_color) diff --git a/src/mol-model-formats/structure/pdb/entity.ts b/src/mol-model-formats/structure/pdb/entity.ts index b40f9b2e2cd6808d34d9993ee0afb6d00461596b..9276a0c851c8a830df298f9c6642e211365295eb 100644 --- a/src/mol-model-formats/structure/pdb/entity.ts +++ b/src/mol-model-formats/structure/pdb/entity.ts @@ -25,7 +25,7 @@ export function parseCmpnd(lines: Tokens, lineStart: number, lineEnd: number) { let currentSpec: Spec | undefined; let currentCompound: EntityCompound = { chains: [], description: '' }; - const Compounds: EntityCompound[] = []; + const compounds: EntityCompound[] = []; for (let i = lineStart; i < lineEnd; i++) { const line = getLine(i); @@ -55,7 +55,7 @@ export function parseCmpnd(lines: Tokens, lineStart: number, lineEnd: number) { chains: [], description: '' }; - Compounds.push(currentCompound); + compounds.push(currentCompound); } else if (currentSpec === 'MOLECULE') { if (currentCompound.description) currentCompound.description += ' '; currentCompound.description += value; @@ -64,7 +64,31 @@ export function parseCmpnd(lines: Tokens, lineStart: number, lineEnd: number) { } } - return Compounds; + // Define a seprate entity for each chain + // -------------------------------------- + // + // This is a workaround for how sequences are currently determined for PDB files. + // + // The current approach infers the "observed sequence" from the atomic hierarchy. + // However, for example for PDB ID 3HHR, this approach fails, since chains B and C + // belong to the same entity but contain different observed sequence, which causes display + // errors in the sequence viewer (since the sequences are determined "per entity"). + // + // A better approach could be to parse SEQRES categories and use it to construct + // entity_poly_seq category. However, this would require constructing label_seq_id (with gaps) + // from RES ID pdb column (auth_seq_id), which isn't a trivial exercise. + // + // (properly formatted) mmCIF structures do not exhibit this issue. + const singletons: EntityCompound[] = []; + for (const comp of compounds) { + for (const chain of comp.chains) { + singletons.push({ + description: comp.description, + chains: [chain] + }); + } + } + return singletons; } export function parseHetnam(lines: Tokens, lineStart: number, lineEnd: number) { diff --git a/src/mol-model/structure/structure/unit/bonds/intra-compute.ts b/src/mol-model/structure/structure/unit/bonds/intra-compute.ts index 3aa5ed8acda7632ff620e31763799f61dbfaa751..9a77f179656b166a9dfdfc4a7465714ffc2522a3 100644 --- a/src/mol-model/structure/structure/unit/bonds/intra-compute.ts +++ b/src/mol-model/structure/structure/unit/bonds/intra-compute.ts @@ -79,7 +79,7 @@ function findIndexPairBonds(unit: Unit.Atomic) { if ((d !== -1 && equalEps(dist, d, 0.5)) || dist < maxDistance) { atomA[atomA.length] = _aI; atomB[atomB.length] = _bI; - orders[order.length] = order[i]; + orders[orders.length] = order[i]; flags[flags.length] = flag[i]; } } diff --git a/src/mol-plugin/behavior/dynamic/selection/structure-focus-representation.ts b/src/mol-plugin/behavior/dynamic/selection/structure-focus-representation.ts index 43ad81abd070d9b3d51ec70d004b6bc6ce6ff664..fbd8fa87c570f069641eacf95c3e36b46badd536 100644 --- a/src/mol-plugin/behavior/dynamic/selection/structure-focus-representation.ts +++ b/src/mol-plugin/behavior/dynamic/selection/structure-focus-representation.ts @@ -25,7 +25,7 @@ const StructureFocusRepresentationParams = (plugin: PluginContext) => { expandRadius: PD.Numeric(5, { min: 1, max: 10, step: 1 }), targetParams: PD.Group(reprParams, { label: 'Target', - customDefault: createStructureRepresentationParams(plugin, void 0, { type: 'ball-and-stick', size: 'physical', typeParams: { sizeFactor: 0.26, alpha: 0.51 } }) + customDefault: createStructureRepresentationParams(plugin, void 0, { type: 'ball-and-stick', size: 'physical', typeParams: { sizeFactor: 0.26, alpha: 0.51, adjustCylinderLength: true } }) }), surroundingsParams: PD.Group(reprParams, { label: 'Surroundings', diff --git a/src/mol-repr/structure/visual/bond-inter-unit-cylinder.ts b/src/mol-repr/structure/visual/bond-inter-unit-cylinder.ts index c735dbeaeac4b67371671abddc47e9aa9a1398a5..5385bac813dbc3f0b461d149c8d9d3a116de447f 100644 --- a/src/mol-repr/structure/visual/bond-inter-unit-cylinder.ts +++ b/src/mol-repr/structure/visual/bond-inter-unit-cylinder.ts @@ -215,6 +215,9 @@ export function InterUnitBondCylinderImpostorVisual(materialId: number): Complex newProps.linkSpacing !== currentProps.linkSpacing || newProps.ignoreHydrogens !== currentProps.ignoreHydrogens || newProps.linkCap !== currentProps.linkCap || + newProps.aromaticScale !== currentProps.aromaticScale || + newProps.aromaticSpacing !== currentProps.aromaticSpacing || + newProps.aromaticDashCount !== currentProps.aromaticDashCount || newProps.dashCount !== currentProps.dashCount || newProps.dashScale !== currentProps.dashScale || newProps.dashCap !== currentProps.dashCap || @@ -254,6 +257,9 @@ export function InterUnitBondCylinderMeshVisual(materialId: number): ComplexVisu newProps.linkSpacing !== currentProps.linkSpacing || newProps.ignoreHydrogens !== currentProps.ignoreHydrogens || newProps.linkCap !== currentProps.linkCap || + newProps.aromaticScale !== currentProps.aromaticScale || + newProps.aromaticSpacing !== currentProps.aromaticSpacing || + newProps.aromaticDashCount !== currentProps.aromaticDashCount || newProps.dashCount !== currentProps.dashCount || newProps.dashScale !== currentProps.dashScale || newProps.dashCap !== currentProps.dashCap || diff --git a/src/mol-repr/structure/visual/bond-inter-unit-line.ts b/src/mol-repr/structure/visual/bond-inter-unit-line.ts index 62c030b93f5533c4ee499c60c4a126ef66329e12..1fb4b9784d8fe7cfbb7a56fa27a9243d96ab69f0 100644 --- a/src/mol-repr/structure/visual/bond-inter-unit-line.ts +++ b/src/mol-repr/structure/visual/bond-inter-unit-line.ts @@ -131,6 +131,7 @@ export function InterUnitBondLineVisual(materialId: number): ComplexVisual<Inter newProps.sizeFactor !== currentProps.sizeFactor || newProps.linkScale !== currentProps.linkScale || newProps.linkSpacing !== currentProps.linkSpacing || + newProps.aromaticDashCount !== currentProps.aromaticDashCount || newProps.dashCount !== currentProps.dashCount || newProps.ignoreHydrogens !== currentProps.ignoreHydrogens || !arrayEqual(newProps.includeTypes, currentProps.includeTypes) || diff --git a/src/mol-repr/structure/visual/bond-intra-unit-cylinder.ts b/src/mol-repr/structure/visual/bond-intra-unit-cylinder.ts index 3e42f0cc066fa5b14bad7a9f83b35b5e1363d01b..abd5d82a7282c0f403faec6fbb92597030c134f5 100644 --- a/src/mol-repr/structure/visual/bond-intra-unit-cylinder.ts +++ b/src/mol-repr/structure/visual/bond-intra-unit-cylinder.ts @@ -228,6 +228,9 @@ export function IntraUnitBondCylinderImpostorVisual(materialId: number): UnitsVi newProps.linkSpacing !== currentProps.linkSpacing || newProps.ignoreHydrogens !== currentProps.ignoreHydrogens || newProps.linkCap !== currentProps.linkCap || + newProps.aromaticScale !== currentProps.aromaticScale || + newProps.aromaticSpacing !== currentProps.aromaticSpacing || + newProps.aromaticDashCount !== currentProps.aromaticDashCount || newProps.dashCount !== currentProps.dashCount || newProps.dashScale !== currentProps.dashScale || newProps.dashCap !== currentProps.dashCap || @@ -272,6 +275,9 @@ export function IntraUnitBondCylinderMeshVisual(materialId: number): UnitsVisual newProps.linkSpacing !== currentProps.linkSpacing || newProps.ignoreHydrogens !== currentProps.ignoreHydrogens || newProps.linkCap !== currentProps.linkCap || + newProps.aromaticScale !== currentProps.aromaticScale || + newProps.aromaticSpacing !== currentProps.aromaticSpacing || + newProps.aromaticDashCount !== currentProps.aromaticDashCount || newProps.dashCount !== currentProps.dashCount || newProps.dashScale !== currentProps.dashScale || newProps.dashCap !== currentProps.dashCap || diff --git a/src/mol-repr/structure/visual/bond-intra-unit-line.ts b/src/mol-repr/structure/visual/bond-intra-unit-line.ts index 10708af2f9f5b6e92df1ccf9afc6a761e66efd6d..1ad1fa45f7bbbad9eda44e63e311bd0e995925a4 100644 --- a/src/mol-repr/structure/visual/bond-intra-unit-line.ts +++ b/src/mol-repr/structure/visual/bond-intra-unit-line.ts @@ -153,6 +153,7 @@ export function IntraUnitBondLineVisual(materialId: number): UnitsVisual<IntraUn newProps.sizeFactor !== currentProps.sizeFactor || newProps.linkScale !== currentProps.linkScale || newProps.linkSpacing !== currentProps.linkSpacing || + newProps.aromaticDashCount !== currentProps.aromaticDashCount || newProps.dashCount !== currentProps.dashCount || newProps.ignoreHydrogens !== currentProps.ignoreHydrogens || !arrayEqual(newProps.includeTypes, currentProps.includeTypes) || diff --git a/src/mol-repr/structure/visual/util/bond.ts b/src/mol-repr/structure/visual/util/bond.ts index 11fd2cf27adf49274b85e6fab523a4e7ce936d33..d2fb94a7769d27880135d6008e0c46c724ae1ef4 100644 --- a/src/mol-repr/structure/visual/util/bond.ts +++ b/src/mol-repr/structure/visual/util/bond.ts @@ -28,7 +28,7 @@ export type BondProps = typeof DefaultBondProps export const BondCylinderParams = { ...LinkCylinderParams, ...BondParams, - adjustCylinderLength: PD.Boolean(true, { description: 'Shorten cylinders to reduce overlap with spheres.' }) + adjustCylinderLength: PD.Boolean(false, { description: 'Shorten cylinders to reduce overlap with spheres. Useful for for transparent bonds. Not working well with aromatic bonds.' }) }; export const DefaultBondCylinderProps = PD.getDefaultValues(BondCylinderParams); export type BondCylinderProps = typeof DefaultBondCylinderProps diff --git a/src/mol-repr/structure/visual/util/link.ts b/src/mol-repr/structure/visual/util/link.ts index f28aef6918560ea4c199a515931d3222292252b6..c62aea5d0a496badcf2924404c35ce6153cf9c3f 100644 --- a/src/mol-repr/structure/visual/util/link.ts +++ b/src/mol-repr/structure/visual/util/link.ts @@ -21,6 +21,9 @@ export const LinkCylinderParams = { linkScale: PD.Numeric(0.45, { min: 0, max: 1, step: 0.01 }), linkSpacing: PD.Numeric(1, { min: 0, max: 2, step: 0.01 }), 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 }), dashCount: PD.Numeric(4, { min: 2, max: 10, step: 2 }), dashScale: PD.Numeric(0.8, { min: 0, max: 2, step: 0.1 }), dashCap: PD.Boolean(true), @@ -33,6 +36,7 @@ export type LinkCylinderProps = typeof DefaultLinkCylinderProps export const LinkLineParams = { linkScale: PD.Numeric(0.5, { min: 0, max: 1, step: 0.1 }), linkSpacing: PD.Numeric(0.1, { min: 0, max: 2, step: 0.01 }), + aromaticDashCount: PD.Numeric(2, { min: 2, max: 6, step: 2 }), dashCount: PD.Numeric(4, { min: 2, max: 10, step: 2 }), }; export const DefaultLinkLineProps = PD.getDefaultValues(LinkLineParams); @@ -107,7 +111,7 @@ export function createLinkCylinderMesh(ctx: VisualContext, linkBuilder: LinkBuil if (!linkCount) return Mesh.createEmpty(mesh); - const { linkScale, linkSpacing, radialSegments, linkCap, dashCount, dashScale, dashCap, stubCap } = props; + const { linkScale, linkSpacing, radialSegments, linkCap, aromaticScale, aromaticSpacing, aromaticDashCount, dashCount, dashScale, dashCap, stubCap } = props; const vertexCountEstimate = radialSegments * 2 * linkCount * 2; const builderState = MeshBuilder.createState(vertexCountEstimate, vertexCountEstimate / 4, mesh); @@ -138,8 +142,7 @@ export function createLinkCylinderMesh(ctx: VisualContext, linkBuilder: LinkBuil const [topCap, bottomCap] = dirFlag ? [linkStub, linkCap] : [linkCap, linkStub]; builderState.currentGroup = edgeIndex; - const aromaticOffsetFactor = 5.5; - const multipleOffsetFactor = 4; + const aromaticSegmentCount = aromaticDashCount + 1; if (linkStyle === LinkStyle.Solid) { cylinderProps.radiusTop = cylinderProps.radiusBottom = linkRadius; @@ -153,8 +156,8 @@ export function createLinkCylinderMesh(ctx: VisualContext, linkBuilder: LinkBuil addFixedCountDashedCylinder(builderState, va, vb, 0.5, segmentCount, cylinderProps); } 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 : - linkStyle === LinkStyle.Triple || linkStyle === LinkStyle.OffsetTriple ? 3 : 1.5; + const order = (linkStyle === LinkStyle.Double || linkStyle === LinkStyle.OffsetDouble) ? 2 : + (linkStyle === LinkStyle.Triple || linkStyle === LinkStyle.OffsetTriple) ? 3 : 1.5; const multiRadius = linkRadius * (linkScale / (0.5 * order)); const absOffset = (linkRadius - multiRadius) * linkSpacing; @@ -167,21 +170,28 @@ export function createLinkCylinderMesh(ctx: VisualContext, linkBuilder: LinkBuil cylinderProps.radiusTop = cylinderProps.radiusBottom = linkRadius; addCylinder(builderState, va, vb, 0.5, cylinderProps); - cylinderProps.radiusTop = cylinderProps.radiusBottom = linkRadius * linkScale; + const aromaticOffset = linkRadius + aromaticScale * linkRadius + aromaticScale * linkRadius * aromaticSpacing; + + v3setMagnitude(tmpV12, v3sub(tmpV12, vb, va), linkRadius * 0.5); + v3add(va, va, tmpV12); + v3sub(vb, vb, tmpV12); + + cylinderProps.radiusTop = cylinderProps.radiusBottom = linkRadius * aromaticScale; cylinderProps.topCap = cylinderProps.bottomCap = dashCap; - v3setMagnitude(vShift, vShift, absOffset * aromaticOffsetFactor); + v3setMagnitude(vShift, vShift, aromaticOffset); v3sub(va, va, vShift); v3sub(vb, vb, vShift); - addFixedCountDashedCylinder(builderState, va, vb, 0.5, 3, cylinderProps); + addFixedCountDashedCylinder(builderState, va, vb, 0.5, aromaticSegmentCount, cylinderProps); if (linkStyle === LinkStyle.MirroredAromatic) { - v3setMagnitude(vShift, vShift, absOffset * aromaticOffsetFactor * 2); + v3setMagnitude(vShift, vShift, aromaticOffset * 2); v3add(va, va, vShift); v3add(vb, vb, vShift); - addFixedCountDashedCylinder(builderState, va, vb, 0.5, 3, cylinderProps); + addFixedCountDashedCylinder(builderState, va, vb, 0.5, aromaticSegmentCount, cylinderProps); } } else if (linkStyle === LinkStyle.OffsetDouble || linkStyle === LinkStyle.OffsetTriple) { - v3setMagnitude(vShift, vShift, absOffset); + const multipleOffset = linkRadius + multiRadius + linkScale * linkRadius * linkSpacing; + v3setMagnitude(vShift, vShift, multipleOffset); cylinderProps.radiusTop = cylinderProps.radiusBottom = linkRadius; addCylinder(builderState, va, vb, 0.5, cylinderProps); @@ -193,13 +203,13 @@ export function createLinkCylinderMesh(ctx: VisualContext, linkBuilder: LinkBuil cylinderProps.radiusTop = cylinderProps.radiusBottom = multiRadius; cylinderProps.topCap = dirFlag ? linkStub : dashCap; cylinderProps.bottomCap = dirFlag ? dashCap : linkStub; - v3setMagnitude(vShift, vShift, absOffset * multipleOffsetFactor); + v3setMagnitude(vShift, vShift, multipleOffset); v3sub(va, va, vShift); v3sub(vb, vb, vShift); addCylinder(builderState, va, vb, 0.5, cylinderProps); if (order === 3) { - v3setMagnitude(vShift, vShift, absOffset * multipleOffsetFactor * 2); + v3setMagnitude(vShift, vShift, multipleOffset * 2); v3add(va, va, vShift); v3add(vb, vb, vShift); addCylinder(builderState, va, vb, 0.5, cylinderProps); @@ -236,7 +246,7 @@ export function createLinkCylinderImpostors(ctx: VisualContext, linkBuilder: Lin if (!linkCount) return Cylinders.createEmpty(cylinders); - const { linkScale, linkSpacing, linkCap, dashCount, dashScale, dashCap, stubCap } = props; + const { linkScale, linkSpacing, linkCap, aromaticScale, aromaticSpacing, aromaticDashCount, dashCount, dashScale, dashCap, stubCap } = props; const cylindersCountEstimate = linkCount * 2; const builder = CylindersBuilder.create(cylindersCountEstimate, cylindersCountEstimate / 4, cylinders); @@ -250,10 +260,8 @@ export function createLinkCylinderImpostors(ctx: VisualContext, linkBuilder: Lin const segmentCount = dashCount % 2 === 1 ? dashCount : dashCount + 1; const lengthScale = 0.5 - (0.5 / 2 / segmentCount); - const aromaticSegmentCount = 3; + const aromaticSegmentCount = aromaticDashCount + 1; const aromaticLengthScale = 0.5 - (0.5 / 2 / aromaticSegmentCount); - const aromaticOffsetFactor = 5.5; - const multipleOffsetFactor = 4; for (let edgeIndex = 0, _eI = linkCount; edgeIndex < _eI; ++edgeIndex) { if (ignore && ignore(edgeIndex)) continue; @@ -272,8 +280,8 @@ export function createLinkCylinderImpostors(ctx: VisualContext, linkBuilder: Lin v3sub(vb, vb, tmpV12); builder.addFixedCountDashes(va, vb, segmentCount, dashScale, dashCap, dashCap, 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 : - linkStyle === LinkStyle.Triple || linkStyle === LinkStyle.OffsetTriple ? 3 : 1.5; + const order = (linkStyle === LinkStyle.Double || linkStyle === LinkStyle.OffsetDouble) ? 2 : + (linkStyle === LinkStyle.Triple || linkStyle === LinkStyle.OffsetTriple) ? 3 : 1.5; const multiScale = linkScale / (0.5 * order); const absOffset = (linkRadius - multiScale * linkRadius) * linkSpacing; @@ -283,26 +291,32 @@ export function createLinkCylinderImpostors(ctx: VisualContext, linkBuilder: Lin if (linkStyle === LinkStyle.Aromatic || linkStyle === LinkStyle.MirroredAromatic) { builder.add(va[0], va[1], va[2], vm[0], vm[1], vm[2], 1, linkCap, linkStub, edgeIndex); + const aromaticOffset = linkRadius + aromaticScale * linkRadius + aromaticScale * linkRadius * aromaticSpacing; + v3scale(tmpV12, v3sub(tmpV12, vb, va), aromaticLengthScale); v3sub(vb, vb, tmpV12); - v3setMagnitude(vShift, vShift, absOffset * aromaticOffsetFactor); + v3setMagnitude(tmpV12, v3sub(tmpV12, vb, 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, linkScale, dashCap, dashCap, edgeIndex); + builder.addFixedCountDashes(va, vb, aromaticSegmentCount, aromaticScale, dashCap, dashCap, edgeIndex); if (linkStyle === LinkStyle.MirroredAromatic) { - v3setMagnitude(vShift, vShift, absOffset * aromaticOffsetFactor * 2); + v3setMagnitude(vShift, vShift, aromaticOffset * 2); v3add(va, va, vShift); v3add(vb, vb, vShift); - builder.addFixedCountDashes(va, vb, aromaticSegmentCount, linkScale, dashCap, dashCap, edgeIndex); + builder.addFixedCountDashes(va, vb, aromaticSegmentCount, aromaticScale, dashCap, dashCap, edgeIndex); } } else if (linkStyle === LinkStyle.OffsetDouble || linkStyle === LinkStyle.OffsetTriple) { - v3setMagnitude(vShift, vShift, absOffset * multipleOffsetFactor); + const multipleOffset = linkRadius + multiScale * linkRadius + linkScale * linkRadius * linkSpacing; + v3setMagnitude(vShift, vShift, multipleOffset); builder.add(va[0], va[1], va[2], vm[0], vm[1], vm[2], 1, linkCap, linkStub, edgeIndex); - v3scale(tmpV12, v3sub(tmpV12, va, vb), linkSpacing * linkScale * 0.2); + v3setMagnitude(tmpV12, v3sub(tmpV12, va, vb), 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); @@ -335,7 +349,7 @@ export function createLinkLines(ctx: VisualContext, linkBuilder: LinkBuilderProp if (!linkCount) return Lines.createEmpty(lines); - const { linkScale, linkSpacing, dashCount } = props; + const { linkScale, linkSpacing, aromaticDashCount, dashCount } = props; const linesCountEstimate = linkCount * 2; const builder = LinesBuilder.create(linesCountEstimate, linesCountEstimate / 4, lines); @@ -349,7 +363,7 @@ export function createLinkLines(ctx: VisualContext, linkBuilder: LinkBuilderProp const segmentCount = dashCount % 2 === 1 ? dashCount : dashCount + 1; const lengthScale = 0.5 - (0.5 / 2 / segmentCount); - const aromaticSegmentCount = 3; + const aromaticSegmentCount = aromaticDashCount + 1; const aromaticLengthScale = 0.5 - (0.5 / 2 / aromaticSegmentCount); const aromaticOffsetFactor = 4.5; const multipleOffsetFactor = 3; diff --git a/src/servers/model/config.ts b/src/servers/model/config.ts index a557bc8d93070c3d7247e06aecc2c640e9d72a56..5fa1823a046593b2cbeaa08b125b6412fdd05685 100644 --- a/src/servers/model/config.ts +++ b/src/servers/model/config.ts @@ -230,7 +230,6 @@ function addJsonConfigArgs(parser: argparse.ArgumentParser) { 'If a property is not specified, cmd line param/OS variable/default value are used.' ].join('\n'), required: false, - action: 'store_true' }); parser.add_argument('--printCfg', { help: 'Print current config for validation and exit.', required: false, action: 'store_true' }); parser.add_argument('--cfgTemplate', { help: 'Prints default JSON config template to be modified and exits.', required: false, action: 'store_true' }); diff --git a/src/servers/volume/config.ts b/src/servers/volume/config.ts index 3a9e380f0f66859faee46d926676c418ddc27029..cc51934c1acc0275d88c3bb37b1e846b8e91e7d1 100644 --- a/src/servers/volume/config.ts +++ b/src/servers/volume/config.ts @@ -90,7 +90,6 @@ function addJsonConfigArgs(parser: argparse.ArgumentParser) { 'If a property is not specified, cmd line param/OS variable/default value are used.' ].join('\n'), required: false, - action: 'store_true' }); parser.add_argument('--printCfg', { help: 'Print current config for validation and exit.', required: false, action: 'store_true' }); parser.add_argument('--cfgTemplate', { help: 'Prints default JSON config template to be modified and exits.', required: false, action: 'store_true' });