Exemple #1
0
        /// <summary>
        /// Creates the base octahedron.
        /// </summary>
        private TriangleMesh CreateBaseOctahedron()
        {
            TriangleMesh baseMesh = new TriangleMesh();

            baseMesh.Vertices.Add(new Vertex(0, 0, 0.5));
            baseMesh.Vertices.Add(new Vertex(0.5, 0, 0));
            baseMesh.Vertices.Add(new Vertex(0, 0.5, 0));
            baseMesh.Vertices.Add(new Vertex(-0.5, 0, 0));
            baseMesh.Vertices.Add(new Vertex(0, -0.5, 0));
            baseMesh.Vertices.Add(new Vertex(0, 0, -0.5));

            baseMesh.Add(new Triangle(0, 1, 2));
            baseMesh.Add(new Triangle(0, 2, 3));
            baseMesh.Add(new Triangle(0, 3, 4));
            baseMesh.Add(new Triangle(0, 4, 1));
            baseMesh.Add(new Triangle(5, 2, 1));
            baseMesh.Add(new Triangle(5, 3, 2));
            baseMesh.Add(new Triangle(5, 4, 3));
            baseMesh.Add(new Triangle(5, 1, 4));

            return(baseMesh);
        }
Exemple #2
0
        /// <summary>
        /// The given StreamReader <paramref name="file"/> is parsed and the TriangleMesh built.
        /// </summary>
        /// <param name="file">The *.OFF file to be parsed.</param>
        public static void Parse(StreamReader file)
        {
            TriMMApp.Mesh          = new TriangleMesh();
            TriMMApp.CurrentFormat = 0;

            // Temporary variables.
            Vertex vertex;
            Vector normal;
            String input    = null;
            int    count    = 0;
            int    vertices = 0;
            int    faces    = 0;
            bool   vN       = false;

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

            nFI.NumberDecimalSeparator = ".";

            // The header is processed here.
            while (count < 2)
            {
                input = file.ReadLine();
                input = input.Replace("\t", " ").Trim();

                // Empty lines and comment-lines are skipped.
                if ((input != "") && (!input.StartsWith("#")))
                {
                    // A header exists.
                    if (input.Contains("OFF"))
                    {
                        // Vertex normal vectors are contained.
                        if (input.Contains("N"))
                        {
                            vN = true;
                        }

                        count++;
                    }
                    else if (count == 1)
                    {
                        // Cuts comments at the end of the last line of the header.
                        if (input.Contains("#"))
                        {
                            input = input.Substring(0, input.IndexOf("#"));
                        }

                        // RemoveEmptyEntities removes empty entities, resulting from more than one whitespace.
                        String[] v = input.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                        // The last line of the header contains the numbers of Vertices, Faces (Triangles) and Edges (not needed).
                        if (v.Length != 3)
                        {
                            throw new Exception(TriMMApp.Lang.GetElementsByTagName("OffCounterError")[0].InnerText);
                        }
                        else
                        {
                            vertices = int.Parse(v[0]);
                            faces    = int.Parse(v[1]);
                        }
                        count++;
                    }
                    else
                    {
                        // There is only the last line of the header with the numbers of Vertices, Faces and Edges present.
                        count++;
                    }
                }
            }

            // The following lines in the file contain the Vertices.
            count = 0;
            while (count < vertices)
            {
                input = file.ReadLine();
                input = input.Replace("\t", " ").Trim();
                if ((input != "") && (!input.StartsWith("#")))
                {
                    if (input.Contains("#"))
                    {
                        input = input.Substring(0, input.IndexOf("#"));
                    }

                    // RemoveEmptyEntities removes empty entities, resulting from more than one whitespace.
                    String[] v = input.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                    // Only the Vertex is read and added to the VertexList of the owners TriangleMesh, everything else in the line is ignored.
                    vertex = new Vertex(double.Parse(v[0], NumberStyles.Float, nFI),
                                        double.Parse(v[1], NumberStyles.Float, nFI), double.Parse(v[2], NumberStyles.Float, nFI));

                    // Vertex normals can follow the Vertices.
                    if (vN)
                    {
                        normal = new Vector(double.Parse(v[3], NumberStyles.Float, nFI),
                                            double.Parse(v[4], NumberStyles.Float, nFI), double.Parse(v[5], NumberStyles.Float, nFI));
                        vertex.Normal = normal;
                    }
                    TriMMApp.Mesh.Vertices.Add(vertex);

                    count++;
                }
            }

            // The following lines in the file contain the Faces as combinations of the indices of the Vertices parsed above.
            count = 0;
            while (count < faces)
            {
                input = file.ReadLine();
                input.Trim();
                if ((input != "") && (!input.StartsWith("#")))
                {
                    if (input.Contains("#"))
                    {
                        input = input.Substring(0, input.IndexOf("#"));
                    }

                    // RemoveEmptyEntities removes empty entities, resulting from more than one whitespace
                    String[] v = input.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                    // Only the Triangle is read and added to the owners TriangleMesh, everything else in the line is ignored.
                    TriMMApp.Mesh.Add(new Triangle(int.Parse(v[1], nFI), int.Parse(v[2], nFI), int.Parse(v[3], nFI)));

                    count++;
                }
            }

            // The TriangleMesh is complete and can be finalized.
            // If there are no Vertex normals in the file, they are calculated with the chosen algorithm.
            if (!vN)
            {
                TriMMApp.Mesh.Finish(true);
                TriangleMesh mesh = TriMMApp.Mesh;
                TriMMApp.VertexNormalAlgorithm.GetVertexNormals(ref mesh);
            }
            else
            {
                TriMMApp.Mesh.Finish(true);
            }

            TriMMApp.Mesh.SetArrays();
        }
