示例#1
0
        /* From https://github.com/dotnet/corefx/blob/master/src/Common/src/CoreLib/System/IO/BinaryReader.cs
         *
         *  public virtual unsafe float ReadSingle()
         *  {
         *      FillBuffer(4);
         *      uint tmpBuffer = (uint)(_buffer[0] | _buffer[1] << 8 | _buffer[2] << 16 | _buffer[3] << 24);
         *      return *((float*)&tmpBuffer);
         *  }
         *
         * public virtual unsafe double ReadDouble()
         * {
         * FillBuffer(8);
         * uint lo = (uint)(_buffer[0] | _buffer[1] << 8 |
         *                 _buffer[2] << 16 | _buffer[3] << 24);
         * uint hi = (uint)(_buffer[4] | _buffer[5] << 8 |
         *                 _buffer[6] << 16 | _buffer[7] << 24);
         *
         * ulong tmpBuffer = ((ulong)hi) << 32 | lo;
         * return *((double*)&tmpBuffer);
         * }
         *
         * public virtual short ReadInt16()
         *  {
         *      FillBuffer(2);
         *      return (short)(_buffer[0] | _buffer[1] << 8);
         *  }
         *
         *  [CLSCompliant(false)]
         *  public virtual ushort ReadUInt16()
         *  {
         *      FillBuffer(2);
         *      return (ushort)(_buffer[0] | _buffer[1] << 8);
         *  }
         *
         *  public virtual int ReadInt32()
         *  {
         *      if (_isMemoryStream)
         *      {
         *          if (_stream == null)
         *          {
         *              throw Error.GetFileNotOpen();
         *          }
         *
         *          // read directly from MemoryStream buffer
         *          MemoryStream mStream = _stream as MemoryStream;
         *          Debug.Assert(mStream != null, "_stream as MemoryStream != null");
         *
         *          return mStream.InternalReadInt32();
         *      }
         *      else
         *      {
         *          FillBuffer(4);
         *          return (int)(_buffer[0] | _buffer[1] << 8 | _buffer[2] << 16 | _buffer[3] << 24);
         *      }
         *  }
         */

        /* Retain as reference implementation using the standard binary reader IO for comparison with
         * the optimised direct memory access implementation below.
         * /// <summary>
         * /// Reads the set of triangles in the model utilising the given reader
         * /// </summary>
         * /// <param name="reader"></param>
         * /// <param name="header"></param>
         * public void Read(BinaryReader reader, TTMHeader header)
         * {
         * Items = new Triangle[header.NumberOfTriangles];
         * bool readInt16s = header.VertexNumberSize == sizeof(short);
         *
         * void Read(ref Triangle tri)
         * {
         *  if (readInt16s)
         *  {
         *    tri.Vertex0 = reader.ReadInt16() - 1;
         *    tri.Vertex1 = reader.ReadInt16() - 1;
         *    tri.Vertex2 = reader.ReadInt16() - 1;
         *  }
         *  else
         *  {
         *    tri.Vertex0 = reader.ReadInt32() - 1;
         *    tri.Vertex1 = reader.ReadInt32() - 1;
         *    tri.Vertex2 = reader.ReadInt32() - 1;
         *  }
         *
         *  // This loop does not need to be executed since the reader repositions the reading location after each serialise in
         *  //for (int i = 0; i < 3; i++)
         *  //{
         *  //  int NeighbourIndex = Utilities.ReadInteger(reader, header.TriangleNumberSize);
         *  // SetNeighbour(i, (NeighbourIndex < 1 || NeighbourIndex > triangles.Items.Length) ? null : triangles.Items[NeighbourIndex - 1]);
         *  //}
         * }
         *
         * int loopLimit = header.NumberOfTriangles;
         * for (int i = 0; i < loopLimit; i++)
         * {
         *  long RecPos = reader.BaseStream.Position;
         *  Read(ref Items[i]);
         *  reader.BaseStream.Position = RecPos + header.TriangleRecordSize;
         * }
         * }
         */

        /// <summary>
        /// Reads the set of triangles in the model utilising the given reader
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="bufPos"></param>
        /// <param name="header"></param>
        public void Read(byte[] bytes, int bufPos, TTMHeader header)
        {
            Items = new Triangle[header.NumberOfTriangles];
            bool readInt16s = header.VertexNumberSize == sizeof(short);

            int loopLimit = header.NumberOfTriangles;

            for (int i = 0; i < loopLimit; i++)
            {
                if (readInt16s)
                {
                    Items[i].Vertex0 = (bytes[bufPos] | bytes[bufPos + 1] << 8) - 1;
                    Items[i].Vertex1 = (bytes[bufPos + 2] | bytes[bufPos + 3] << 8) - 1;
                    Items[i].Vertex2 = (bytes[bufPos + 4] | bytes[bufPos + 5] << 8) - 1;
                }
                else
                {
                    Items[i].Vertex0 = (bytes[bufPos] | bytes[bufPos + 1] << 8 | bytes[bufPos + 2] << 16 | bytes[bufPos + 3] << 24) - 1;
                    Items[i].Vertex1 = (bytes[bufPos + 4] | bytes[bufPos + 5] << 8 | bytes[bufPos + 6] << 16 | bytes[bufPos + 7] << 24) - 1;
                    Items[i].Vertex2 = (bytes[bufPos + 8] | bytes[bufPos + 9] << 8 | bytes[bufPos + 10] << 16 | bytes[bufPos + 11] << 24) - 1;
                }

                // This loop does not need to be executed since the reader repositions the reading location after each serialise in
                //for (int i = 0; i < 3; i++)
                //{
                //  int NeighbourIndex = Utilities.ReadInteger(reader, header.TriangleNumberSize);
                // SetNeighbour(i, (NeighbourIndex < 1 || NeighbourIndex > triangles.Items.Length) ? null : triangles.Items[NeighbourIndex - 1]);
                //}

                bufPos += header.TriangleRecordSize;
            }
        }
