Beispiel #1
0
        /// <summary>
        /// Reads a mesh file filtered by filter.
        /// </summary>
        /// <param name="file">The mesh file.</param>
        /// <param name="filter">The filter to filter by.</param>
        /// <param name="excludedModel">The DMTModel that doesn't obey to the filter condition.</param>
        /// <returns>The DMTModel that obeys to the filter condition.</returns>
        /// <exception cref="DMTFileException">
        /// Thrown for any of the following reasons:<br></br><br></br>
        /// Specified file does not exist.<br></br>File format is unsupported.<br></br>File contains no triangle blocks.<br></br>
        /// File contains no vertices.<br></br>File contains no triangles.<br></br>Block version does not match file version.
        /// </exception>
        public static DMTModel ReadFile(File file, IDMTModelFilter filter, out DMTModel excludedModel)
        {
            var dmtModel = new DMTModel();

            AppendFile(dmtModel, file, filter, out excludedModel);
            return(dmtModel);
        }
Beispiel #2
0
        /// <summary>
        /// Returns a clone of the current Model.
        /// </summary>
        public DMTModel Clone()
        {
            DMTModel cloneModel = new DMTModel();

            foreach (DMTTriangleBlock block in TriangleBlocks)
            {
                cloneModel.TriangleBlocks.Add(block.Clone());
            }
            return(cloneModel);
        }
Beispiel #3
0
        /// <summary>
        /// Write the contents of the model into the specified file. If the provided file is a DMT file, it will use the DMT file writer. If the provided file is a STL file, it will use a STL file writer.
        /// </summary>
        /// <param name="dmtModel">The DMTModel to write.</param>
        /// <param name="file">Destination file.</param>
        public static void WriteFile(DMTModel dmtModel, File file)
        {
            switch (file.Extension.ToUpper())
            {
            case "DMT":
                WriteToDMTFile(dmtModel, file);
                break;

            case "STL":
                WriteToSTLFile(dmtModel, file);
                break;
            }
        }
Beispiel #4
0
        /// <summary>
        /// Appends the contents of the specified STL <paramref name="file"/> to the model.
        /// </summary>
        /// <param name="file">Path and filename of the STL model.</param>
        private static void AppendSTLFile(DMTModel dmtModel, File file, IDMTModelFilter filter, out DMTModel excludedDmtModel)
        {
            var asciiStlReader  = new AsciiStlFileReader();
            var binaryStlReader = new BinaryStlFileReader();
            var models          = file.ReadFirstLine().StartsWith("solid")
                ? asciiStlReader.ReadFile(file, filter)
                : binaryStlReader.ReadFile(file, filter);

            var withinFilter = models[0];

            excludedDmtModel = models[1];

            dmtModel.TriangleBlocks.AddRange(withinFilter.TriangleBlocks);
        }
Beispiel #5
0
        private static void AppendDMTFile(
            DMTModel dmtModel,
            File fileToAppend,
            IDMTModelFilter filter,
            out DMTModel excludedDmtModel)
        {
            var dmtReader    = new DMTFileReader();
            var models       = dmtReader.ReadFile(fileToAppend, filter);
            var withinFilter = models[0];

            excludedDmtModel = models[1];

            dmtModel.TriangleBlocks.AddRange(withinFilter.TriangleBlocks);
        }
