【问题标题】:Smoothing STL file平滑 STL 文件
【发布时间】:2021-03-05 18:16:27
【问题描述】:

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

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

在 CropStl 方法结束时,brut 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;
    }
}

【问题讨论】:

    标签: c# 3d stl


    【解决方案1】:

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

    我想分享我的经验。

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

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

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

    这是我的 .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 用于精确应用平滑的次数。

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

    在 C# 中调用此方法会在 Meshlab 中打开 3D 对象,平滑边界并将其保存到方法中指定的文件夹中:

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

    结果非常好!

    【讨论】:

      猜你喜欢
      • 2019-11-16
      • 2021-07-16
      • 2022-08-19
      • 1970-01-01
      • 2016-05-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-17
      相关资源
      最近更新 更多