You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何借助Three.js的STEPLoader识别并着色两个STEP模型的网格差异

对比两个STEP模型差异并高亮的实现方案

一、预处理:保证模型对齐与拓扑匹配

  • 首先确保两个模型在三维空间中完全重合:加载Before.stp和After.stp后,对两个模型应用相同的平移/旋转变换,让基准特征(如基准面、孔位)完全对齐。
  • 确认两个模型的拓扑结构一致:即brep_faces的数量、对应面的类型/边界逻辑匹配,否则直接对比顶点会出现错位。如果拓扑不一致,建议先用CAD软件对齐模型特征后再导出STEP文件。

二、提取面信息并计算偏差

针对每个索引对应的brep_face,计算位置偏差是否超过设定阈值:

1. 三角化网格的顶点对比

如果模型加载后已三角化,直接提取面的顶点计算距离:

const tolerance = 0.01; // 偏差阈值,根据模型尺寸调整
const diffFaceIndices = [];

// 假设已加载beforeMesh和afterMesh,且brep_faces索引一一对应
for (let i = 0; i < beforeMesh.userData.brep_faces.length; i++) {
  const beforeFace = beforeMesh.userData.brep_faces[i];
  const afterFace = afterMesh.userData.brep_faces[i];
  
  // 提取当前面的所有顶点
  const beforeVertices = extractFaceVertices(beforeMesh.geometry, beforeFace.indices);
  const afterVertices = extractFaceVertices(afterMesh.geometry, afterFace.indices);
  
  // 计算顶点间的最大距离
  let maxDist = 0;
  beforeVertices.forEach((v1, idx) => {
    const dist = v1.distanceTo(afterVertices[idx]);
    maxDist = Math.max(maxDist, dist);
  });
  
  // 超过阈值则标记为差异面
  if (maxDist > tolerance) {
    diffFaceIndices.push(i);
  }
}

// 辅助函数:从几何体中提取指定面的顶点
function extractFaceVertices(geometry, faceIndices) {
  const positionAttr = geometry.attributes.position;
  return faceIndices.map(idx => {
    const v = new THREE.Vector3();
    v.fromBufferAttribute(positionAttr, idx);
    return v;
  });
}

2. NURBS曲面的采样对比

如果brep_faces是NURBS曲面,通过多点采样计算偏差更准确:

const uSamples = 8; // U方向采样数
const vSamples = 8; // V方向采样数
let hasDiff = false;

for (let i = 0; i < beforeMesh.userData.brep_faces.length; i++) {
  const beforeSurface = beforeMesh.userData.brep_faces[i].surface;
  const afterSurface = afterMesh.userData.brep_faces[i].surface;
  
  hasDiff = false;
  for (let u = 0; u <= uSamples; u++) {
    for (let v = 0; v <= vSamples; v++) {
      const uParam = u / uSamples;
      const vParam = v / vSamples;
      const p1 = beforeSurface.getPoint(uParam, vParam);
      const p2 = afterSurface.getPoint(uParam, vParam);
      
      if (p1.distanceTo(p2) > tolerance) {
        hasDiff = true;
        break;
      }
    }
    if (hasDiff) break;
  }
  
  if (hasDiff) diffFaceIndices.push(i);
}

三、高亮差异区域

标记差异面后,可通过两种方式可视化:

1. 叠加高亮网格

提取差异面的几何体,创建半透明高亮网格叠加在原模型上:

const highlightMat = new THREE.MeshBasicMaterial({
  color: 0xff0000,
  transparent: true,
  opacity: 0.6
});
const highlightGeo = new THREE.BufferGeometry();
const positions = [];
const indices = [];

diffFaceIndices.forEach(faceIdx => {
  const face = beforeMesh.userData.brep_faces[faceIdx];
  const positionAttr = beforeMesh.geometry.attributes.position;
  
  // 提取顶点数据
  face.indices.forEach(idx => {
    positions.push(
      positionAttr.getX(idx),
      positionAttr.getY(idx),
      positionAttr.getZ(idx)
    );
  });
  
  // 提取三角索引
  indices.push(...face.indices);
});

highlightGeo.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
highlightGeo.setIndex(indices);
const highlightMesh = new THREE.Mesh(highlightGeo, highlightMat);
scene.add(highlightMesh);

2. 修改原模型顶点颜色

给原模型添加颜色属性,直接将差异面顶点染成高亮色:

const colorAttr = new THREE.ColorBufferAttribute(
  beforeMesh.geometry.attributes.position.count,
  3
);
const defaultColor = new THREE.Color(0xcccccc);
const highlightColor = new THREE.Color(0xff0000);

// 初始化所有顶点为默认颜色
colorAttr.set(defaultColor);

// 给差异面顶点设置高亮色
diffFaceIndices.forEach(faceIdx => {
  const face = beforeMesh.userData.brep_faces[faceIdx];
  face.indices.forEach(idx => {
    colorAttr.setColor(idx, highlightColor);
  });
});

beforeMesh.geometry.setAttribute('color', colorAttr);
beforeMesh.material.vertexColors = true; // 启用顶点颜色渲染

四、关键注意事项

  • 若两个模型拓扑不匹配(面数量、对应关系不一致),上述方法会失效,需先通过CAD软件做模型对齐或使用拓扑匹配算法预处理。
  • 阈值tolerance需根据模型实际尺寸调整,避免因浮点精度问题误判。
  • 面对超大规模模型时,建议用Web Worker异步计算差异,避免阻塞主线程。

内容的提问来源于stack exchange,提问作者Tranquillity

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 21:14:51