Beispiel #6
0
        /// <summary>
        /// Appends the contents of the specified DMT file that obeys to a specified filter to the existing model.
        /// </summary>
        /// <param name="dmtModel">The DMTModel to append to.</param>
        /// <param name="file">Path and filename of the DMT model.</param>
        /// <param name="filter">The filterto filter by.</param>
        /// <param name="excludedModel">The DMTModel that doesn't obey to the filter condition.</param>
        /// <exception cref="DMTFileException">
        /// Thrown for any of the following reasons:<br></br><br></br>
        /// Specified file does not exist.<br></br>File format is unsupported.<br></br>File contains no triangle blocks.<br></br>
        /// File contains no vertices.<br></br>File contains no triangles.<br></br>Block version does not match file version.
        /// </exception>
        public static void AppendFile(DMTModel dmtModel, File file, IDMTModelFilter filter, out DMTModel excludedModel)
        {
            excludedModel = new DMTModel();
            switch (file.Extension.ToUpper())
            {
            case "DMT":
                AppendDMTFile(dmtModel, file, filter, out excludedModel);
                break;

            case "STL":
                AppendSTLFile(dmtModel, file, filter, out excludedModel);
                break;
            }
        }
        /// <summary>
        /// Writes the model to a binary STL file.
        /// </summary>
        /// <param name="model">The DMTModel to write.</param>
        /// <param name="file">The file to write to.</param>
        public void WriteFile(DMTModel model, File file)
        {
            //Check that we are not going to inadvertantly overwrite a file
            file.Delete();

            BinaryFileWriter binaryWriter = null;

            try
            {
                binaryWriter = new BinaryFileWriter(file);

                //If there are no triangles then return
                if (model.TotalNoOfTriangles == 0)
                {
                    throw new DMTFileException(DMTFileError.NoTriangles);
                }

                // Write header
                for (var i = 0; i < 80; i++)
                {
                    byte b = 0;
                    binaryWriter.WriteByte(b);
                }

                // write number of triangles
                binaryWriter.WriteUInteger(model.TotalNoOfTriangles);

                Point  vertex1 = null;
                Point  vertex2 = null;
                Point  vertex3 = null;
                Vector normal  = null;
                foreach (var block in model.TriangleBlocks)
                {
                    for (var intCounter = 0; intCounter <= block.NoOfTriangles - 1; intCounter++)
                    {
                        // STL wants a triangle Normal
                        vertex1 = block.GetVertex1(intCounter);
                        vertex2 = block.GetVertex2(intCounter);
                        vertex3 = block.GetVertex3(intCounter);
                        normal  = DMTTriangle.GetNormal(vertex1, vertex2, vertex3);
                        binaryWriter.WriteSingle((float)normal.I.Value);
                        binaryWriter.WriteSingle((float)normal.J.Value);
                        binaryWriter.WriteSingle((float)normal.K.Value);

                        // Write vertices
                        var x = (float)vertex1.X;
                        var y = (float)vertex1.Y;
                        var z = (float)vertex1.Z;
                        binaryWriter.WriteSingle(x);
                        binaryWriter.WriteSingle(y);
                        binaryWriter.WriteSingle(z);
                        x = (float)vertex2.X;
                        y = (float)vertex2.Y;
                        z = (float)vertex2.Z;
                        binaryWriter.WriteSingle(x);
                        binaryWriter.WriteSingle(y);
                        binaryWriter.WriteSingle(z);
                        x = (float)vertex3.X;
                        y = (float)vertex3.Y;
                        z = (float)vertex3.Z;
                        binaryWriter.WriteSingle(x);
                        binaryWriter.WriteSingle(y);
                        binaryWriter.WriteSingle(z);

                        // padding to 50 bytes
                        ushort code = 0;
                        binaryWriter.WriteUInt16(code);
                    }
                }
            }
            finally
            {
                if (binaryWriter != null)
                {
                    binaryWriter.Close();
                }
            }
        }
Beispiel #8
0
        /// <summary>
        /// Appends the contents of the specified DMT file that obeys to a specified filter to the existing model.
        /// </summary>
        /// <param name="dmtModel">The DMTModel to append to.</param>
        /// <param name="file">Path and filename of the DMT model.</param>
        /// <param name="filter">The filterto filter by.</param>
        /// <exception cref="DMTFileException">
        /// Thrown for any of the following reasons:<br></br><br></br>
        /// Specified file does not exist.<br></br>File format is unsupported.<br></br>File contains no triangle blocks.<br></br>
        /// File contains no vertices.<br></br>File contains no triangles.<br></br>Block version does not match file version.
        /// </exception>
        public static void AppendFile(DMTModel dmtModel, File file, IDMTModelFilter filter)
        {
            DMTModel excludedModel;

            AppendFile(dmtModel, file, filter, out excludedModel);
        }
