예제 #1
0
        /// <summary>
        /// Parse STL-ASCII-Format.
        /// </summary>
        /// <param name="file">Stream to parse</param>
        private static void ParseASCII(StreamReader file)
        {
            TriMMApp.CurrentFormat = 1;
            String input = null;
            int    count = 0;

            // The numbers in the file must have the decimal separator ".".
            NumberFormatInfo nFI = new NumberFormatInfo();

            nFI.NumberDecimalSeparator = ".";

            file.BaseStream.Position = 0;
            StreamReader sr = new StreamReader(file.BaseStream);

            List <Vector>   normals   = new List <Vector>(count);
            List <Vertex[]> triangles = new List <Vertex[]>(count);

            Vertex[] tmp = new Vertex[3] {
                new Vertex(0, 0, 0), new Vertex(0, 0, 0), new Vertex(0, 0, 0)
            };

#if !DEBUG
            try {
#endif
            while ((input = sr.ReadLine()) != null)
            {
                input = input.Replace("\t", " ").Trim();
                if (count == 4)
                {
                    count = 0;
                    triangles.Add(tmp);
                    tmp = new Vertex[3] {
                        new Vertex(0, 0, 0), new Vertex(0, 0, 0), new Vertex(0, 0, 0)
                    };
                }

                // RemoveEmptyEntities removes empty entities, resulting from more than one whitespace
                String[] v = input.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                if (v.Length > 0)
                {
                    if (v[0].ToLower() == "vertex")
                    {
                        // Parse string, NumberStyles.Float secures that different formats can be parsed
                        // such as: "-2.23454e-001" (exponential format)
                        for (int i = 0; i < 3; i++)
                        {
                            tmp[count - 1][i] = double.Parse(v[i + 1], NumberStyles.Float, nFI);
                        }
                        if (!TriMMApp.Mesh.Vertices.Contains(tmp[count - 1]))
                        {
                            TriMMApp.Mesh.Vertices.Add(tmp[count - 1]);
                        }
                        count++;
                    }
                    else if (v[0].ToLower() == "facet")
                    {
                        normals.Add(new Vector(double.Parse(v[2], NumberStyles.Float, nFI),
                                               double.Parse(v[3], NumberStyles.Float, nFI), double.Parse(v[4], NumberStyles.Float, nFI)));
                        count++;
                    }
                }
            }

            // Adds the Triangles with the given normals to the mesh, calculating their centroid.
            for (int i = 0; i < normals.Count; i++)
            {
                int    ind0     = TriMMApp.Mesh.Vertices.IndexOf(triangles[i][0]);
                int    ind1     = TriMMApp.Mesh.Vertices.IndexOf(triangles[i][1]);
                int    ind2     = TriMMApp.Mesh.Vertices.IndexOf(triangles[i][2]);
                Vertex centroid = Triangle.GetCentroidOf(triangles[i][0], triangles[i][1], triangles[i][2]);
                centroid.Normal = normals[i];

                Triangle newTriangle = new Triangle(ind0, ind1, ind2);
                newTriangle.Centroid = centroid;
                TriMMApp.Mesh.Add(newTriangle);
            }
#if !DEBUG
        }

        catch {
            MessageBox.Show(TriMMApp.Lang.GetElementsByTagName("STLBrokenFileError")[0].InnerText, TriMMApp.Lang.GetElementsByTagName("ErrorTitle")[0].InnerText, MessageBoxButton.OK, MessageBoxImage.Error);
        } finally {
#endif
            sr.Close();
#if !DEBUG
        }
#endif
            TriMMApp.Mesh.Finish(false);
            TriangleMesh mesh = TriMMApp.Mesh;
            TriMMApp.VertexNormalAlgorithm.GetVertexNormals(ref mesh);
            TriMMApp.Mesh.SetArrays();
        }
