private static void AddTriangle(
            Dictionary <Point, int> mapPointVertexIndex,
            DMTTriangleBlock block,
            Point objPoint1,
            Point objPoint2,
            Point objPoint3)
        {
            int point1Index;
            int point2Index;
            int point3Index;

            if (!mapPointVertexIndex.TryGetValue(objPoint1, out point1Index))
            {
                point1Index = mapPointVertexIndex.Count;
                mapPointVertexIndex.Add(objPoint1, point1Index);
                block.AddVertex(objPoint1);
            }

            if (!mapPointVertexIndex.TryGetValue(objPoint2, out point2Index))
            {
                point2Index = mapPointVertexIndex.Count;
                mapPointVertexIndex.Add(objPoint2, point2Index);
                block.AddVertex(objPoint2);
            }

            if (!mapPointVertexIndex.TryGetValue(objPoint3, out point3Index))
            {
                point3Index = mapPointVertexIndex.Count;
                mapPointVertexIndex.Add(objPoint3, point3Index);
                block.AddVertex(objPoint3);
            }

            block.AddTriangle(point1Index, point2Index, point3Index);
        }
示例#2
0
        private static void AddTriangle(
            Dictionary <int, int> oldIndexToNewIndexMap,
            DMTTriangleBlock block,
            bool verticesHaveNormals,
            List <Point> vertices,
            List <Vector> vertexNormals,
            int vertex1Index,
            int vertex2Index,
            int vertex3Index)
        {
            if (oldIndexToNewIndexMap.ContainsKey(vertex1Index))
            {
                block.TriangleFirstVertexIndices.Add(oldIndexToNewIndexMap[vertex1Index]);
            }
            else
            {
                block.TriangleVertices.Add(vertices[vertex1Index]);
                block.TriangleFirstVertexIndices.Add(block.TriangleVertices.Count - 1);
                oldIndexToNewIndexMap.Add(vertex1Index, block.TriangleVertices.Count - 1);

                if (verticesHaveNormals)
                {
                    block.VertexNormals.Add(vertexNormals[vertex1Index]);
                }
            }

            if (oldIndexToNewIndexMap.ContainsKey(vertex2Index))
            {
                block.TriangleSecondVertexIndices.Add(oldIndexToNewIndexMap[vertex2Index]);
            }
            else
            {
                block.TriangleVertices.Add(vertices[vertex2Index]);
                block.TriangleSecondVertexIndices.Add(block.TriangleVertices.Count - 1);
                oldIndexToNewIndexMap.Add(vertex2Index, block.TriangleVertices.Count - 1);

                if (verticesHaveNormals)
                {
                    block.VertexNormals.Add(vertexNormals[vertex2Index]);
                }
            }

            if (oldIndexToNewIndexMap.ContainsKey(vertex3Index))
            {
                block.TriangleThirdVertexIndices.Add(oldIndexToNewIndexMap[vertex3Index]);
            }
            else
            {
                block.TriangleVertices.Add(vertices[vertex3Index]);
                block.TriangleThirdVertexIndices.Add(block.TriangleVertices.Count - 1);
                oldIndexToNewIndexMap.Add(vertex3Index, block.TriangleVertices.Count - 1);

                if (verticesHaveNormals)
                {
                    block.VertexNormals.Add(vertexNormals[vertex3Index]);
                }
            }
        }
        /// <summary>
        /// Returns a clone of this block.
        /// </summary>
        public DMTTriangleBlock Clone()
        {
            DMTTriangleBlock cloneBlock = new DMTTriangleBlock();

            cloneBlock.DoVerticesHaveNormals = DoVerticesHaveNormals;

            // Clone triangles
            cloneBlock.TriangleFirstVertexIndices.AddRange(_triangleFirstVertexIndices);
            cloneBlock.TriangleSecondVertexIndices.AddRange(_triangleSecondVertexIndices);
            cloneBlock.TriangleThirdVertexIndices.AddRange(_triangleThirdVertexIndices);

            // Clone vertices
            foreach (Point vertex in _triangleVertices)
            {
                cloneBlock.TriangleVertices.Add(vertex.Clone());
            }

            return(cloneBlock);
        }
示例#4
0
        /// <summary>
        /// This operation extracts a boundary from the list of edges
        /// </summary>
        /// <param name="edges">The list of edges.  As edges are used they are removed from this list</param>
        /// <param name="block">The block from which to extract the eges</param>
        /// <returns>A polyline representing a boundary</returns>
        private Polyline NextBoundary(ref List <Edge> edges, DMTTriangleBlock block)
        {
            // Initialise the next boundary
            Polyline boundary = new Polyline();

            // Return if the list is empty
            if (edges.Count == 0)
            {
                return(null);
            }

            // Get the first edge
            Edge firstEdge = edges[0];

            // And remove it from the list
            edges.Remove(firstEdge);

            // Now get the first vertex and the next vertex
            Point firstVertex = block.TriangleVertices[firstEdge.Point1Index];

            boundary.Add(firstVertex);
            int nextNode = firstEdge.Point2Index;

            boundary.Add(block.TriangleVertices[firstEdge.Point2Index]);

            // foundNextEdge will handle cases where the boundary is open
            bool foundNextEdge = true;

            // Loop until we hit the firstNode again or run out of boundary
            while ((firstVertex != nextNode) & foundNextEdge)
            {
                foundNextEdge = false;
                Edge egdeToRemove = null;

                // Find the vertex that nextNode is attached to
                foreach (Edge edge in edges)
                {
                    // See if the edge contains the next vertex
                    if (edge.Point1Index == nextNode)
                    {
                        nextNode = edge.Point2Index;
                    }
                    else if (edge.Point2Index == nextNode)
                    {
                        nextNode = edge.Point1Index;
                    }
                    else
                    {
                        // No so look at the next edge
                        continue;
                    }

                    // Add the next vertex
                    boundary.Add(block.TriangleVertices[nextNode]);
                    egdeToRemove  = edge;
                    foundNextEdge = true;
                    break;
                }

                // Remove the last edge
                if (egdeToRemove != null)
                {
                    edges.Remove(egdeToRemove);
                }
            }

            // Return the boundary
            return(boundary);
        }
示例#5
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);
        }
示例#6
0
 /// <summary>
 /// Adds a new Block to the list of blocks
 /// </summary>
 /// <param name="block">Block to be added.</param>
 public void AddTriangleBlock(DMTTriangleBlock block)
 {
     _blocks.Add(block);
 }
        /// <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();
            }
        }
 /// <summary>
 /// Returns a vector normal to the surface of the triangle.
 /// </summary>
 /// <param name="block">Block containing this triangle is part of.</param>
 public Vector GetNormal(DMTTriangleBlock block)
 {
     return(GetNormal(block.GetVertex(_vertex1), block.GetVertex(_vertex2), block.GetVertex(_vertex3)));
 }
示例#10
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();
                }
            }
        }