//----------------------------------------------------------------------------- public void WritePoints <T>(T[] prmPoints, Int64 prmNoOfPoints = -1) where T : TiLasPoint { Int32 count = prmNoOfPoints < 0 ? prmPoints.Length : (Int32)prmNoOfPoints; Int32 pointSize = Marshal.SizeOf(typeof(TsXYZLasPoint)); Int32 totalSize = pointSize * count; // Allocates memory and totalPtr points to the 1st location. IntPtr totalPtr = Marshal.AllocHGlobal(totalSize); IntPtr structPtr; // Classification point. TsXYZLasPoint clsPoint; // This is used to increment the location of the pointer later. It cant be done with IntPtr. // ptrLoc points to the 1st location of totalPtr. Int64 ptrLoc = totalPtr.ToInt64(); for (int i = 0; i < count; i++) { // Creating the classification point from the las point. clsPoint = new TsXYZLasPoint() { X = prmPoints[i].X, Y = prmPoints[i].Y, Z = prmPoints[i].Z }; // structPtr points to ptrLoc. structPtr = new IntPtr(ptrLoc); // Converts the structure into memory pointed by structPtr Marshal.StructureToPtr(clsPoint, structPtr, false); // Move the pointer. ptrLoc += pointSize; } byte[] buffer = new byte[totalSize]; // Copies the data from totalPtr memory to arr array. Marshal.Copy(totalPtr, buffer, 0, totalSize); // Free the memory from the heap. Marshal.FreeHGlobal(totalPtr); // Write the array. m_ClsWriter.Write(buffer); }
//----------------------------------------------------------------------------- /// <summary> /// This function reads a given number of points from the current location of the reader. /// If enough points not found in the file, it returns the available points. /// </summary> /// <typeparam name="T">Type of the las point</typeparam> /// <param name="prmNoOfPoints">Number of points to read</param> /// <returns>An array of LAS points</returns> public TsXYZLasPoint[] ReadPoints(Int64 prmNoOfPoints) { // Points loaded from file. Int64 noOfPointsLoaded = 0; // Points need to be loaded. Int64 noOfPointsToRead = 0; // No of bytes to read from the file. Int32 bytesToRead = 0; // Memory stream. Byte[] readBuffer; Int64 noOfPointsAvailable = (Int64)((m_Reader.BaseStream.Length - m_Reader.BaseStream.Position) / c_PointSize); prmNoOfPoints = Math.Min(prmNoOfPoints, noOfPointsAvailable); // Create a las point array of required size. TsXYZLasPoint[] returnBlocks = new TsXYZLasPoint[prmNoOfPoints]; // Set a handle to the las point array. GCHandle pinnedHandle = GCHandle.Alloc(returnBlocks, GCHandleType.Pinned); // Pointer to the current pointed object. IntPtr blockPtr = pinnedHandle.AddrOfPinnedObject(); // Value of the pointer. Int64 ptrLoc = blockPtr.ToInt64(); try { while (noOfPointsLoaded < prmNoOfPoints) { noOfPointsToRead = Math.Min(TcConstants.MaxLasPointsToProcessAtOnce, prmNoOfPoints - noOfPointsLoaded); // Read required bytes from the file. bytesToRead = c_PointSize * (Int32)noOfPointsToRead; readBuffer = m_Reader.ReadBytes(bytesToRead); // Copy the stream to the structures. Marshal.Copy(readBuffer, 0, blockPtr, bytesToRead); // Update the processed item counter. noOfPointsLoaded += noOfPointsToRead; // Update the pointer value. ptrLoc += bytesToRead; // Move the pointer. blockPtr = new IntPtr(ptrLoc); } return(returnBlocks); } finally { if (pinnedHandle.IsAllocated) { pinnedHandle.Free(); } readBuffer = new Byte[0]; } }