private static PointCloudAnalysisResult QuantEstimateDensity(IPointCloudBinarySource source, int maxSegmentLength, SQuantizedExtentGrid <int> tileCounts, ProgressManager progressManager) { Statistics stats = null; List <PointCloudBinarySourceEnumeratorSparseGridRegion> gridIndexSegments = null; var extent = source.Extent; var quantizedExtent = source.QuantizedExtent; var statsMapping = new ScaledStatisticsMapping(quantizedExtent.MinZ, quantizedExtent.RangeZ, 1024); var gridCounter = new GridCounter(source, tileCounts); using (var process = progressManager.StartProcess("QuantEstimateDensity")) { var group = new ChunkProcessSet(gridCounter, statsMapping); group.Process(source.GetBlockEnumerator(process)); } stats = statsMapping.ComputeStatistics(extent.MinZ, extent.RangeZ); var density = new PointCloudTileDensity(tileCounts, source.Quantization); gridIndexSegments = gridCounter.GetGridIndex(density, maxSegmentLength); var result = new PointCloudAnalysisResult(density, stats, source.Quantization, gridIndexSegments); return(result); }
public GridCounter(IPointCloudBinarySource source, SQuantizedExtentGrid<int> grid) { m_source = source; m_grid = grid; m_quantizedExtent = source.QuantizedExtent; m_chunkTiles = new List<int[]>(); }
public GridCounter(IPointCloudBinarySource source, SQuantizedExtentGrid <int> grid) { m_source = source; m_grid = grid; m_quantizedExtent = source.QuantizedExtent; m_chunkTiles = new List <int[]>(); }
public QuantizationTest(IPointCloudBinarySource source) { m_source = source; m_quantized = (m_source.Quantization != null); m_count = GetPrecisionTestingPointCount(source); m_index = 0; m_values = new T[3][]; for (int i = 0; i < 3; i++) { m_values[i] = new T[m_count]; } }
/// <summary> /// Initializes a new instance of the <see cref="PointBufferWrapper"/> class, /// for wrapping a binary source segment buffer. /// </summary> /// <param name="buffer">The buffer.</param> /// <param name="source">The source.</param> /// <param name="pointCount">The point count.</param> public PointBufferWrapper(BufferInstance buffer, IPointCloudBinarySource source, int pointCount) { m_buffer = buffer; m_pointCount = pointCount; m_pointSizeBytes = source.PointSizeBytes; m_length = m_pointCount * m_pointSizeBytes; m_pointDataPtr = m_buffer.DataPtr; m_pointDataEndPtr = m_pointDataPtr + m_length; m_bufferIndex = 0; }
public PointCloudBinarySourceComposite(FileHandlerBase file, Extent3D extent, IPointCloudBinarySource[] sources) : base(file) { m_sources = sources; // verify that they are compatible m_count = m_sources.Sum(s => s.Count); m_extent = extent; m_quantization = m_sources[0].Quantization; m_pointSizeBytes = m_sources[0].PointSizeBytes; m_quantizedExtent = m_quantization.Convert(m_extent); }
/* * public Quantization3D CreateQuantization() * { * if (m_quantized) * return Quantization3D.Create(m_source.Extent, m_source.Quantization as SQuantization3D, m_values as int[][], m_index); * else * return Quantization3D.Create(m_source.Extent, m_values as double[][], m_index); * } */ private static unsafe int GetPrecisionTestingPointCount(IPointCloudBinarySource source) { int maxBytesForPrecisionTest = (int)PROPERTY_QUANTIZATION_MEMORY_LIMIT.Value; int maxPointsForPrecisionTest = maxBytesForPrecisionTest / sizeof(SQuantizedPoint3D); // block-alignment is no longer necessary //int maxPointsForPrecisionTestBlockAligned = (maxPointsForPrecisionTest / source.PointsPerBuffer) * source.PointsPerBuffer; //int pointsToTest = (int)Math.Min(source.Count, maxPointsForPrecisionTestBlockAligned); int pointsToTest = (int)Math.Min(source.Count, maxPointsForPrecisionTest); return(pointsToTest); }
public LASHeader(IPointCloudBinarySource source) { // params I need? // (skip global encoding) // (skip file creation date) // vlrs // evlrs // attributes that make up point format // point count // quantization // extent // points by return //new ParameterDefinition<ushort>("FileSourceID", 0); //m_fileSourceID = 0; //m_globalEncoding = new LASGlobalEncoding(); //m_projectID = new LASProjectID(); //m_version = LASVersionInfo.Create(LASVersion.LAS_1_4); //m_systemIdentifier = header.m_systemIdentifier; //m_generatingSoftware = header.m_generatingSoftware; //m_fileCreationDayOfYear = header.m_fileCreationDayOfYear; //m_fileCreationYear = header.m_fileCreationYear; //m_headerSize = c_minHeaderSize[LASVersion.LAS_1_4]; //m_offsetToPointData = m_headerSize + (uint)vlrs.Sum(vlr => vlr.Length); //m_numberOfVariableLengthRecords = (uint)vlrs.Length; //m_pointDataRecordFormat = header.m_pointDataRecordFormat; //m_pointDataRecordLength = header.m_pointDataRecordLength; //m_legacyNumberOfPointRecords = header.m_legacyNumberOfPointRecords; //m_legacyNumberOfPointsByReturn = (uint[])header.m_legacyNumberOfPointsByReturn.Clone(); //m_quantization = source.Quantization; //m_extent = source.Extent; //m_startOfWaveformDataPacketRecord = 0; //m_startOfFirstExtendedVariableLengthRecord = m_offsetToPointData + (m_numberOfPointRecords * m_pointDataRecordLength); //m_numberOfExtendedVariableLengthRecords = header.m_numberOfExtendedVariableLengthRecords; //m_numberOfPointRecords = (ulong)source.Count; //m_numberOfPointsByReturn = (ulong[])header.m_numberOfPointsByReturn.Clone(); }
public SQuantizedExtentGrid <int> CreateTileCountsForInitialization(IPointCloudBinarySource source) { if (m_tileCountsForInitialization == null) { // median works better usually, but max is safer for substantially varying density // (like terrestrial, although that requires a more thorough redesign) //double tileArea = PROPERTY_DESIRED_TILE_COUNT.Value / density.MaxTileDensity; var tileArea = PointCloudTileManager.PROPERTY_DESIRED_TILE_COUNT.Value / MedianTileDensity; var tileSize = Math.Sqrt(tileArea); Context.WriteLine("TileSide: {0}", tileSize); m_tileCountsForInitialization = source.QuantizedExtent.CreateGridFromCellSize <int>(tileSize, source.Quantization, true); } return(m_tileCountsForInitialization); }
public SQuantizedExtentGrid<int> CreateTileCountsForInitialization(IPointCloudBinarySource source) { if (m_tileCountsForInitialization == null) { // median works better usually, but max is safer for substantially varying density // (like terrestrial, although that requires a more thorough redesign) //double tileArea = PROPERTY_DESIRED_TILE_COUNT.Value / density.MaxTileDensity; var tileArea = PointCloudTileManager.PROPERTY_DESIRED_TILE_COUNT.Value / MedianTileDensity; var tileSize = Math.Sqrt(tileArea); Context.WriteLine("TileSide: {0}", tileSize); m_tileCountsForInitialization = source.QuantizedExtent.CreateGridFromCellSize<int>(tileSize, source.Quantization, true); } return m_tileCountsForInitialization; }
private static SQuantizedExtentGrid <int> CreateTileCountsForEstimation(IPointCloudBinarySource source) { var count = source.Count; var extent = source.Extent; var tileCountForUniformData = (int)(count / PROPERTY_DESIRED_TILE_COUNT.Value); //int tileCount = Math.Min(tileCountForUniformData, PROPERTY_MAX_TILES_FOR_ESTIMATION.Value); var tileCount = tileCountForUniformData; // for estimation, use a reduced tile size to minimize indexing overlap tileCount *= 16; tileCount = Math.Min(tileCount, PROPERTY_MAX_TILES_FOR_ESTIMATION.Value); var tileArea = extent.Area / tileCount; var tileSize = Math.Sqrt(tileArea); return(source.QuantizedExtent.CreateGridFromCellSize <int>(tileSize, source.Quantization, true)); }
public PointCloudTileSet(IPointCloudBinarySource source, PointCloudTileDensity density, SQuantizedExtentGrid <int> tileCounts, Grid <int> lowResCounts) { Extent = source.Extent; Quantization = source.Quantization; QuantizedExtent = source.QuantizedExtent; Density = density; Cols = tileCounts.SizeX; Rows = tileCounts.SizeY; TileSizeX = tileCounts.CellSizeX; TileSizeY = tileCounts.CellSizeY; //TileSize = tileCounts.CellSize; PointCount = density.PointCount; TileCount = density.TileCount; ValidTileCount = density.ValidTileCount; LowResCount = 0; m_tileIndex = CreateTileIndex(ValidTileCount); m_tiles = new PointCloudTile[density.ValidTileCount]; // create valid tiles (in order) long offset = 0; int validTileIndex = 0; foreach (var tile in GetTileOrdering(Rows, Cols)) { int pointCount = tileCounts.Data[tile.Row, tile.Col]; if (pointCount > 0) { var lowResCount = lowResCounts.Data[tile.Row, tile.Col]; m_tiles[validTileIndex] = new PointCloudTile(this, tile.Col, tile.Row, validTileIndex, offset, pointCount, LowResCount, lowResCount); m_tileIndex.Add(tile.Index, validTileIndex); ++validTileIndex; offset += (pointCount - lowResCount); LowResCount += lowResCount; } } }
public static LASFile Create(string path, IPointCloudBinarySource source) { var pcbs = source as PointCloudSource; if (pcbs != null) { var lasFile = pcbs.FileHandler as LASFile; if (lasFile != null) { var evlrs = (new List <LASEVLR>(lasFile.m_evlrs) { new LASEVLR(new LASRecordIdentifier("Jacere", 0), null), new LASEVLR(new LASRecordIdentifier("Jacere", 1), null) }).ToArray(); var header = new LASHeader(new [] { lasFile.Header }, lasFile.m_vlrs, evlrs); return(new LASFile(path, header, lasFile.m_vlrs, evlrs)); } } // this will require more work return(new LASFile(path)); }
public PointBufferWrapper(BufferInstance buffer, IPointCloudBinarySource source) : this(buffer, source, (int)source.Count) { }
public PointCloudTileSource Process(ProgressManager progressManager) { progressManager.Log("<= {0}", m_inputHandler.FilePath); PerformanceManager.Start(m_inputHandler.FilePath); // check for existing tile source LoadFromCache(progressManager); if (m_tileSource == null) { using (var process = progressManager.StartProcess("ProcessSet")) { m_binarySource = m_inputHandler.GenerateBinarySource(progressManager); m_tiledHandler = LASFile.Create(m_tiledHandler.FilePath, m_binarySource); using (var segmentBuffer = BufferManager.AcquireBuffer(m_id, (int)PROPERTY_SEGMENT_SIZE.Value, true)) { var tileManager = new PointCloudTileManager(m_binarySource); m_tileSource = tileManager.TilePointFileIndex(m_tiledHandler, segmentBuffer, progressManager); } #warning this was for xyz, but I have not yet re-implemented that anyway //if (m_binarySource.FilePath != m_inputHandler.FilePath) // File.Delete(m_binarySource.FilePath); if (m_tileSource.IsDirty) { m_tileSource.Close(); File.Delete(m_tileSource.FilePath); m_tileSource = null; process.LogTime("=> Processing Cancelled"); } else { process.LogTime("=> Processing Completed"); } } GC.Collect(); } TransferRate averageReadSpeed = PerformanceManager.GetReadSpeed(); TransferRate averageWriteSpeed = PerformanceManager.GetWriteSpeed(); Context.WriteLine("IO Read Speed: {0}", averageReadSpeed); Context.WriteLine("IO Write Speed: {0}", averageWriteSpeed); //{ // // test // Stopwatch stopwatch = new Stopwatch(); // stopwatch.Start(); // PointCloudTile tempTile = m_tileSource.TileSet[0, 0]; // Grid<float> grid = new Grid<float>(tempTile.Extent, 540, (float)m_tileSource.Extent.MinZ - 1.0f, true); // Grid<uint> quantizedGrid = new Grid<uint>(grid.SizeX, grid.SizeY, m_tileSource.Extent, true); // using (GridTileSource<float> gridSource = new GridTileSource<float>(m_tiledPath + ".grid", grid.SizeX, grid.SizeY, m_tileSource.TileSet.Cols, m_tileSource.TileSet.Rows)) // { // int tempBufferSize = (int)(m_tileSource.TileSet.Max(t => t.PointCount)); // byte[] tempBuffer = new byte[tempBufferSize * m_tileSource.PointSizeBytes]; // foreach (PointCloudTile tile in m_tileSource) // { // m_tileSource.LoadTileGrid(tile, tempBuffer, grid, quantizedGrid); // gridSource.WriteTile(tile.Col, tile.Row, grid.Data); // if (!progressManager.Update((float)tile.Index / m_tileSource.TileSet.TileCount)) // break; // } // //gridSource.ReadTile(tempTile.Col, tempTile.Row, grid.Data); // } // m_tileSource.Close(); // progressManager.Log(stopwatch, "Generated GRID"); //} return(m_tileSource); }
private static PointCloudAnalysisResult QuantEstimateDensity(IPointCloudBinarySource source, int maxSegmentLength, SQuantizedExtentGrid<int> tileCounts, ProgressManager progressManager) { Statistics stats = null; List<PointCloudBinarySourceEnumeratorSparseGridRegion> gridIndexSegments = null; var extent = source.Extent; var quantizedExtent = source.QuantizedExtent; var statsMapping = new ScaledStatisticsMapping(quantizedExtent.MinZ, quantizedExtent.RangeZ, 1024); var gridCounter = new GridCounter(source, tileCounts); using (var process = progressManager.StartProcess("QuantEstimateDensity")) { var group = new ChunkProcessSet(gridCounter, statsMapping); group.Process(source.GetBlockEnumerator(process)); } stats = statsMapping.ComputeStatistics(extent.MinZ, extent.RangeZ); var density = new PointCloudTileDensity(tileCounts, source.Quantization); gridIndexSegments = gridCounter.GetGridIndex(density, maxSegmentLength); var result = new PointCloudAnalysisResult(density, stats, source.Quantization, gridIndexSegments); return result; }
private static SQuantizedExtentGrid<int> CreateTileCountsForEstimation(IPointCloudBinarySource source) { var count = source.Count; var extent = source.Extent; var tileCountForUniformData = (int)(count / PROPERTY_DESIRED_TILE_COUNT.Value); //int tileCount = Math.Min(tileCountForUniformData, PROPERTY_MAX_TILES_FOR_ESTIMATION.Value); var tileCount = tileCountForUniformData; // for estimation, use a reduced tile size to minimize indexing overlap tileCount *= 16; tileCount = Math.Min(tileCount, PROPERTY_MAX_TILES_FOR_ESTIMATION.Value); var tileArea = extent.Area / tileCount; var tileSize = Math.Sqrt(tileArea); return source.QuantizedExtent.CreateGridFromCellSize<int>(tileSize, source.Quantization, true); }
public LASHeader(IPointCloudBinarySource source) { // params I need? // (skip global encoding) // (skip file creation date) // vlrs // evlrs // attributes that make up point format // point count // quantization // extent // points by return //new ParameterDefinition<ushort>("FileSourceID", 0); //m_fileSourceID = 0; //m_globalEncoding = new LASGlobalEncoding(); //m_projectID = new LASProjectID(); //m_version = LASVersionInfo.Create(LASVersion.LAS_1_4); //m_systemIdentifier = header.m_systemIdentifier; //m_generatingSoftware = header.m_generatingSoftware; //m_fileCreationDayOfYear = header.m_fileCreationDayOfYear; //m_fileCreationYear = header.m_fileCreationYear; //m_headerSize = c_minHeaderSize[LASVersion.LAS_1_4]; //m_offsetToPointData = m_headerSize + (uint)vlrs.Sum(vlr => vlr.Length); //m_numberOfVariableLengthRecords = (uint)vlrs.Length; //m_pointDataRecordFormat = header.m_pointDataRecordFormat; //m_pointDataRecordLength = header.m_pointDataRecordLength; //m_legacyNumberOfPointRecords = header.m_legacyNumberOfPointRecords; //m_legacyNumberOfPointsByReturn = (uint[])header.m_legacyNumberOfPointsByReturn.Clone(); //m_quantization = source.Quantization; //m_extent = source.Extent; //m_startOfWaveformDataPacketRecord = 0; //m_startOfFirstExtendedVariableLengthRecord = m_offsetToPointData + (m_numberOfPointRecords * m_pointDataRecordLength); //m_numberOfExtendedVariableLengthRecords = header.m_numberOfExtendedVariableLengthRecords; //m_numberOfPointRecords = (ulong)source.Count; //m_numberOfPointsByReturn = (ulong[])header.m_numberOfPointsByReturn.Clone(); }
private static unsafe void QuantTilePointsIndexed(IPointCloudBinarySource source, PointBufferWrapper segmentBuffer, TileRegionFilter tileFilter, SQuantizedExtentGrid<int> tileCounts, PointBufferWrapper lowResBuffer, Grid<int> lowResGrid, Grid<int> lowResCounts, ProgressManager progressManager) { var quantizedExtent = source.QuantizedExtent; // generate counts and add points to buffer using (var process = progressManager.StartProcess("QuantTilePointsIndexedFilter")) { var group = new ChunkProcessSet(tileFilter, segmentBuffer); group.Process(source.GetBlockEnumerator(process)); } // sort points in buffer using (var process = progressManager.StartProcess("QuantTilePointsIndexedSort")) { var tilePositions = tileFilter.CreatePositionGrid(segmentBuffer, source.PointSizeBytes); var sortedCount = 0; foreach (var tile in tileFilter.GetCellOrdering()) { var currentPosition = tilePositions[tile.Row, tile.Col]; if (currentPosition.IsIncomplete) { while (currentPosition.IsIncomplete) { var p = (SQuantizedPoint3D*)currentPosition.DataPtr; var targetPosition = tilePositions[ (((*p).Y - quantizedExtent.MinY) / tileCounts.CellSizeY), (((*p).X - quantizedExtent.MinX) / tileCounts.CellSizeX) ]; if (targetPosition.DataPtr != currentPosition.DataPtr) { // the point tile is not the current traversal tile, // so swap the points and resume on the swapped point targetPosition.Swap(currentPosition.DataPtr); } else { // this point is in the correct tile, move on currentPosition.Increment(); } ++sortedCount; } if (!process.Update((float)sortedCount / segmentBuffer.PointCount)) break; } } } // TEST /*using (var process = progressManager.StartProcess("QuantTilePointsIndexedTEST")) { //var templateQuantizedExtent = quantizedExtent.ComputeQuantizedTileExtent(new SimpleGridCoord(0, 0), tileCounts); //var cellSizeX = (int)(templateQuantizedExtent.RangeX / lowResGrid.SizeX); //var cellSizeY = (int)(templateQuantizedExtent.RangeY / lowResGrid.SizeY); var sX2 = Math.Pow(source.Quantization.ScaleFactorX, 2); var sY2 = Math.Pow(source.Quantization.ScaleFactorY, 2); var sZ2 = Math.Pow(source.Quantization.ScaleFactorZ, 2); var index = 0; foreach (var tile in tileFilter.GetCellOrdering()) { var count = tileCounts.Data[tile.Row, tile.Col]; var dataPtr = segmentBuffer.PointDataPtr + (index * source.PointSizeBytes); var dataEndPtr = dataPtr + (count * source.PointSizeBytes); //var tileQuantizedExtent = quantizedExtent.ComputeQuantizedTileExtent(tile, tileCounts); //lowResGrid.Reset(); //var grid = Grid<int>.Create(); var pb = dataPtr; while (pb < dataEndPtr) { var p = (SQuantizedPoint3D*)pb; // meters? var searchRadius = 1; var pointsWithinRadius = 0; var pb2 = dataPtr; //while (pb2 < dataEndPtr) while (pb2 < (byte*)Math.Min((long)dataEndPtr, (long)(dataPtr + 20 * source.PointSizeBytes))) { var p2 = (SQuantizedPoint3D*)pb2; //var d2 = // sX2 * Math.Pow((*p2).X - (*p).X, 2) + // sY2 * Math.Pow((*p2).Y - (*p).Y, 2) + // sZ2 * Math.Pow((*p2).Z - (*p).Z, 2); //if (Math.Sqrt(d2) < searchRadius) //{ // ++pointsWithinRadius; //} pb2 += source.PointSizeBytes; } //(*p).Z = (int)(quantizedExtent.MinX + (pointsWithinRadius * 100) / source.Quantization.ScaleFactorZ); //var cellX = (((*p).X - tileQuantizedExtent.MinX) / cellSizeX); //var cellY = (((*p).Y - tileQuantizedExtent.MinY) / cellSizeY); //var offset = lowResGrid.Data[cellY, cellX]; //if (offset == -1) //{ // lowResGrid.Data[cellY, cellX] = (int)(pb - segmentBuffer.PointDataPtr); //} //else //{ // var pBest = (SQuantizedPoint3D*)(segmentBuffer.PointDataPtr + offset); // if ((*p).Z < (*pBest).Z) // lowResGrid.Data[cellY, cellX] = (int)(pb - segmentBuffer.PointDataPtr); //} pb += source.PointSizeBytes; ++index; } if (!process.Update((float)index / segmentBuffer.PointCount)) break; } }*/ // determine representative low-res points for each tile and swap them to a new buffer using (var process = progressManager.StartProcess("QuantTilePointsIndexedExtractLowRes")) { var removedBytes = 0; var templateQuantizedExtent = quantizedExtent.ComputeQuantizedTileExtent(new SimpleGridCoord(0, 0), tileCounts); var cellSizeX = (int)(templateQuantizedExtent.RangeX / lowResGrid.SizeX); var cellSizeY = (int)(templateQuantizedExtent.RangeY / lowResGrid.SizeY); var index = 0; foreach (var tile in tileFilter.GetCellOrdering()) { var count = tileCounts.Data[tile.Row, tile.Col]; var dataPtr = segmentBuffer.PointDataPtr + (index * source.PointSizeBytes); var dataEndPtr = dataPtr + (count * source.PointSizeBytes); var tileQuantizedExtent = quantizedExtent.ComputeQuantizedTileExtent(tile, tileCounts); lowResGrid.Reset(); var pb = dataPtr; while (pb < dataEndPtr) { var p = (SQuantizedPoint3D*)pb; var cellX = (((*p).X - tileQuantizedExtent.MinX) / cellSizeX); var cellY = (((*p).Y - tileQuantizedExtent.MinY) / cellSizeY); // todo: make lowResGrid <long> to avoid cast? var offset = lowResGrid.Data[cellY, cellX]; if (offset == -1) { lowResGrid.Data[cellY, cellX] = (int)(pb - segmentBuffer.PointDataPtr); } else { var pBest = (SQuantizedPoint3D*)(segmentBuffer.PointDataPtr + offset); //if ((*p).Z > (*pBest).Z) if ((*p).Z < (*pBest).Z) lowResGrid.Data[cellY, cellX] = (int)(pb - segmentBuffer.PointDataPtr); //var cellCenterX = (cellX + 0.5) * cellSizeX; //var cellCenterY = (cellY + 0.5) * cellSizeY; //var bd2 = DistanceRatioFromPointToCellCenter2(pBest, cellCenterX, cellCenterY, cellSizeX, cellSizeY); //var cd2 = DistanceRatioFromPointToCellCenter2(p, cellCenterX, cellCenterY, cellSizeX, cellSizeY); //if (cd2 < bd2) // lowResGrid.Data[cellY, cellX] = (int)(pb - segmentBuffer.PointDataPtr); } pb += source.PointSizeBytes; ++index; } // ignore boundary points lowResGrid.ClearOverflow(); // sort valid cells var offsets = lowResGrid.Data.Cast<int>().Where(v => v != lowResGrid.FillVal).ToArray(); if (offsets.Length > 0) { Array.Sort(offsets); // shift the data up to the first offset var tileSrc = (int)(dataPtr - segmentBuffer.PointDataPtr); Buffer.BlockCopy(segmentBuffer.Data, tileSrc, segmentBuffer.Data, (tileSrc - removedBytes), (offsets[0] - tileSrc)); // pack the remaining points for (var i = 0; i < offsets.Length; i++) { var currentOffset = offsets[i]; // copy point to buffer lowResBuffer.Append(segmentBuffer.Data, currentOffset, source.PointSizeBytes); // shift everything between here and the next offset var copyEnd = (i == offsets.Length - 1) ? (dataEndPtr - segmentBuffer.PointDataPtr) : (offsets[i + 1]); var copySrc = (currentOffset + source.PointSizeBytes); var copyDst = (currentOffset - removedBytes); var copyLen = (int)(copyEnd - copySrc); Buffer.BlockCopy(segmentBuffer.Data, copySrc, segmentBuffer.Data, copyDst, copyLen); removedBytes += source.PointSizeBytes; } lowResCounts.Data[tile.Row, tile.Col] = offsets.Length; } if (!process.Update((float)index / segmentBuffer.PointCount)) break; } } }
public PointCloudTileManager(IPointCloudBinarySource source) { m_id = IdentityManager.AcquireIdentity(GetType().Name); m_source = source; }
public static LASFile Create(string path, IPointCloudBinarySource source) { var pcbs = source as PointCloudSource; if (pcbs != null) { var lasFile = pcbs.FileHandler as LASFile; if (lasFile != null) { var evlrs = (new List<LASEVLR>(lasFile.m_evlrs) { new LASEVLR(new LASRecordIdentifier("Jacere", 0), null), new LASEVLR(new LASRecordIdentifier("Jacere", 1), null) }).ToArray(); var header = new LASHeader(new [] {lasFile.Header}, lasFile.m_vlrs, evlrs); return new LASFile(path, header, lasFile.m_vlrs, evlrs); } } // this will require more work return new LASFile(path); }
public PointCloudTileManager(IPointCloudBinarySource source) { m_id = IdentityManager.AcquireIdentity(GetType().Name); m_source = source; }
private static unsafe void QuantTilePointsIndexed(IPointCloudBinarySource source, PointBufferWrapper segmentBuffer, TileRegionFilter tileFilter, SQuantizedExtentGrid <int> tileCounts, PointBufferWrapper lowResBuffer, Grid <int> lowResGrid, Grid <int> lowResCounts, ProgressManager progressManager) { var quantizedExtent = source.QuantizedExtent; // generate counts and add points to buffer using (var process = progressManager.StartProcess("QuantTilePointsIndexedFilter")) { var group = new ChunkProcessSet(tileFilter, segmentBuffer); group.Process(source.GetBlockEnumerator(process)); } // sort points in buffer using (var process = progressManager.StartProcess("QuantTilePointsIndexedSort")) { var tilePositions = tileFilter.CreatePositionGrid(segmentBuffer, source.PointSizeBytes); var sortedCount = 0; foreach (var tile in tileFilter.GetCellOrdering()) { var currentPosition = tilePositions[tile.Row, tile.Col]; if (currentPosition.IsIncomplete) { while (currentPosition.IsIncomplete) { var p = (SQuantizedPoint3D *)currentPosition.DataPtr; var targetPosition = tilePositions[ (((*p).Y - quantizedExtent.MinY) / tileCounts.CellSizeY), (((*p).X - quantizedExtent.MinX) / tileCounts.CellSizeX) ]; if (targetPosition.DataPtr != currentPosition.DataPtr) { // the point tile is not the current traversal tile, // so swap the points and resume on the swapped point targetPosition.Swap(currentPosition.DataPtr); } else { // this point is in the correct tile, move on currentPosition.Increment(); } ++sortedCount; } if (!process.Update((float)sortedCount / segmentBuffer.PointCount)) { break; } } } } // TEST /*using (var process = progressManager.StartProcess("QuantTilePointsIndexedTEST")) * { * //var templateQuantizedExtent = quantizedExtent.ComputeQuantizedTileExtent(new SimpleGridCoord(0, 0), tileCounts); * //var cellSizeX = (int)(templateQuantizedExtent.RangeX / lowResGrid.SizeX); * //var cellSizeY = (int)(templateQuantizedExtent.RangeY / lowResGrid.SizeY); * * var sX2 = Math.Pow(source.Quantization.ScaleFactorX, 2); * var sY2 = Math.Pow(source.Quantization.ScaleFactorY, 2); * var sZ2 = Math.Pow(source.Quantization.ScaleFactorZ, 2); * * var index = 0; * foreach (var tile in tileFilter.GetCellOrdering()) * { * var count = tileCounts.Data[tile.Row, tile.Col]; * var dataPtr = segmentBuffer.PointDataPtr + (index * source.PointSizeBytes); * var dataEndPtr = dataPtr + (count * source.PointSizeBytes); * * //var tileQuantizedExtent = quantizedExtent.ComputeQuantizedTileExtent(tile, tileCounts); * * //lowResGrid.Reset(); * * * //var grid = Grid<int>.Create(); * * * var pb = dataPtr; * while (pb < dataEndPtr) * { * var p = (SQuantizedPoint3D*)pb; * * // meters? * var searchRadius = 1; * var pointsWithinRadius = 0; * * var pb2 = dataPtr; * //while (pb2 < dataEndPtr) * while (pb2 < (byte*)Math.Min((long)dataEndPtr, (long)(dataPtr + 20 * source.PointSizeBytes))) * { * var p2 = (SQuantizedPoint3D*)pb2; * * //var d2 = * // sX2 * Math.Pow((*p2).X - (*p).X, 2) + * // sY2 * Math.Pow((*p2).Y - (*p).Y, 2) + * // sZ2 * Math.Pow((*p2).Z - (*p).Z, 2); * * //if (Math.Sqrt(d2) < searchRadius) * //{ * // ++pointsWithinRadius; * //} * * pb2 += source.PointSizeBytes; * } * * //(*p).Z = (int)(quantizedExtent.MinX + (pointsWithinRadius * 100) / source.Quantization.ScaleFactorZ); * * * * //var cellX = (((*p).X - tileQuantizedExtent.MinX) / cellSizeX); * //var cellY = (((*p).Y - tileQuantizedExtent.MinY) / cellSizeY); * * //var offset = lowResGrid.Data[cellY, cellX]; * //if (offset == -1) * //{ * // lowResGrid.Data[cellY, cellX] = (int)(pb - segmentBuffer.PointDataPtr); * //} * //else * //{ * // var pBest = (SQuantizedPoint3D*)(segmentBuffer.PointDataPtr + offset); * * // if ((*p).Z < (*pBest).Z) * // lowResGrid.Data[cellY, cellX] = (int)(pb - segmentBuffer.PointDataPtr); * //} * * pb += source.PointSizeBytes; ++index; * } * * if (!process.Update((float)index / segmentBuffer.PointCount)) * break; * } * }*/ // determine representative low-res points for each tile and swap them to a new buffer using (var process = progressManager.StartProcess("QuantTilePointsIndexedExtractLowRes")) { var removedBytes = 0; var templateQuantizedExtent = quantizedExtent.ComputeQuantizedTileExtent(new SimpleGridCoord(0, 0), tileCounts); var cellSizeX = (int)(templateQuantizedExtent.RangeX / lowResGrid.SizeX); var cellSizeY = (int)(templateQuantizedExtent.RangeY / lowResGrid.SizeY); var index = 0; foreach (var tile in tileFilter.GetCellOrdering()) { var count = tileCounts.Data[tile.Row, tile.Col]; var dataPtr = segmentBuffer.PointDataPtr + (index * source.PointSizeBytes); var dataEndPtr = dataPtr + (count * source.PointSizeBytes); var tileQuantizedExtent = quantizedExtent.ComputeQuantizedTileExtent(tile, tileCounts); lowResGrid.Reset(); var pb = dataPtr; while (pb < dataEndPtr) { var p = (SQuantizedPoint3D *)pb; var cellX = (((*p).X - tileQuantizedExtent.MinX) / cellSizeX); var cellY = (((*p).Y - tileQuantizedExtent.MinY) / cellSizeY); // todo: make lowResGrid <long> to avoid cast? var offset = lowResGrid.Data[cellY, cellX]; if (offset == -1) { lowResGrid.Data[cellY, cellX] = (int)(pb - segmentBuffer.PointDataPtr); } else { var pBest = (SQuantizedPoint3D *)(segmentBuffer.PointDataPtr + offset); //if ((*p).Z > (*pBest).Z) if ((*p).Z < (*pBest).Z) { lowResGrid.Data[cellY, cellX] = (int)(pb - segmentBuffer.PointDataPtr); } //var cellCenterX = (cellX + 0.5) * cellSizeX; //var cellCenterY = (cellY + 0.5) * cellSizeY; //var bd2 = DistanceRatioFromPointToCellCenter2(pBest, cellCenterX, cellCenterY, cellSizeX, cellSizeY); //var cd2 = DistanceRatioFromPointToCellCenter2(p, cellCenterX, cellCenterY, cellSizeX, cellSizeY); //if (cd2 < bd2) // lowResGrid.Data[cellY, cellX] = (int)(pb - segmentBuffer.PointDataPtr); } pb += source.PointSizeBytes; ++index; } // ignore boundary points lowResGrid.ClearOverflow(); // sort valid cells var offsets = lowResGrid.Data.Cast <int>().Where(v => v != lowResGrid.FillVal).ToArray(); if (offsets.Length > 0) { Array.Sort(offsets); // shift the data up to the first offset var tileSrc = (int)(dataPtr - segmentBuffer.PointDataPtr); Buffer.BlockCopy(segmentBuffer.Data, tileSrc, segmentBuffer.Data, (tileSrc - removedBytes), (offsets[0] - tileSrc)); // pack the remaining points for (var i = 0; i < offsets.Length; i++) { var currentOffset = offsets[i]; // copy point to buffer lowResBuffer.Append(segmentBuffer.Data, currentOffset, source.PointSizeBytes); // shift everything between here and the next offset var copyEnd = (i == offsets.Length - 1) ? (dataEndPtr - segmentBuffer.PointDataPtr) : (offsets[i + 1]); var copySrc = (currentOffset + source.PointSizeBytes); var copyDst = (currentOffset - removedBytes); var copyLen = (int)(copyEnd - copySrc); Buffer.BlockCopy(segmentBuffer.Data, copySrc, segmentBuffer.Data, copyDst, copyLen); removedBytes += source.PointSizeBytes; } lowResCounts.Data[tile.Row, tile.Col] = offsets.Length; } if (!process.Update((float)index / segmentBuffer.PointCount)) { break; } } } }
public PointCloudTileSource Process(ProgressManager progressManager) { progressManager.Log("<= {0}", m_inputHandler.FilePath); PerformanceManager.Start(m_inputHandler.FilePath); // check for existing tile source LoadFromCache(progressManager); if (m_tileSource == null) { using (var process = progressManager.StartProcess("ProcessSet")) { m_binarySource = m_inputHandler.GenerateBinarySource(progressManager); m_tiledHandler = LASFile.Create(m_tiledHandler.FilePath, m_binarySource); using (var segmentBuffer = BufferManager.AcquireBuffer(m_id, (int)PROPERTY_SEGMENT_SIZE.Value, true)) { var tileManager = new PointCloudTileManager(m_binarySource); m_tileSource = tileManager.TilePointFileIndex(m_tiledHandler, segmentBuffer, progressManager); } #warning this was for xyz, but I have not yet re-implemented that anyway //if (m_binarySource.FilePath != m_inputHandler.FilePath) // File.Delete(m_binarySource.FilePath); if (m_tileSource.IsDirty) { m_tileSource.Close(); File.Delete(m_tileSource.FilePath); m_tileSource = null; process.LogTime("=> Processing Cancelled"); } else { process.LogTime("=> Processing Completed"); } } GC.Collect(); } TransferRate averageReadSpeed = PerformanceManager.GetReadSpeed(); TransferRate averageWriteSpeed = PerformanceManager.GetWriteSpeed(); Context.WriteLine("IO Read Speed: {0}", averageReadSpeed); Context.WriteLine("IO Write Speed: {0}", averageWriteSpeed); //{ // // test // Stopwatch stopwatch = new Stopwatch(); // stopwatch.Start(); // PointCloudTile tempTile = m_tileSource.TileSet[0, 0]; // Grid<float> grid = new Grid<float>(tempTile.Extent, 540, (float)m_tileSource.Extent.MinZ - 1.0f, true); // Grid<uint> quantizedGrid = new Grid<uint>(grid.SizeX, grid.SizeY, m_tileSource.Extent, true); // using (GridTileSource<float> gridSource = new GridTileSource<float>(m_tiledPath + ".grid", grid.SizeX, grid.SizeY, m_tileSource.TileSet.Cols, m_tileSource.TileSet.Rows)) // { // int tempBufferSize = (int)(m_tileSource.TileSet.Max(t => t.PointCount)); // byte[] tempBuffer = new byte[tempBufferSize * m_tileSource.PointSizeBytes]; // foreach (PointCloudTile tile in m_tileSource) // { // m_tileSource.LoadTileGrid(tile, tempBuffer, grid, quantizedGrid); // gridSource.WriteTile(tile.Col, tile.Row, grid.Data); // if (!progressManager.Update((float)tile.Index / m_tileSource.TileSet.TileCount)) // break; // } // //gridSource.ReadTile(tempTile.Col, tempTile.Row, grid.Data); // } // m_tileSource.Close(); // progressManager.Log(stopwatch, "Generated GRID"); //} return m_tileSource; }