簡體   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