示例#2
0
        /// <summary>
        /// Builds a triangle mesh from the vertices contained in the TIN model. All
        /// triangles are discarded. When using BuildTINMesh, it is sufficient to
        /// populate the vertex list (using AddVertex()) with all the vertices
        /// requiring tinning, then calling BuildTINMesh. All points to be tinned must be
        /// added prior to calling BuilTINMesh. To build TIN surfaces incrementally
        /// use InitialiseInitialTriangles() and IncorporateCoordIntoTriangle() to
        /// construct the TIN mesh.
        /// </summary>
        /// <returns></returns>
        public bool BuildTINMesh()
        {
            Triangle CurrentTri = null;

            double MinElevation = 0, MaxElevation = 0;

            // Clear all existing triangles
            TIN.Triangles.Clear();
            TIN.Triangles.Capacity = TIN.Vertices.Count * 2;

            // Update the physical extents of the TIN model
            TTMHeader LocalHeader = TIN.Header;

            TIN.Vertices.GetLimits(ref LocalHeader.MinimumEasting, ref LocalHeader.MinimumNorthing, ref MinElevation,
                                   ref LocalHeader.MaximumEasting, ref LocalHeader.MaximumNorthing, ref MaxElevation);
            TIN.Header = LocalHeader;

            // Set up the initial state to insert the coordinates into
            MakeMinimumBoundingRectangle(out TriVertex TL, out TriVertex TR, out TriVertex BL, out TriVertex BR);
            CreateInitialTriangles(TL, TR, BL, BR);

            // Make sure all the vertices are numbered correctly, along with the 4 MBR vertices
            TIN.Vertices.NumberVertices();

            // Subtract the origin from the vertices to preserve numeric precision
            for (int I = 0; I < TIN.Vertices.Count; I++)
            {
                TIN.Vertices[I].X -= TIN.Header.MinimumEasting;
                TIN.Vertices[I].Y -= TIN.Header.MinimumNorthing;
            }

            // Iterate through all the vertices adding them to the surface
            DateTime StartTime = DateTime.UtcNow;

            surfaceWalkOverflowCount = 0;

            // Don't read the 4 vertices we added for the bounding rectangle tris
            int MaxRealVertex = TIN.Vertices.Count - 1 - 4;

            for (int I = 0; I < MaxRealVertex; I++)
            {
                if (!IncorporateCoord(TIN.Vertices[I], ref CurrentTri))
                {
                    return(false);
                }
            }

            DateTime FinishTime = DateTime.UtcNow;

            Log.LogInformation($"Coordinate incorporation took {FinishTime - StartTime} to process {TIN.Vertices.Count} vertices into {TIN.Triangles.Count} triangles " +
                               $"at a rate of {TIN.Vertices.Count / ((FinishTime - StartTime).TotalSeconds)} vertices/sec, encountering {surfaceWalkOverflowCount} surface walk overflows");

            // Add the origin back to the vertex positions to re-translate than back to their correct positions
            for (int I = 0; I < TIN.Vertices.Count; I++)
            {
                TIN.Vertices[I].X += TIN.Header.MinimumEasting;
                TIN.Vertices[I].Y += TIN.Header.MinimumNorthing;
            }

            RemoveCornerTriangles(MaxRealVertex + 1);
            return(true);
        }