biojs-vis-pdbviewer
Version:
A BioJS 2.0 component to view protein structures
363 lines (361 loc) • 12.1 kB
JavaScript
Clazz.declarePackage ("J.g3d");
Clazz.load (["J.g3d.G3DRenderer", "JU.P3", "$.V3"], "J.g3d.HermiteRenderer", ["JU.Lst", "$.P3i", "JU.Point3fi"], function () {
c$ = Clazz.decorateAsClass (function () {
this.g3d = null;
this.pLeft = null;
this.pRight = null;
this.sLeft = null;
this.sRight = null;
this.pTopLeft = null;
this.pTopRight = null;
this.pBotLeft = null;
this.pBotRight = null;
this.a1 = null;
this.a2 = null;
this.b1 = null;
this.b2 = null;
this.c1 = null;
this.c2 = null;
this.d1 = null;
this.d2 = null;
this.T1 = null;
this.T2 = null;
this.depth1 = null;
this.needToFill = null;
Clazz.instantialize (this, arguments);
}, J.g3d, "HermiteRenderer", null, J.g3d.G3DRenderer);
Clazz.prepareFields (c$, function () {
this.pLeft = new Array (16);
this.pRight = new Array (16);
this.sLeft = Clazz.newFloatArray (16, 0);
this.sRight = Clazz.newFloatArray (16, 0);
this.pTopLeft = new Array (16);
this.pTopRight = new Array (16);
this.pBotLeft = new Array (16);
this.pBotRight = new Array (16);
{
for (var i = 16; --i >= 0; ) {
this.pLeft[i] = new JU.P3i ();
this.pRight[i] = new JU.P3i ();
this.pTopLeft[i] = new JU.P3 ();
this.pTopRight[i] = new JU.P3 ();
this.pBotLeft[i] = new JU.P3 ();
this.pBotRight[i] = new JU.P3 ();
}
}this.a1 = new JU.P3 ();
this.a2 = new JU.P3 ();
this.b1 = new JU.P3 ();
this.b2 = new JU.P3 ();
this.c1 = new JU.P3 ();
this.c2 = new JU.P3 ();
this.d1 = new JU.P3 ();
this.d2 = new JU.P3 ();
this.T1 = new JU.V3 ();
this.T2 = new JU.V3 ();
this.depth1 = new JU.V3 ();
this.needToFill = Clazz.newBooleanArray (16, false);
});
Clazz.makeConstructor (c$,
function () {
});
Clazz.overrideMethod (c$, "set",
function (g3d) {
this.g3d = g3d;
return this;
}, "J.api.JmolRendererInterface");
Clazz.defineMethod (c$, "renderHermiteRope",
function (fill, tension, diameterBeg, diameterMid, diameterEnd, p0, p1, p2, p3) {
if (p0.z == 1 || p1.z == 1 || p2.z == 1 || p3.z == 1) return;
if (this.g3d.isClippedZ (p1.z) || this.g3d.isClippedZ (p2.z)) return;
var x1 = p1.x;
var y1 = p1.y;
var z1 = p1.z;
var x2 = p2.x;
var y2 = p2.y;
var z2 = p2.z;
var xT1 = Clazz.doubleToInt (((x2 - p0.x) * tension) / 8);
var yT1 = Clazz.doubleToInt (((y2 - p0.y) * tension) / 8);
var zT1 = Clazz.doubleToInt (((z2 - p0.z) * tension) / 8);
var xT2 = Clazz.doubleToInt (((p3.x - x1) * tension) / 8);
var yT2 = Clazz.doubleToInt (((p3.y - y1) * tension) / 8);
var zT2 = Clazz.doubleToInt (((p3.z - z1) * tension) / 8);
this.sLeft[0] = 0;
this.pLeft[0].setT (p1);
this.sRight[0] = 1;
this.pRight[0].setT (p2);
var sp = 0;
var dDiameterFirstHalf = 0;
var dDiameterSecondHalf = 0;
if (fill) {
dDiameterFirstHalf = 2 * (diameterMid - diameterBeg);
dDiameterSecondHalf = 2 * (diameterEnd - diameterMid);
}do {
var a = this.pLeft[sp];
var b = this.pRight[sp];
var dx = b.x - a.x;
if (dx >= -1 && dx <= 1) {
var dy = b.y - a.y;
if (dy >= -1 && dy <= 1) {
var s = this.sLeft[sp];
if (fill) {
var d = (s < 0.5 ? diameterBeg + Clazz.floatToInt (dDiameterFirstHalf * s) : diameterMid + Clazz.floatToInt (dDiameterSecondHalf * (s - 0.5)));
this.g3d.fillSphereI (d, a);
} else {
this.g3d.plotPixelClippedP3i (a);
}--sp;
continue;
}}var s = (this.sLeft[sp] + this.sRight[sp]) / 2;
var s2 = s * s;
var s3 = s2 * s;
var h1 = 2 * s3 - 3 * s2 + 1;
var h2 = -2 * s3 + 3 * s2;
var h3 = s3 - 2 * s2 + s;
var h4 = s3 - s2;
if (sp >= 15) break;
var pMid = this.pRight[sp + 1];
pMid.x = Clazz.doubleToInt (h1 * x1 + h2 * x2 + h3 * xT1 + h4 * xT2);
pMid.y = Clazz.doubleToInt (h1 * y1 + h2 * y2 + h3 * yT1 + h4 * yT2);
pMid.z = Clazz.doubleToInt (h1 * z1 + h2 * z2 + h3 * zT1 + h4 * zT2);
this.pRight[sp + 1] = this.pRight[sp];
this.sRight[sp + 1] = this.sRight[sp];
this.pRight[sp] = pMid;
this.sRight[sp] = s;
++sp;
this.pLeft[sp].setT (pMid);
this.sLeft[sp] = s;
} while (sp >= 0);
}, "~B,~N,~N,~N,~N,JU.P3i,JU.P3i,JU.P3i,JU.P3i");
Clazz.defineMethod (c$, "renderHermiteRibbon",
function (fill, border, tension, p0, p1, p2, p3, p4, p5, p6, p7, aspectRatio, fillType) {
if (p0.z == 1 || p1.z == 1 || p2.z == 1 || p3.z == 1 || p4.z == 1 || p5.z == 1 || p6.z == 1 || p7.z == 1) return;
if (!fill) {
tension = Math.abs (tension);
this.renderParallelPair (fill, tension, p0, p1, p2, p3, p4, p5, p6, p7);
return;
}var isRev = (tension < 0);
if (isRev) tension = -tension;
var ratio = 1 / aspectRatio;
var x1 = p1.x;
var y1 = p1.y;
var z1 = p1.z;
var x2 = p2.x;
var y2 = p2.y;
var z2 = p2.z;
var xT1 = Clazz.doubleToInt (((x2 - p0.x) * tension) / 8);
var yT1 = Clazz.doubleToInt (((y2 - p0.y) * tension) / 8);
var zT1 = Clazz.doubleToInt (((z2 - p0.z) * tension) / 8);
var xT2 = Clazz.doubleToInt (((p3.x - x1) * tension) / 8);
var yT2 = Clazz.doubleToInt (((p3.y - y1) * tension) / 8);
var zT2 = Clazz.doubleToInt (((p3.z - z1) * tension) / 8);
JU.Point3fi.set2 (this.pTopLeft[0], p1);
JU.Point3fi.set2 (this.pTopRight[0], p2);
var x5 = p5.x;
var y5 = p5.y;
var z5 = p5.z;
var x6 = p6.x;
var y6 = p6.y;
var z6 = p6.z;
var xT5 = Clazz.doubleToInt (((x6 - p4.x) * tension) / 8);
var yT5 = Clazz.doubleToInt (((y6 - p4.y) * tension) / 8);
var zT5 = Clazz.doubleToInt (((z6 - p4.z) * tension) / 8);
var xT6 = Clazz.doubleToInt (((p7.x - x5) * tension) / 8);
var yT6 = Clazz.doubleToInt (((p7.y - y5) * tension) / 8);
var zT6 = Clazz.doubleToInt (((p7.z - z5) * tension) / 8);
JU.Point3fi.set2 (this.pBotLeft[0], p5);
JU.Point3fi.set2 (this.pBotRight[0], p6);
this.sLeft[0] = 0;
this.sRight[0] = 1;
this.needToFill[0] = true;
var sp = 0;
var closeEnd = false;
do {
var a = this.pTopLeft[sp];
var b = this.pTopRight[sp];
var dxTop = b.x - a.x;
var dxTop2 = dxTop * dxTop;
if (dxTop2 < 10) {
var dyTop = b.y - a.y;
var dyTop2 = dyTop * dyTop;
if (dyTop2 < 10) {
var c = this.pBotLeft[sp];
var d = this.pBotRight[sp];
var dxBot = d.x - c.x;
var dxBot2 = dxBot * dxBot;
if (dxBot2 < 8) {
var dyBot = d.y - c.y;
var dyBot2 = dyBot * dyBot;
if (dyBot2 < 8) {
if (border) {
this.g3d.fillSphere (3, a);
this.g3d.fillSphere (3, c);
}if (this.needToFill[sp]) {
if (aspectRatio > 0) {
this.T1.sub2 (a, c);
this.T1.scale (ratio);
this.T2.sub2 (a, b);
this.depth1.cross (this.T1, this.T2);
this.depth1.scale (this.T1.length () / this.depth1.length ());
this.a1.add2 (a, this.depth1);
this.a2.sub2 (a, this.depth1);
this.b1.add2 (b, this.depth1);
this.b2.sub2 (b, this.depth1);
this.c1.add2 (c, this.depth1);
this.c2.sub2 (c, this.depth1);
this.d1.add2 (d, this.depth1);
this.d2.sub2 (d, this.depth1);
this.g3d.fillQuadrilateral (this.a1, this.b1, this.d1, this.c1);
this.g3d.fillQuadrilateral (this.a2, this.b2, this.d2, this.c2);
this.g3d.fillQuadrilateral (this.a1, this.b1, this.b2, this.a2);
this.g3d.fillQuadrilateral (this.c1, this.d1, this.d2, this.c2);
closeEnd = true;
} else {
if (fillType == 0) {
if (isRev) this.g3d.fillQuadrilateral (c, d, b, a);
else this.g3d.fillQuadrilateral (a, b, d, c);
} else {
if (isRev) {
if (fillType != J.g3d.HermiteRenderer.isFront (a, b, d)) this.g3d.fillTriangle3f (a, b, d, false);
if (fillType != J.g3d.HermiteRenderer.isFront (a, d, c)) this.g3d.fillTriangle3f (a, d, c, false);
} else {
if (fillType == J.g3d.HermiteRenderer.isFront (a, b, d)) this.g3d.fillTriangle3f (a, b, d, false);
if (fillType == J.g3d.HermiteRenderer.isFront (a, d, c)) this.g3d.fillTriangle3f (a, d, c, false);
}}}this.needToFill[sp] = false;
}if (dxTop2 + dyTop2 < 2 && dxBot2 + dyBot2 < 2) {
--sp;
continue;
}}}}}var s = (this.sLeft[sp] + this.sRight[sp]) / 2;
var s2 = s * s;
var s3 = s2 * s;
var h1 = 2 * s3 - 3 * s2 + 1;
var h2 = -2 * s3 + 3 * s2;
var h3 = s3 - 2 * s2 + s;
var h4 = s3 - s2;
if (sp >= 15) break;
var spNext = sp + 1;
var pMidTop = this.pTopRight[spNext];
pMidTop.x = (h1 * x1 + h2 * x2 + h3 * xT1 + h4 * xT2);
pMidTop.y = (h1 * y1 + h2 * y2 + h3 * yT1 + h4 * yT2);
pMidTop.z = (h1 * z1 + h2 * z2 + h3 * zT1 + h4 * zT2);
var pMidBot = this.pBotRight[spNext];
pMidBot.x = (h1 * x5 + h2 * x6 + h3 * xT5 + h4 * xT6);
pMidBot.y = (h1 * y5 + h2 * y6 + h3 * yT5 + h4 * yT6);
pMidBot.z = (h1 * z5 + h2 * z6 + h3 * zT5 + h4 * zT6);
this.pTopRight[spNext] = this.pTopRight[sp];
this.pTopRight[sp] = pMidTop;
this.pBotRight[spNext] = this.pBotRight[sp];
this.pBotRight[sp] = pMidBot;
this.sRight[spNext] = this.sRight[sp];
this.sRight[sp] = s;
this.needToFill[spNext] = this.needToFill[sp];
this.pTopLeft[spNext].setT (pMidTop);
this.pBotLeft[spNext].setT (pMidBot);
this.sLeft[spNext] = s;
++sp;
} while (sp >= 0);
if (closeEnd) {
this.a1.z += 1;
this.c1.z += 1;
this.c2.z += 1;
this.a2.z += 1;
this.g3d.fillQuadrilateral (this.a1, this.c1, this.c2, this.a2);
}}, "~B,~B,~N,JU.P3i,JU.P3i,JU.P3i,JU.P3i,JU.P3i,JU.P3i,JU.P3i,JU.P3i,~N,~N");
c$.isFront = Clazz.defineMethod (c$, "isFront",
function (a, b, c) {
J.g3d.HermiteRenderer.vAB.sub2 (b, a);
J.g3d.HermiteRenderer.vAC.sub2 (c, a);
J.g3d.HermiteRenderer.vAB.cross (J.g3d.HermiteRenderer.vAB, J.g3d.HermiteRenderer.vAC);
return (J.g3d.HermiteRenderer.vAB.z < 0 ? -1 : 1);
}, "JU.P3,JU.P3,JU.P3");
Clazz.defineMethod (c$, "renderParallelPair",
function (fill, tension, p0, p1, p2, p3, p4, p5, p6, p7) {
var endPoints = [p2, p1, p6, p5];
var points = new JU.Lst ();
var whichPoint = 0;
var numTopStrandPoints = 2;
var numPointsPerSegment = 5.0;
var interval = (1.0 / numPointsPerSegment);
var currentInt = 0.0;
var x1 = p1.x;
var y1 = p1.y;
var z1 = p1.z;
var x2 = p2.x;
var y2 = p2.y;
var z2 = p2.z;
var xT1 = Clazz.doubleToInt (((x2 - p0.x) * tension) / 8);
var yT1 = Clazz.doubleToInt (((y2 - p0.y) * tension) / 8);
var zT1 = Clazz.doubleToInt (((z2 - p0.z) * tension) / 8);
var xT2 = Clazz.doubleToInt (((p3.x - x1) * tension) / 8);
var yT2 = Clazz.doubleToInt (((p3.y - y1) * tension) / 8);
var zT2 = Clazz.doubleToInt (((p3.z - z1) * tension) / 8);
this.sLeft[0] = 0;
this.pLeft[0].setT (p1);
this.sRight[0] = 1;
this.pRight[0].setT (p2);
var sp = 0;
for (var strands = 2; strands > 0; strands--) {
if (strands == 1) {
x1 = p5.x;
y1 = p5.y;
z1 = p5.z;
x2 = p6.x;
y2 = p6.y;
z2 = p6.z;
xT1 = Clazz.doubleToInt (((x2 - p4.x) * tension) / 8);
yT1 = Clazz.doubleToInt (((y2 - p4.y) * tension) / 8);
zT1 = Clazz.doubleToInt (((z2 - p4.z) * tension) / 8);
xT2 = Clazz.doubleToInt (((p7.x - x1) * tension) / 8);
yT2 = Clazz.doubleToInt (((p7.y - y1) * tension) / 8);
zT2 = Clazz.doubleToInt (((p7.z - z1) * tension) / 8);
this.sLeft[0] = 0;
this.pLeft[0].setT (p5);
this.sRight[0] = 1;
this.pRight[0].setT (p6);
sp = 0;
}points.addLast (endPoints[whichPoint++]);
currentInt = interval;
do {
var a = this.pLeft[sp];
var b = this.pRight[sp];
var dx = b.x - a.x;
var dy = b.y - a.y;
var dist2 = dx * dx + dy * dy;
if (dist2 <= 2) {
var s = this.sLeft[sp];
this.g3d.fillSphereI (3, a);
if (s < 1.0 - currentInt) {
var temp = new JU.P3i ();
temp.setT (a);
points.addLast (temp);
currentInt += interval;
if (strands == 2) {
numTopStrandPoints++;
}}--sp;
} else {
var s = (this.sLeft[sp] + this.sRight[sp]) / 2;
var s2 = s * s;
var s3 = s2 * s;
var h1 = 2 * s3 - 3 * s2 + 1;
var h2 = -2 * s3 + 3 * s2;
var h3 = s3 - 2 * s2 + s;
var h4 = s3 - s2;
if (sp >= 15) break;
var pMid = this.pRight[sp + 1];
pMid.x = Clazz.doubleToInt (h1 * x1 + h2 * x2 + h3 * xT1 + h4 * xT2);
pMid.y = Clazz.doubleToInt (h1 * y1 + h2 * y2 + h3 * yT1 + h4 * yT2);
pMid.z = Clazz.doubleToInt (h1 * z1 + h2 * z2 + h3 * zT1 + h4 * zT2);
this.pRight[sp + 1] = this.pRight[sp];
this.sRight[sp + 1] = this.sRight[sp];
this.pRight[sp] = pMid;
this.sRight[sp] = s;
++sp;
this.pLeft[sp].setT (pMid);
this.sLeft[sp] = s;
}} while (sp >= 0);
points.addLast (endPoints[whichPoint++]);
}
var size = points.size ();
for (var top = 0; top < numTopStrandPoints && (top + numTopStrandPoints) < size; top++) this.g3d.drawLineAB (points.get (top), points.get (top + numTopStrandPoints));
}, "~B,~N,JU.P3i,JU.P3i,JU.P3i,JU.P3i,JU.P3i,JU.P3i,JU.P3i,JU.P3i");
c$.vAB = c$.prototype.vAB = new JU.V3 ();
c$.vAC = c$.prototype.vAC = new JU.V3 ();
});