Skip to content

Commit

Permalink
Merge pull request #641 from dxdc/patch-1
Browse files Browse the repository at this point in the history
Dashed bonds for bond order < 1
  • Loading branch information
dkoes authored Nov 1, 2023
2 parents b03407b + 5e4bd76 commit 2e1c453
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 8 deletions.
73 changes: 65 additions & 8 deletions src/GLModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Sphere, Cylinder } from "./WebGL/shapes";
import { Vector3, Matrix4, conversionMatrix3, Matrix3, XYZ } from "./WebGL/math";
import { Color, CC, ColorschemeSpec, ColorSpec } from "./colors";
import { InstancedMaterial, SphereImposterMaterial, MeshLambertMaterial, Object3D, Mesh, LineBasicMaterial, Line, LineStyle } from "./WebGL";
import { GLDraw } from "./GLDraw"
import { CAP, GLDraw } from "./GLDraw"
import { CartoonStyleSpec, drawCartoon } from "./glcartoon";
import { elementColors } from "./colors";
import { get, deepCopy, extend, getExtent, getAtomProperty, makeFunction, getPropertyRange, specStringToObject, getbin, getColorFromStyle } from "./utilities";
Expand Down Expand Up @@ -658,8 +658,46 @@ export class GLModel {
this.drawSphereImposter(geo, atom as XYZ, radius, C);
};

