首先檢測A面有沒有端點與B面干涉,如果有則用這個點與B面的法向量判定前後。如果沒有,則檢測B面有沒有端點與A面干涉,如果有則用這個點與A面的法向量判定前後。如果兩個面都沒有點與另一個面干涉,再用邊判定。排除點在面上的情況,當兩個面的點都處於另一個面上,則像之前那樣警告並返回null。
在用邊判定的時候,之前直接用的是邊的中點,現在改為先截取這條邊所干涉到另一個面的線段,之後再取這條線段的中點。
所有的代碼和注釋都要使用英文。
代码: 全选
/**
* Evaluates whether Face A is positioned in front of Face B based on normal vectors.
* It iterates through all edges and returns true or false immediately upon finding a definitive relation.
* If no definitive relation is found, it logs a warning listing the coplanar edges and returns null.
* @param {Object} faceA - The first face object containing pts, pts3D, and normal3D.
* @param {Object} faceB - The second face object containing pts, pts3D, and normal3D.
* @returns {boolean|null} true if Face A is in front, false if Face A is behind, or null if inconclusive.
*/
checkEdgeNormalRelation(faceA, faceB) {
const coplanarEdgesA = [];
const coplanarEdgesB = [];
// ==========================================
// Step 1: Evaluate projecting edges of Face A against Face B's plane
// ==========================================
for (let i = 0; i < faceA.pts.length; i++) {
const p1_2d = faceA.pts[i];
const p2_2d = faceA.pts[(i + 1) % faceA.pts.length];
if (this.edgeProjects(p1_2d, p2_2d, faceB)) {
const p1_3d = faceA.pts3D[i];
const p2_3d = faceA.pts3D[(i + 1) % faceA.pts3D.length];
const midX = (p1_3d.x + p2_3d.x) / 2;
const midY = (p1_3d.y + p2_3d.y) / 2;
const midZ = (p1_3d.z + p2_3d.z) / 2;
const q = faceB.pts3D[0];
const dot = (midX - q.x) * faceB.normal3D.x + (midY - q.y) * faceB.normal3D.y + (midZ - q.z) * faceB.normal3D.z;
if (Math.abs(dot) > 1e-4) {
return dot > 0; // true if front, false if behind
} else {
coplanarEdgesA.push(i);
}
}
}
// ==========================================
// Step 2: Evaluate projecting edges of Face B against Face A's plane
// ==========================================
for (let i = 0; i < faceB.pts.length; i++) {
const p1_2d = faceB.pts[i];
const p2_2d = faceB.pts[(i + 1) % faceB.pts.length];
if (this.edgeProjects(p1_2d, p2_2d, faceA)) {
const p1_3d = faceB.pts3D[i];
const p2_3d = faceB.pts3D[(i + 1) % faceB.pts3D.length];
const midX = (p1_3d.x + p2_3d.x) / 2;
const midY = (p1_3d.y + p2_3d.y) / 2;
const midZ = (p1_3d.z + p2_3d.z) / 2;
const q = faceA.pts3D[0];
const dot = (midX - q.x) * faceA.normal3D.x + (midY - q.y) * faceA.normal3D.y + (midZ - q.z) * faceA.normal3D.z;
if (Math.abs(dot) > 1e-4) {
return dot <= 0; // false if dot > 0 (A is behind), true if dot < 0 (A is front)
} else {
coplanarEdgesB.push(i);
}
}
}
// ==========================================
// Step 3: Handle inconclusive cases
// ==========================================
if (coplanarEdgesA.length > 0) {
console.warn(`Which edges of Face A are completely on Face B: Indices [${coplanarEdgesA.join(', ')}]`);
}
if (coplanarEdgesB.length > 0) {
console.warn(`Which edges of Face B are completely on Face A: Indices [${coplanarEdgesB.join(', ')}]`);
}
if (coplanarEdgesA.length === 0 && coplanarEdgesB.length === 0) {
console.warn('No overlapping projection edges found between Face A and Face B.');
}
return null;
}
改進checkEdgeNormalRelation這個函式:
首先檢測A面有沒有端點與B面干涉,如果有則用這個點與B面的法向量判定前後。如果沒有,則檢測B面有沒有端點與A面干涉,如果有則用這個點與A面的法向量判定前後。如果兩個面都沒有點與另一個面干涉,再用邊判定。排除點在面上的情況,當兩個面的點都處於另一個面上,則像之前那樣警告並返回null。
在用邊判定的時候,之前直接用的是邊的中點,現在改為先截取這條邊所干涉到另一個面的線段,之後再取這條線段的中點。
所有的代碼和注釋都要使用英文。