STL三维模型切片(一)——文件导入
STL格式的三维模型由大量三角形面片构成,文件中只记录了每个三角形的基本信息,包括三个顶点及其法向量(表示内外)。在对该模型进行处理之前,首先必须将其导入进来。STL格式的有两种记录形式:二进制及文本方式,二者没有本质区别,都只是记录了三角形的信息。先放代码,再逐个功能进行分析。
private MeshGeometry3D GetMeshModelFromSTLFile(string path)
{
StreamReader srFirstLine = new StreamReader(path);
string fileType = srFirstLine.ReadLine().Substring(0, 5);
string secondLine = srFirstLine.ReadLine().Trim().Substring(0, 5);
srFirstLine.Close();
MeshGeometry3D mesh3D = new MeshGeometry3D();
int indexOfTriangles = 0;
if (fileType == "solid" && secondLine == "facet") //ASCII type
{
StreamReader sr = new StreamReader(path);
sr.ReadLine();//remove first line
while (sr.ReadLine() != null) //remove facet normal line
{
if (sr.ReadLine() == null)
{
break;
}//remove outer loop line
mesh3D.Positions.Add(StringToPoint3D(sr.ReadLine()));
mesh3D.TriangleIndices.Add(indexOfTriangles++);
mesh3D.Positions.Add(StringToPoint3D(sr.ReadLine()));
mesh3D.TriangleIndices.Add(indexOfTriangles++);
mesh3D.Positions.Add(StringToPoint3D(sr.ReadLine()));
mesh3D.TriangleIndices.Add(indexOfTriangles++);
sr.ReadLine(); //remove endloop
sr.ReadLine(); //remove endfacet
}
sr.Close();
return mesh3D;
Point3D StringToPoint3D(string vertexStr)
{
var tt = vertexStr.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
return new Point3D
{
X = Convert.ToDouble(tt[1]),
Y = Convert.ToDouble(tt[2]),
Z = Convert.ToDouble(tt[3])
};
}
}
else //Binary type
{
BinaryReader br = new BinaryReader(File.OpenRead(path));
br.ReadBytes(80);//去掉80字节
var count = (int)br.ReadUInt32();//三角形数目
for (int i = 0; i < count; i++)
{
br.ReadBytes(12);//三个4字节表示三角形法向量,不需要
mesh3D.Positions.Add(new Point3D { X = br.ReadSingle(), Y = br.ReadSingle(), Z = br.ReadSingle() });
mesh3D.TriangleIndices.Add(indexOfTriangles++);
mesh3D.Positions.Add(new Point3D { X = br.ReadSingle(), Y = br.ReadSingle(), Z = br.ReadSingle() });
mesh3D.TriangleIndices.Add(indexOfTriangles++);
mesh3D.Positions.Add(new Point3D { X = br.ReadSingle(), Y = br.ReadSingle(), Z = br.ReadSingle() });
mesh3D.TriangleIndices.Add(indexOfTriangles++);
br.ReadBytes(2);//去掉最后两个字节
}
br.Close();
return mesh3D;
}
}
首先,我们需要判断STL文件是二进制还是文本格式。一般来说,文本格式第一行以solid开头,即当第一行前5个字符为solid时,可以认为该文件为文本格式。经过大量检验,发现该方法是可行的。直到有一次发现某个二进制格式的STL文件开头5个字符也是solid,说明该方法不能百分之百保证判断准确。于是,添加第二行判断,文本格式的STL文件第二行以facet开头,两者都满足的情况下,基本可以确定该文件为文本格式,否则为二进制格式。
随后,确定格式后,分别按其格式字义逐行(字)读取,并添加到Mesh对象中,这样就将STL文件读取进来了。