biojs-vis-pdbviewer
Version:
A BioJS 2.0 component to view protein structures
399 lines (397 loc) • 15.2 kB
JavaScript
Clazz.declarePackage ("JU");
Clazz.load (["JU.V3"], "JU.Measure", ["java.lang.Float", "javajs.api.Interface", "JU.Lst", "$.P3", "$.P4", "$.Quat"], function () {
c$ = Clazz.declareType (JU, "Measure");
c$.computeAngle = Clazz.defineMethod (c$, "computeAngle",
function (pointA, pointB, pointC, vectorBA, vectorBC, asDegrees) {
vectorBA.sub2 (pointA, pointB);
vectorBC.sub2 (pointC, pointB);
var angle = vectorBA.angle (vectorBC);
return (asDegrees ? angle / 0.017453292 : angle);
}, "JU.T3,JU.T3,JU.T3,JU.V3,JU.V3,~B");
c$.computeAngleABC = Clazz.defineMethod (c$, "computeAngleABC",
function (pointA, pointB, pointC, asDegrees) {
var vectorBA = new JU.V3 ();
var vectorBC = new JU.V3 ();
return JU.Measure.computeAngle (pointA, pointB, pointC, vectorBA, vectorBC, asDegrees);
}, "JU.T3,JU.T3,JU.T3,~B");
c$.computeTorsion = Clazz.defineMethod (c$, "computeTorsion",
function (p1, p2, p3, p4, asDegrees) {
var ijx = p1.x - p2.x;
var ijy = p1.y - p2.y;
var ijz = p1.z - p2.z;
var kjx = p3.x - p2.x;
var kjy = p3.y - p2.y;
var kjz = p3.z - p2.z;
var klx = p3.x - p4.x;
var kly = p3.y - p4.y;
var klz = p3.z - p4.z;
var ax = ijy * kjz - ijz * kjy;
var ay = ijz * kjx - ijx * kjz;
var az = ijx * kjy - ijy * kjx;
var cx = kjy * klz - kjz * kly;
var cy = kjz * klx - kjx * klz;
var cz = kjx * kly - kjy * klx;
var ai2 = 1 / (ax * ax + ay * ay + az * az);
var ci2 = 1 / (cx * cx + cy * cy + cz * cz);
var ai = Math.sqrt (ai2);
var ci = Math.sqrt (ci2);
var denom = ai * ci;
var cross = ax * cx + ay * cy + az * cz;
var cosang = cross * denom;
if (cosang > 1) {
cosang = 1;
}if (cosang < -1) {
cosang = -1;
}var torsion = Math.acos (cosang);
var dot = ijx * cx + ijy * cy + ijz * cz;
var absDot = Math.abs (dot);
torsion = (dot / absDot > 0) ? torsion : -torsion;
return (asDegrees ? torsion / 0.017453292 : torsion);
}, "JU.T3,JU.T3,JU.T3,JU.T3,~B");
c$.computeHelicalAxis = Clazz.defineMethod (c$, "computeHelicalAxis",
function (a, b, dq) {
var vab = new JU.V3 ();
vab.sub2 (b, a);
var theta = dq.getTheta ();
var n = dq.getNormal ();
var v_dot_n = vab.dot (n);
if (Math.abs (v_dot_n) < 0.0001) v_dot_n = 0;
var va_prime_d = new JU.V3 ();
va_prime_d.cross (vab, n);
if (va_prime_d.dot (va_prime_d) != 0) va_prime_d.normalize ();
var vda = new JU.V3 ();
var vcb = JU.V3.newV (n);
if (v_dot_n == 0) {
v_dot_n = 1.4E-45;
vcb.scale (v_dot_n);
}vda.sub2 (vcb, vab);
vda.scale (0.5);
va_prime_d.scale (theta == 0 ? 0 : (vda.length () / Math.tan (theta / 2 / 180 * 3.141592653589793)));
var r = JU.V3.newV (va_prime_d);
if (theta != 0) r.add (vda);
var pt_a_prime = JU.P3.newP (a);
pt_a_prime.sub (r);
var pt_b_prime = JU.P3.newP (pt_a_prime);
pt_b_prime.add (n);
theta = JU.Measure.computeTorsion (a, pt_a_prime, pt_b_prime, b, true);
if (Float.isNaN (theta) || r.length () < 0.0001) theta = dq.getThetaDirectedV (n);
var residuesPerTurn = Math.abs (theta == 0 ? 0 : 360 / theta);
var pitch = Math.abs (v_dot_n == 1.4E-45 ? 0 : n.length () * (theta == 0 ? 1 : 360 / theta));
return [pt_a_prime, n, r, JU.P3.new3 (theta, pitch, residuesPerTurn), pt_b_prime];
}, "JU.P3,JU.P3,JU.Quat");
c$.getPlaneThroughPoints = Clazz.defineMethod (c$, "getPlaneThroughPoints",
function (pointA, pointB, pointC, vNorm, vAB, vAC, plane) {
var w = JU.Measure.getNormalThroughPoints (pointA, pointB, pointC, vNorm, vAB, vAC);
plane.set4 (vNorm.x, vNorm.y, vNorm.z, w);
}, "JU.T3,JU.T3,JU.T3,JU.V3,JU.V3,JU.V3,JU.P4");
c$.getPlaneThroughPoint = Clazz.defineMethod (c$, "getPlaneThroughPoint",
function (pt, normal, plane) {
plane.set4 (normal.x, normal.y, normal.z, -normal.dot (pt));
}, "JU.T3,JU.V3,JU.P4");
c$.distanceToPlane = Clazz.defineMethod (c$, "distanceToPlane",
function (plane, pt) {
return (plane == null ? NaN : (plane.x * pt.x + plane.y * pt.y + plane.z * pt.z + plane.w) / Math.sqrt (plane.x * plane.x + plane.y * plane.y + plane.z * plane.z));
}, "JU.P4,JU.T3");
c$.distanceToPlaneD = Clazz.defineMethod (c$, "distanceToPlaneD",
function (plane, d, pt) {
return (plane == null ? NaN : (plane.x * pt.x + plane.y * pt.y + plane.z * pt.z + plane.w) / d);
}, "JU.P4,~N,JU.P3");
c$.distanceToPlaneV = Clazz.defineMethod (c$, "distanceToPlaneV",
function (norm, w, pt) {
return (norm == null ? NaN : (norm.x * pt.x + norm.y * pt.y + norm.z * pt.z + w) / Math.sqrt (norm.x * norm.x + norm.y * norm.y + norm.z * norm.z));
}, "JU.V3,~N,JU.P3");
c$.calcNormalizedNormal = Clazz.defineMethod (c$, "calcNormalizedNormal",
function (pointA, pointB, pointC, vNormNorm, vAB, vAC) {
vAB.sub2 (pointB, pointA);
vAC.sub2 (pointC, pointA);
vNormNorm.cross (vAB, vAC);
vNormNorm.normalize ();
}, "JU.T3,JU.T3,JU.T3,JU.V3,JU.V3,JU.V3");
c$.getDirectedNormalThroughPoints = Clazz.defineMethod (c$, "getDirectedNormalThroughPoints",
function (pointA, pointB, pointC, ptRef, vNorm, vAB, vAC) {
var nd = JU.Measure.getNormalThroughPoints (pointA, pointB, pointC, vNorm, vAB, vAC);
if (ptRef != null) {
var pt0 = JU.P3.newP (pointA);
pt0.add (vNorm);
var d = pt0.distance (ptRef);
pt0.sub2 (pointA, vNorm);
if (d > pt0.distance (ptRef)) {
vNorm.scale (-1);
nd = -nd;
}}return nd;
}, "JU.T3,JU.T3,JU.T3,JU.T3,JU.V3,JU.V3,JU.V3");
c$.getNormalThroughPoints = Clazz.defineMethod (c$, "getNormalThroughPoints",
function (pointA, pointB, pointC, vNorm, vAB, vAC) {
JU.Measure.calcNormalizedNormal (pointA, pointB, pointC, vNorm, vAB, vAC);
vAB.setT (pointA);
return -vAB.dot (vNorm);
}, "JU.T3,JU.T3,JU.T3,JU.V3,JU.V3,JU.V3");
c$.getPlaneProjection = Clazz.defineMethod (c$, "getPlaneProjection",
function (pt, plane, ptProj, vNorm) {
var dist = JU.Measure.distanceToPlane (plane, pt);
vNorm.set (plane.x, plane.y, plane.z);
vNorm.normalize ();
vNorm.scale (-dist);
ptProj.add2 (pt, vNorm);
}, "JU.P3,JU.P4,JU.P3,JU.V3");
c$.getNormalFromCenter = Clazz.defineMethod (c$, "getNormalFromCenter",
function (ptCenter, ptA, ptB, ptC, isOutward, normal) {
var vAB = new JU.V3 ();
var vAC = new JU.V3 ();
var d = JU.Measure.getNormalThroughPoints (ptA, ptB, ptC, normal, vAB, vAC);
var isReversed = (JU.Measure.distanceToPlaneV (normal, d, ptCenter) > 0);
if (isReversed == isOutward) normal.scale (-1.0);
return !isReversed;
}, "JU.P3,JU.P3,JU.P3,JU.P3,~B,JU.V3");
c$.getNormalToLine = Clazz.defineMethod (c$, "getNormalToLine",
function (pointA, pointB, vNormNorm) {
vNormNorm.sub2 (pointA, pointB);
vNormNorm.cross (vNormNorm, JU.Measure.axisY);
vNormNorm.normalize ();
if (Float.isNaN (vNormNorm.x)) vNormNorm.set (1, 0, 0);
}, "JU.P3,JU.P3,JU.V3");
c$.getBisectingPlane = Clazz.defineMethod (c$, "getBisectingPlane",
function (pointA, vAB, ptTemp, vTemp, plane) {
ptTemp.scaleAdd2 (0.5, vAB, pointA);
vTemp.setT (vAB);
vTemp.normalize ();
JU.Measure.getPlaneThroughPoint (ptTemp, vTemp, plane);
}, "JU.P3,JU.V3,JU.P3,JU.V3,JU.P4");
c$.projectOntoAxis = Clazz.defineMethod (c$, "projectOntoAxis",
function (point, axisA, axisUnitVector, vectorProjection) {
vectorProjection.sub2 (point, axisA);
var projectedLength = vectorProjection.dot (axisUnitVector);
point.scaleAdd2 (projectedLength, axisUnitVector, axisA);
vectorProjection.sub2 (point, axisA);
}, "JU.P3,JU.P3,JU.V3,JU.V3");
c$.calcBestAxisThroughPoints = Clazz.defineMethod (c$, "calcBestAxisThroughPoints",
function (points, axisA, axisUnitVector, vectorProjection, nTriesMax) {
var nPoints = points.length;
axisA.setT (points[0]);
axisUnitVector.sub2 (points[nPoints - 1], axisA);
axisUnitVector.normalize ();
JU.Measure.calcAveragePointN (points, nPoints, axisA);
var nTries = 0;
while (nTries++ < nTriesMax && JU.Measure.findAxis (points, nPoints, axisA, axisUnitVector, vectorProjection) > 0.001) {
}
var tempA = JU.P3.newP (points[0]);
JU.Measure.projectOntoAxis (tempA, axisA, axisUnitVector, vectorProjection);
axisA.setT (tempA);
}, "~A,JU.P3,JU.V3,JU.V3,~N");
c$.findAxis = Clazz.defineMethod (c$, "findAxis",
function (points, nPoints, axisA, axisUnitVector, vectorProjection) {
var sumXiYi = new JU.V3 ();
var vTemp = new JU.V3 ();
var pt = new JU.P3 ();
var ptProj = new JU.P3 ();
var a = JU.V3.newV (axisUnitVector);
var sum_Xi2 = 0;
for (var i = nPoints; --i >= 0; ) {
pt.setT (points[i]);
ptProj.setT (pt);
JU.Measure.projectOntoAxis (ptProj, axisA, axisUnitVector, vectorProjection);
vTemp.sub2 (pt, ptProj);
vTemp.cross (vectorProjection, vTemp);
sumXiYi.add (vTemp);
sum_Xi2 += vectorProjection.lengthSquared ();
}
var m = JU.V3.newV (sumXiYi);
m.scale (1 / sum_Xi2);
vTemp.cross (m, axisUnitVector);
axisUnitVector.add (vTemp);
axisUnitVector.normalize ();
vTemp.sub2 (axisUnitVector, a);
return vTemp.length ();
}, "~A,~N,JU.P3,JU.V3,JU.V3");
c$.calcAveragePoint = Clazz.defineMethod (c$, "calcAveragePoint",
function (pointA, pointB, pointC) {
pointC.set ((pointA.x + pointB.x) / 2, (pointA.y + pointB.y) / 2, (pointA.z + pointB.z) / 2);
}, "JU.P3,JU.P3,JU.P3");
c$.calcAveragePointN = Clazz.defineMethod (c$, "calcAveragePointN",
function (points, nPoints, averagePoint) {
averagePoint.setT (points[0]);
for (var i = 1; i < nPoints; i++) averagePoint.add (points[i]);
averagePoint.scale (1 / nPoints);
}, "~A,~N,JU.P3");
c$.transformPoints = Clazz.defineMethod (c$, "transformPoints",
function (vPts, m4, center) {
var v = new JU.Lst ();
for (var i = 0; i < vPts.size (); i++) {
var pt = JU.P3.newP (vPts.get (i));
pt.sub (center);
m4.rotTrans2 (pt, pt);
pt.add (center);
v.addLast (pt);
}
return v;
}, "JU.Lst,JU.M4,JU.P3");
c$.isInTetrahedron = Clazz.defineMethod (c$, "isInTetrahedron",
function (pt, ptA, ptB, ptC, ptD, plane, vTemp, vTemp2, vTemp3, fullyEnclosed) {
JU.Measure.getPlaneThroughPoints (ptC, ptD, ptA, vTemp, vTemp2, vTemp3, plane);
var b = (JU.Measure.distanceToPlane (plane, pt) >= 0);
JU.Measure.getPlaneThroughPoints (ptA, ptD, ptB, vTemp, vTemp2, vTemp3, plane);
if (b != (JU.Measure.distanceToPlane (plane, pt) >= 0)) return false;
JU.Measure.getPlaneThroughPoints (ptB, ptD, ptC, vTemp, vTemp2, vTemp3, plane);
if (b != (JU.Measure.distanceToPlane (plane, pt) >= 0)) return false;
JU.Measure.getPlaneThroughPoints (ptA, ptB, ptC, vTemp, vTemp2, vTemp3, plane);
var d = JU.Measure.distanceToPlane (plane, pt);
if (fullyEnclosed) return (b == (d >= 0));
var d1 = JU.Measure.distanceToPlane (plane, ptD);
return d1 * d <= 0 || Math.abs (d1) > Math.abs (d);
}, "JU.P3,JU.P3,JU.P3,JU.P3,JU.P3,JU.P4,JU.V3,JU.V3,JU.V3,~B");
c$.getIntersectionPP = Clazz.defineMethod (c$, "getIntersectionPP",
function (plane1, plane2) {
var a1 = plane1.x;
var b1 = plane1.y;
var c1 = plane1.z;
var d1 = plane1.w;
var a2 = plane2.x;
var b2 = plane2.y;
var c2 = plane2.z;
var d2 = plane2.w;
var norm1 = JU.V3.new3 (a1, b1, c1);
var norm2 = JU.V3.new3 (a2, b2, c2);
var nxn = new JU.V3 ();
nxn.cross (norm1, norm2);
var ax = Math.abs (nxn.x);
var ay = Math.abs (nxn.y);
var az = Math.abs (nxn.z);
var x;
var y;
var z;
var diff;
var type = (ax > ay ? (ax > az ? 1 : 3) : ay > az ? 2 : 3);
switch (type) {
case 1:
x = 0;
diff = (b1 * c2 - b2 * c1);
if (Math.abs (diff) < 0.01) return null;
y = (c1 * d2 - c2 * d1) / diff;
z = (b2 * d1 - d2 * b1) / diff;
break;
case 2:
diff = (a1 * c2 - a2 * c1);
if (Math.abs (diff) < 0.01) return null;
x = (c1 * d2 - c2 * d1) / diff;
y = 0;
z = (a2 * d1 - d2 * a1) / diff;
break;
case 3:
default:
diff = (a1 * b2 - a2 * b1);
if (Math.abs (diff) < 0.01) return null;
x = (b1 * d2 - b2 * d1) / diff;
y = (a2 * d1 - d2 * a1) / diff;
z = 0;
}
var list = new JU.Lst ();
list.addLast (JU.P3.new3 (x, y, z));
nxn.normalize ();
list.addLast (nxn);
return list;
}, "JU.P4,JU.P4");
c$.getIntersection = Clazz.defineMethod (c$, "getIntersection",
function (pt1, v, plane, ptRet, tempNorm, vTemp) {
JU.Measure.getPlaneProjection (pt1, plane, ptRet, tempNorm);
tempNorm.set (plane.x, plane.y, plane.z);
tempNorm.normalize ();
if (v == null) v = JU.V3.newV (tempNorm);
var l_dot_n = v.dot (tempNorm);
if (Math.abs (l_dot_n) < 0.01) return null;
vTemp.sub2 (ptRet, pt1);
ptRet.scaleAdd2 (vTemp.dot (tempNorm) / l_dot_n, v, pt1);
return ptRet;
}, "JU.P3,JU.V3,JU.P4,JU.P3,JU.V3,JU.V3");
c$.calculateQuaternionRotation = Clazz.defineMethod (c$, "calculateQuaternionRotation",
function (centerAndPoints, retStddev) {
retStddev[1] = NaN;
var q = new JU.Quat ();
if (centerAndPoints[0].length == 1 || centerAndPoints[0].length != centerAndPoints[1].length) return q;
var n = centerAndPoints[0].length - 1;
if (n < 2) return q;
var Sxx = 0;
var Sxy = 0;
var Sxz = 0;
var Syx = 0;
var Syy = 0;
var Syz = 0;
var Szx = 0;
var Szy = 0;
var Szz = 0;
var ptA = new JU.P3 ();
var ptB = new JU.P3 ();
for (var i = n + 1; --i >= 1; ) {
var aij = centerAndPoints[0][i];
var bij = centerAndPoints[1][i];
ptA.sub2 (aij, centerAndPoints[0][0]);
ptB.sub2 (bij, centerAndPoints[0][1]);
Sxx += ptA.x * ptB.x;
Sxy += ptA.x * ptB.y;
Sxz += ptA.x * ptB.z;
Syx += ptA.y * ptB.x;
Syy += ptA.y * ptB.y;
Syz += ptA.y * ptB.z;
Szx += ptA.z * ptB.x;
Szy += ptA.z * ptB.y;
Szz += ptA.z * ptB.z;
}
retStddev[0] = JU.Measure.getRmsd (centerAndPoints, q);
var N = Clazz.newDoubleArray (4, 4, 0);
N[0][0] = Sxx + Syy + Szz;
N[0][1] = N[1][0] = Syz - Szy;
N[0][2] = N[2][0] = Szx - Sxz;
N[0][3] = N[3][0] = Sxy - Syx;
N[1][1] = Sxx - Syy - Szz;
N[1][2] = N[2][1] = Sxy + Syx;
N[1][3] = N[3][1] = Szx + Sxz;
N[2][2] = -Sxx + Syy - Szz;
N[2][3] = N[3][2] = Syz + Szy;
N[3][3] = -Sxx - Syy + Szz;
var v = (javajs.api.Interface.getInterface ("JU.Eigen")).setM (N).getEigenvectorsFloatTransposed ()[3];
q = JU.Quat.newP4 (JU.P4.new4 (v[1], v[2], v[3], v[0]));
retStddev[1] = JU.Measure.getRmsd (centerAndPoints, q);
return q;
}, "~A,~A");
c$.getTransformMatrix4 = Clazz.defineMethod (c$, "getTransformMatrix4",
function (ptsA, ptsB, m, centerA) {
var cptsA = JU.Measure.getCenterAndPoints (ptsA);
var cptsB = JU.Measure.getCenterAndPoints (ptsB);
var retStddev = Clazz.newFloatArray (2, 0);
var q = JU.Measure.calculateQuaternionRotation ([cptsA, cptsB], retStddev);
var v = JU.V3.newVsub (cptsB[0], cptsA[0]);
m.setMV (q.getMatrix (), v);
if (centerA != null) centerA.setT (cptsA[0]);
return retStddev[1];
}, "JU.Lst,JU.Lst,JU.M4,JU.P3");
c$.getCenterAndPoints = Clazz.defineMethod (c$, "getCenterAndPoints",
function (vPts) {
var n = vPts.size ();
var pts = new Array (n + 1);
pts[0] = new JU.P3 ();
if (n > 0) {
for (var i = 0; i < n; i++) {
pts[0].add (pts[i + 1] = vPts.get (i));
}
pts[0].scale (1 / n);
}return pts;
}, "JU.Lst");
c$.getRmsd = Clazz.defineMethod (c$, "getRmsd",
function (centerAndPoints, q) {
var sum2 = 0;
var ptsA = centerAndPoints[0];
var ptsB = centerAndPoints[1];
var cA = ptsA[0];
var cB = ptsB[0];
var n = ptsA.length - 1;
var ptAnew = new JU.P3 ();
for (var i = n + 1; --i >= 1; ) {
ptAnew.sub2 (ptsA[i], cA);
q.transformP2 (ptAnew, ptAnew).add (cB);
sum2 += ptAnew.distanceSquared (ptsB[i]);
}
return Math.sqrt (sum2 / n);
}, "~A,JU.Quat");
Clazz.defineStatics (c$,
"radiansPerDegree", (0.017453292519943295));
c$.axisY = c$.prototype.axisY = JU.V3.new3 (0, 1, 0);
});