//------------------------------------------------------------------ /// <summary> /// Function to write LAS points into file with considering custom options. /// N.B. Use 'WritePoints' if you don't care about customization for faster processing. /// </summary> /// <typeparam name="T">Point type</typeparam> /// <param name="prmInputLas">The input LAS file</param> public void WriteLasWithOptions <T>(String prmInputLas, int nr) where T : TiLasPoint { using (TcLasReader reader = new TcLasReader(prmInputLas)) { TsLasPoint1[] points; Int64 pointsToProcess; Int64 pointsProcessed = 0; Int64 noOfPoints = reader.Header.GetNumberOfPoints(); TiLasHeader header = GetDuplicateEmptyHeader(reader.Header); // Write header and the offset bytes. WriteHeader(header, reader.OffsetBytes); while (pointsProcessed < noOfPoints) { pointsToProcess = Math.Min(TcConstants.MaxLasPointsToProcessAtOnce, noOfPoints - pointsProcessed); points = reader.ReadPoints <TsLasPoint1>(pointsToProcess); for (int i = 0; i < points.Length; i++) { points[i].PointSourceID = (ushort)nr; } WritePointsWithOptions <TsLasPoint1>(points, ref header); pointsProcessed += pointsToProcess; } WriteHeader(header); } }
//----------------------------------------------------------------------------- public TcLasPointBase[] GetPointObjectsByTile <T>(Int32 prmIndex, TiLasHeader prmHeader) where T : TiLasPoint { Int32 col = prmIndex % m_TileInfo.TileInfo.Col; Int32 row = (prmIndex - col) / m_TileInfo.TileInfo.Col; return(GetPointObjectsByTile <T>(row, col, prmHeader)); }
//----------------------------------------------------------------------------- /// <summary> /// Calculates the size of the canvas and determine the number of required tiles. /// It then creates polygons (rectangle) for each area considering the given offset. /// </summary> /// <param name="prmFiles">List of LAS files to be processed</param> private void UpdateCommonHeader(IEnumerable <String> prmFiles) { m_AreaHeader = GetDefaultLasHeader(); foreach (String lasFile in prmFiles) { using (TcLasReader lasReader = new TcLasReader(lasFile)) { m_AreaHeader.MinX = Math.Min(m_AreaHeader.MinX, lasReader.Header.MinX); m_AreaHeader.MinY = Math.Min(m_AreaHeader.MinY, lasReader.Header.MinY); m_AreaHeader.MinZ = Math.Min(m_AreaHeader.MinZ, lasReader.Header.MinZ); m_AreaHeader.MaxX = Math.Max(m_AreaHeader.MaxX, lasReader.Header.MaxX); m_AreaHeader.MaxY = Math.Max(m_AreaHeader.MaxY, lasReader.Header.MaxY); m_AreaHeader.MaxZ = Math.Max(m_AreaHeader.MaxZ, lasReader.Header.MaxZ); m_AreaHeader.XOffset = Math.Min(m_AreaHeader.XOffset, lasReader.Header.XOffset); m_AreaHeader.YOffset = Math.Min(m_AreaHeader.YOffset, lasReader.Header.YOffset); m_AreaHeader.ZOffset = Math.Min(m_AreaHeader.ZOffset, lasReader.Header.ZOffset); m_AreaHeader.XScaleFactor = Math.Min(m_AreaHeader.XScaleFactor, lasReader.Header.XScaleFactor); m_AreaHeader.YScaleFactor = Math.Min(m_AreaHeader.YScaleFactor, lasReader.Header.YScaleFactor); m_AreaHeader.ZScaleFactor = Math.Min(m_AreaHeader.ZScaleFactor, lasReader.Header.ZScaleFactor); m_TileInfos[lasFile] = new TcIndexedLasInfo(lasFile) { Header = lasReader.Header }; } } }
//----------------------------------------------------------------------------- protected void WriteHeaderToFile(TiLasHeader prmHeader) { if (!m_Writer.BaseStream.CanWrite) { throw new IOException("Cannot write the header into the LAS file"); } // Allocate global memory of a size of header + extra = offset. IntPtr ptr = Marshal.AllocHGlobal((Int32)prmHeader.HeaderSize); try { m_Writer.BaseStream.Position = 0; Byte[] arr = new Byte[prmHeader.HeaderSize]; // Convert the header to the pointer. Marshal.StructureToPtr(prmHeader, ptr, true); // Copy the data. Marshal.Copy(ptr, arr, 0, (Int32)prmHeader.HeaderSize); m_Writer.Write(arr); } finally { Marshal.FreeHGlobal(ptr); } }
//----------------------------------------------------------------------------- private TiLasHeader GetHeaderForMergedLas(TiLasHeader prmHeader, Int64 prmAddedPoints) { if (prmHeader.HeaderSize == Marshal.SizeOf(typeof(TsLasHeader12))) { TsLasHeader12 header = (TsLasHeader12)prmHeader; header.NumberOfPointRecords += (UInt32)prmAddedPoints; header.NumberofPointsByReturn1 += (UInt32)prmAddedPoints; return(header); } else if (prmHeader.HeaderSize == Marshal.SizeOf(typeof(TsLasHeader13))) { TsLasHeader13 header = (TsLasHeader13)prmHeader; header.NumberOfPointRecords += (UInt32)prmAddedPoints; header.NumberofPointsByReturn1 += (UInt32)prmAddedPoints; return(header); } else if (prmHeader.HeaderSize == Marshal.SizeOf(typeof(TsLasHeader14))) { TsLasHeader14 header = (TsLasHeader14)prmHeader; header.LegNumberOfPointRecords += (UInt32)prmAddedPoints; header.LegNumberofPointsByReturn1 += (UInt32)prmAddedPoints; header.NumberOfPointRecords += (UInt64)prmAddedPoints; header.NumberofPointsByReturn1 += (UInt64)prmAddedPoints; return(header); } throw new InvalidDataException("Header size is wrong"); }
//----------------------------------------------------------------------------- /// <summary> /// Internal function to produce a single grid file. /// </summary> /// <param name="prmInput">Input las file</param> /// <param name="prmObjects">Grid objects to keep the information together</param> private void Grid(String prmInput, IEnumerable <TcGridObject> prmObjects) { using (TcTileLasReader reader = new TcTileLasReader(prmInput, m_Info)) { m_LasHeader = reader.Header; switch (reader.Header.PointDataFormatID) { case 0: Grid <TsLasPoint0>(reader, prmObjects); break; case 1: Grid <TsLasPoint1>(reader, prmObjects); break; case 2: Grid <TsLasPoint2>(reader, prmObjects); break; case 3: Grid <TsLasPoint3>(reader, prmObjects); break; case 4: Grid <TsLasPoint4>(reader, prmObjects); break; case 5: Grid <TsLasPoint5>(reader, prmObjects); break; case 6: Grid <TsLasPoint6>(reader, prmObjects); break; case 7: Grid <TsLasPoint7>(reader, prmObjects); break; case 8: Grid <TsLasPoint8>(reader, prmObjects); break; case 9: Grid <TsLasPoint9>(reader, prmObjects); break; case 10: Grid <TsLasPoint10>(reader, prmObjects); break; default: throw new FormatException("Couldn't process the tile. LAS format not supported"); } } }
public TcClsXYZWriter(TiLasHeader prmLasHeader, String prmOutputClsFile) { if (!Directory.Exists(Path.GetDirectoryName(prmOutputClsFile))) { throw new FileNotFoundException("Output directory not found"); } m_LasHeader = prmLasHeader; m_ClsWriter = new BinaryWriter(new FileStream(prmOutputClsFile, FileMode.Create)); }
//----------------------------------------------------------------------------- private TiLasHeader GetHeaderForCls(TiLasHeader prmHeader, Int64 prmNewNumberOfPoints) { if (prmHeader.HeaderSize == Marshal.SizeOf(typeof(TsLasHeader12))) { TsLasHeader12 header = (TsLasHeader12)prmHeader; header.NumberOfPointRecords = (UInt32)prmNewNumberOfPoints; header.NumberofPointsByReturn1 = header.NumberOfPointRecords; header.NumberofPointsByReturn2 = 0; header.NumberofPointsByReturn3 = 0; header.NumberofPointsByReturn4 = 0; header.NumberofPointsByReturn5 = 0; return(header); } else if (prmHeader.HeaderSize == Marshal.SizeOf(typeof(TsLasHeader13))) { TsLasHeader13 header = (TsLasHeader13)prmHeader; header.NumberOfPointRecords = (UInt32)prmNewNumberOfPoints; header.NumberofPointsByReturn1 = header.NumberOfPointRecords; header.NumberofPointsByReturn2 = 0; header.NumberofPointsByReturn3 = 0; header.NumberofPointsByReturn4 = 0; header.NumberofPointsByReturn5 = 0; return(header); } else if (prmHeader.HeaderSize == Marshal.SizeOf(typeof(TsLasHeader14))) { TsLasHeader14 header = (TsLasHeader14)prmHeader; header.LegNumberOfPointRecords = (UInt32)prmNewNumberOfPoints; header.LegNumberofPointsByReturn1 = header.LegNumberOfPointRecords; header.LegNumberofPointsByReturn2 = 0; header.LegNumberofPointsByReturn3 = 0; header.LegNumberofPointsByReturn4 = 0; header.LegNumberofPointsByReturn5 = 0; header.NumberOfPointRecords = (UInt64)prmNewNumberOfPoints; header.NumberofPointsByReturn1 = header.NumberOfPointRecords; header.NumberofPointsByReturn2 = 0; header.NumberofPointsByReturn3 = 0; header.NumberofPointsByReturn4 = 0; header.NumberofPointsByReturn5 = 0; header.NumberofPointsByReturn6 = 0; header.NumberofPointsByReturn7 = 0; header.NumberofPointsByReturn8 = 0; header.NumberofPointsByReturn9 = 0; header.NumberofPointsByReturn10 = 0; header.NumberofPointsByReturn11 = 0; header.NumberofPointsByReturn12 = 0; header.NumberofPointsByReturn13 = 0; header.NumberofPointsByReturn14 = 0; header.NumberofPointsByReturn15 = 0; return(header); } throw new InvalidDataException("Header size is wrong"); }
/// <summary> /// Write the LAS points with adjusted X, Y and Z based on a common header. /// </summary> /// <typeparam name="T">Type of the LAS ponts</typeparam> /// <param name="prmPoints">LAS points</param> /// <param name="prmHeader">Actual header for these points</param> /// <param name="prmCommonHeader">Common header for a whole area</param> /// <param name="prmNoOfPoints">Total number of points to write from the array</param> public void WriteModifiedPoints <T>(T[] prmPoints, TiLasHeader prmHeader, TiLasHeader prmCommonHeader, Int64 prmNoOfPoints) where T : TiLasPoint { for (int i = 0; i < prmNoOfPoints; i++) { prmPoints[i].X = (Int32)(((prmHeader.XOffset + prmPoints[i].X * prmHeader.XScaleFactor) - prmCommonHeader.XOffset) / prmCommonHeader.XScaleFactor); prmPoints[i].Y = (Int32)(((prmHeader.YOffset + prmPoints[i].Y * prmHeader.YScaleFactor) - prmCommonHeader.YOffset) / prmCommonHeader.YScaleFactor); prmPoints[i].Z = (Int32)(((prmHeader.ZOffset + prmPoints[i].Z * prmHeader.ZScaleFactor) - prmCommonHeader.ZOffset) / prmCommonHeader.ZScaleFactor); } base.WritePoints <T>(prmPoints, prmNoOfPoints); }
//----------------------------------------------------------------------------- #warning Vicky: It can be removed if it didn't affect other projects. private void UpdateTileCounts(ref TiLasHeader prmHeader, Int32 prmSize) { prmHeader.MinX = (prmHeader.MinX + XAdjustment) - ((prmHeader.MinX + XAdjustment) % (prmSize * Factor)); prmHeader.MinY = (prmHeader.MinY + YAdjustment) - ((prmHeader.MinY + YAdjustment) % (prmSize * Factor)); prmHeader.MaxX = (prmHeader.MaxX + XAdjustment) - ((prmHeader.MaxX + XAdjustment) % (prmSize * Factor)) + (prmSize * Factor); prmHeader.MaxY = (prmHeader.MaxY + YAdjustment) - ((prmHeader.MaxY + YAdjustment) % (prmSize * Factor)) + (prmSize * Factor); m_RevisedEast = (Int32)prmHeader.MinX; m_RevisedNorth = (Int32)prmHeader.MaxY; m_TileColumns = (Int32)(prmHeader.MaxX - prmHeader.MinX) / (prmSize * Factor); m_TileRows = (Int32)(prmHeader.MaxY - prmHeader.MinY) / (prmSize * Factor); m_TileBlockInfoCollection = new TcTileBlockInfoCollection(prmSize, m_TileRows, m_TileColumns); }
public TcClsXYZReader(String prmInput) { if (!File.Exists(prmInput)) { throw new FileNotFoundException(String.Format("Las file not found : {0}", prmInput)); } m_Input = prmInput; c_PointSize = Marshal.SizeOf(typeof(TsXYZLasPoint)); m_Reader = new BinaryReader(new FileStream(m_Input, FileMode.Open)); m_Header = GetHeader(); m_OffsetBytes = GetOffsetBytes(); m_TotalPoints = (Int64)((m_Reader.BaseStream.Length - m_Header.PointOffset) / c_PointSize); }
//----------------------------------------------------------------------------- public void WriteHeader(TiLasHeader prmHeader, Byte[] prmOffsetBytes) { // Write the actual header. WriteHeaderToFile(prmHeader); // Write the offset bits. Int64 offsetBytesLength = (Int64)Math.Min(prmHeader.PointOffset - prmHeader.HeaderSize, prmOffsetBytes.Length); if (offsetBytesLength > 0) { m_Writer.BaseStream.Seek(prmHeader.HeaderSize, SeekOrigin.Begin); m_Writer.Write(prmOffsetBytes); } }
//----------------------------------------------------------------------------- protected Int64 GetNumberOfPoints(TiLasHeader prmHeader) { if (prmHeader is TsLasHeader12) { return(((TsLasHeader12)prmHeader).NumberOfPointRecords); } if (prmHeader is TsLasHeader13) { return(((TsLasHeader13)prmHeader).NumberOfPointRecords); } if (prmHeader is TsLasHeader14) { return((Int64)((TsLasHeader14)prmHeader).NumberOfPointRecords); } throw new FormatException("Couldn't process the tile. LAS format not supported"); }
public TcLasReader(String prmInput) { if (!File.Exists(prmInput)) { throw new FileNotFoundException(String.Format("Las file not found : {0}", prmInput)); } if (!prmInput.EndsWith(".las", StringComparison.CurrentCultureIgnoreCase)) { throw new FileNotFoundException(String.Format("Invalid LAS file : {0}", prmInput)); } m_Input = prmInput; m_Reader = new BinaryReader(new FileStream(m_Input, FileMode.Open)); m_Header = GetHeader(); m_OffsetBytes = GetOffsetBytes(); m_TotalPoints = (Int64)((m_Reader.BaseStream.Length - m_Header.PointOffset) / m_Header.PointDataRecordLength); }
private TiLasHeader UpdateTileCounts <T>(TiLasHeader prmTileHeader, Int32 prmSize) where T : TiLasPoint { if (prmTileHeader is TsLasHeader12) { TsLasHeader12 tileHeader = (TsLasHeader12)prmTileHeader; tileHeader.MinX = (tileHeader.MinX + XAdjustment) - ((tileHeader.MinX + XAdjustment) % (prmSize * Factor)); tileHeader.MinY = (tileHeader.MinY + YAdjustment) - ((tileHeader.MinY + YAdjustment) % (prmSize * Factor)); tileHeader.MaxX = (tileHeader.MaxX + XAdjustment) - ((tileHeader.MaxX + XAdjustment) % (prmSize * Factor)) + (prmSize * Factor); tileHeader.MaxY = (tileHeader.MaxY + YAdjustment) - ((tileHeader.MaxY + YAdjustment) % (prmSize * Factor)) + (prmSize * Factor); tileHeader.NumberOfPointRecords = 0; tileHeader.NumberofPointsByReturn1 = 0; tileHeader.NumberofPointsByReturn2 = 0; tileHeader.NumberofPointsByReturn3 = 0; tileHeader.NumberofPointsByReturn4 = 0; tileHeader.NumberofPointsByReturn5 = 0; m_RevisedEast = (Int32)tileHeader.MinX; m_RevisedNorth = (Int32)tileHeader.MaxY; m_TileColumns = (Int32)(tileHeader.MaxX - tileHeader.MinX) / (prmSize * Factor); m_TileRows = (Int32)(tileHeader.MaxY - tileHeader.MinY) / (prmSize * Factor); m_TileBlockInfoCollection = new TcTileBlockInfoCollection(prmSize, m_TileRows, m_TileColumns); return(tileHeader); } else if (prmTileHeader is TsLasHeader13) { TsLasHeader13 tileHeader = (TsLasHeader13)prmTileHeader; tileHeader.MinX = (tileHeader.MinX + XAdjustment) - ((tileHeader.MinX + XAdjustment) % (prmSize * Factor)); tileHeader.MinY = (tileHeader.MinY + YAdjustment) - ((tileHeader.MinY + YAdjustment) % (prmSize * Factor)); tileHeader.MaxX = (tileHeader.MaxX + XAdjustment) - ((tileHeader.MaxX + XAdjustment) % (prmSize * Factor)) + (prmSize * Factor); tileHeader.MaxY = (tileHeader.MaxY + YAdjustment) - ((tileHeader.MaxY + YAdjustment) % (prmSize * Factor)) + (prmSize * Factor); tileHeader.NumberOfPointRecords = 0; tileHeader.NumberofPointsByReturn1 = 0; tileHeader.NumberofPointsByReturn2 = 0; tileHeader.NumberofPointsByReturn3 = 0; tileHeader.NumberofPointsByReturn4 = 0; tileHeader.NumberofPointsByReturn5 = 0; m_RevisedEast = (Int32)tileHeader.MinX; m_RevisedNorth = (Int32)tileHeader.MaxY; m_TileColumns = (Int32)(tileHeader.MaxX - tileHeader.MinX) / (prmSize * Factor); m_TileRows = (Int32)(tileHeader.MaxY - tileHeader.MinY) / (prmSize * Factor); m_TileBlockInfoCollection = new TcTileBlockInfoCollection(prmSize, m_TileRows, m_TileColumns); return(tileHeader); } else if (prmTileHeader is TsLasHeader14) { TsLasHeader14 tileHeader = (TsLasHeader14)prmTileHeader; tileHeader.MinX = (tileHeader.MinX + XAdjustment) - ((tileHeader.MinX + XAdjustment) % (prmSize * Factor)); tileHeader.MinY = (tileHeader.MinY + YAdjustment) - ((tileHeader.MinY + YAdjustment) % (prmSize * Factor)); tileHeader.MaxX = (tileHeader.MaxX + XAdjustment) - ((tileHeader.MaxX + XAdjustment) % (prmSize * Factor)) + (prmSize * Factor); tileHeader.MaxY = (tileHeader.MaxY + YAdjustment) - ((tileHeader.MaxY + YAdjustment) % (prmSize * Factor)) + (prmSize * Factor); tileHeader.NumberOfPointRecords = 0; tileHeader.NumberofPointsByReturn1 = 0; tileHeader.NumberofPointsByReturn2 = 0; tileHeader.NumberofPointsByReturn3 = 0; tileHeader.NumberofPointsByReturn4 = 0; tileHeader.NumberofPointsByReturn5 = 0; tileHeader.NumberofPointsByReturn6 = 0; tileHeader.NumberofPointsByReturn7 = 0; tileHeader.NumberofPointsByReturn8 = 0; tileHeader.NumberofPointsByReturn9 = 0; tileHeader.NumberofPointsByReturn10 = 0; tileHeader.NumberofPointsByReturn11 = 0; tileHeader.NumberofPointsByReturn12 = 0; tileHeader.NumberofPointsByReturn13 = 0; tileHeader.NumberofPointsByReturn14 = 0; tileHeader.NumberofPointsByReturn15 = 0; tileHeader.LegNumberofPointsByReturn1 = 0; tileHeader.LegNumberofPointsByReturn2 = 0; tileHeader.LegNumberofPointsByReturn3 = 0; tileHeader.LegNumberofPointsByReturn4 = 0; tileHeader.LegNumberofPointsByReturn5 = 0; m_RevisedEast = (Int32)tileHeader.MinX; m_RevisedNorth = (Int32)tileHeader.MaxY; m_TileColumns = (Int32)(tileHeader.MaxX - tileHeader.MinX) / (prmSize * Factor); m_TileRows = (Int32)(tileHeader.MaxY - tileHeader.MinY) / (prmSize * Factor); m_TileBlockInfoCollection = new TcTileBlockInfoCollection(prmSize, m_TileRows, m_TileColumns); return(tileHeader); } throw new InvalidDataException("Couldn't update the Tile Header. Invalid data format."); }
//----------------------------------------------------------------------------- /// <summary> /// Adjusts the LAS points for the tile and update the tile header. It takes the las file header for the block /// of points and the modified header for this specific tile. It then update the points by taking the common LAS /// header for the full area as reference. It also updates the tile header from the computed values of the points. /// </summary> /// <typeparam name="T">Type of the las point</typeparam> /// <param name="prmHeader">LAS header to update</param> /// <param name="X">X coordinate</param> /// <param name="Y">Y coordinate</param> /// <param name="Z">Z coordinate</param> /// <param name="prmReturnNo">The return number from the laser shot</param> /// <returns>The header as an interface to converted to the specific header structure.</returns> protected TiLasHeader UpdateHeader <T>(TiLasHeader prmTileHeader, Double X, Double Y, Double Z, Byte prmReturnNo) where T : TiLasPoint { if (prmTileHeader is TsLasHeader12) { TsLasHeader12 tileHeader = (TsLasHeader12)prmTileHeader; tileHeader.MinX = Math.Min(tileHeader.MinX, X); tileHeader.MinY = Math.Min(tileHeader.MinY, Y); tileHeader.MinZ = Math.Min(tileHeader.MinZ, Z); tileHeader.MaxX = Math.Max(tileHeader.MaxX, X); tileHeader.MaxY = Math.Max(tileHeader.MaxY, Y); tileHeader.MaxZ = Math.Max(tileHeader.MaxZ, Z); tileHeader.NumberOfPointRecords++; switch (prmReturnNo) { case 1: tileHeader.NumberofPointsByReturn1++; break; case 2: tileHeader.NumberofPointsByReturn2++; break; case 3: tileHeader.NumberofPointsByReturn3++; break; case 4: tileHeader.NumberofPointsByReturn4++; break; case 5: tileHeader.NumberofPointsByReturn5++; break; } return(tileHeader); } else if (prmTileHeader is TsLasHeader13) { TsLasHeader13 tileHeader = (TsLasHeader13)prmTileHeader; tileHeader.MinX = Math.Min(tileHeader.MinX, X); tileHeader.MinY = Math.Min(tileHeader.MinY, Y); tileHeader.MinZ = Math.Min(tileHeader.MinZ, Z); tileHeader.MaxX = Math.Max(tileHeader.MaxX, X); tileHeader.MaxY = Math.Max(tileHeader.MaxY, Y); tileHeader.MaxZ = Math.Max(tileHeader.MaxZ, Z); tileHeader.NumberOfPointRecords++; switch (prmReturnNo) { case 1: tileHeader.NumberofPointsByReturn1++; break; case 2: tileHeader.NumberofPointsByReturn2++; break; case 3: tileHeader.NumberofPointsByReturn3++; break; case 4: tileHeader.NumberofPointsByReturn4++; break; case 5: tileHeader.NumberofPointsByReturn5++; break; } return(tileHeader); } else if (prmTileHeader is TsLasHeader14) { TsLasHeader14 tileHeader = (TsLasHeader14)prmTileHeader; tileHeader.MinX = Math.Min(tileHeader.MinX, X); tileHeader.MinY = Math.Min(tileHeader.MinY, Y); tileHeader.MinZ = Math.Min(tileHeader.MinZ, Z); tileHeader.MaxX = Math.Max(tileHeader.MaxX, X); tileHeader.MaxY = Math.Max(tileHeader.MaxY, Y); tileHeader.MaxZ = Math.Max(tileHeader.MaxZ, Z); tileHeader.NumberOfPointRecords++; tileHeader.LegNumberOfPointRecords++; switch (prmReturnNo) { case 1: tileHeader.NumberofPointsByReturn1++; tileHeader.LegNumberofPointsByReturn1++; break; case 2: tileHeader.NumberofPointsByReturn2++; tileHeader.LegNumberofPointsByReturn2++; break; case 3: tileHeader.NumberofPointsByReturn3++; tileHeader.LegNumberofPointsByReturn3++; break; case 4: tileHeader.NumberofPointsByReturn4++; tileHeader.LegNumberofPointsByReturn4++; break; case 5: tileHeader.NumberofPointsByReturn5++; tileHeader.LegNumberofPointsByReturn5++; break; case 6: tileHeader.NumberofPointsByReturn6++; break; case 7: tileHeader.NumberofPointsByReturn7++; break; case 8: tileHeader.NumberofPointsByReturn8++; break; case 9: tileHeader.NumberofPointsByReturn9++; break; case 10: tileHeader.NumberofPointsByReturn10++; break; case 11: tileHeader.NumberofPointsByReturn11++; break; case 12: tileHeader.NumberofPointsByReturn12++; break; case 13: tileHeader.NumberofPointsByReturn13++; break; case 14: tileHeader.NumberofPointsByReturn14++; break; case 15: tileHeader.NumberofPointsByReturn15++; break; } return(tileHeader); } throw new InvalidDataException("Couldn't update the header. Invalid data format."); }
//----------------------------------------------------------------------------- /// <summary> /// Adjusts the LAS points for the tile and update the tile header. It takes the las file header for the block /// of points and the modified header for this specific tile. It then update the points by taking the common LAS /// header for the full area as reference. It also updates the tile header from the computed values of the points. /// </summary> /// <typeparam name="T">Type of the las point</typeparam> /// <param name="prmHeader">LAS header to update</param> /// <param name="prmPoints">Array of LAS points</param> /// <param name="prmCount">Number of points to be considered</param> /// <returns>The header as an interface to converted to the specific header structure.</returns> protected TiLasHeader UpdateHeader <T>(TiLasHeader prmTileHeader, T[] prmPoints, Int32 prmCount) where T : TiLasPoint { Double X, Y, Z; if (prmTileHeader is TsLasHeader12) { TsLasHeader12 tileHeader = (TsLasHeader12)prmTileHeader; for (int i = 0; i < prmCount; i++) { X = tileHeader.XOffset + tileHeader.XScaleFactor * prmPoints[i].X; Y = tileHeader.YOffset + tileHeader.YScaleFactor * prmPoints[i].Y; Z = tileHeader.ZOffset + tileHeader.ZScaleFactor * prmPoints[i].Z; tileHeader.MinX = Math.Min(tileHeader.MinX, X); tileHeader.MinY = Math.Min(tileHeader.MinY, Y); tileHeader.MinZ = Math.Min(tileHeader.MinZ, Z); tileHeader.MaxX = Math.Max(tileHeader.MaxX, X); tileHeader.MaxY = Math.Max(tileHeader.MaxY, Y); tileHeader.MaxZ = Math.Max(tileHeader.MaxZ, Z); tileHeader.NumberOfPointRecords++; switch (prmPoints[i].ReturnNumber()) { case 1: tileHeader.NumberofPointsByReturn1++; break; case 2: tileHeader.NumberofPointsByReturn2++; break; case 3: tileHeader.NumberofPointsByReturn3++; break; case 4: tileHeader.NumberofPointsByReturn4++; break; case 5: tileHeader.NumberofPointsByReturn5++; break; } } return(tileHeader); } else if (prmTileHeader is TsLasHeader13) { TsLasHeader13 tileHeader = (TsLasHeader13)prmTileHeader; for (int i = 0; i < prmCount; i++) { X = tileHeader.XOffset + tileHeader.XScaleFactor * prmPoints[i].X; Y = tileHeader.YOffset + tileHeader.YScaleFactor * prmPoints[i].Y; Z = tileHeader.ZOffset + tileHeader.ZScaleFactor * prmPoints[i].Z; tileHeader.MinX = Math.Min(tileHeader.MinX, X); tileHeader.MinY = Math.Min(tileHeader.MinY, Y); tileHeader.MinZ = Math.Min(tileHeader.MinZ, Z); tileHeader.MaxX = Math.Max(tileHeader.MaxX, X); tileHeader.MaxY = Math.Max(tileHeader.MaxY, Y); tileHeader.MaxZ = Math.Max(tileHeader.MaxZ, Z); tileHeader.NumberOfPointRecords++; switch (prmPoints[i].ReturnNumber()) { case 1: tileHeader.NumberofPointsByReturn1++; break; case 2: tileHeader.NumberofPointsByReturn2++; break; case 3: tileHeader.NumberofPointsByReturn3++; break; case 4: tileHeader.NumberofPointsByReturn4++; break; case 5: tileHeader.NumberofPointsByReturn5++; break; } } return(tileHeader); } else if (prmTileHeader is TsLasHeader14) { TsLasHeader14 tileHeader = (TsLasHeader14)prmTileHeader; for (int i = 0; i < prmCount; i++) { X = tileHeader.XOffset + tileHeader.XScaleFactor * prmPoints[i].X; Y = tileHeader.YOffset + tileHeader.YScaleFactor * prmPoints[i].Y; Z = tileHeader.ZOffset + tileHeader.ZScaleFactor * prmPoints[i].Z; tileHeader.MinX = Math.Min(tileHeader.MinX, X); tileHeader.MinY = Math.Min(tileHeader.MinY, Y); tileHeader.MinZ = Math.Min(tileHeader.MinZ, Z); tileHeader.MaxX = Math.Max(tileHeader.MaxX, X); tileHeader.MaxY = Math.Max(tileHeader.MaxY, Y); tileHeader.MaxZ = Math.Max(tileHeader.MaxZ, Z); tileHeader.NumberOfPointRecords++; tileHeader.LegNumberOfPointRecords++; switch (prmPoints[i].ReturnNumber()) { case 1: tileHeader.NumberofPointsByReturn1++; tileHeader.LegNumberofPointsByReturn1++; break; case 2: tileHeader.NumberofPointsByReturn2++; tileHeader.LegNumberofPointsByReturn2++; break; case 3: tileHeader.NumberofPointsByReturn3++; tileHeader.LegNumberofPointsByReturn3++; break; case 4: tileHeader.NumberofPointsByReturn4++; tileHeader.LegNumberofPointsByReturn4++; break; case 5: tileHeader.NumberofPointsByReturn5++; tileHeader.LegNumberofPointsByReturn5++; break; case 6: tileHeader.NumberofPointsByReturn6++; break; case 7: tileHeader.NumberofPointsByReturn7++; break; case 8: tileHeader.NumberofPointsByReturn8++; break; case 9: tileHeader.NumberofPointsByReturn9++; break; case 10: tileHeader.NumberofPointsByReturn10++; break; case 11: tileHeader.NumberofPointsByReturn11++; break; case 12: tileHeader.NumberofPointsByReturn12++; break; case 13: tileHeader.NumberofPointsByReturn13++; break; case 14: tileHeader.NumberofPointsByReturn14++; break; case 15: tileHeader.NumberofPointsByReturn15++; break; } } return(tileHeader); } throw new InvalidDataException("Couldn't update the header. Invalid data format."); }
//----------------------------------------------------------------------------- private void ProcessTiles <T>(IEnumerable <TcTileAreaBlock> prmTileAreaBlocks , IEnumerable <TcTileFileBlock> prmTileFileBlocks) where T : TiLasPoint { // Load the LAS points into the memory. Dictionary <TcTileBlockInfo, T[]> loadedLasPoints = new Dictionary <TcTileBlockInfo, T[]>(); try { foreach (TcTileFileBlock fileBlock in prmTileFileBlocks) { if (fileBlock.TileBlocks.Count > 0) { // Callback for the message. ReportMessage(String.Format("Loading blocks from file {0}", Path.GetFileNameWithoutExtension(fileBlock.File))); using (TcTileLasReader lasReader = new TcTileLasReader(m_TileInfos[fileBlock.File])) { foreach (TcTileBlockInfo blockInfo in fileBlock.TileBlocks) { loadedLasPoints[blockInfo] = lasReader.GetPointsByTileBlock <T>(blockInfo); } } } } // Point blocks that has been transformed. HashSet <TcTileBlockInfo> tranformedBlocks = new HashSet <TcTileBlockInfo>(); // The points to be saved after filtering. List <T> filteredLasPoints = new List <T>(); // Reference of the points to be written in file. T[] writablePoints; // LAS writer. TcTileLasWriter lasWriter = null; // Total number of points to be processed. Int64 glbTotalPointsToProcess = prmTileAreaBlocks.SelectMany(iter => iter.FileBlocks).SelectMany(iter => iter.TileBlocks).Sum(iter => iter.NoOfPoints); // Process each tile and write into the LAS file. foreach (TcTileAreaBlock areaBlock in prmTileAreaBlocks) { // Points to be processed for this tile. Int64 tilePointsToProcess = areaBlock.FileBlocks.SelectMany(iter => iter.TileBlocks).Sum(iter => iter.NoOfPoints); try { // Header for this tile. TiLasHeader tileHeader = null; // Progress to report to the upper layer. Double progress = 0.0; // Write the las points. foreach (TcTileFileBlock fileBlock in areaBlock.FileBlocks) { TiLasHeader header = m_TileInfos[fileBlock.File].Header; // Load the blocks of points from the specific LAS file. foreach (TcTileBlockInfo blockInfo in fileBlock.TileBlocks) { // When the user wants to filter the points from the tile. if (ApplyFiltering) { filteredLasPoints.Clear(); writablePoints = loadedLasPoints[blockInfo]; for (int i = 0; i < writablePoints.Length; i++) { if (areaBlock.Area.Contains(header.XOffset + header.XScaleFactor * writablePoints[i].X, header.YOffset + header.YScaleFactor * writablePoints[i].Y)) { filteredLasPoints.Add(writablePoints[i]); } } writablePoints = filteredLasPoints.ToArray(); } else { writablePoints = loadedLasPoints[blockInfo]; } if (writablePoints.Length > 0) { if (lasWriter == null) { ReportMessage(String.Format("{1}------------ Started Tile {0} ------------{1}", areaBlock.Index, Environment.NewLine)); lasWriter = new TcTileLasWriter(areaBlock.OutputFile); // Get the default header based on version. tileHeader = GetDefaultLasHeader(); // Write the default header based on version. lasWriter.WriteHeader(tileHeader); } // Get the updated point counts and header with Min/Max. Doesn't update if already updated once. tileHeader = UpdateLasInformation <T>(tileHeader, header, writablePoints, tranformedBlocks.Add(blockInfo) || ApplyFiltering); // Write the points after modifying the X Y Z based on a common offset. lasWriter.WritePoints <T>(writablePoints); } // Report the progress. progress += (loadedLasPoints[blockInfo].Length) * 100.0 / tilePointsToProcess; } // Report the progress. ReportProgress(areaBlock.Index, progress); } // Write the updated header if required. if (tileHeader != null && lasWriter != null) { // Update the min-max offsets for the whole are. tileHeader.XOffset = m_AreaHeader.XOffset; tileHeader.YOffset = m_AreaHeader.YOffset; tileHeader.ZOffset = m_AreaHeader.ZOffset; tileHeader.XScaleFactor = m_AreaHeader.XScaleFactor; tileHeader.YScaleFactor = m_AreaHeader.YScaleFactor; tileHeader.ZScaleFactor = m_AreaHeader.ZScaleFactor; lasWriter.WriteHeader(tileHeader); ReportMessage(String.Format("{1}------------ Finished Tile#{0} ------------{1}", areaBlock.Index, Environment.NewLine)); } } finally { if (lasWriter != null) { lasWriter.Dispose(); lasWriter = null; } } } } finally { // Clean data. foreach (TcTileBlockInfo key in loadedLasPoints.Keys.ToList()) { loadedLasPoints[key] = new T[0]; } loadedLasPoints.Clear(); } }
//----------------------------------------------------------------------------- /// <summary> /// Adjusts the LAS points for the tile and update the tile header. It takes the las file header for the block /// of points and the modified header for this specific tile. It then update the points by taking the common LAS /// header for the full area as reference. It also updates the tile header from the computed values of the points. /// </summary> /// <typeparam name="T">Type of the las point</typeparam> /// <param name="prmTileHeader">LAS header for this specific tile</param> /// <param name="prmLasHeader">LAS header for the las file where this points belong to</param> /// <param name="prmLasPoints">An array of las points to be updated</param> /// <returns>The header as an interface to converted to the specific header structure.</returns> private TiLasHeader UpdateLasInformation <T>(TiLasHeader prmTileHeader, TiLasHeader prmLasHeader, T[] prmLasPoints, Boolean prmModifyPoints) where T : TiLasPoint { Double X, Y, Z; if (prmTileHeader is TsLasHeader12) { TsLasHeader12 tileHeader = (TsLasHeader12)prmTileHeader; for (int i = 0; i < prmLasPoints.Length; i++) { X = prmLasHeader.XOffset + prmLasPoints[i].X * prmLasHeader.XScaleFactor; Y = prmLasHeader.YOffset + prmLasPoints[i].Y * prmLasHeader.YScaleFactor; Z = prmLasHeader.ZOffset + prmLasPoints[i].Z * prmLasHeader.ZScaleFactor; if (prmModifyPoints) { prmLasPoints[i].X = (Int32)((X - m_AreaHeader.XOffset) / m_AreaHeader.XScaleFactor); prmLasPoints[i].Y = (Int32)((Y - m_AreaHeader.YOffset) / m_AreaHeader.YScaleFactor); prmLasPoints[i].Z = (Int32)((Z - m_AreaHeader.ZOffset) / m_AreaHeader.ZScaleFactor); } tileHeader.MinX = Math.Min(tileHeader.MinX, X); tileHeader.MinY = Math.Min(tileHeader.MinY, Y); tileHeader.MinZ = Math.Min(tileHeader.MinZ, Z); tileHeader.MaxX = Math.Max(tileHeader.MaxX, X); tileHeader.MaxY = Math.Max(tileHeader.MaxY, Y); tileHeader.MaxZ = Math.Max(tileHeader.MaxZ, Z); tileHeader.NumberOfPointRecords++; switch (prmLasPoints[i].ReturnNumber()) { case 1: tileHeader.NumberofPointsByReturn1++; break; case 2: tileHeader.NumberofPointsByReturn2++; break; case 3: tileHeader.NumberofPointsByReturn3++; break; case 4: tileHeader.NumberofPointsByReturn4++; break; case 5: tileHeader.NumberofPointsByReturn5++; break; } } return(tileHeader); } else if (prmTileHeader is TsLasHeader13) { TsLasHeader13 tileHeader = (TsLasHeader13)prmTileHeader; for (int i = 0; i < prmLasPoints.Length; i++) { X = prmLasHeader.XOffset + prmLasPoints[i].X * prmLasHeader.XScaleFactor; Y = prmLasHeader.YOffset + prmLasPoints[i].Y * prmLasHeader.YScaleFactor; Z = prmLasHeader.ZOffset + prmLasPoints[i].Z * prmLasHeader.ZScaleFactor; prmLasPoints[i].X = (Int32)((X - m_AreaHeader.XOffset) / m_AreaHeader.XScaleFactor); prmLasPoints[i].Y = (Int32)((Y - m_AreaHeader.YOffset) / m_AreaHeader.YScaleFactor); prmLasPoints[i].Z = (Int32)((Z - m_AreaHeader.ZOffset) / m_AreaHeader.ZScaleFactor); tileHeader.MinX = Math.Min(tileHeader.MinX, X); tileHeader.MinY = Math.Min(tileHeader.MinY, Y); tileHeader.MinZ = Math.Min(tileHeader.MinZ, Z); tileHeader.MaxX = Math.Max(tileHeader.MaxX, X); tileHeader.MaxY = Math.Max(tileHeader.MaxY, Y); tileHeader.MaxZ = Math.Max(tileHeader.MaxZ, Z); tileHeader.NumberOfPointRecords++; switch (prmLasPoints[i].ReturnNumber()) { case 1: tileHeader.NumberofPointsByReturn1++; break; case 2: tileHeader.NumberofPointsByReturn2++; break; case 3: tileHeader.NumberofPointsByReturn3++; break; case 4: tileHeader.NumberofPointsByReturn4++; break; case 5: tileHeader.NumberofPointsByReturn5++; break; } } return(tileHeader); } else if (prmTileHeader is TsLasHeader14) { TsLasHeader14 tileHeader = (TsLasHeader14)prmTileHeader; for (int i = 0; i < prmLasPoints.Length; i++) { X = prmLasHeader.XOffset + prmLasPoints[i].X * prmLasHeader.XScaleFactor; Y = prmLasHeader.YOffset + prmLasPoints[i].Y * prmLasHeader.YScaleFactor; Z = prmLasHeader.ZOffset + prmLasPoints[i].Z * prmLasHeader.ZScaleFactor; prmLasPoints[i].X = (Int32)((X - m_AreaHeader.XOffset) / m_AreaHeader.XScaleFactor); prmLasPoints[i].Y = (Int32)((Y - m_AreaHeader.YOffset) / m_AreaHeader.YScaleFactor); prmLasPoints[i].Z = (Int32)((Z - m_AreaHeader.ZOffset) / m_AreaHeader.ZScaleFactor); tileHeader.MinX = Math.Min(tileHeader.MinX, X); tileHeader.MinY = Math.Min(tileHeader.MinY, Y); tileHeader.MinZ = Math.Min(tileHeader.MinZ, Z); tileHeader.MaxX = Math.Max(tileHeader.MaxX, X); tileHeader.MaxY = Math.Max(tileHeader.MaxY, Y); tileHeader.MaxZ = Math.Max(tileHeader.MaxZ, Z); tileHeader.NumberOfPointRecords++; tileHeader.LegNumberOfPointRecords++; switch (prmLasPoints[i].ReturnNumber()) { case 1: tileHeader.NumberofPointsByReturn1++; tileHeader.LegNumberofPointsByReturn1++; break; case 2: tileHeader.NumberofPointsByReturn2++; tileHeader.LegNumberofPointsByReturn2++; break; case 3: tileHeader.NumberofPointsByReturn3++; tileHeader.LegNumberofPointsByReturn3++; break; case 4: tileHeader.NumberofPointsByReturn4++; tileHeader.LegNumberofPointsByReturn4++; break; case 5: tileHeader.NumberofPointsByReturn5++; tileHeader.LegNumberofPointsByReturn5++; break; case 6: tileHeader.NumberofPointsByReturn6++; break; case 7: tileHeader.NumberofPointsByReturn7++; break; case 8: tileHeader.NumberofPointsByReturn8++; break; case 9: tileHeader.NumberofPointsByReturn9++; break; case 10: tileHeader.NumberofPointsByReturn10++; break; case 11: tileHeader.NumberofPointsByReturn11++; break; case 12: tileHeader.NumberofPointsByReturn12++; break; case 13: tileHeader.NumberofPointsByReturn13++; break; case 14: tileHeader.NumberofPointsByReturn14++; break; case 15: tileHeader.NumberofPointsByReturn15++; break; } } return(tileHeader); } throw new InvalidDataException("Couldn't update the header. Invalid data format."); }
//----------------------------------------------------------------------------- public TcLasPointBase[] GetPointObjectsByTileBlock <T>(TcTileBlockInfo block, TiLasHeader prmHeader) where T : TiLasPoint { SeekToPoint(block.StartPoint); return(ReadPointsAsObject <T>(block.NoOfPoints, prmHeader)); }
//----------------------------------------------------------------------------- public TcLasPointBase[] GetPointObjectsByArea <T>(TcRectangle prmArea, TiLasHeader prmHeader) where T : TiLasPoint { return(GetPointObjectsByTileBlocks <T>(m_TileInfo.GetTileBlocks(prmArea), prmHeader)); }
//------------------------------------------------------------------ /// <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> /// <param name="prmHeader">LAS header interface</param> /// <returns>An array of LAS points</returns> public TcLasPointBase[] ReadPointsAsObject <T>(Int64 prmNoOfPoints, TiLasHeader prmHeader) where T : TiLasPoint { Int64 pointCounter = 0; switch (prmHeader.PointDataFormatID) { case 0: TsLasHeader12 header0 = (TsLasHeader12)prmHeader; return(ReadPoints <TsLasPoint0>(prmNoOfPoints).Aggregate(new TcLasPointBase[prmNoOfPoints], (res, iter) => { res[pointCounter++] = new TcLasPoint0(iter, header0); return res; })); case 1: TsLasHeader12 header1 = (TsLasHeader12)prmHeader; return(ReadPoints <TsLasPoint1>(prmNoOfPoints).Aggregate(new TcLasPointBase[prmNoOfPoints], (res, iter) => { res[pointCounter++] = new TcLasPoint1(iter, header1); return res; })); case 2: TsLasHeader12 header2 = (TsLasHeader12)prmHeader; return(ReadPoints <TsLasPoint2>(prmNoOfPoints).Aggregate(new TcLasPointBase[prmNoOfPoints], (res, iter) => { res[pointCounter++] = new TcLasPoint2(iter, header2); return res; })); case 3: TsLasHeader12 header3 = (TsLasHeader12)prmHeader; return(ReadPoints <TsLasPoint3>(prmNoOfPoints).Aggregate(new TcLasPointBase[prmNoOfPoints], (res, iter) => { res[pointCounter++] = new TcLasPoint3(iter, header3); return res; })); case 4: TsLasHeader13 header4 = (TsLasHeader13)prmHeader; return(ReadPoints <TsLasPoint4>(prmNoOfPoints).Aggregate(new TcLasPointBase[prmNoOfPoints], (res, iter) => { res[pointCounter++] = new TcLasPoint4(iter, header4); return res; })); case 5: TsLasHeader13 header5 = (TsLasHeader13)prmHeader; return(ReadPoints <TsLasPoint5>(prmNoOfPoints).Aggregate(new TcLasPointBase[prmNoOfPoints], (res, iter) => { res[pointCounter++] = new TcLasPoint5(iter, header5); return res; })); case 6: TsLasHeader14 header6 = (TsLasHeader14)prmHeader; return(ReadPoints <TsLasPoint6>(prmNoOfPoints).Aggregate(new TcLasPointBase[prmNoOfPoints], (res, iter) => { res[pointCounter++] = new TcLasPoint6(iter, header6); return res; })); case 7: TsLasHeader14 header7 = (TsLasHeader14)prmHeader; return(ReadPoints <TsLasPoint7>(prmNoOfPoints).Aggregate(new TcLasPointBase[prmNoOfPoints], (res, iter) => { res[pointCounter++] = new TcLasPoint7(iter, header7); return res; })); case 8: TsLasHeader14 header8 = (TsLasHeader14)prmHeader; return(ReadPoints <TsLasPoint8>(prmNoOfPoints).Aggregate(new TcLasPointBase[prmNoOfPoints], (res, iter) => { res[pointCounter++] = new TcLasPoint8(iter, header8); return res; })); case 9: TsLasHeader14 header9 = (TsLasHeader14)prmHeader; return(ReadPoints <TsLasPoint9>(prmNoOfPoints).Aggregate(new TcLasPointBase[prmNoOfPoints], (res, iter) => { res[pointCounter++] = new TcLasPoint9(iter, header9); return res; })); case 10: TsLasHeader14 header10 = (TsLasHeader14)prmHeader; return(ReadPoints <TsLasPoint10>(prmNoOfPoints).Aggregate(new TcLasPointBase[prmNoOfPoints], (res, iter) => { res[pointCounter++] = new TcLasPoint10(iter, header10); return res; })); } return(null); }
//----------------------------------------------------------------------------- public void WriteHeader(TiLasHeader prmHeader) { WriteHeader(prmHeader, new Byte[0]); }
//----------------------------------------------------------------------------- private void ProcessTiles <T>(TcLasReader prmReader, String prmOutput) where T : TiLasPoint { // Variables to be used inside the big loop. Int32 tileOffset = 0; Int32 index = -1; Int32 pointsProcessed = 0; // Key: Index of the Tile, Value: Array of 1000 points. Dictionary <Int32, T[]> m_TileBlocks = new Dictionary <Int32, T[]>(); TiLasHeader newHeader = UpdateTileCounts <T>(prmReader.Header, TileSize); Byte[] offsetBytes = prmReader.OffsetBytes; String blockFile = String.Format(@"{0}\{1}.xml", Path.GetDirectoryName(prmOutput), Path.GetFileNameWithoutExtension(prmOutput)); if (File.Exists(blockFile)) { File.Delete(blockFile); } using (TcLasWriter writer = new TcLasWriter(prmOutput) { MinClampZ = MinClampZ, MaxClampZ = MaxClampZ, /* Added By Dean */ ZAdjustment = this.ZAdjustment, XAdjustment = this.XAdjustment, YAdjustment = this.YAdjustment }) { writer.WriteHeader(newHeader, offsetBytes); Int64 numberOfPointRecords = GetNumberOfPoints(prmReader.Header); Int32 onePercent = (Int32)numberOfPointRecords / 100; Int32[] rowCol = new Int32[2]; DateTime now = DateTime.Now; Boolean[] availIndices = new Boolean[m_TileBlockInfoCollection.TileInfo.Row * m_TileBlockInfoCollection.TileInfo.Col]; Double x, y; Double z = 0; // Added Z Property - Dean Int64 noOfPointsLoaded = 0; Int64 noOfPointsToRead = 0; while (noOfPointsLoaded < numberOfPointRecords) { noOfPointsToRead = Math.Min(TcConstants.MaxLasPointsToProcessAtOnce, numberOfPointRecords - noOfPointsLoaded); T[] loadedPoints = prmReader.ReadPoints <T>(noOfPointsToRead); noOfPointsLoaded += noOfPointsToRead; for (int i = 0; i < noOfPointsToRead; i++) { x = loadedPoints[i].X * newHeader.XScaleFactor + newHeader.XOffset + XAdjustment; y = loadedPoints[i].Y * newHeader.YScaleFactor + newHeader.YOffset + YAdjustment; //added by dean z = loadedPoints[i].Z * newHeader.ZScaleFactor + newHeader.ZOffset + ZAdjustment; if (x <= 0 || y <= 0) { continue; } // Calculate the tile index for the point. tileOffset = TileSize * Factor; rowCol = TcMathUtil.GetRowCol(x, y, m_RevisedEast, m_RevisedNorth, tileOffset, tileOffset); index = rowCol[1] * m_TileRows + rowCol[0]; if (!availIndices[index]) { m_TileBlocks[index] = new T[PointBlockSize]; m_BlockPointCount[index] = 0; availIndices[index] = true; } // Convert the int XY back with adjusted values. loadedPoints[i].X = (Int32)((x - newHeader.XOffset) / newHeader.XScaleFactor); loadedPoints[i].Y = (Int32)((y - newHeader.YOffset) / newHeader.YScaleFactor); loadedPoints[i].Z = (Int32)((z - newHeader.ZOffset) / newHeader.ZScaleFactor); m_TileBlocks[index][m_BlockPointCount[index]] = loadedPoints[i]; m_BlockPointCount[index]++; // When a tile block is full, write into file and remove the points. if (m_BlockPointCount[index] == PointBlockSize) { // writer.WritePoints<T>(m_TileBlocks[index], PointBlockSize); writer.WritePointsWithOptions <T>(m_TileBlocks[index], ref newHeader, PointBlockSize); ProcessTileBlock <T>(m_TileBlocks, rowCol[0], rowCol[1], index, pointsProcessed); pointsProcessed += PointBlockSize; availIndices[index] = false; } } } // Process the remaining blocks with incomplete size. int row, col; foreach (Int32 idx in m_TileBlocks.Keys.ToList()) { row = idx % m_TileRows; col = (idx - row) / m_TileRows; writer.WritePointsWithOptions <T>(m_TileBlocks[idx], ref newHeader, m_BlockPointCount[idx]); ProcessTileBlock <T>(m_TileBlocks, row, col, idx, pointsProcessed); pointsProcessed += m_BlockPointCount[idx]; } // Write the updated header. writer.WriteHeader(newHeader); TcTileUtils.SaveTileBlocks(m_TileBlockInfoCollection, blockFile); } }
//------------------------------------------------------------------ public void WritePointsWithOptions <T>(T[] prmPoints, ref TiLasHeader prmHeader, Int64 prmNoOfPoints = -1) where T : TiLasPoint { Double Z; Byte returnNo, noOfReturns; Int32 count = prmNoOfPoints < 0 ? prmPoints.Length : (Int32)prmNoOfPoints; T[] writablePoints = new T[count]; Int32 writableCount = 0; for (int i = 0; i < count; i++) { if (i % Decimation != 0) { continue; } if (ClampRequired) { Z = prmPoints[i].Z * prmHeader.ZScaleFactor + prmHeader.ZOffset + ZAdjustment; if (Z < MinClampZ && Z > MaxClampZ) { continue; } } if (EchoRequired) { returnNo = prmPoints[i].ReturnNumber(); if (FirstEchoOnly && returnNo != 1) { continue; } noOfReturns = prmPoints[i].NumberOfReturns(); if (LastEchoOnly && returnNo != noOfReturns) { continue; } } if (AdjustmentRequired) { var x = prmPoints[i].X * prmHeader.XScaleFactor + prmHeader.XOffset + XAdjustment; var y = prmPoints[i].Y * prmHeader.YScaleFactor + prmHeader.YOffset + YAdjustment; var z = prmPoints[i].Z * prmHeader.ZScaleFactor + prmHeader.ZOffset + ZAdjustment; prmPoints[i].X = (Int32)((x - prmHeader.XOffset) / prmHeader.XScaleFactor); prmPoints[i].Y = (Int32)((y - prmHeader.YOffset) / prmHeader.YScaleFactor); prmPoints[i].Z = (Int32)((z - prmHeader.ZOffset) / prmHeader.ZScaleFactor); //prmPoints[i].X += (Int32)(XAdjustment / prmHeader.XScaleFactor); //prmPoints[i].Y += (Int32)(YAdjustment / prmHeader.YScaleFactor); //prmPoints[i].Z += (Int32)(ZAdjustment / prmHeader.ZScaleFactor); } writablePoints[writableCount++] = prmPoints[i]; } WritePoints <T>(writablePoints, writableCount); prmHeader = UpdateHeader <T>(prmHeader, writablePoints, writableCount); }
//----------------------------------------------------------------------------- public TcLasPointBase[] GetPointObjectsByTileBlocks <T>(IEnumerable <TcTileBlockInfo> blocks, TiLasHeader prmHeader) where T : TiLasPoint { Int32 numberOfPoints = blocks.Aggregate(0, (result, iter) => result += iter.NoOfPoints); TcLasPointBase[] points = new TcLasPointBase[numberOfPoints]; Int32 arrayStart = 0; foreach (TcTileBlockInfo info in blocks) { Array.Copy(GetPointObjectsByTileBlock <T>(info, prmHeader), 0, points, arrayStart, info.NoOfPoints); arrayStart += info.NoOfPoints; } return(points); }
//----------------------------------------------------------------------------- protected TiLasHeader GetDuplicateEmptyHeader(TiLasHeader prmHeader) { prmHeader.MinX = Double.MaxValue; prmHeader.MaxX = Double.MinValue; prmHeader.MinY = Double.MaxValue; prmHeader.MaxY = Double.MinValue; prmHeader.MinZ = Double.MaxValue; prmHeader.MaxZ = Double.MinValue; if (prmHeader.HeaderSize == Marshal.SizeOf(typeof(TsLasHeader12))) { TsLasHeader12 header = (TsLasHeader12)(((TsLasHeader12)prmHeader).Clone()); header.NumberOfPointRecords = 0; header.NumberofPointsByReturn1 = 0; header.NumberofPointsByReturn2 = 0; header.NumberofPointsByReturn3 = 0; header.NumberofPointsByReturn4 = 0; header.NumberofPointsByReturn5 = 0; return(header); } else if (prmHeader.HeaderSize == Marshal.SizeOf(typeof(TsLasHeader13))) { TsLasHeader13 header = (TsLasHeader13)(((TsLasHeader13)prmHeader).Clone()); header.NumberOfPointRecords = 0; header.NumberofPointsByReturn1 = 0; header.NumberofPointsByReturn2 = 0; header.NumberofPointsByReturn3 = 0; header.NumberofPointsByReturn4 = 0; header.NumberofPointsByReturn5 = 0; return(header); } else if (prmHeader.HeaderSize == Marshal.SizeOf(typeof(TsLasHeader14))) { TsLasHeader14 header = (TsLasHeader14)(((TsLasHeader14)prmHeader).Clone()); header.LegNumberOfPointRecords = 0; header.LegNumberofPointsByReturn1 = 0; header.LegNumberofPointsByReturn2 = 0; header.LegNumberofPointsByReturn3 = 0; header.LegNumberofPointsByReturn4 = 0; header.LegNumberofPointsByReturn5 = 0; header.NumberOfPointRecords = 0; header.NumberofPointsByReturn1 = 0; header.NumberofPointsByReturn2 = 0; header.NumberofPointsByReturn3 = 0; header.NumberofPointsByReturn4 = 0; header.NumberofPointsByReturn5 = 0; header.NumberofPointsByReturn6 = 0; header.NumberofPointsByReturn7 = 0; header.NumberofPointsByReturn8 = 0; header.NumberofPointsByReturn9 = 0; header.NumberofPointsByReturn10 = 0; header.NumberofPointsByReturn11 = 0; header.NumberofPointsByReturn12 = 0; header.NumberofPointsByReturn13 = 0; header.NumberofPointsByReturn14 = 0; header.NumberofPointsByReturn15 = 0; return(header); } throw new InvalidDataException("Header size is wrong"); }
//----------------------------------------------------------------------------- public TcLasPointBase[] GetPointObjectsByTile <T>(Int32 prmRow, Int32 prmColumn, TiLasHeader prmHeader) where T : TiLasPoint { return(GetPointObjectsByTileBlocks <T>(m_TileInfo.TileBlocks.Where(iter => iter.Row == prmRow && iter.Col == prmColumn), prmHeader)); }