in packages/miew/src/gfx/geometries/IsosurfaceBuildNormals.js [31:155]
createVoxels() {
let numAtomsRefs;
let rad;
const ATOM_VOXEL_REF_SCALE = 4.5;
const numAtoms = this._numAtoms | 0;
const atoms = this._atoms;
const dx = this._vBoxMax.x - this._vBoxMin.x;
const dy = this._vBoxMax.y - this._vBoxMin.y;
const dz = this._vBoxMax.z - this._vBoxMin.z;
let w = (dx < dy) ? dx : dy;
w = (dz < w) ? dz : w;
let maxRad = 0.0;
let aveRad = 0.0;
let i;
for (i = 0; i < numAtoms; i++) {
rad = (atoms[i].radius + this._probeRadius) * 2.0;
maxRad = (rad > maxRad) ? rad : maxRad;
aveRad += rad;
}
let numCells = Math.floor(w / maxRad);
if (numCells < 2) {
numCells = 2;
}
aveRad /= numAtoms;
this._numCells = numCells;
this._aveRad = aveRad;
this._maxRad = maxRad;
const side = numCells;
const side2 = numCells * numCells;
const side3 = numCells * numCells * numCells;
const xScale = this._xScale = 1.0 / (this._vBoxMax.x - this._vBoxMin.x);
const yScale = this._yScale = 1.0 / (this._vBoxMax.y - this._vBoxMin.y);
const zScale = this._zScale = 1.0 / (this._vBoxMax.z - this._vBoxMin.z);
// estimate number of individual atom refs in each voxel list
let maxAtomsRefs = 0;
const xNumVoxMult = xScale * numCells;
const yNumVoxMult = yScale * numCells;
const zNumVoxMult = zScale * numCells;
for (i = 0; i < numAtoms; i++) {
const radAffect = (atoms[i].radius + this._probeRadius) * ATOM_VOXEL_REF_SCALE;
const diaAffect = radAffect * 2.0;
let numVoxX = Math.floor(xNumVoxMult * diaAffect + 0.8);
let numVoxY = Math.floor(yNumVoxMult * diaAffect + 0.8);
let numVoxZ = Math.floor(zNumVoxMult * diaAffect + 0.8);
// avoid case numVox? == 0
// also use loop i <=
numVoxX++;
numVoxY++;
numVoxZ++;
maxAtomsRefs += numVoxX * numVoxY * numVoxZ;
} // for (i)
// maxAtomsRefs = numAtoms * MAX_ATOMS_IN_SINGLE_VOXEL;
this._voxelList = utils.allocateTyped(Int32Array, side3);
const atomsList = [];
atomsList.length = maxAtomsRefs;
if ((this._voxelList === null) || (atomsList === null)) {
return 0 - 1;
}
// init voxel list
for (i = 0; i < side3; i++) {
this._voxelList[i] = -1;
}
numAtomsRefs = 0;
// create voxel lists
for (i = 0; i < numAtoms; i++) {
// use multiplier 4 to locate this atom in different voxels
rad = (atoms[i].radius + this._probeRadius) * ATOM_VOXEL_REF_SCALE;
let xIndMin = Math.floor((atoms[i].coord.x - this._vBoxMin.x - rad) * numCells * xScale);
let yIndMin = Math.floor((atoms[i].coord.y - this._vBoxMin.y - rad) * numCells * yScale);
let zIndMin = Math.floor((atoms[i].coord.z - this._vBoxMin.z - rad) * numCells * zScale);
let xIndMax = Math.floor((atoms[i].coord.x - this._vBoxMin.x + rad) * numCells * xScale);
let yIndMax = Math.floor((atoms[i].coord.y - this._vBoxMin.y + rad) * numCells * yScale);
let zIndMax = Math.floor((atoms[i].coord.z - this._vBoxMin.z + rad) * numCells * zScale);
xIndMin = (xIndMin >= 0) ? xIndMin : 0;
yIndMin = (yIndMin >= 0) ? yIndMin : 0;
zIndMin = (zIndMin >= 0) ? zIndMin : 0;
xIndMax = (xIndMax < numCells) ? xIndMax : (numCells - 1);
yIndMax = (yIndMax < numCells) ? yIndMax : (numCells - 1);
zIndMax = (zIndMax < numCells) ? zIndMax : (numCells - 1);
for (let z = zIndMin; z <= zIndMax; z++) {
for (let y = yIndMin; y <= yIndMax; y++) {
for (let x = xIndMin; x <= xIndMax; x++) {
// add atom with index "i" to this voxel list
const indVoxel = x + y * side + z * side2;
// assert indVoxel >= 0
// assert indVoxel < side3
// add first
if (this._voxelList[indVoxel] < 0) {
atomsList[numAtomsRefs * 2 + 0] = i;
atomsList[numAtomsRefs * 2 + 1] = 0 - 1;
this._voxelList[indVoxel] = numAtomsRefs;
numAtomsRefs++;
// assert numAtomsRefs < maxAtomsRefs - 1
continue;
}
// insert into head of list
const indexNext = this._voxelList[indVoxel];
this._voxelList[indVoxel] = numAtomsRefs;
atomsList[numAtomsRefs * 2 + 0] = i;
atomsList[numAtomsRefs * 2 + 1] = indexNext;
numAtomsRefs++;
} // for (x)
} // for (y)
} // for (z)
} // for (i)
// convert Array to Int32Array
this._atomsList = Int32Array.from(atomsList);
return 0;
}