예제 #2
0
        /// <summary>
        /// Parses a binary STL file.
        /// </summary>
        /// <remarks>
        /// Because ASCII STL files can become very large, a binary version of STL exists.
        /// A binary STL file has an 80 character header (which is generally ignored - but
        /// which should never begin with 'solid' because that will lead most software to assume
        /// that this is an ASCII STL file). Following the header is a 4 byte unsigned
        /// integer indicating the number of triangular facets in the file. Following that
        /// is data describing each triangle in turn. The file simply ends after the last triangle.
        /// Each triangle is described by twelve floating point numbers: three for the normal
        /// and then three for the X/Y/Z coordinate of each vertex - just as with the ASCII version
        /// of STL. After the twelve floats there is a two byte unsigned 'short' integer that
        /// is the 'attribute byte count' - in the standard format, this should be zero because most
        /// software does not understand anything else.( http://en.wikipedia.org/wiki/STL_(file_format) )
        /// </remarks>
        /// <param name="file">Stream to parse</param>
        private static void ParseBinary(StreamReader file)
        {
            TriMMApp.CurrentFormat = 2;
            BinaryReader binReader = new BinaryReader(file.BaseStream);

            // Set stream back to zero.
            binReader.BaseStream.Position = 0;
            char[] charBuf = new char[80];

            // The first 80 bytes are trash
            binReader.Read(charBuf, 0, 80);

            // Next 4 bytes contain the count of the normal/3D-vertexes record
            int count = (int)binReader.ReadUInt32();

            // Throw InvalidDataException if size does not fit
            // 84 Byte for header+count, count * (size of data = 50 Bytes)
            if (binReader.BaseStream.Length != (84 + count * 50))
            {
                throw new InvalidDataException();
            }

#if !DEBUG
            try {
#endif
            List <Vector> normals     = new List <Vector>(count);
            List <Vertex[]> triangles = new List <Vertex[]>(count);

            // Read the records
            for (int i = 0; i < count; i++)
            {
                Vertex[] tmp = new Vertex[3] {
                    new Vertex(0, 0, 0), new Vertex(0, 0, 0), new Vertex(0, 0, 0)
                };

                // Normal/vertices

                // First one is the normal
                normals.Add(new Vector((double)binReader.ReadSingle(), (double)binReader.ReadSingle(), (double)binReader.ReadSingle()));

                // Next three are vertices
                for (int j = 0; j < 3; j++)
                {
                    for (int k = 0; k < 3; k++)
                    {
                        tmp[j][k] = (double)binReader.ReadSingle();
                    }
                }
                triangles.Add(tmp);
                TriMMApp.Mesh.Vertices = TriMMApp.Mesh.Vertices.Union(tmp).ToList();

                // Last two bytes are only to fill up to 50 bytes
                binReader.Read(charBuf, 0, 2);
            }

            // Adds the Triangles with the given normals to the mesh, calculating their centroid.
            for (int i = 0; i < count; i++)
            {
                int    ind0     = TriMMApp.Mesh.Vertices.IndexOf(triangles[i][0]);
                int    ind1     = TriMMApp.Mesh.Vertices.IndexOf(triangles[i][1]);
                int    ind2     = TriMMApp.Mesh.Vertices.IndexOf(triangles[i][2]);
                Vertex centroid = Triangle.GetCentroidOf(triangles[i][0], triangles[i][1], triangles[i][2]);
                centroid.Normal = normals[i];

                Triangle newTriangle = new Triangle(ind0, ind1, ind2);
                newTriangle.Centroid = centroid;
                TriMMApp.Mesh.Add(newTriangle);
            }
#if !DEBUG
        }

        catch {
            MessageBox.Show(TriMMApp.Lang.GetElementsByTagName("STLBrokenFileError")[0].InnerText, TriMMApp.Lang.GetElementsByTagName("ErrorTitle")[0].InnerText, MessageBoxButton.OK, MessageBoxImage.Error);
        } finally {
#endif
            binReader.Close();
#if !DEBUG
        }
#endif

            TriMMApp.Mesh.Finish(false);
            TriangleMesh mesh = TriMMApp.Mesh;
            TriMMApp.VertexNormalAlgorithm.GetVertexNormals(ref mesh);
            TriMMApp.Mesh.SetArrays();
        }