//----------------------------------------------------------------------------- /// <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"); } } }
//----------------------------------------------------------------------------- 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> /// This function reads the LAS file and arrange points into the specific grid. /// It also applies filtering for some given pre-defined gridding types. /// </summary> /// <typeparam name="T">Type of the LAS points</typeparam> /// <param name="prmReader">Tile LAS reader which reads LAS points by tile</param> /// <param name="prmObjects">A collection of grid data objects (1 per gridding type)</param> private void Grid <T>(TcTileLasReader prmReader, IEnumerable <TcGridObject> prmObjects) where T : TiLasPoint { TcLasPointBase[] points; TcTileBlockInfo info; for (int row = 0; row < m_Info.TileInfo.Row; row++) { for (int col = 0; col < m_Info.TileInfo.Col; col++) { if ((info = m_Info.TileBlocks.FirstOrDefault(iter => iter.Row == row && iter.Col == col)) != null) { points = prmReader.GetPointObjectsByTile <T>(row, col, m_LasHeader); foreach (TcGridObject gridObject in prmObjects) { // Report the message. ReportMessage(String.Format("Processing Tile({0},{1}) of {2} ({3}m)", row, col, TcEnums.ShortName(gridObject.Type), gridObject.GridSize)); // Filter points that are not required by 1M grid. if (gridObject.Type == TeGriddingType.M1FirstEcho || gridObject.Type == TeGriddingType.M1LastEcho) { FilterOutOfInterestPoints(points); } UpdateGrid(gridObject, info, points); } } } } foreach (TcGridObject gridObject in prmObjects) { // Write the tor file. TcTolObject objDiff = new TcTolObject(gridObject.OutputFile) { Rows = m_Info.TileInfo.Row * gridObject.GridCount, Columns = m_Info.TileInfo.Col * gridObject.GridCount, UpperLeftEast = m_LasHeader.MinX, UpperLeftNorth = m_LasHeader.MaxY, LowerRightEast = m_LasHeader.MaxX, LowerRightNorth = m_LasHeader.MinY, MinHeight = (Single)gridObject.MinZ, MaxHeight = (Single)gridObject.MaxZ, ScalingX = gridObject.GridSize, ScalingY = gridObject.GridSize, Model = m_CoordinateSystem, BitSize = 32 }; // Report the message. ReportMessage(String.Format("Writing {0}", Path.GetFileName(gridObject.OutputFile))); TcTorObject objTor = new TcTorObject(objDiff) { Blocks = gridObject.TorBlocks }; using (TcTorWriter writer = new TcTorWriter(objDiff)) { writer.WriteTol(); writer.Write(objTor); } } ReportFinished(); }