Browse Source

link visual helper improvements

- more configurable dashes
- better cap handling
Alexander Rose 4 years ago
parent
commit
d6c4366f40

+ 5 - 0
src/mol-model-props/computed/representations/interactions-inter-unit-cylinder.ts

@@ -80,6 +80,8 @@ export const InteractionsInterUnitParams = {
     ...ComplexMeshParams,
     ...LinkCylinderParams,
     sizeFactor: PD.Numeric(0.3, { min: 0, max: 10, step: 0.01 }),
+    dashCount: PD.Numeric(6, { min: 2, max: 10, step: 2 }),
+    dashScale: PD.Numeric(0.4, { min: 0, max: 2, step: 0.1 }),
 };
 export type InteractionsInterUnitParams = typeof InteractionsInterUnitParams
 
@@ -93,6 +95,9 @@ export function InteractionsInterUnitVisual(materialId: number): ComplexVisual<I
         setUpdateState: (state: VisualUpdateState, newProps: PD.Values<InteractionsInterUnitParams>, currentProps: PD.Values<InteractionsInterUnitParams>, newTheme: Theme, currentTheme: Theme, newStructure: Structure, currentStructure: Structure) => {
             state.createGeometry = (
                 newProps.sizeFactor !== currentProps.sizeFactor ||
+                newProps.dashCount !== currentProps.dashCount ||
+                newProps.dashScale !== currentProps.dashScale ||
+                newProps.dashCap !== currentProps.dashCap ||
                 newProps.radialSegments !== currentProps.radialSegments
             );
 

+ 5 - 0
src/mol-model-props/computed/representations/interactions-intra-unit-cylinder.ts

@@ -66,6 +66,8 @@ export const InteractionsIntraUnitParams = {
     ...UnitsMeshParams,
     ...LinkCylinderParams,
     sizeFactor: PD.Numeric(0.3, { min: 0, max: 10, step: 0.01 }),
+    dashCount: PD.Numeric(6, { min: 2, max: 10, step: 2 }),
+    dashScale: PD.Numeric(0.4, { min: 0, max: 2, step: 0.1 }),
 };
 export type InteractionsIntraUnitParams = typeof InteractionsIntraUnitParams
 
@@ -79,6 +81,9 @@ export function InteractionsIntraUnitVisual(materialId: number): UnitsVisual<Int
         setUpdateState: (state: VisualUpdateState, newProps: PD.Values<InteractionsIntraUnitParams>, currentProps: PD.Values<InteractionsIntraUnitParams>, newTheme: Theme, currentTheme: Theme, newStructureGroup: StructureGroup, currentStructureGroup: StructureGroup) => {
             state.createGeometry = (
                 newProps.sizeFactor !== currentProps.sizeFactor ||
+                newProps.dashCount !== currentProps.dashCount ||
+                newProps.dashScale !== currentProps.dashScale ||
+                newProps.dashCap !== currentProps.dashCap ||
                 newProps.radialSegments !== currentProps.radialSegments
             );
 

+ 3 - 0
src/mol-repr/structure/visual/bond-inter-unit-cylinder.ts

@@ -149,6 +149,9 @@ export function InterUnitBondCylinderVisual(materialId: number): ComplexVisual<I
                 newProps.linkSpacing !== currentProps.linkSpacing ||
                 newProps.ignoreHydrogens !== currentProps.ignoreHydrogens ||
                 newProps.linkCap !== currentProps.linkCap ||
+                newProps.dashCount !== currentProps.dashCount ||
+                newProps.dashScale !== currentProps.dashScale ||
+                newProps.dashCap !== currentProps.dashCap ||
                 !arrayEqual(newProps.includeTypes, currentProps.includeTypes) ||
                 !arrayEqual(newProps.excludeTypes, currentProps.excludeTypes)
             );

+ 1 - 0
src/mol-repr/structure/visual/bond-inter-unit-line.ts

@@ -121,6 +121,7 @@ export function InterUnitBondLineVisual(materialId: number): ComplexVisual<Inter
                 newProps.sizeFactor !== currentProps.sizeFactor ||
                 newProps.linkScale !== currentProps.linkScale ||
                 newProps.linkSpacing !== currentProps.linkSpacing ||
+                newProps.dashCount !== currentProps.dashCount ||
                 newProps.ignoreHydrogens !== currentProps.ignoreHydrogens ||
                 !arrayEqual(newProps.includeTypes, currentProps.includeTypes) ||
                 !arrayEqual(newProps.excludeTypes, currentProps.excludeTypes)

+ 3 - 0
src/mol-repr/structure/visual/bond-intra-unit-cylinder.ts

@@ -135,6 +135,9 @@ export function IntraUnitBondCylinderVisual(materialId: number): UnitsVisual<Int
                 newProps.linkSpacing !== currentProps.linkSpacing ||
                 newProps.ignoreHydrogens !== currentProps.ignoreHydrogens ||
                 newProps.linkCap !== currentProps.linkCap ||
+                newProps.dashCount !== currentProps.dashCount ||
+                newProps.dashScale !== currentProps.dashScale ||
+                newProps.dashCap !== currentProps.dashCap ||
                 !arrayEqual(newProps.includeTypes, currentProps.includeTypes) ||
                 !arrayEqual(newProps.excludeTypes, currentProps.excludeTypes)
             );