Exemple #3
0
        /// <summary>
        /// The given StreamReader <paramref name="file"/> is parsed and the TriangleMesh built.
        /// </summary>
        /// <param name="file">The *.OBJ file to be parsed.</param>
        public static void Parse(StreamReader file)
        {
            TriMMApp.Mesh          = new TriangleMesh();
            TriMMApp.CurrentFormat = 4;

            // Temporary variables.
            Vertex vertex;
            Vector normal;
            String input = null;

            String[] inputList;
            int      vertices = 0;
            int      normals = 0;
            int      a, b, c;

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

            nFI.NumberDecimalSeparator = ".";

#if !DEBUG
            try {
#endif

            input = file.ReadLine();

            while (input != null)
            {
                input = input.Replace("\t", " ").Trim();

                // RemoveEmptyEntities removes empty entities, resulting from more than one whitespace.
                inputList = input.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                if (inputList[0] == "v")
                {
                    // Vertices must start with the letter "v" and contain three coordinates.
                    vertex = new Vertex(double.Parse(inputList[1], NumberStyles.Float, nFI),
                                        double.Parse(inputList[2], NumberStyles.Float, nFI), double.Parse(inputList[3], NumberStyles.Float, nFI));
                    TriMMApp.Mesh.Vertices.Add(vertex);
                    vertices++;
                }
                else if (inputList[0] == "vn")
                {
                    // Vertex normals must start with the letters "vn" and contain three coordinates.
                    // There must be one Vertex normal for every Vertex.
                    normal = new Vector(double.Parse(inputList[1], NumberStyles.Float, nFI),
                                        double.Parse(inputList[2], NumberStyles.Float, nFI), double.Parse(inputList[3], NumberStyles.Float, nFI));
                    TriMMApp.Mesh.Vertices[normals].Normal = normal;
                    normals++;
                }
                else if (inputList[0] == "f")
                {
                    // Triangles must start with the letter "f" and contain three indices of Vertices.
                    if (inputList[1].Contains("/"))
                    {
                        // The OBJ format allows entering information about the Vertices (v), the texture (vt) and the normal vectors at the Vertices (vn) in the form v/vt/vn.
                        // Only the Vertex informations are used, as no texture is supported by this program and the normal vectors are attached to the Vertices directly.
                        a = int.Parse(inputList[1].Substring(0, inputList[1].IndexOf('/')), nFI) - 1;
                        b = int.Parse(inputList[2].Substring(0, inputList[2].IndexOf('/')), nFI) - 1;
                        c = int.Parse(inputList[3].Substring(0, inputList[3].IndexOf('/')), nFI) - 1;
                    }
                    else
                    {
                        // The simple version only gives information about the Vertices.
                        a = int.Parse(inputList[1], nFI) - 1;
                        b = int.Parse(inputList[2], nFI) - 1;
                        c = int.Parse(inputList[3], nFI) - 1;
                    }

                    // The OBJ format allows refering to the indices of the Vertices with a negative number indicating the position of the Vertex above the face.
                    // This notation must be used consistently, so if (a < 0) so are b and c.
                    if (a < 0)
                    {
                        a += TriMMApp.Mesh.Vertices.Count;
                        b += TriMMApp.Mesh.Vertices.Count;
                        c += TriMMApp.Mesh.Vertices.Count;
                    }
                    TriMMApp.Mesh.Add(new Triangle(a, b, c));
                }

                input = file.ReadLine();
            }

            // The TriangleMesh is complete and can be finalized.
            // If there are no Vertex normals in the file, they are calculated with the chosen algorithm.
            // If there were Vertex normals missing for some Vertices, all are calculated.
            if (vertices != normals)
            {
                TriMMApp.Mesh.Finish(true);
                TriangleMesh mesh = TriMMApp.Mesh;
                TriMMApp.VertexNormalAlgorithm.GetVertexNormals(ref mesh);
            }
            else
            {
                TriMMApp.Mesh.Finish(true);
            }
            TriMMApp.Mesh.SetArrays();

#if !DEBUG
        }

        catch {
            throw new Exception(TriMMApp.Lang.GetElementsByTagName("ObjBrokenFileError")[0].InnerText);
        }
#endif
        }