Beispiel #9
0
 /// <summary>
 /// Appends the contents of the specified DMT file to the model.
 /// </summary>
 /// <param name="dmtModel">The DMTModel to append to.</param>
 /// <param name="file">Path and filename of the DMT model.</param>
 /// <exception cref="DMTFileException">
 /// Thrown for any of the following reasons:<br></br><br></br>
 /// Specified file does not exist.<br></br>File format is unsupported.<br></br>File contains no triangle blocks.<br></br>
 /// File contains no vertices.<br></br>File contains no triangles.<br></br>Block version does not match file version.
 /// </exception>
 public static void AppendFile(DMTModel dmtModel, File file)
 {
     AppendFile(dmtModel, file, new DMTModelFilterByNone());
 }
Beispiel #10
0
        /// <summary>
        /// Writes the contents of the model to the specified STL <paramref name="file"/>.
        /// </summary>
        /// <param name="dmtModel">The DMTModel to write.</param>
        /// <param name="file">Destination file.</param>
        private static void WriteToSTLFile(DMTModel dmtModel, File file)
        {
            var stlFileWriter = new BinaryStlFileWriter();

            stlFileWriter.WriteFile(dmtModel, file);
        }
Beispiel #11
0
        /// <summary>
        /// Writes the contents of the model to the specified DMT <paramref name="file"/>.
        /// </summary>
        /// <param name="dmtModel">The DMTModel to write.</param>
        /// <param name="file">Destination file.</param>
        /// <exception cref="DMTFileException">
        /// Thrown for any of the following reasons:<br></br><br></br>
        /// The model contains no blocks.<br></br>The model contains no vertices.<br></br>The model contains no triangles.
        /// </exception>
        private static void WriteToDMTFile(DMTModel dmtModel, File file)
        {
            var dmtFileWriter = new DMTFileWriter();

            dmtFileWriter.WriteFile(dmtModel, file);
        }
        /// <summary>
        /// Writes the model to a DMT file.
        /// </summary>
        /// <param name="model">The DMTModel to write.</param>
        /// <param name="file">The file to write to.</param>
        public void WriteFile(DMTModel model, File file)
        {
            BinaryFileWriter binaryWriter = null;

            try
            {
                // If there are no blocks then return
                if (model.TriangleBlocks.Count == 0)
                {
                    throw new DMTFileException(DMTFileError.NoTriangleBlocks);
                }

                // If there are no vertices then return
                if (model.TotalNoOfVertices == 0)
                {
                    throw new DMTFileException(DMTFileError.NoVertices);
                }

                // If there are no triangles then return
                if (model.TotalNoOfTriangles == 0)
                {
                    throw new DMTFileException(DMTFileError.NoTriangles);
                }

                // Delete the file
                file.Delete();

                // Create the writer
                binaryWriter = new BinaryFileWriter(file);

                // Write the header
                string header = null;
                header = "DMT Triangles saved by Automation Interface v" +
                         Assembly.GetExecutingAssembly().GetName().Version +
                         " in MM " +
                         DateTime.Now.ToShortDateString();
                if (header.Length > 255)
                {
                    header = header.Substring(0, 255);
                }
                header += Strings.Chr(0);

                binaryWriter.WriteString(header);

                // Write version
                ushort version = 1000;
                binaryWriter.WriteUShort(version);

                // Write file flags (Bit 1 = 0 (doubles), Bit 2 = 1 (MMs))
                uint fileFlags = 2;
                binaryWriter.WriteUInteger(fileFlags);

                // Write total block count
                uint totalNoOfBlocks = 0;
                totalNoOfBlocks = (uint)model.TriangleBlocks.Count;
                binaryWriter.WriteUInteger(totalNoOfBlocks);

                // Write total vertex count
                uint totalNoOfTriangleVertices = 0;
                totalNoOfTriangleVertices = model.TotalNoOfVertices;
                binaryWriter.WriteUInteger(totalNoOfTriangleVertices);

                // Write total triangle count
                uint   totalNoOfTriangles = 0;
                var    triangleIndex      = 0;
                Vector normal             = null;
                totalNoOfTriangles = model.TotalNoOfTriangles;
                binaryWriter.WriteUInteger(totalNoOfTriangles);

                foreach (var block in model.TriangleBlocks)
                {
                    binaryWriter.WriteUInteger(block.Flags);
                    binaryWriter.WriteUInteger((uint)block.NoOfVertices);
                    binaryWriter.WriteUInteger((uint)block.NoOfTriangles);

                    for (var vertexNo = 0; vertexNo <= block.TriangleVertices.Count - 1; vertexNo++)
                    {
                        binaryWriter.WriteDouble(block.TriangleVertices.ElementAt(vertexNo).X);
                        binaryWriter.WriteDouble(block.TriangleVertices.ElementAt(vertexNo).Y);
                        binaryWriter.WriteDouble(block.TriangleVertices.ElementAt(vertexNo).Z);

                        if (block.DoVerticesHaveNormals)
                        {
                            binaryWriter.WriteDouble(block.VertexNormals.ElementAt(vertexNo).I.Value);
                            binaryWriter.WriteDouble(block.VertexNormals.ElementAt(vertexNo).J.Value);
                            binaryWriter.WriteDouble(block.VertexNormals.ElementAt(vertexNo).K.Value);
                        }
                    }

                    var use32bitPointers = false;
                    use32bitPointers = block.TriangleVertices.Count > ushort.MaxValue;

                    for (var triangleNo = 0; triangleNo <= block.NoOfTriangles - 1; triangleNo++)
                    {
                        if (use32bitPointers)
                        {
                            binaryWriter.WriteInteger(block.TriangleFirstVertexIndices.ElementAt(triangleNo));
                            binaryWriter.WriteInteger(block.TriangleSecondVertexIndices.ElementAt(triangleNo));
                            binaryWriter.WriteInteger(block.TriangleThirdVertexIndices.ElementAt(triangleNo));
                        }
                        else
                        {
                            binaryWriter.WriteUShort((ushort)block.TriangleFirstVertexIndices.ElementAt(triangleNo));
                            binaryWriter.WriteUShort((ushort)block.TriangleSecondVertexIndices.ElementAt(triangleNo));
                            binaryWriter.WriteUShort((ushort)block.TriangleThirdVertexIndices.ElementAt(triangleNo));
                        }
                    }

                    binaryWriter.WriteUShort(version);
                }

                // All done, close the writer
                binaryWriter.Close();
            }
            finally
            {
                if (binaryWriter != null)
                {
                    binaryWriter.Close();
                }
            }
        }
Beispiel #13
0
        /// <summary>
        /// Creates a new model from all the points that make up the "Top" surface
        /// of the DMT Model (i.e. those triangles that can be seen in entirety from above).
        /// </summary>
        /// <returns>DMTModel object of the top surface.</returns>
        public DMTModel SurfaceFromTop()
        {
            //Get the points that make up the top surface
            PointCloud topSurfacePoints = PointCloudFromTop();

            DMTModel topSurfaceDMT = new DMTModel();

            foreach (DMTTriangleBlock block in _blocks)
            {
                DMTTriangleBlock newBlock = new DMTTriangleBlock();

                for (int intTriangleNo = 0; intTriangleNo <= TotalNoOfTriangles - 1; intTriangleNo++)
                {
                    Point vertex1 = null;
                    Point vertex2 = null;
                    Point vertex3 = null;
                    vertex1 = block.GetVertex1(intTriangleNo);
                    vertex2 = block.GetVertex2(intTriangleNo);
                    vertex3 = block.GetVertex3(intTriangleNo);

                    // See if this triangle is part of the top surface

                    if (topSurfacePoints.Contains(vertex1) && topSurfacePoints.Contains(vertex2) &&
                        topSurfacePoints.Contains(vertex3))
                    {
                        // Add the vertices to the list of vertices if they are not already in there
                        int vertex1Index = 0;
                        int vertex2Index = 0;
                        int vertex3Index = 0;
                        if (newBlock.TriangleVertices.Contains(vertex1))
                        {
                            vertex1Index = newBlock.TriangleVertices.IndexOf(vertex1);
                        }
                        else
                        {
                            vertex1Index = newBlock.TriangleVertices.Count;
                            newBlock.TriangleVertices.Add(vertex1);
                        }
                        if (newBlock.TriangleVertices.Contains(vertex2))
                        {
                            vertex2Index = newBlock.TriangleVertices.IndexOf(vertex2);
                        }
                        else
                        {
                            vertex2Index = newBlock.TriangleVertices.Count;
                            newBlock.TriangleVertices.Add(vertex2);
                        }
                        if (newBlock.TriangleVertices.Contains(vertex3))
                        {
                            vertex3Index = newBlock.TriangleVertices.IndexOf(vertex3);
                        }
                        else
                        {
                            vertex3Index = newBlock.TriangleVertices.Count;
                            newBlock.TriangleVertices.Add(vertex3);
                        }

                        // Create a new DMTTriangle that points to the Nodes
                        newBlock.TriangleFirstVertexIndices.Add(vertex1Index);
                        newBlock.TriangleSecondVertexIndices.Add(vertex2Index);
                        newBlock.TriangleThirdVertexIndices.Add(vertex3Index);
                    }
                }

                topSurfaceDMT.AddTriangleBlock(newBlock);
            }

            // With the new structure we don't need this
            //' Make sure each vertex knows which triangle it is a part of
            //topSurfaceDMT.RelinkNodesToTriangles()

            // Return the top surface
            return(topSurfaceDMT);
        }
        /// <summary>
        /// Reads an ASCII STL file filtered by a provided filter.
        /// </summary>
        /// <param name="file">The mesh file.</param>
        /// <param name="filter">The provided filtered.</param>
        /// <returns>The DMTModel that obeys to the filter condition.</returns>
        public List <DMTModel> ReadFile(File file, IDMTModelFilter filter)
        {
            if (file.Exists == false)
            {
                throw new DMTFileException(DMTFileError.FileDoesNotExist);
            }

            var blocksIn  = new List <DMTTriangleBlock>();
            var blocksOut = new List <DMTTriangleBlock>();
            var blockIn   = new DMTTriangleBlock();
            var blockOut  = new DMTTriangleBlock();
            var vertices  = new List <Point>();

            foreach (var strLine in file.ReadTextLines())
            {
                if (strLine.Trim().StartsWith("vertex "))
                {
                    //Add position
                    var    strCoords  = strLine.Trim().Split(' ');
                    var    intCounter = 0;
                    double x          = 0;
                    double y          = 0;
                    double z          = 0;
                    foreach (var strCoord in strCoords)
                    {
                        if (Information.IsNumeric(strCoord))
                        {
                            if (intCounter == 0)
                            {
                                x = Convert.ToDouble(strCoord);
                            }
                            else if (intCounter == 1)
                            {
                                y = Convert.ToDouble(strCoord);
                            }
                            else
                            {
                                z = Convert.ToDouble(strCoord);
                            }
                            intCounter += 1;
                        }
                    }

                    vertices.Add(new Point(x, y, z));
                }
                else if (strLine.Trim().StartsWith("endloop"))
                {
                    if (filter.CanAddTriangle(vertices.ElementAt(0), vertices.ElementAt(1), vertices.ElementAt(2)))
                    {
                        blockIn.AddTriangle(vertices.ElementAt(0), vertices.ElementAt(1), vertices.ElementAt(2));
                    }
                    else
                    {
                        blockOut.AddTriangle(vertices.ElementAt(0), vertices.ElementAt(1), vertices.ElementAt(2));
                    }

                    vertices.Clear();
                }
            }

            blocksIn.Add(blockIn);
            blocksOut.Add(blockOut);

            var modelWithinFilter  = new DMTModel();
            var modelOutsideFilter = new DMTModel();

            modelWithinFilter.TriangleBlocks.AddRange(blocksIn);
            modelOutsideFilter.TriangleBlocks.AddRange(blocksOut);
            var result = new List <DMTModel>();

            result.Add(modelWithinFilter);
            result.Add(modelOutsideFilter);
            return(result);
        }
        /// <summary>
        /// Reads a binary STL file filtered by a provided filter.
        /// </summary>
        /// <param name="file">The mesh file.</param>
        /// <param name="filter">The provided filtered.</param>
        /// <returns>The DMTModel that obeys to the filter condition.</returns>
        public List <DMTModel> ReadFile(File file, IDMTModelFilter filter)
        {
            if (file.Exists == false)
            {
                throw new DMTFileException(DMTFileError.FileDoesNotExist);
            }

            var blocksIn  = new List <DMTTriangleBlock>();
            var blocksOut = new List <DMTTriangleBlock>();
            var blockIn   = new DMTTriangleBlock();
            var blockOut  = new DMTTriangleBlock();
            var objReader = new BinaryFileReader(file);

            try
            {
                //Read first 80 characters (bytes) and ignore them
                objReader.ReadBytes(80);

                //Read the next 4 bytes to get an unsigned integer of number of triangles
                var intNoOfFacets = objReader.ReadUInteger();

                //Now keep reading until the end of the file
                var mapPointVertexIndexBlockIn  = new Dictionary <Point, int>();
                var mapPointVertexIndexBlockOut = new Dictionary <Point, int>();
                var point1Index = -1;
                var point2Index = -1;
                var point3Index = -1;
                for (uint intCounter = 0; intCounter <= intNoOfFacets - 1; intCounter++)
                {
                    //Read 3 32bit floating point numbers - triangle normal
                    // We do not keep the normals in memory, they take too much space
                    objReader.ReadSingle();
                    objReader.ReadSingle();
                    objReader.ReadSingle();

                    //Read 3 32bit floating point numbers - vertex 1 X/Y/Z
                    var objPoint1 = new Point();
                    objPoint1.X = objReader.ReadSingle();
                    objPoint1.Y = objReader.ReadSingle();
                    objPoint1.Z = objReader.ReadSingle();

                    //Read 3 32bit floating point numbers - vertex 2 X/Y/Z
                    var objPoint2 = new Point();
                    objPoint2.X = objReader.ReadSingle();
                    objPoint2.Y = objReader.ReadSingle();
                    objPoint2.Z = objReader.ReadSingle();

                    //Read 3 32bit floating point numbers - vertex 3 X/Y/Z
                    var objPoint3 = new Point();
                    objPoint3.X = objReader.ReadSingle();
                    objPoint3.Y = objReader.ReadSingle();
                    objPoint3.Z = objReader.ReadSingle();

                    if (filter.CanAddTriangle(objPoint1, objPoint2, objPoint3))
                    {
                        AddTriangle(mapPointVertexIndexBlockIn, blockIn, objPoint1, objPoint2, objPoint3);
                    }
                    else
                    {
                        AddTriangle(mapPointVertexIndexBlockOut, blockOut, objPoint1, objPoint2, objPoint3);
                    }

                    //Read 16 bit number
                    objReader.ReadUInt16();
                }

                blockIn.DoVerticesHaveNormals  = false;
                blockOut.DoVerticesHaveNormals = false;
                blocksIn.Add(blockIn);
                blocksOut.Add(blockOut);

                var modelWithinFilter  = new DMTModel();
                var modelOutsideFilter = new DMTModel();
                modelWithinFilter.TriangleBlocks.AddRange(blocksIn);
                modelOutsideFilter.TriangleBlocks.AddRange(blocksOut);
                var result = new List <DMTModel>();
                result.Add(modelWithinFilter);
                result.Add(modelOutsideFilter);
                return(result);
            }
            finally
            {
                objReader.Close();
            }
        }