+ 1 - 0
src/mol-repr/structure/visual/bond-intra-unit-line.ts

@@ -111,6 +111,7 @@ export function IntraUnitBondLineVisual(materialId: number): UnitsVisual<IntraUn
                 newProps.sizeFactor !== currentProps.sizeFactor ||
                 newProps.linkScale !== currentProps.linkScale ||
                 newProps.linkSpacing !== currentProps.linkSpacing ||
+                newProps.dashCount !== currentProps.dashCount ||
                 newProps.ignoreHydrogens !== currentProps.ignoreHydrogens ||
                 !arrayEqual(newProps.includeTypes, currentProps.includeTypes) ||
                 !arrayEqual(newProps.excludeTypes, currentProps.excludeTypes)

+ 30 - 18
src/mol-repr/structure/visual/util/link.ts

@@ -19,6 +19,9 @@ export const LinkCylinderParams = {
     linkScale: PD.Numeric(0.4, { min: 0, max: 1, step: 0.1 }),
     linkSpacing: PD.Numeric(1, { min: 0, max: 2, step: 0.01 }),
     linkCap: PD.Boolean(false),
+    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),
     radialSegments: PD.Numeric(16, { min: 2, max: 56, step: 2 }, BaseGeometry.CustomQualityParamInfo),
 };
 export const DefaultLinkCylinderProps = PD.getDefaultValues(LinkCylinderParams);
@@ -27,6 +30,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 }),
+    dashCount: PD.Numeric(4, { min: 2, max: 10, step: 2 }),
 };
 export const DefaultLinkLineProps = PD.getDefaultValues(LinkLineParams);
 export type LinkLineProps = typeof DefaultLinkLineProps