Exemple #4
0
        /// <summary>
        /// Creates the base dodecahedron.
        /// </summary>
        private TriangleMesh CreateBaseDodecahedron()
        {
            TriangleMesh baseMesh = new TriangleMesh();

            double phi    = (1 + Math.Sqrt(5)) / 2;
            double phiInv = 2 / (1 + Math.Sqrt(5));

            baseMesh.Vertices.Add(new Vertex(1, 1, 1));                                          // 0
            baseMesh.Vertices.Add(new Vertex(-1, 1, 1));                                         // 1
            baseMesh.Vertices.Add(new Vertex(1, -1, 1));                                         // 2
            baseMesh.Vertices.Add(new Vertex(1, 1, -1));                                         // 3
            baseMesh.Vertices.Add(new Vertex(-1, -1, 1));                                        // 4
            baseMesh.Vertices.Add(new Vertex(-1, 1, -1));                                        // 5
            baseMesh.Vertices.Add(new Vertex(1, -1, -1));                                        // 6
            baseMesh.Vertices.Add(new Vertex(-1, -1, -1));                                       // 7
            baseMesh.Vertices.Add(new Vertex(0, phiInv, phi));                                   // 8
            baseMesh.Vertices.Add(new Vertex(0, -phiInv, phi));                                  // 9
            baseMesh.Vertices.Add(new Vertex(0, phiInv, -phi));                                  // 10
            baseMesh.Vertices.Add(new Vertex(0, -phiInv, -phi));                                 // 11
            baseMesh.Vertices.Add(new Vertex(phiInv, phi, 0));                                   // 12
            baseMesh.Vertices.Add(new Vertex(-phiInv, phi, 0));                                  // 13
            baseMesh.Vertices.Add(new Vertex(phiInv, -phi, 0));                                  // 14
            baseMesh.Vertices.Add(new Vertex(-phiInv, -phi, 0));                                 // 15
            baseMesh.Vertices.Add(new Vertex(phi, 0, phiInv));                                   // 16
            baseMesh.Vertices.Add(new Vertex(-phi, 0, phiInv));                                  // 17
            baseMesh.Vertices.Add(new Vertex(phi, 0, -phiInv));                                  // 18
            baseMesh.Vertices.Add(new Vertex(-phi, 0, -phiInv));                                 // 19

            baseMesh.Vertices.Add(new Vertex(0, (2 * (1 + phi) + phiInv) / 5, (2 + phi) / 5));   // 20
            baseMesh.Vertices.Add(new Vertex((2 + phi) / 5, 0, (2 * (1 + phi) + phiInv) / 5));   // 21
            baseMesh.Vertices.Add(new Vertex((2 * (1 + phi) + phiInv) / 5, (2 + phi) / 5, 0));   // 22
            baseMesh.Vertices.Add(new Vertex(-(2 * (1 + phi) + phiInv) / 5, (2 + phi) / 5, 0));  // 23
            baseMesh.Vertices.Add(new Vertex(-(2 + phi) / 5, 0, -(2 * (1 + phi) + phiInv) / 5)); // 24
            baseMesh.Vertices.Add(new Vertex(-(2 * (1 + phi) + phiInv) / 5, -(2 + phi) / 5, 0)); // 25
            baseMesh.Vertices.Add(new Vertex(-(2 + phi) / 5, 0, (2 * (1 + phi) + phiInv) / 5));  // 26
            baseMesh.Vertices.Add(new Vertex(0, -(2 * (1 + phi) + phiInv) / 5, (2 + phi) / 5));  // 27
            baseMesh.Vertices.Add(new Vertex((2 * (1 + phi) + phiInv) / 5, -(2 + phi) / 5, 0));  // 28
            baseMesh.Vertices.Add(new Vertex((2 + phi) / 5, 0, -(2 * (1 + phi) + phiInv) / 5));  // 29
            baseMesh.Vertices.Add(new Vertex(0, -(2 * (1 + phi) + phiInv) / 5, -(2 + phi) / 5)); // 30
            baseMesh.Vertices.Add(new Vertex(0, (2 * (1 + phi) + phiInv) / 5, -(2 + phi) / 5));  // 31

            baseMesh.Add(new Triangle(0, 12, 20));
            baseMesh.Add(new Triangle(12, 13, 20));
            baseMesh.Add(new Triangle(13, 1, 20));
            baseMesh.Add(new Triangle(1, 8, 20));
            baseMesh.Add(new Triangle(8, 0, 20));
            baseMesh.Add(new Triangle(0, 8, 21));
            baseMesh.Add(new Triangle(8, 9, 21));
            baseMesh.Add(new Triangle(9, 2, 21));
            baseMesh.Add(new Triangle(2, 16, 21));
            baseMesh.Add(new Triangle(16, 0, 21));
            baseMesh.Add(new Triangle(0, 16, 22));
            baseMesh.Add(new Triangle(16, 18, 22));
            baseMesh.Add(new Triangle(18, 3, 22));
            baseMesh.Add(new Triangle(3, 12, 22));
            baseMesh.Add(new Triangle(12, 0, 22));
            baseMesh.Add(new Triangle(19, 17, 23));
            baseMesh.Add(new Triangle(17, 1, 23));
            baseMesh.Add(new Triangle(1, 13, 23));
            baseMesh.Add(new Triangle(13, 5, 23));
            baseMesh.Add(new Triangle(5, 19, 23));
            baseMesh.Add(new Triangle(19, 5, 24));
            baseMesh.Add(new Triangle(5, 10, 24));
            baseMesh.Add(new Triangle(10, 11, 24));
            baseMesh.Add(new Triangle(11, 7, 24));
            baseMesh.Add(new Triangle(7, 19, 24));
            baseMesh.Add(new Triangle(19, 7, 25));
            baseMesh.Add(new Triangle(7, 15, 25));
            baseMesh.Add(new Triangle(15, 4, 25));
            baseMesh.Add(new Triangle(4, 17, 25));
            baseMesh.Add(new Triangle(17, 19, 25));
            baseMesh.Add(new Triangle(1, 17, 26));
            baseMesh.Add(new Triangle(17, 4, 26));
            baseMesh.Add(new Triangle(4, 9, 26));
            baseMesh.Add(new Triangle(9, 8, 26));
            baseMesh.Add(new Triangle(8, 1, 26));
            baseMesh.Add(new Triangle(2, 9, 27));
            baseMesh.Add(new Triangle(9, 4, 27));
            baseMesh.Add(new Triangle(4, 15, 27));
            baseMesh.Add(new Triangle(15, 14, 27));
            baseMesh.Add(new Triangle(14, 2, 27));
            baseMesh.Add(new Triangle(2, 14, 28));
            baseMesh.Add(new Triangle(14, 6, 28));
            baseMesh.Add(new Triangle(6, 18, 28));
            baseMesh.Add(new Triangle(18, 16, 28));
            baseMesh.Add(new Triangle(16, 2, 28));
            baseMesh.Add(new Triangle(3, 18, 29));
            baseMesh.Add(new Triangle(18, 6, 29));
            baseMesh.Add(new Triangle(6, 11, 29));
            baseMesh.Add(new Triangle(11, 10, 29));
            baseMesh.Add(new Triangle(10, 3, 29));
            baseMesh.Add(new Triangle(6, 14, 30));
            baseMesh.Add(new Triangle(14, 15, 30));
            baseMesh.Add(new Triangle(15, 7, 30));
            baseMesh.Add(new Triangle(7, 11, 30));
            baseMesh.Add(new Triangle(11, 6, 30));
            baseMesh.Add(new Triangle(3, 10, 31));
            baseMesh.Add(new Triangle(10, 5, 31));
            baseMesh.Add(new Triangle(5, 13, 31));
            baseMesh.Add(new Triangle(13, 12, 31));
            baseMesh.Add(new Triangle(12, 3, 31));

            return(baseMesh);
        }
