RodenLuo/oxdna-viewer

Position calculations

Opened this issue · 0 comments

https://dna.physics.ox.ac.uk/index.php/Documentation#Configuration_file

image

image

calcPositionsFromConfLine(l: string[], colorUpdate?: boolean) {
//extract position
let p = new THREE.Vector3(
parseFloat(l[0]),
parseFloat(l[1]),
parseFloat(l[2])
);
// extract axis vector a1 (backbone vector) and a3 (stacking vector)
let a1 = new THREE.Vector3(
parseFloat(l[3]),
parseFloat(l[4]),
parseFloat(l[5])
);
let a3 = new THREE.Vector3(
parseFloat(l[6]),
parseFloat(l[7]),
parseFloat(l[8])
);
this.calcPositions(p, a1, a3, colorUpdate)
};
calcPositions(p: THREE.Vector3, a1: THREE.Vector3, a3: THREE.Vector3, colorUpdate?: boolean) {
let sys = this.getSystem(),
sid = this.sid;
if (this.dummySys !== null) {
sys = this.dummySys;
}
// according to base.py a2 is the cross of a1 and a3
let a2 = a1.clone().cross(a3);
// compute backbone position
let bb = this.calcBBPos(p, a1, a2, a3);
// compute nucleoside cm
let ns = new THREE.Vector3(
p.x + 0.4 * a1.x,
p.y + 0.4 * a1.y,
p.z + 0.4 * a1.z
)
// compute nucleoside rotation
const baseRotation = new THREE.Quaternion().setFromUnitVectors(new THREE.Vector3(0, 1, 0),a3);
//compute connector position
const con = bb.clone().add(ns).divideScalar(2);
// compute connector rotation
const rotationCon = new THREE.Quaternion().setFromUnitVectors(
new THREE.Vector3(0, 1, 0),
con.clone().sub(ns).normalize());
// compute connector length
let conLen = this.bbnsDist;
if (a1.length() == 0 && a2.length() == 0) {
conLen = 0;
}
// compute sugar-phosphate positions/rotations, or set them all to 0 if there is no sugar-phosphate.
let sp: THREE.Vector3, spLen: number, spRotation;
if (this.n3) {
let bbLast = this.n3.getInstanceParameter3('bbOffsets');
sp = bb.clone().add(bbLast).divideScalar(2);
spLen = bb.distanceTo(bbLast);
//introduce distance based cutoff of the backbone connectors
if (spLen>=box.x*.9 ||spLen>=box.y*.9 || spLen>=box.z*.9 ) spLen = 0;
spRotation = new THREE.Quaternion().setFromUnitVectors(
new THREE.Vector3(0, 1, 0), sp.clone().sub(bb).normalize()
);
}
else {
sp = new THREE.Vector3();
spLen = 0;
spRotation = new THREE.Quaternion(0, 0, 0, 0);
}
this.handleCircularStrands(sys, sid, bb);
if (colorUpdate) {
// determine the mesh color, either from a supplied colormap json or by the strand ID.
const bbColor = this.strandToColor(this.strand.id);
sys.fillVec('bbColors', 3, sid, [bbColor.r, bbColor.g, bbColor.b]);
const nsColor = this.elemToColor(this.type);
sys.fillVec('nsColors', 3, sid, [nsColor.r, nsColor.g, nsColor.b]);
let idColor = new THREE.Color();
idColor.setHex(this.id+1); //has to be +1 or you can't grab nucleotide 0
sys.fillVec('bbLabels', 3, sid, [idColor.r, idColor.g, idColor.b]);
}
//fill the instance matrices with data
sys.fillVec('cmOffsets', 3, sid, p.toArray());
sys.fillVec('bbOffsets', 3, sid, bb.toArray());
sys.fillVec('nsOffsets', 3, sid, ns.toArray());
sys.fillVec('nsRotation', 4, sid, [baseRotation.w, baseRotation.z, baseRotation.y, baseRotation.x]);
sys.fillVec('conOffsets', 3, sid, con.toArray());
sys.fillVec('conRotation', 4, sid, [rotationCon.w, rotationCon.z, rotationCon.y, rotationCon.x]);
sys.fillVec('bbconOffsets', 3, sid, sp.toArray());
sys.fillVec('bbconRotation', 4, sid, [spRotation.w, spRotation.z, spRotation.y, spRotation.x]);
sys.fillVec('scales', 3, sid, [1, 1, 1]);
sys.fillVec('nsScales', 3, sid, [0.7, 0.3, 0.7]);
sys.fillVec('conScales', 3, sid, [1, conLen, 1]);
if(spLen == 0) {
sys.fillVec('bbconScales', 3, sid, [0, 0, 0]);
} else {
sys.fillVec('bbconScales', 3, sid, [1, spLen, 1]);
}
sys.fillVec('visibility', 3, sid, [1,1,1]);
};

calcBBPos(p: THREE.Vector3, a1: THREE.Vector3, a2: THREE.Vector3, a3: THREE.Vector3): THREE.Vector3 {
return new THREE.Vector3(
p.x - (0.34 * a1.x + 0.3408 * a2.x),
p.y - (0.34 * a1.y + 0.3408 * a2.y),
p.z - (0.34 * a1.z + 0.3408 * a2.z)
);
};