繁体   English   中英

平滑 STL 文件

[英]Smoothing STL file

所以在我们的 3D 扫描应用程序中,我应该扫描一个泡沫箱并将结果保存为 STL 文件。

为了只保留足迹部分,我使用 class 中的 CropStl 方法删除了一些高于 Z 值的顶点。

在 CropStl 方法结束时,粗制滥造的 stl 从 img1 变为 img2。 但是正如您在图像上看到的那样,结果的边界并不平滑。

在此处输入图像描述 在此处输入图像描述

有没有办法平滑 C# 中第二个 stl 的边框,或者有没有工具?

注意:我使用从 NuGet 安装的 IxMilia 和 geometry3Sharp。

  public class STLEditor
  {
    //Takes the path of the brut stl file.
    string stlPath;
    public STLEditor(string _stlPath)
    {
        stlPath = _stlPath;
    }


    internal void CropStl()
    {
        try
        {
            using (FileStream fs = new FileStream(stlPath, FileMode.Open))
            {
                //Load the stl file
                var stl = IxMilia.Stl.StlFile.Load(fs);

                //Gets all triangles of the stl file into a list.
                var triangles = stl.Triangles.ToList();
                stl.Triangles.Clear();

                //Removes vertexes which have the Z value > -15
                Predicate<IxMilia.Stl.StlTriangle> predicate = FindTriangle;
                triangles.RemoveAll(predicate);


                stl.Triangles.AddRange(triangles);

                using (FileStream fsSave = new FileStream(System.IO.Path.GetDirectoryName(stlPath) + "\\croped.stl", FileMode.Create))
                {
                    stl.Save(fsSave, false);
                }

                System.Threading.Thread.Sleep(500);

                //Tried some smoothing methods but it doesn't work as expected.
                GeometricOperations();

                System.IO.File.Delete(System.IO.Path.GetDirectoryName(stlPath) + "\\croped.stl");
            }
        }
        catch (Exception ex)
        {
            UserMethods.ParseError(ex, "CropSTL");
        }
    }

    //Gets the croped stl and smooths it. (It doesn't change the result).
    private void GeometricOperations()
    {
        g3.ReadOptions optRead = new g3.ReadOptions();
        g3.WriteOptions optWrite = new g3.WriteOptions();
        optWrite.bWriteBinary = true;
        g3.DMesh3Builder meshBuilder = new g3.DMesh3Builder();

        g3.StandardMeshReader.ReadFile(System.IO.Path.GetDirectoryName(stlPath) + "\\croped.stl", optRead, meshBuilder);

        var mesh = meshBuilder.Meshes[0];

        mesh = SmoothMesh(mesh);


        using (g3.StandardMeshWriter mr = new g3.StandardMeshWriter())
        {
            g3.STLWriter sr = new g3.STLWriter();

            List<g3.WriteMesh> wMeshList = new List<g3.WriteMesh>();
            g3.WriteMesh wMesh = new g3.WriteMesh(meshBuilder.Meshes[0]);
            wMeshList.Add(wMesh);
            mr.Write(System.IO.Path.GetDirectoryName(stlPath) + "\\smoothed.stl", wMeshList, optWrite);
        }
    }

    private DMesh3 SmoothMesh(DMesh3 mesh)
    {
        Remesher r = new Remesher(mesh);
        r.SetTargetEdgeLength(0.0240);

        for (int k = 0; k < 5; ++k)
            r.BasicRemeshPass();

        return mesh;
    }

    public static bool FindTriangle(IxMilia.Stl.StlTriangle triangle)
    {
        return triangle.Vertex1.Z > -15;
    }
}

当我明白这不是一件容易的事时,我尝试了很多方法,最终找到了解决方案。

我想分享我的经验。

我发现最好的方法是应用拉普拉斯平滑。 为此,我安装了 Meshlab,这是一个免费且非常棒的工具。

使用 Meshlab 服务器,可以对 select 的边界进行 3D object 并像魔术一样应用拉普拉斯平滑。

为此,您需要一个 .mlx 文件来告诉 Meshlab 服务器您要处理哪个操作。

这是 my.mlx 文件的内容:

<!DOCTYPE FilterScript>
<FilterScript>
  <filter name="Select Border"/>
  <filter name="Laplacian Smooth">
  <Param description="Smoothing steps" name="stepSmoothNum" value="72" isxmlparam="0" 
   tooltip="The number of times that the whole algorithm (normal smoothing + vertex 
   fitting) is iterated." type="RichInt"/>
  <Param description="1D Boundary Smoothing" name="Boundary" value="true" 
  isxmlparam="0" tooltip="Smooth boundary edges only by themselves (e.g. the polyline 
  forming the boundary of the mesh is independently smoothed). This can reduce the 
  shrinking on the border but can have strange effects on very small boundaries." 
  type="RichBool"/>
  <Param description="Cotangent weighting" name="cotangentWeight" value="true" 
  isxmlparam="0" tooltip="Use cotangent weighting scheme for the averaging of the 
  position. Otherwise the simpler umbrella scheme (1 if the edge is present) is used." 
  type="RichBool"/>
  <Param description="Affect only selection" name="Selected" value="true" 
  isxmlparam="0" tooltip="If checked the filter is performed only on the selected area" 
 type="RichBool"/>
 </filter>
</FilterScript>

此过滤器脚本告诉 Meshlab 究竟要执行哪个操作。 参数 stepSmoothNum 用于精确应用平滑的次数。

简而言之,此过滤器脚本用于 select 3D object 的边界,并仅对选定的面应用拉普拉斯平滑 72 次。 仅平滑边界的目的是不丢失表面扫描的细节。

并在 C# 中调用此方法在 Meshlab 中打开 3D object,平滑边界并将其保存到方法中精确的文件夹中:

  //input => the path of the 3D object to smooth
  //output => the path where the smoothed object will be saved.
  public static bool BoundrySmoothing(string input, string output)
    {
        bool retVal = true;
        try
        {
            string strCmdText;
            string mlxPath = Tools.MeshLabRoot + "BoundrySmoothing.mlx";
            strCmdText = "/C " + Tools.MeshLabRoot +
                @"meshlabserver " +
                @"-i " + input + " " +
                @"-o " + output + " -m wt -s " +
                mlxPath;

            System.Diagnostics.Process process = new System.Diagnostics.Process();
            System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
            startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
            startInfo.FileName = "cmd.exe";
            startInfo.Arguments = strCmdText;
            startInfo.WindowStyle = ProcessWindowStyle.Hidden;
            process.StartInfo = startInfo;

            process.Start();

            process.WaitForExit();
        }
        catch (Exception ex)
        {
            UserMethods.ParseError(ex, "BoundrySmoothing");
            retVal = false;
        }

        return retVal;
    }

结果非常好!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM