Commits

Lars Brubaker committed 013e01a

We can now load stl files into meshes.
Refactored some mesh api.
You can get an aabb.

  • Participants
  • Parent commits 0f391bb

Comments (0)

Files changed (5)

File PolygonMesh/Face.cs

 
         public void CalculateNormal()
         {
-            FaceEdge face0 = firstFaceEdge;
-            FaceEdge face1 = face0.nextFaceEdge;
-            Vector3 face1Minus0 = face1.vertex.Position - face0.vertex.Position;
-            FaceEdge face2 = face1;
+            FaceEdge faceEdge0 = firstFaceEdge;
+            FaceEdge faceEdge1 = faceEdge0.nextFaceEdge;
+            Vector3 faceEdge1Minus0 = faceEdge1.vertex.Position - faceEdge0.vertex.Position;
+            FaceEdge faceEdge2 = faceEdge1;
             bool collinear = false;
             do
             {
-                face2 = face2.nextFaceEdge;
-                if (face2 == firstFaceEdge)
+                faceEdge2 = faceEdge2.nextFaceEdge;
+                if (faceEdge2 == firstFaceEdge)
                 {
-                    throw new Exception("Error: This face is all collinear.");
+                    //throw new Exception("Error: This face is all collinear.");
                 }
-                Vector3 test2Minus0 = (face2.vertex.Position - face0.vertex.Position).GetNormal() * face1Minus0.Length;
-                if ((face1Minus0 - test2Minus0).Length > .00001)
+                Vector3 test2Minus0 = (faceEdge2.vertex.Position - faceEdge0.vertex.Position).GetNormal() * faceEdge1Minus0.Length;
+                if ((faceEdge1Minus0 - test2Minus0).Length > .00001)
                 {
                     collinear = false;
                 }
                 {
                     collinear = true;
                 }
-            } while (collinear);
-            Vector3 face2Minus0 = face2.vertex.Position - face0.vertex.Position;
-            normal = Vector3.Cross(face1Minus0, face2Minus0).GetNormal();
+            } while (collinear && faceEdge2 != faceEdge0);
+            Vector3 face2Minus0 = faceEdge2.vertex.Position - faceEdge0.vertex.Position;
+            normal = Vector3.Cross(faceEdge1Minus0, face2Minus0).GetNormal();
         }
 
         public bool FaceEdgeLoopIsGood()

File PolygonMesh/Mesh.cs

         MetaData data = new MetaData();
         public MetaData Data { get { return data; } }
 
-        public VertexCollecton vertices = new VertexCollecton();
+        VertexCollecton vertices = new VertexCollecton();
+        public VertexCollecton Vertices
+        {
+            get
+            {
+                return vertices;
+            }
+        }
         public List<MeshEdge> meshEdges = new List<MeshEdge>();
-        public List<Face> faces = new List<Face>();
+        List<Face> faces = new List<Face>();
+        public List<Face> Faces
+        {
+            get
+            {
+                return faces;
+            }
+        }
 
         public Mesh()
         {
         }
 
         #endregion // Face
+        
+        public void GetAxisAlignedBounds(out Vector3 minBounds, out Vector3 maxBounds)
+        {
+            minBounds = new Vector3(double.MaxValue, double.MaxValue, double.MaxValue);
+            maxBounds = new Vector3(double.MinValue, double.MinValue, double.MinValue);
+
+            foreach (Vertex vertex in vertices)
+            {
+                minBounds.x = Math.Min(minBounds.x, vertex.Position.x);
+                minBounds.y = Math.Min(minBounds.y, vertex.Position.y);
+                minBounds.z = Math.Min(minBounds.z, vertex.Position.z);
+
+                maxBounds.x = Math.Max(maxBounds.x, vertex.Position.x);
+                maxBounds.y = Math.Max(maxBounds.y, vertex.Position.y);
+                maxBounds.z = Math.Max(maxBounds.z, vertex.Position.z);
+            }
+        }
+
         #endregion // Public Members
 
         #region Private Members

File PolygonMesh/PolygonMesh.csproj

     <Compile Include="MetaData.cs" />
     <Compile Include="FaceEdge.cs" />
     <Compile Include="Mesh.cs" />
+    <Compile Include="Processors\StlProcessing.cs" />
     <Compile Include="Solids\PlatonicSolids.cs" />
     <Compile Include="UnitTests.cs" />
     <Compile Include="Vertex.cs" />

File PolygonMesh/Processors/StlProcessing.cs