@@ -95,7 +99,7 @@ export function createLinkCylinderMesh(ctx: VisualContext, linkBuilder: LinkBuil
 
     if (!linkCount) return Mesh.createEmpty(mesh);
 
-    const { linkScale, linkSpacing, radialSegments, linkCap } = props;
+    const { linkScale, linkSpacing, radialSegments, linkCap, dashCount, dashScale, dashCap } = props;
 
     const vertexCountEstimate = radialSegments * 2 * linkCount * 2;
     const builderState = MeshBuilder.createState(vertexCountEstimate, vertexCountEstimate / 4, mesh);
@@ -111,25 +115,30 @@ export function createLinkCylinderMesh(ctx: VisualContext, linkBuilder: LinkBuil
         bottomCap: linkCap
     };
 
+    const segmentCount = dashCount + 1;
+
     for (let edgeIndex = 0, _eI = linkCount; edgeIndex < _eI; ++edgeIndex) {
         if (ignore && ignore(edgeIndex)) continue;
 
         position(va, vb, edgeIndex);
+        v3sub(tmpV12, vb, va);
 
         const linkRadius = radius(edgeIndex);
         const linkStyle = style ? style(edgeIndex) : LinkStyle.Solid;
+        const [topCap, bottomCap] = (v3dot(tmpV12, up) > 0) ? [false, linkCap] : [linkCap, false];
         builderState.currentGroup = edgeIndex;
 
         if (linkStyle === LinkStyle.Solid) {
             cylinderProps.radiusTop = cylinderProps.radiusBottom = linkRadius;
-            cylinderProps.topCap = cylinderProps.bottomCap = linkCap;
+            cylinderProps.topCap = topCap;
+            cylinderProps.bottomCap = bottomCap;
 
             addCylinder(builderState, va, vb, 0.5, cylinderProps);
         } else if (linkStyle === LinkStyle.Dashed) {
-            cylinderProps.radiusTop = cylinderProps.radiusBottom = linkRadius / 3;
-            cylinderProps.topCap = cylinderProps.bottomCap = true;
+            cylinderProps.radiusTop = cylinderProps.radiusBottom = linkRadius * dashScale;
+            cylinderProps.topCap = cylinderProps.bottomCap = dashCap;
 
-            addFixedCountDashedCylinder(builderState, va, vb, 0.5, 7, cylinderProps);
+            addFixedCountDashedCylinder(builderState, va, vb, 0.5, segmentCount, cylinderProps);
         } else if (linkStyle === LinkStyle.Double || linkStyle === LinkStyle.Triple) {
             const order = linkStyle === LinkStyle.Double ? 2 : 3;
             const multiRadius = linkRadius * (linkScale / (0.5 * order));
@@ -139,23 +148,19 @@ export function createLinkCylinderMesh(ctx: VisualContext, linkBuilder: LinkBuil
             v3setMagnitude(vShift, vShift, absOffset);
 
             cylinderProps.radiusTop = cylinderProps.radiusBottom = multiRadius;
-            cylinderProps.topCap = cylinderProps.bottomCap = linkCap;
+            cylinderProps.topCap = topCap;
+            cylinderProps.bottomCap = bottomCap;
 
             if (order === 3) addCylinder(builderState, va, vb, 0.5, cylinderProps);
             addDoubleCylinder(builderState, va, vb, 0.5, vShift, cylinderProps);
         } else if (linkStyle === LinkStyle.Disk) {
-            v3scale(tmpV12, v3sub(tmpV12, vb, va), 0.475);
+            v3scale(tmpV12, tmpV12, 0.475);
             v3add(va, va, tmpV12);
             v3sub(vb, vb, tmpV12);
 
             cylinderProps.radiusTop = cylinderProps.radiusBottom = linkRadius;
-            if (v3dot(tmpV12, up) > 0) {
-                cylinderProps.topCap = false;
-                cylinderProps.bottomCap = linkCap;
-            } else {
-                cylinderProps.topCap = linkCap;
-                cylinderProps.bottomCap = false;
-            }
+            cylinderProps.topCap = topCap;
+            cylinderProps.bottomCap = bottomCap;
 
             addCylinder(builderState, va, vb, 0.5, cylinderProps);
         }
@@ -173,7 +178,7 @@ export function createLinkLines(ctx: VisualContext, linkBuilder: LinkBuilderProp
 
     if (!linkCount) return Lines.createEmpty(lines);
 
-    const { linkScale, linkSpacing } = props;
+    const { linkScale, linkSpacing, dashCount } = props;
 
     const linesCountEstimate = linkCount * 2;
     const builder = LinesBuilder.create(linesCountEstimate, linesCountEstimate / 4, lines);
@@ -182,20 +187,27 @@ export function createLinkLines(ctx: VisualContext, linkBuilder: LinkBuilderProp
     const vb = Vec3();
     const vShift = Vec3();
 
+    // automatically adjust length for evenly spaced dashed lines
+    const segmentCount = dashCount % 2 === 1 ? dashCount : dashCount + 1;
+    const lengthScale = 0.5 - (0.5 / 2 / segmentCount);
+
     for (let edgeIndex = 0, _eI = linkCount; edgeIndex < _eI; ++edgeIndex) {
         if (ignore && ignore(edgeIndex)) continue;
 
         position(va, vb, edgeIndex);
-        v3scale(vb, v3add(vb, va, vb), 0.5);
 
         const linkStyle = style ? style(edgeIndex) : LinkStyle.Solid;
 
         if (linkStyle === LinkStyle.Solid) {
+            v3scale(vb, v3add(vb, va, vb), 0.5);
             builder.add(va[0], va[1], va[2], vb[0], vb[1], vb[2], edgeIndex);
         } else if (linkStyle === LinkStyle.Dashed) {
-            builder.addFixedCountDashes(va, vb, 7, edgeIndex);
+            v3scale(tmpV12, v3sub(tmpV12, vb, va), lengthScale);
+            v3sub(vb, vb, tmpV12);
+            builder.addFixedCountDashes(va, vb, segmentCount, edgeIndex);
         } else if (linkStyle === LinkStyle.Double || linkStyle === LinkStyle.Triple) {
-            const order = LinkStyle.Double ? 2 : 3;
+            v3scale(vb, v3add(vb, va, vb), 0.5);
+            const order = linkStyle === LinkStyle.Double ? 2 : 3;
             const multiRadius = 1 * (linkScale / (0.5 * order));
             const absOffset = (1 - multiRadius) * linkSpacing;