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