biojs-vis-pdbviewer
Version:
A BioJS 2.0 component to view protein structures
352 lines (347 loc) • 12.8 kB
JavaScript
Clazz.declarePackage ("J.geodesic");
Clazz.load (["J.api.JmolEnvCalc", "JU.P3", "J.atomdata.AtomData"], "J.geodesic.EnvelopeCalculation", ["JU.AU", "$.BS", "$.V3", "J.atomdata.RadiusData", "JU.BSUtil", "$.Geodesic", "$.Normix"], function () {
c$ = Clazz.decorateAsClass (function () {
this.geodesicMap = null;
this.mapT = null;
this.mads = null;
this.atomData = null;
this.vwr = null;
this.ac = 0;
this.maxRadius = 0;
this.modelZeroBased = false;
this.disregardNeighbors = false;
this.bsMySelected = null;
this.dotsConvexMaps = null;
this.dotsConvexMax = 0;
this.geodesicCount = 0;
this.bsSurface = null;
this.radiusP = 0;
this.diameterP = 0;
this.bsTemp = null;
this.bsIgnore = null;
this.onlySelectedDots = false;
this.isSurface = false;
this.multiModel = false;
this.currentPoints = null;
this.indexI = 0;
this.centerI = null;
this.radiusI = 0;
this.radiiIP2 = 0;
this.pointT = null;
this.centerT = null;
this.vertexTest = null;
this.neighborCount = 0;
this.neighborIndices = null;
this.neighborCenters = null;
this.neighborPlusProbeRadii2 = null;
this.neighborRadii2 = null;
Clazz.instantialize (this, arguments);
}, J.geodesic, "EnvelopeCalculation", null, J.api.JmolEnvCalc);
Clazz.prepareFields (c$, function () {
this.atomData = new J.atomdata.AtomData ();
this.pointT = new JU.P3 ();
this.vertexTest = new Array (12);
{
for (var i = 0; i < 12; i++) this.vertexTest[i] = new JU.P3 ();
}this.neighborIndices = Clazz.newIntArray (16, 0);
this.neighborCenters = new Array (16);
this.neighborPlusProbeRadii2 = Clazz.newFloatArray (16, 0);
this.neighborRadii2 = Clazz.newFloatArray (16, 0);
});
Clazz.makeConstructor (c$,
function () {
});
Clazz.overrideMethod (c$, "set",
function (vwr, ac, mads) {
this.vwr = vwr;
this.ac = ac;
this.mads = mads;
this.geodesicCount = JU.Geodesic.getVertexCount (3);
this.geodesicMap = JU.BS.newN (this.geodesicCount);
this.mapT = JU.BS.newN (this.geodesicCount);
J.geodesic.EnvelopeCalculation.EMPTY_SET = JU.BSUtil.emptySet;
return this;
}, "J.atomdata.AtomDataServer,~N,~A");
Clazz.defineMethod (c$, "getDotsConvexMaps",
function () {
return this.dotsConvexMaps;
});
Clazz.defineMethod (c$, "getDotsConvexMax",
function () {
return this.dotsConvexMax;
});
Clazz.defineMethod (c$, "allocDotsConvexMaps",
function (max) {
if (this.dotsConvexMax >= max) return;
this.dotsConvexMax = max;
this.dotsConvexMaps = new Array (max);
}, "~N");
Clazz.overrideMethod (c$, "getBsSurfaceClone",
function () {
return JU.BSUtil.copy (this.bsSurface);
});
Clazz.defineMethod (c$, "setMads",
function (mads) {
this.mads = mads;
}, "~A");
Clazz.defineMethod (c$, "setFromBits",
function (index, bs) {
this.geodesicMap.setBits (0, this.geodesicCount);
for (var iDot = this.geodesicCount; --iDot >= 0; ) if (!bs.get (iDot)) this.geodesicMap.clear (iDot);
if (this.dotsConvexMaps == null) this.dotsConvexMaps = new Array (this.ac);
var map;
if (this.geodesicMap.isEmpty ()) map = J.geodesic.EnvelopeCalculation.EMPTY_SET;
else map = JU.BSUtil.copy (this.geodesicMap);
if (index >= this.dotsConvexMaps.length) return;
this.dotsConvexMaps[index] = map;
this.dotsConvexMax = Math.max (this.dotsConvexMax, index);
}, "~N,JU.BS");
Clazz.defineMethod (c$, "newSet",
function () {
this.dotsConvexMax = 0;
this.dotsConvexMaps = null;
this.radiusP = this.diameterP = 0;
this.mads = null;
});
Clazz.defineMethod (c$, "reCalculate",
function (bs, m) {
if (this.atomData.radiusData != null) {
this.calculate (null, this.maxRadius, bs, this.bsIgnore, this.disregardNeighbors, this.onlySelectedDots, this.isSurface, this.multiModel);
return;
}if (this.dotsConvexMaps == null || this.dotsConvexMax == 0) return;
var pt = new JU.V3 ();
if (this.bsTemp == null) this.bsTemp = JU.Normix.newVertexBitSet ();
for (var i = bs.nextSetBit (0); i >= 0; i = bs.nextSetBit (i + 1)) {
if (i >= this.dotsConvexMax) return;
var map = this.dotsConvexMaps[i];
if (map == null || map.isEmpty ()) continue;
var bsNew = new JU.BS ();
for (var j = map.nextSetBit (0); j >= 0; j = map.nextSetBit (j + 1)) {
pt.setT (JU.Geodesic.getVertexVector (j));
m.rotate (pt);
bsNew.set (JU.Normix.getNormixV (pt, this.bsTemp));
}
this.dotsConvexMaps[i] = bsNew;
}
}, "JU.BS,JU.M3");
Clazz.overrideMethod (c$, "calculate",
function (rd, maxRadius, bsSelected, bsIgnore, disregardNeighbors, onlySelectedDots, isSurface, multiModel) {
if (rd == null) {
rd = this.atomData.radiusData;
if (rd == null) return;
} else {
this.atomData.radiusData = rd;
this.bsIgnore = bsIgnore;
this.onlySelectedDots = onlySelectedDots;
this.multiModel = multiModel;
this.isSurface = isSurface;
}if (rd.value == 3.4028235E38) rd.value = 3.0;
this.atomData.modelIndex = (multiModel ? -1 : 0);
this.modelZeroBased = !multiModel;
this.vwr.fillAtomData (this.atomData, 1 | (this.mads == null ? 2 : 0));
this.ac = this.atomData.ac;
if (this.mads != null) for (var i = 0; i < this.ac; i++) this.atomData.atomRadius[i] = this.mads[i] / 1000;
this.bsMySelected = (onlySelectedDots && bsSelected != null ? JU.BSUtil.copy (bsSelected) : bsIgnore != null ? JU.BSUtil.setAll (this.ac) : null);
JU.BSUtil.andNot (this.bsMySelected, bsIgnore);
this.disregardNeighbors = disregardNeighbors;
this.maxRadius = maxRadius;
this.bsSurface = new JU.BS ();
var isAll = (bsSelected == null);
var iter = this.vwr.getSelectedAtomIterator (this.bsMySelected, false, this.modelZeroBased, false);
var i0 = (isAll ? this.ac - 1 : bsSelected.nextSetBit (0));
for (var i = i0; i >= 0; i = (isAll ? i - 1 : bsSelected.nextSetBit (i + 1))) if (bsIgnore == null || !bsIgnore.get (i)) {
this.setAtomI (i);
this.getNeighbors (iter);
this.calcConvexMap (isSurface);
}
iter.release ();
this.currentPoints = null;
this.setDotsConvexMax ();
}, "J.atomdata.RadiusData,~N,JU.BS,JU.BS,~B,~B,~B,~B");
Clazz.defineMethod (c$, "getRadius",
function (atomIndex) {
return this.atomData.atomRadius[atomIndex];
}, "~N");
Clazz.overrideMethod (c$, "getPoints",
function () {
if (this.dotsConvexMaps == null) {
this.calculate ( new J.atomdata.RadiusData (null, 3.0, J.atomdata.RadiusData.EnumType.ABSOLUTE, null), 3.4028235E38, this.bsMySelected, null, false, false, false, false);
}if (this.currentPoints != null) return this.currentPoints;
var nPoints = 0;
var dotCount = 42;
for (var i = this.dotsConvexMax; --i >= 0; ) if (this.dotsConvexMaps[i] != null) nPoints += this.dotsConvexMaps[i].cardinalityN (dotCount);
var points = new Array (nPoints);
if (nPoints == 0) return points;
nPoints = 0;
for (var i = this.dotsConvexMax; --i >= 0; ) if (this.dotsConvexMaps[i] != null) {
var iDot = this.dotsConvexMaps[i].size ();
if (iDot > dotCount) iDot = dotCount;
while (--iDot >= 0) if (this.dotsConvexMaps[i].get (iDot)) {
var pt = new JU.P3 ();
pt.scaleAdd2 (this.atomData.atomRadius[i], JU.Geodesic.getVertexVector (iDot), this.atomData.atomXyz[i]);
points[nPoints++] = pt;
}
}
this.currentPoints = points;
return points;
});
Clazz.defineMethod (c$, "setDotsConvexMax",
function () {
if (this.dotsConvexMaps == null) this.dotsConvexMax = 0;
else {
var i;
for (i = this.ac; --i >= 0 && this.dotsConvexMaps[i] == null; ) {
}
this.dotsConvexMax = i + 1;
}});
Clazz.defineMethod (c$, "getAppropriateRadius",
function (atomIndex) {
return (this.mads != null ? (atomIndex >= this.mads.length ? 0 : this.mads[atomIndex] / 1000) : this.atomData.atomRadius[atomIndex]);
}, "~N");
Clazz.defineMethod (c$, "setAtomI",
function (indexI) {
this.indexI = indexI;
this.centerI = this.atomData.atomXyz[indexI];
this.radiusI = this.atomData.atomRadius[indexI];
this.radiiIP2 = this.radiusI + this.radiusP;
this.radiiIP2 *= this.radiiIP2;
}, "~N");
Clazz.defineMethod (c$, "calcConvexMap",
function (isSurface) {
if (this.dotsConvexMaps == null) this.dotsConvexMaps = new Array (this.ac);
this.calcConvexBits ();
var map;
if (this.geodesicMap.isEmpty ()) map = J.geodesic.EnvelopeCalculation.EMPTY_SET;
else {
this.bsSurface.set (this.indexI);
if (isSurface) {
this.addIncompleteFaces (this.geodesicMap);
this.addIncompleteFaces (this.geodesicMap);
}map = JU.BSUtil.copy (this.geodesicMap);
}this.dotsConvexMaps[this.indexI] = map;
}, "~B");
Clazz.defineMethod (c$, "addIncompleteFaces",
function (points) {
this.mapT.clearAll ();
var faces = JU.Geodesic.getFaceVertexes (3);
var len = faces.length;
var maxPt = -1;
for (var f = 0; f < len; ) {
var p1 = faces[f++];
var p2 = faces[f++];
var p3 = faces[f++];
var ok1 = points.get (p1);
var ok2 = points.get (p2);
var ok3 = points.get (p3);
if (!(ok1 || ok2 || ok3) || ok1 && ok2 && ok3) continue;
if (!ok1) {
this.mapT.set (p1);
if (maxPt < p1) maxPt = p1;
}if (!ok2) {
this.mapT.set (p2);
if (maxPt < p2) maxPt = p2;
}if (!ok3) {
this.mapT.set (p3);
if (maxPt < p3) maxPt = p3;
}}
for (var i = 0; i <= maxPt; i++) {
if (this.mapT.get (i)) points.set (i);
}
}, "JU.BS");
Clazz.defineMethod (c$, "calcConvexBits",
function () {
this.geodesicMap.setBits (0, this.geodesicCount);
var combinedRadii = this.radiusI + this.radiusP;
if (this.neighborCount == 0) return;
var faceTest;
var p1;
var p2;
var p3;
var faces = JU.Geodesic.getFaceVertexes (3);
var p4 = J.geodesic.EnvelopeCalculation.power4[2];
var ok1;
var ok2;
var ok3;
this.mapT.clearAll ();
for (var i = 0; i < 12; i++) {
this.vertexTest[i].scaleAdd2 (combinedRadii, JU.Geodesic.getVertexVector (i), this.centerI);
}
for (var f = 0; f < 20; f++) {
faceTest = 0;
p1 = faces[3 * p4 * (4 * f + 0)];
p2 = faces[3 * p4 * (4 * f + 1)];
p3 = faces[3 * p4 * (4 * f + 2)];
for (var j = 0; j < this.neighborCount; j++) {
var maxDist = this.neighborPlusProbeRadii2[j];
this.centerT = this.neighborCenters[j];
ok1 = this.vertexTest[p1].distanceSquared (this.centerT) >= maxDist;
ok2 = this.vertexTest[p2].distanceSquared (this.centerT) >= maxDist;
ok3 = this.vertexTest[p3].distanceSquared (this.centerT) >= maxDist;
if (!ok1) this.geodesicMap.clear (p1);
if (!ok2) this.geodesicMap.clear (p2);
if (!ok3) this.geodesicMap.clear (p3);
if (!ok1 && !ok2 && !ok3) {
faceTest = -1;
break;
}}
var kFirst = f * 12 * p4;
var kLast = kFirst + 12 * p4;
for (var k = kFirst; k < kLast; k++) {
var vect = faces[k];
if (this.mapT.get (vect) || !this.geodesicMap.get (vect)) continue;
switch (faceTest) {
case -1:
this.geodesicMap.clear (vect);
break;
case 0:
for (var j = 0; j < this.neighborCount; j++) {
var maxDist = this.neighborPlusProbeRadii2[j];
this.centerT = this.neighborCenters[j];
this.pointT.scaleAdd2 (combinedRadii, JU.Geodesic.getVertexVector (vect), this.centerI);
if (this.pointT.distanceSquared (this.centerT) < maxDist) this.geodesicMap.clear (vect);
}
break;
case 1:
}
this.mapT.set (vect);
}
}
});
Clazz.defineMethod (c$, "getNeighbors",
function (iter) {
this.neighborCount = 0;
if (this.disregardNeighbors) return null;
this.vwr.setIteratorForAtom (iter, this.indexI, this.radiusI + this.diameterP + this.maxRadius);
while (iter.hasNext ()) {
var indexN = iter.next ();
var neighborRadius = this.atomData.atomRadius[indexN];
if (this.centerI.distance (this.atomData.atomXyz[indexN]) > this.radiusI + this.radiusP + this.radiusP + neighborRadius) continue;
if (this.neighborCount == this.neighborIndices.length) {
this.neighborIndices = JU.AU.doubleLengthI (this.neighborIndices);
this.neighborCenters = JU.AU.doubleLength (this.neighborCenters);
this.neighborPlusProbeRadii2 = JU.AU.doubleLengthF (this.neighborPlusProbeRadii2);
this.neighborRadii2 = JU.AU.doubleLengthF (this.neighborRadii2);
}this.neighborCenters[this.neighborCount] = this.atomData.atomXyz[indexN];
this.neighborIndices[this.neighborCount] = indexN;
var r = neighborRadius + this.radiusP;
this.neighborPlusProbeRadii2[this.neighborCount] = r * r;
this.neighborRadii2[this.neighborCount] = neighborRadius * neighborRadius;
++this.neighborCount;
}
return iter;
}, "J.api.AtomIndexIterator");
Clazz.defineMethod (c$, "deleteAtoms",
function (firstAtomDeleted, nAtomsDeleted) {
this.dotsConvexMaps = JU.AU.deleteElements (this.dotsConvexMaps, firstAtomDeleted, nAtomsDeleted);
this.dotsConvexMax = this.dotsConvexMaps.length;
if (this.mads != null) this.mads = JU.AU.deleteElements (this.mads, firstAtomDeleted, nAtomsDeleted);
this.atomData.atomRadius = JU.AU.deleteElements (this.atomData.atomRadius, firstAtomDeleted, nAtomsDeleted);
this.atomData.atomXyz = JU.AU.deleteElements (this.atomData.atomXyz, firstAtomDeleted, nAtomsDeleted);
this.atomData.ac -= nAtomsDeleted;
this.ac = this.atomData.ac;
}, "~N,~N");
Clazz.defineStatics (c$,
"EMPTY_SET", null);
Clazz.defineStatics (c$,
"power4", [1, 4, 16, 64, 256]);
});