_updateVertices()

in packages/miew/src/gfx/VolumeMesh.js [89:228]


  _updateVertices() {
    // Algorithm:
    // 1. Get plane parameters
    // 2. Compute culling flags for all vertices
    // 3. If intersection occurs => compute from 3 to 6 intersection points
    const corners = VolumeMesh._corners;
    const edges = VolumeMesh._edges;
    const edgeIntersections = VolumeMesh._edgeIntersections;

    let i;

    const norm = this.clipPlane.normal;
    const D = this.clipPlane.constant;

    const vert = this.vertices;
    const { size } = this;

    const cornerMark = [0, 0, 0, 0, 0, 0, 0, 0];
    const edgeMark = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1];

    const curEdge = new THREE.Vector3();
    let curEdgeInter = null;

    function CheckX() {
      if (norm.x === 0) return 0;
      const x = -(norm.dot(curEdge) + D) / norm.x;
      if (-size.x <= x && x <= size.x) {
        curEdgeInter.set(x, curEdge.y, curEdge.z);
        if (x === size.x) return 2;
        if (x === -size.x) return -2;
        return 1;
      }
      return 0;
    }

    function CheckY() {
      if (norm.y === 0) return 0;
      const y = -(norm.dot(curEdge) + D) / norm.y;
      if (-size.y <= y && y <= size.y) {
        curEdgeInter.set(curEdge.x, y, curEdge.z);
        if (y === size.y) return 2;
        if (y === -size.y) return -2;
        return 1;
      }
      return 0;
    }

    function CheckZ() {
      if (norm.z === 0) return 0;
      const z = -(norm.dot(curEdge) + D) / norm.z;
      if (-size.z <= z && z <= size.z) {
        curEdgeInter.set(curEdge.x, curEdge.y, z);
        if (z === size.z) return 2;
        if (z === -size.z) return -2;
        return 1;
      }
      return 0;
    }

    // for each edge
    for (let curEdgeIdx = 0; curEdgeIdx < 12; ++curEdgeIdx) {
      const curEdgeSource = edges[curEdgeIdx];
      curEdgeInter = edgeIntersections[curEdgeIdx];

      curEdge.set(curEdgeSource[2], curEdgeSource[3], curEdgeSource[4]);
      curEdge.multiply(size);

      // calculate intersection point
      let flag = 0;
      if (curEdgeSource[2] === 0) flag = CheckX();
      if (curEdgeSource[3] === 0) flag = CheckY();
      if (curEdgeSource[4] === 0) flag = CheckZ();

      // mark corresponding corner (if plane cuts through one)
      if (flag === -2) {
        cornerMark[curEdgeSource[0]] = 1;
      } else if (flag === 2) {
        cornerMark[curEdgeSource[1]] = 1;
      } else if (flag === 0) {
        // edge is not intersected by the plane (doesn't produce a vertex)
        edgeMark[curEdgeIdx] = 0;
      }
    }

    const face = {
      indices: [],
      norm: norm.clone().negate(),
    };

    let nextVertex = 8;

    // for each marked corner
    for (i = 0; i < 8; ++i) {
      if (cornerMark[i] === 1) {
        // add corner as vertex to the face
        vert[nextVertex].set(corners[i][0], corners[i][1], corners[i][2]).multiply(size);
        face.indices.push(nextVertex++);
        // skip adjacent edges
        edgeMark[corners[i][3]] = 0;
        edgeMark[corners[i][4]] = 0;
        edgeMark[corners[i][5]] = 0;
      }
    }

    // for each edge that has internal intersection
    for (i = 0; i < 12; ++i) {
      if (edgeMark[i] === 1) {
        // add intersection point as vertex to the face
        vert[nextVertex].copy(edgeIntersections[i]);
        face.indices.push(nextVertex++);
      }
    }

    this.faces[6] = face;

    const diff = new THREE.Vector3();
    const coplanarPoint = new THREE.Vector3();
    this.clipPlane.coplanarPoint(coplanarPoint);
    for (i = 0; i < vert.length; ++i) {
      this.cullFlag[i] = false;
      if (i < 8) {
        // corners should be culled by clipping plane
        diff.subVectors(vert[i], coplanarPoint);
        this.cullFlag[i] = (norm.dot(diff) >= 0.0);
      } else if (i < 8 + face.indices.length) {
        // cross section vertices don't get culled
        this.cullFlag[i] = true;
      }
    }

    // write data to vertex buffer
    const positions = this.geometry.getAttribute('position');
    let idx = 0;
    for (i = 0; i < vert.length; ++i) {
      positions.array[idx++] = vert[i].x;
      positions.array[idx++] = vert[i].y;
      positions.array[idx++] = vert[i].z;
    }
    positions.needsUpdate = true;
  }