+/*
+Copyright (c) 2012, Lars Brubaker
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met: 
+
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer. 
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+The views and conclusions contained in the software and documentation are those
+of the authors and should not be interpreted as representing official policies, 
+either expressed or implied, of the FreeBSD Project.
+*/
+
+using System;
+using System.IO;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using MatterHackers.PolygonMesh;
+using MatterHackers.VectorMath;
+
+namespace MatterHackers.PolygonMesh.Processors
+{
+    public static class StlProcessing
+    {
+        public static void Save(Mesh meshToSave, string fileName)
+        {
+            FileStream file = new FileStream(fileName, FileMode.Create, FileAccess.Write);
+
+            Save(meshToSave, file);
+            file.Close();
+        }
+
+        public static string FormatForStl(Vector3 value)
+        {
+            return value.x.ToString("e") + " " + value.y.ToString("e") + " " + value.z.ToString("e");
+        }
+
+        public static void Save(Mesh meshToSave, Stream stream)
+        {
+            StreamWriter streamWriter = new StreamWriter(stream);
+
+            streamWriter.WriteLine("solid Default");
+
+            foreach(Face face in meshToSave.Faces)
+            {
+                foreach (FaceEdge faceEdge in face.FaceEdgeIterator())
+                {
+                    // feed this into the tesselator and get back the triangles to emit to the stl file
+                }
+                Vector3 normalForFace = Vector3.Zero;
+                streamWriter.WriteLine("  facet normal " + FormatForStl(normalForFace));
+                streamWriter.WriteLine("    outer loop");
+                //streamWriter.WriteLine("      vertex " + FormatForStl(meshToSave.vertices[meshToSave.renderVertexIndices[polygon * 3 + 0]]));
+                //streamWriter.WriteLine("      vertex " + FormatForStl(meshToSave.vertices[meshToSave.renderVertexIndices[polygon * 3 + 1]]));
+                //streamWriter.WriteLine("      vertex " + FormatForStl(meshToSave.vertices[meshToSave.renderVertexIndices[polygon * 3 + 2]]));
+                //streamWriter.WriteLine("    endloop");
+                streamWriter.WriteLine("  endfacet");
+            }
+
+            streamWriter.WriteLine("endsolid Default");
+
+            streamWriter.Close();
+        }
+
+        public static Mesh Load(string fileName)
+        {
+            FileStream file = new FileStream(fileName, FileMode.Create, FileAccess.Write);
+
+            return Load(file);
+            file.Close();
+        }
+
+        public static Mesh Load(Stream stream)
+        {
+            StreamReader sw = new StreamReader(stream);
+            string fileString = sw.ReadToEnd();
+            sw.Close();
+
+            return ParseFileContents(fileString);
+        }
+        
+
+        public static Mesh ParseFileContents(string stlFileString)
+        {
+            Mesh meshFromStlFile = new Mesh();
+            stlFileString = stlFileString.Replace("\r\n", "\n");
+            stlFileString = stlFileString.Replace('\r', '\n');
+            string[] splitOnLF = stlFileString.Split('\n');
+            int lineIndex = 0;
+            if (!splitOnLF[lineIndex++].Trim().StartsWith("solid"))
+            {
+                throw new Exception("This is not an STL file.");
+            }
+
+            do
+            {
+                if (splitOnLF[lineIndex].Trim().StartsWith("endsolid"))
+                {
+                    break;
+                }
+                if (!splitOnLF[lineIndex++].Trim().StartsWith("facet normal"))
+                {
+                    throw new Exception("Error in STL file.");
+                }
+                if (!splitOnLF[lineIndex++].Trim().StartsWith("outer loop"))
+                {
+                    throw new Exception("Error in STL file.");
+                }
+                Vertex vertex1 = ParseLine(meshFromStlFile, splitOnLF, lineIndex++);
+                Vertex vertex2 = ParseLine(meshFromStlFile, splitOnLF, lineIndex++);
+                Vertex vertex3 = ParseLine(meshFromStlFile, splitOnLF, lineIndex++);
+                meshFromStlFile.CreateFace(new Vertex[] { vertex1, vertex2, vertex3 });
+                if (!splitOnLF[lineIndex++].Trim().StartsWith("endloop"))
+                {
+                    throw new Exception("Error in STL file.");
+                }
+                if (!splitOnLF[lineIndex++].Trim().StartsWith("endfacet"))
+                {
+                    throw new Exception("Error in STL file.");
+                }
+            } while (true);
+
+            return meshFromStlFile;
+        }
+
+        private static Vertex ParseLine(Mesh meshFromStlFile, string[] splitOnLF, int lineIndex)
+        {
+            string thisLine = splitOnLF[lineIndex++].Trim();
+            string noDoubleSpaces = thisLine;
+            while (noDoubleSpaces.Contains("  "))
+            {
+                noDoubleSpaces = noDoubleSpaces.Replace("  ", " ");
+            }
+            string[] splitOnSpace = noDoubleSpaces.Split(' ');
+            return meshFromStlFile.CreateVertex(double.Parse(splitOnSpace[1]), double.Parse(splitOnSpace[2]), double.Parse(splitOnSpace[3]));
+        }
+    }
+}

File RenderOpenGl/RenderMeshToGl.cs

             if (meshToRender != null)
             {
                 Gl.glColor3d(partColor.red, partColor.green, partColor.blue);
-                for (int i = 0; i < meshToRender.faces.Count; i++)
+                for (int i = 0; i < meshToRender.Faces.Count; i++)
                 {
-                    Face face = meshToRender.faces[i];
+                    Face face = meshToRender.Faces[i];
                     int numVerts = face.NumVertices;
                     Gl.glBegin(Gl.GL_TRIANGLE_FAN);
                     Gl.glNormal3dv(face.normal.ToArray());