in packages/miew/src/gfx/geometries/ContactSurface.js [335:440]
function projectPoints() {
// For each atom:
// Iterate over a subsection of the grid, for each point:
// If current value < 0.0, unvisited, set positive
//
// In any case: Project this point onto surface of the atomic sphere
// If this projected point is not obscured by any other atom
// Calcualte delta distance and set grid value to minimum of
// itself and delta
// Should we alias frequently accessed closure constiables??
// Assume JS engine capable of optimizing this
// anyway...
const maxRad = 4.0;
const sigma = (maxRad) / 3;
const sigma2Inv = 1 / (2 * sigma * sigma);
for (let innI = 0; innI < nAtoms; innI++) {
const innCI = itemSize * innI;
const ax = posRad[innCI];
const ay = posRad[innCI + 1];
const az = posRad[innCI + 2];
const ar = posRad[innCI + 3];
const ar2 = r2[innI];
hash.withinRadii(ax, ay, az, ar, neighbours);
// Number of grid points, round this up...
const ng = Math.ceil(ar * scaleFactor);
// Center of the atom, mapped to grid points (take floor)
const iax = Math.floor(scaleFactor * (ax - min[0]));
const iay = Math.floor(scaleFactor * (ay - min[1]));
const iaz = Math.floor(scaleFactor * (az - min[2]));
// Extents of grid to consider for this atom
const minx = Math.max(0, iax - ng);
const miny = Math.max(0, iay - ng);
const minz = Math.max(0, iaz - ng);
// Add two to these points:
// - iax are floor'd values so this ensures coverage
// - these are loop limits (exclusive)
const maxx = Math.min(dim[0], iax + ng + 2);
const maxy = Math.min(dim[1], iay + ng + 2);
const maxz = Math.min(dim[2], iaz + ng + 2);
const colIdx = innI * 3;
const cr = colors[colIdx];
const cg = colors[colIdx + 1];
const cb = colors[colIdx + 2];
for (let iz = minz; iz < maxz; iz++) {
const dz = gridz[iz] - az;
const zOffset = dim[1] * dim[0] * iz;
for (let iy = miny; iy < maxy; iy++) {
const dy = gridy[iy] - ay;
const dzy2 = dz * dz + dy * dy;
const zyOffset = zOffset + dim[0] * iy;
for (let ix = minx; ix < maxx; ix++) {
const idx = ix + zyOffset;
const dx = gridx[ix] - ax;
const d2 = dzy2 + dx * dx;
if (d2 < ar2) {
const w = Math.exp(-d2 * sigma2Inv);
const cIdx = idx * 3;
volTex[cIdx] += cr * w;
volTex[cIdx + 1] += cg * w;
volTex[cIdx + 2] += cb * w;
weights[idx] += w;
if (visibilitySelector !== null && w > weightsMap[idx]) {
weightsMap[idx] = w;
atomMap[idx] = atoms[innI];
}
if (grid[idx] < 0.0) {
// Unvisited, make positive
grid[idx] = -grid[idx];
}
// Project on to the surface of the sphere
// sp is the projected point ( dx, dy, dz ) * ( ra / d )
const d = Math.sqrt(d2);
const ap = ar / d;
let spx = dx * ap;
let spy = dy * ap;
let spz = dz * ap;
spx += ax;
spy += ay;
spz += az;
if (obscured(spx, spy, spz, innI, -1) === -1) {
const dd = ar - d;
if (dd < grid[idx]) {
grid[idx] = dd;
}
}
}
}
}
}
}
}