Beispiel #16
0
        /// <summary>
        /// Reads a DMT file filtered by a provided filter.
        /// </summary>
        /// <param name="file">The mesh file.</param>
        /// <param name="filter">The provided filtered.</param>
        /// <returns>The DMTModel that obeys to the filter condition.</returns>
        public List <DMTModel> ReadFile(File file, IDMTModelFilter filter)
        {
            var blocksIn     = new List <DMTTriangleBlock>();
            var blocksOut    = new List <DMTTriangleBlock>();
            var binaryReader = new BinaryFileReader(file);

            try
            {
                if (file.Exists == false)
                {
                    throw new DMTFileException(DMTFileError.FileDoesNotExist);
                }

                // Read the file header. It is terminated with a 0 (null) and or has a
                // maximum of 256 bytes
                string header = null;
                header = binaryReader.ReadStringUntil(0, 256);

                // Read the file version number. Should be 1000 as this is the only format currently supported
                var version = binaryReader.ReadUShort();
                if (version != 1000)
                {
                    //Close the reader and return fail
                    binaryReader.Close();
                    throw new DMTFileException(DMTFileError.UnsupportedFileFormat);
                }

                // Read the file flags
                // The bits of this integer are used as flags to detail file specific features.
                //   1.  If this bit is set then the vertex data are stored as floats, else doubles.
                //   2.  If this bit is set then the file contains triangles which are known to have been written in units of MMs.
                //       If the flag is unset then the units used are unknown. This change was introduced by api#25 and dicc34143
                //
                //   New files (Since TVD release 2000111) MUST be written in MM. The code in dmkdmt always sets the flag and
                //   the write_node() API ensures that you know about the requirement.
                uint fileFlags = 0;
                fileFlags = binaryReader.ReadUInteger();
                var pointsAreFloats = (fileFlags & 1) == 1;

                // Read the number of triangle blocks in the file. Should not be zero
                uint noOfBlocks = 0;
                noOfBlocks = binaryReader.ReadUInteger();
                if (noOfBlocks == 0)
                {
                    binaryReader.Close();
                    throw new DMTFileException(DMTFileError.NoTriangleBlocks);
                }

                // Read the number of vertices in the file. Should not be zero
                uint totalTriangleVertices = 0;
                totalTriangleVertices = binaryReader.ReadUInteger();
                if (totalTriangleVertices == 0)
                {
                    binaryReader.Close();
                    throw new DMTFileException(DMTFileError.NoVertices);
                }

                // Read the number of triangles in the file. Should not be zero
                uint totalTriangles = 0;
                totalTriangles = binaryReader.ReadUInteger();
                if (totalTriangles == 0)
                {
                    binaryReader.Close();
                    throw new DMTFileException(DMTFileError.NoTriangles);
                }

                // Read the blocks
                for (var blockNo = 0; blockNo <= noOfBlocks - 1; blockNo++)
                {
                    var blockIn       = new DMTTriangleBlock();
                    var blockOut      = new DMTTriangleBlock();
                    var vertices      = new List <Point>();
                    var vertexNormals = new List <Vector>();
                    var oldIndexToNewIndexMapBlockIn  = new Dictionary <int, int>();
                    var oldIndexToNewIndexMapBlockOut = new Dictionary <int, int>();

                    // Read the block flags
                    uint blockFlags = 0;
                    blockFlags = binaryReader.ReadUInteger();
                    var verticesHaveNormals = false;
                    verticesHaveNormals            = (blockFlags & 1) == 1;
                    blockIn.DoVerticesHaveNormals  = verticesHaveNormals;
                    blockOut.DoVerticesHaveNormals = verticesHaveNormals;

                    uint noOfTriangleVertices = 0;
                    noOfTriangleVertices = binaryReader.ReadUInteger();
                    uint noOfTriangles = 0;
                    noOfTriangles = binaryReader.ReadUInteger();

                    // Read the vertices
                    var x  = default(MM);
                    var y  = default(MM);
                    var z  = default(MM);
                    var nx = default(MM);
                    var ny = default(MM);
                    var nz = default(MM);

                    for (var intNodeNo = 0; intNodeNo <= noOfTriangleVertices - 1; intNodeNo++)
                    {
                        // Read the XYZ values
                        if (pointsAreFloats)
                        {
                            x = binaryReader.ReadSingle();
                            y = binaryReader.ReadSingle();
                            z = binaryReader.ReadSingle();
                        }
                        else
                        {
                            x = binaryReader.ReadDouble();
                            y = binaryReader.ReadDouble();
                            z = binaryReader.ReadDouble();
                        }

                        // Continue reading
                        if (verticesHaveNormals)
                        {
                            if (pointsAreFloats)
                            {
                                nx = binaryReader.ReadSingle();
                                ny = binaryReader.ReadSingle();
                                nz = binaryReader.ReadSingle();
                            }
                            else
                            {
                                nx = binaryReader.ReadDouble();
                                ny = binaryReader.ReadDouble();
                                nz = binaryReader.ReadDouble();
                            }
                        }

                        // Store the vertex
                        vertices.Add(new Point(x, y, z));
                        if (verticesHaveNormals)
                        {
                            vertexNormals.Add(new Vector(nx, ny, nz));
                        }
                    }

                    // What size are the pointers?
                    // They will use 32 bit Unsigned Integers if 16 bit Unsigned Integer is not enough
                    var use32bitPointers = noOfTriangleVertices > ushort.MaxValue;

                    // Read the triangles
                    var vertex1Index = 0;
                    var vertex2Index = 0;
                    var vertex3Index = 0;

                    for (var triangleNo = 0; triangleNo <= noOfTriangles - 1; triangleNo++)
                    {
                        if (use32bitPointers)
                        {
                            vertex1Index = binaryReader.ReadInteger();
                            vertex2Index = binaryReader.ReadInteger();
                            vertex3Index = binaryReader.ReadInteger();
                        }
                        else
                        {
                            vertex1Index = binaryReader.ReadUShort();
                            vertex2Index = binaryReader.ReadUShort();
                            vertex3Index = binaryReader.ReadUShort();
                        }

                        if (filter.CanAddTriangle(vertices[vertex1Index], vertices[vertex2Index], vertices[vertex3Index]))
                        {
                            AddTriangle(oldIndexToNewIndexMapBlockIn,
                                        blockIn,
                                        verticesHaveNormals,
                                        vertices,
                                        vertexNormals,
                                        vertex1Index,
                                        vertex2Index,
                                        vertex3Index);
                        }
                        else
                        {
                            AddTriangle(oldIndexToNewIndexMapBlockOut,
                                        blockOut,
                                        verticesHaveNormals,
                                        vertices,
                                        vertexNormals,
                                        vertex1Index,
                                        vertex2Index,
                                        vertex3Index);
                        }
                    }

                    // Check that the version number is ok
                    if (binaryReader.ReadUShort() != version)
                    {
                        throw new DMTFileException(DMTFileError.BlockVersionDoesNotMatchFileVersion);
                    }

                    blocksIn.Add(blockIn);
                    blocksOut.Add(blockOut);
                }

                var modelWithinFilter  = new DMTModel();
                var modelOutsideFilter = new DMTModel();
                modelWithinFilter.TriangleBlocks.AddRange(blocksIn);
                modelOutsideFilter.TriangleBlocks.AddRange(blocksOut);
                var result = new List <DMTModel>();
                result.Add(modelWithinFilter);
                result.Add(modelOutsideFilter);
                return(result);
            }
            finally
            {
                // Close the binary reader
                if (binaryReader != null)
                {
                    binaryReader.Close();
                }
            }
        }