static drawDashedStickImposter(geo: Geometry, from: XYZ, to: XYZ, radius: number, color: Color, fromCap: CAP = 0, toCap: CAP = 0, dashLength: number = 0.1, gapLength: number = 0.25) {
var cylinderLength = Math.sqrt(Math.pow((from.x - to.x), 2) + Math.pow((from.y - to.y), 2) + Math.pow((from.z - to.z), 2));

static drawStickImposter(geo: Geometry, from: XYZ, to: XYZ, radius: number, color: Color) {
// Constrain dash and gap lengths to not exceed cylinder length
dashLength = Math.min(dashLength, cylinderLength);
gapLength = Math.min(gapLength, cylinderLength);

// Initial calculations for totalSegments based on input dashLength, gapLength, and radius
var totalSegments = Math.floor(cylinderLength / (dashLength + gapLength + radius));

// Make totalSegments odd to ensure dashed segments at both ends
totalSegments += totalSegments % 2 === 0 ? 1 : 0;

var totalDashLength = totalSegments * dashLength;

// If totalDashLength exceeds cylinder length, adjust it
if (totalDashLength > cylinderLength) {
totalSegments = Math.floor(cylinderLength / dashLength);
totalSegments -= totalSegments % 2 === 0 ? 1 : 0; // Make it odd
totalDashLength = totalSegments * dashLength; // Recalculate totalDashLength
}

// Recalculate gapLength based on final totalSegments and totalDashLength
gapLength = (cylinderLength - totalDashLength) / totalSegments;

var new_from = new Vector3(from.x, from.y, from.z);
var new_to = new Vector3(to.x, to.y, to.z);

var gapVector = new Vector3((to.x - from.x) / (cylinderLength / gapLength), (to.y - from.y) / (cylinderLength / gapLength), (to.z - from.z) / (cylinderLength / gapLength));
var dashVector = new Vector3((to.x - from.x) / (cylinderLength / dashLength), (to.y - from.y) / (cylinderLength / dashLength), (to.z - from.z) / (cylinderLength / dashLength));

for (var place = 0; place < totalSegments; place++) {
new_to = new Vector3(new_from.x + dashVector.x, new_from.y + dashVector.y, new_from.z + dashVector.z);
// this.intersectionShape.cylinder.push(new $3Dmol.Cylinder(new_from, new_to, radius));
GLModel.drawStickImposter(geo, new_from, new_to, radius, color);
new_from = new Vector3(new_to.x + gapVector.x, new_to.y + gapVector.y, new_to.z + gapVector.z);
}
};

static drawStickImposter(geo: Geometry, from: XYZ, to: XYZ, radius: number, color: Color, fromCap:CAP = 0, toCap:CAP = 0) {
//we need the four corners - two have from coord, two have to coord, the normal
//is the opposing point, from which we can get the normal and length
//also need the radius
Expand Down Expand Up @@ -735,8 +773,12 @@ export class GLModel {
var doubleBondScale = style.doubleBondScaling || 0.4;
var tripleBondScale = style.tripleBondScaling || 0.25;

var bondDashLength = style.dashedBondConfig?.dashLength || 0.1;
var bondGapLength = style.dashedBondConfig?.gapLength || 0.25;

var bondR = atomBondR;
var atomSingleBond = style.singleBonds || false;
var atomDashedBonds = style.dashedBonds || false;
var fromCap = 0, toCap = 0;
var atomneedsi, atom2needsi, i, singleBond, bstyle;
var cylinder1a, cylinder1b, cylinder1c, cylinder2a, cylinder2b, cylinder2c;
Expand All @@ -748,12 +790,14 @@ export class GLModel {
if (!atom.capDrawn && atom.bonds.length < 4)
fromCap = 2;

var drawCyl = GLDraw.drawCylinder; //mesh cylinder
if (geo.imposter)
drawCyl = GLModel.drawStickImposter;
var selectCylDrawMethod = function (bondOrder) {
if (geo.imposter) return (atomDashedBonds || bondOrder < 1) ? GLModel.drawDashedStickImposter : GLModel.drawStickImposter;

return GLDraw.drawCylinder; //mesh cylinder
};

for (i = 0; i < atom.bonds.length; i++) {
var drawCyl = selectCylDrawMethod(atom.bondOrder[i]);
var j = atom.bonds[i]; // our neighbor
var atom2 = atoms[j]; //parsePDB, etc should only add defined bonds
mp = mp2 = mp3 = null;
Expand Down Expand Up @@ -797,10 +841,10 @@ export class GLModel {
if (C1 != C2) {
mp = new Vector3().addVectors(p1, p2)
.multiplyScalar(0.5);
drawCyl(geo, p1, mp, bondR, C1, fromCap, 0);
drawCyl(geo, mp, p2, bondR, C2, 0, toCap);
drawCyl(geo, p1, mp, bondR, C1, fromCap, 0, bondDashLength, bondGapLength);
drawCyl(geo, mp, p2, bondR, C2, 0, toCap, bondDashLength, bondGapLength);
} else {
drawCyl(geo, p1, p2, bondR, C1, fromCap, toCap);
drawCyl(geo, p1, p2, bondR, C1, fromCap, toCap, bondDashLength, bondGapLength);
}


Expand Down Expand Up @@ -2868,6 +2912,15 @@ export interface CrossStyleSpec {
opacity?: number;
}

/** Dashed Bond style specification
*/
export interface DashedBondSpec {
/** length of dash (default 0.1) */
dashLength?: number;
/** length of gap (default 0.25) */
gapLength?: number;
}

/** Stick (cylinder) style specification
*/
export interface StickStyleSpec {
Expand All @@ -2879,6 +2932,10 @@ export interface StickStyleSpec {
doubleBondScaling?: number;
/** radius scaling factor for drawing triple bonds (default 0.25) */
tripleBondScaling?: number;
/** dashed bond properties */
dashedBondConfig?: DashedBondSpec;
/** draw all bonds as dashed bonds */
dashedBonds?: boolean;
/** draw all bonds as single bonds */
singleBonds?: boolean;
/** colorscheme to use on atoms; overrides color */
Expand Down
35 changes: 35 additions & 0 deletions tests/auto/tests/partialbonds2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@

/*@div
<div style="width: 400px; height: 400px; position: relative;"
class='viewer_3Dmoljs'
data-element='moldata'
data-backgroundcolor='0xffffff'
data-style='stick'
data-type="sdf"></div>
*/

/*
@data
<textarea style="display: none;" id="moldata">
Molecule002
Mrv1903 01162316393D
6 5 0 0 0 0 999 V2000
0.4761 0.1839 -0.9563 H 0 0 0 0 0 0 0 0 0 0 0 0
0.1475 -0.2251 0.0075 C 0 0 0 0 0 0 0 0 0 0 0 0
-0.8612 -0.6549 0.0499 H 0 0 0 0 0 0 0 0 0 0 0 0
0.5167 0.2726 0.9131 H 0 0 0 0 0 0 0 0 0 0 0 0
1.3194 -2.0204 0.0676 Cl 0 0 0 0 0 0 0 0 0 0 0 0
-1.5985 2.4439 -0.0818 Br 0 0 0 0 0 0 0 0 0 0 0 0
1 2 8 0 0 0 0
2 4 8 0 0 0 0
2 3 8 0 0 0 0
2 6 0.5 0 0 0 0
2 5 0.03 0 0 0 0
M END
> <anyBondsFromCoords>
true
$$$$
</textarea>
*/
35 changes: 35 additions & 0 deletions tests/auto/tests/partialbonds3.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@

/*@div
<div style="width: 400px; height: 400px; position: relative;"
class='viewer_3Dmoljs'
data-element='moldata'
data-backgroundcolor='0xffffff'
data-style='{"stick":{"dashedBonds": true, "dashedBondConfig": { "dashLength": 0.01, "gapLength": 0.05 }}}'
data-type="sdf"></div>
*/

/*
@data
<textarea style="display: none;" id="moldata">
Molecule002
Mrv1903 01162316393D
6 5 0 0 0 0 999 V2000
0.4761 0.1839 -0.9563 H 0 0 0 0 0 0 0 0 0 0 0 0
0.1475 -0.2251 0.0075 C 0 0 0 0 0 0 0 0 0 0 0 0
-0.8612 -0.6549 0.0499 H 0 0 0 0 0 0 0 0 0 0 0 0
0.5167 0.2726 0.9131 H 0 0 0 0 0 0 0 0 0 0 0 0
1.3194 -2.0204 0.0676 Cl 0 0 0 0 0 0 0 0 0 0 0 0
-1.5985 2.4439 -0.0818 Br 0 0 0 0 0 0 0 0 0 0 0 0
1 2 8 0 0 0 0
2 4 8 0 0 0 0
2 3 8 0 0 0 0
2 6 0.5 0 0 0 0
2 5 0.03 0 0 0 0
M END
> <anyBondsFromCoords>
true
$$$$
</textarea>
*/
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 2e1c453

Please sign in to comment.