Exemple #5
0
        /// <summary>
        /// The given StreamReader <paramref name="file"/> is parsed and the TriangleMesh built.
        /// Only the ASCII version of PLY is supported and only triangle meshes are allowed.
        /// </summary>
        /// <param name="file">The *.PLY file to be parsed.</param>
        public static void Parse(StreamReader file)
        {
            TriMMApp.Mesh          = new TriangleMesh();
            TriMMApp.CurrentFormat = 3;

            // Temporary variables.
            String         input    = null;
            int            vertices = 0;
            int            faces    = 0;
            string         format   = "";
            string         version  = "";
            List <Element> elements = new List <Element>();

            String[] inputList;
            Vertex   vertex;
            int      count = 0;

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

            nFI.NumberDecimalSeparator = ".";

            // The file must not be empty!
            input = file.ReadLine();
            if (input == null)
            {
                throw new Exception(TriMMApp.Lang.GetElementsByTagName("PlyBrokenFileError")[0].InnerText);
            }
            input     = input.Replace("\t", " ").Trim();
            inputList = input.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            // The first word in the first line must be "ply"!
            if (inputList[0] != "ply")
            {
                throw new Exception(TriMMApp.Lang.GetElementsByTagName("PlyBrokenFileError")[0].InnerText);
            }

            input     = file.ReadLine();
            input     = input.Replace("\t", " ").Trim();
            inputList = input.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            // There has to be more information than just "ply"!
            if (input == null)
            {
                throw new Exception(TriMMApp.Lang.GetElementsByTagName("PlyBrokenFileError")[0].InnerText);
            }

            // The header is processed here.
            do
            {
                // Empty lines and comment-lines are skipped.
                if ((input == "") || (input.StartsWith("comment")))
                {
                }
                else if (inputList[0] == "format")
                {
                    if (inputList.Length != 3)
                    {
                        throw new Exception(TriMMApp.Lang.GetElementsByTagName("PlyBrokenFileError")[0].InnerText);
                    }
                    format  = inputList[1];
                    version = inputList[2];
                }
                else if (inputList[0] == "element")
                {
                    // The Elements are read and stored. There need to be Elements called "vertex" and "face".
                    if (inputList.Length != 3)
                    {
                        throw new Exception(TriMMApp.Lang.GetElementsByTagName("PlyBrokenFileError")[0].InnerText);
                    }
                    elements.Add(new Element(inputList[1], int.Parse(inputList[2])));
                }
                else if (inputList[0] == "property")
                {
                    // The properties of the Elements are stored with the elements.
                    elements[elements.Count - 1].properties.Add(input);
                }

                // There has to be more information than just the header, which must end with "end_header"!
                input = file.ReadLine();
                if (input == null)
                {
                    throw new Exception(TriMMApp.Lang.GetElementsByTagName("PlyBrokenFileError")[0].InnerText);
                }
                input     = input.Replace("\t", " ").Trim();
                inputList = input.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            } while (input != "end_header");

            for (int i = 0; i < elements.Count; i++)
            {
                Element el = elements[i];
                // Vertices are needed for this program.
                if (el.name == "vertex")
                {
                    vertices = el.count;
                    // At least the x-, y- and z-coordinates of a Vertex are needed.
                    // There could be more informations, but as there are no standard names for them in the original
                    // description of the PLY format, they are ignored by this program.
                    if (el.properties.Count < 3)
                    {
                        throw new Exception(TriMMApp.Lang.GetElementsByTagName("PlyBrokenFileError")[0].InnerText);
                    }
                    else
                    {
                        bool x = false, y = false, z = false;
                        for (int j = 0; j < el.properties.Count; j++)
                        {
                            String[] l = el.properties[j].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
                            switch (l[2])
                            {
                            case "x":
                                x = true;
                                break;

                            case "y":
                                y = true;
                                break;

                            case "z":
                                z = true;
                                break;
                            }
                        }
                        if (!x || !y || !z)
                        {
                            throw new Exception(TriMMApp.Lang.GetElementsByTagName("PlyBrokenFileError")[0].InnerText);
                        }
                    }
                }
                else if (el.name == "face")
                {
                    faces = el.count;
                    // The faces need to be indices of the Vertices!
                    if (el.properties[0] != "property list uchar int vertex_index")
                    {
                        throw new Exception(TriMMApp.Lang.GetElementsByTagName("PlyBrokenFileError")[0].InnerText);
                    }
                }
            }

            // The following lines in the file contain the Vertices.
            count = 0;
            while (count < vertices)
            {
                input = file.ReadLine();
                input = input.Replace("\t", " ").Trim();
                if ((input != "") && (!input.StartsWith("comment")))
                {
                    if (input.Contains("comment"))
                    {
                        input = input.Substring(0, input.IndexOf("comment"));
                    }

                    // RemoveEmptyEntities removes empty entities, resulting from more than one whitespace.
                    inputList = input.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                    // Only the Vertex is read and added to the VertexList of the owners TriangleMesh, everything else in the line is ignored.
                    vertex = new Vertex(double.Parse(inputList[0], NumberStyles.Float, nFI),
                                        double.Parse(inputList[1], NumberStyles.Float, nFI), double.Parse(inputList[2], NumberStyles.Float, nFI));

                    TriMMApp.Mesh.Vertices.Add(vertex);

                    count++;
                }
            }

            // The following lines in the file contain the Faces as combinations of the indices of the Vertices parsed above.
            count = 0;
            while (count < faces)
            {
                input = file.ReadLine();
                input = input.Replace("\t", " ").Trim();
                if ((input != "") && (!input.StartsWith("comment")))
                {
                    if (input.Contains("comment"))
                    {
                        input = input.Substring(0, input.IndexOf("comment"));
                    }

                    // RemoveEmptyEntities removes empty entities, resulting from more than one whitespace
                    inputList = input.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                    // Only triangles are allowed for this program.
                    if (int.Parse(inputList[0]) != 3)
                    {
                        throw new Exception(TriMMApp.Lang.GetElementsByTagName("PlyTriangleError")[0].InnerText);
                    }

                    // Only the Triangle is read and added to the owners TriangleMesh, everything else in the line is ignored.
                    TriMMApp.Mesh.Add(new Triangle(int.Parse(inputList[1], nFI), int.Parse(inputList[2], nFI), int.Parse(inputList[3], nFI)));

                    count++;
                }
            }

            // The TriangleMesh is complete and can be finalized.
            // The Vertex normals are calculated with the chosen algorithm.
            TriMMApp.Mesh.Finish(true);
            TriangleMesh mesh = TriMMApp.Mesh;

            TriMMApp.VertexNormalAlgorithm.GetVertexNormals(ref mesh);
            TriMMApp.Mesh.SetArrays();
        }
Exemple #6
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();
        }
Exemple #7
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();
        }