修复可能坏的.stl文件的法线

时间:2017-07-03 14:08:56

标签: javascript c++ three.js vtk stl-format

我是Three.js的新手,并且被分配了尝试修复偶尔出现的文件中的法线的任务。我们不知道它们是否是错误的扫描或可能是错误的上传。我们正在调查上传功能,但如果可能的话也想尝试修复它们。任何人都可以提供任何想法或提示来修复文件或找到正确的法线吗?

下面是我们抓住法线以及我们如何抓住法线的代码。注意:此代码通常工作正常,只有在法线不好时才会出现问题。我还附加了一个文件,这样你就可以看到法线的类型和#34;坏文件"我正在处理。 Get File here

我们也在后端用C ++使用VTK,所以使用其中任何一个的解决方案或想法都是有帮助的。

my.geometry = geometry;

    var front = new THREE.MeshPhongMaterial(
    {color: 0xe2e4dc, shininess: 50, side: THREE.DoubleSide});

var mesh = [new THREE.Mesh(geometry, front)];

my.scene.add(mesh[0]);
my.objects.push(mesh[0]);

var rc = new THREE.Raycaster();

var modelData = {'objects': [mesh[0].id], 'id': mesh[0].id};

var normalFound = false;
for (var dy = 80; dy >= -80; dy = dy - 10) {
  console.log('finding a normal on', 0, dy, -200);
  rc.set(new THREE.Vector3(0, dy, -200), new THREE.Vector3(0, 0, 1));

  var hit = rc.intersectObjects([mesh[0]]);

  if (hit.length) {
    my.normal = hit[0].face.normal.normalize();
    console.log('normal', my.normal.z);

    modelData['normal'] = my.normal;

    if ((my.normal.z > 0.9 && my.normal.z < 1.1)) {
      my.requireOrienteering = true;
      modelData['arch'] = 'lower';
      normalFound = true;
      console.log('we have a lower arch');
    } else if ((my.normal.z < -0.9 && my.normal.z > -1.1)) {
      modelData['arch'] = 'upper';
      normalFound = true;
      console.log('we have an upper arch');
      }

    break;
  }
}

2 个答案:

答案 0 :(得分:0)

计算法线是一个简单的步骤。如果计算两个向量(几何一)的叉积,您将得到一个向量,与您输入的两个向量正交。你现在所要​​做的就是将它标准化,因为法线应该被标准化,以免弄乱闪电计算。

对于平滑曲面,您必须计算该点上的所有法线并对其求平均值。对于平面,每个顶点都有多个正常(每个表面一个)。

在伪代码中,它对于四边形看起来像这样:

foreach quad : mesh
foreach vertex : quad
    vector1 = neighborVertex.pos - vertex.pos;
    vector2 = otherNeighborVertex.pos - vertex.pos;
    vertex.normal = normalize(cross(vector1, vector2));
end foreach;
end foreach;

答案 1 :(得分:0)

VTK有一个名为vtkPolyDataNormals的过滤器,您可以在该文件上运行以计算法线。您可能希望在运行之前致电ConsistencyOn()NonManifoldTraversalOn()AutoOrientNormalsOn()

如果你想要点法线(而不是每格法线)并且你的形状有尖角,你可能想要提供一个特征角SetFeatureAngle()并调用SplittingOn()