createVoxels()

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;
  }