Example #1
0
        public PointCloudTileSource(LASFile file, PointCloudTileSet tileSet, Statistics zStats)
            : base(file, tileSet.PointCount, tileSet.Extent, file.Header.Quantization, file.Header.OffsetToPointData, (short)file.Header.PointDataRecordLength)
        {
            m_file = file;

            m_id = IdentityManager.AcquireIdentity(GetType().Name);

            m_tileSet            = tileSet;
            m_tileSet.TileSource = this;

            m_statisticsZ          = zStats;
            m_statisticsQuantizedZ = zStats.ConvertToQuantized(Quantization);

            m_lowResBuffer = BufferManager.AcquireBuffer(m_id, tileSet.LowResCount * PointSizeBytes);

            m_file.UpdateEVLR(new LASRecordIdentifier("Jacere", 0), TileSet);
            m_file.UpdateEVLR(new LASRecordIdentifier("Jacere", 1), StatisticsZ);
        }
Example #2
0
        public PointCloudTile(PointCloudTileSet tileSet, ushort col, ushort row, int validIndex, long offset, int count, int lowResOffset, int lowResCount)
        {
            if (count == 0)
            {
                throw new ArgumentException("count");
            }

            TileSet = tileSet;

            m_row        = row;
            m_col        = col;
            PointCount   = count;
            LowResOffset = lowResOffset;
            LowResCount  = lowResCount;

            PointOffset = offset;
            ValidIndex  = validIndex;
        }
Example #3
0
        public PointCloudTileSource TilePointFileIndex(LASFile tiledFile, BufferInstance segmentBuffer, ProgressManager progressManager)
        {
            var stopwatch = new Stopwatch();

            stopwatch.Start();

            var analysis        = AnalyzePointFile(segmentBuffer.Length, progressManager);
            var quantizedExtent = m_source.QuantizedExtent;
            var tileCounts      = analysis.Density.GetTileCountsForInitialization();

            var fileSize = tiledFile.PointDataOffset + (m_source.PointSizeBytes * m_source.Count);

            AttemptFastAllocate(tiledFile.FilePath, fileSize);

            var lowResPointCountMax = PROPERTY_MAX_LOWRES_POINTS.Value;
            var lowResBuffer        = BufferManager.AcquireBuffer(m_id, lowResPointCountMax * m_source.PointSizeBytes);
            var lowResWrapper       = new PointBufferWrapper(lowResBuffer, m_source.PointSizeBytes, lowResPointCountMax);

            var validTiles          = analysis.GridIndex.Sum(r => r.GridRange.ValidCells);
            var lowResPointsPerTile = lowResPointCountMax / validTiles;
            var lowResTileSize      = (ushort)Math.Sqrt(lowResPointsPerTile);

            var lowResGrid = Grid <int> .Create(lowResTileSize, lowResTileSize, true, -1);

            var lowResCounts = tileCounts.Copy <int>();

            using (var outputStream = StreamManager.OpenWriteStream(tiledFile.FilePath, fileSize, tiledFile.PointDataOffset))
            {
                var i = 0;
                foreach (var segment in analysis.GridIndex)
                {
                    progressManager.Log("~ Processing Index Segment {0}/{1}", ++i, analysis.GridIndex.Count);

                    var sparseSegment        = m_source.CreateSparseSegment(segment);
                    var sparseSegmentWrapper = new PointBufferWrapper(segmentBuffer, sparseSegment);

                    var tileRegionFilter = new TileRegionFilter(tileCounts, quantizedExtent, segment.GridRange);

                    // this call will fill the buffer with points, add the counts, and sort
                    QuantTilePointsIndexed(sparseSegment, sparseSegmentWrapper, tileRegionFilter, tileCounts, lowResWrapper, lowResGrid, lowResCounts, progressManager);
                    var segmentFilteredPointCount = tileRegionFilter.GetCellOrdering().Sum(t => tileCounts.Data[t.Row, t.Col]);
                    var segmentFilteredBytes      = segmentFilteredPointCount * sparseSegmentWrapper.PointSizeBytes;

                    // write out the buffer
                    using (var process = progressManager.StartProcess("WriteIndexSegment"))
                    {
                        var segmentBufferIndex = 0;
                        foreach (var tile in segment.GridRange.GetCellOrdering())
                        {
                            var tileCount = tileCounts.Data[tile.Row, tile.Col];
                            if (tileCount > 0)
                            {
                                var tileSize = (tileCount - lowResCounts.Data[tile.Row, tile.Col]) * sparseSegmentWrapper.PointSizeBytes;
                                outputStream.Write(sparseSegmentWrapper.Data, segmentBufferIndex, tileSize);
                                segmentBufferIndex += tileSize;

                                if (!process.Update((float)segmentBufferIndex / segmentFilteredBytes))
                                {
                                    break;
                                }
                            }
                        }
                    }

                    if (progressManager.IsCanceled())
                    {
                        break;
                    }
                }

                // write low-res
                var lowResActualPointCount = lowResCounts.Data.Cast <int>().Sum();
                outputStream.Write(lowResWrapper.Data, 0, lowResActualPointCount * lowResWrapper.PointSizeBytes);
            }

            var actualDensity = new PointCloudTileDensity(tileCounts, m_source.Quantization);
            var tileSet       = new PointCloudTileSet(m_source, actualDensity, tileCounts, lowResCounts);
            var tileSource    = new PointCloudTileSource(tiledFile, tileSet, analysis.Statistics);

            if (!progressManager.IsCanceled())
            {
                tileSource.IsDirty = false;
            }

            tileSource.WriteHeader();

            return(tileSource);
        }
Example #4
0
        public List <PointCloudBinarySourceEnumeratorSparseGridRegion> GetGridIndex(PointCloudTileDensity density, int maxSegmentLength)
        {
            var maxSegmentPointCount = (maxSegmentLength / m_source.PointSizeBytes);

            // update index cells
            var indexGrid = (SQuantizedExtentGrid <GridIndexCell>)m_grid.Copy <GridIndexCell>();

            for (var i = 0; i < m_chunkTiles.Count; i++)
            {
                foreach (var tileIndex in m_chunkTiles[i])
                {
                    var coord     = new PointCloudTileCoord(tileIndex);
                    var indexCell = indexGrid.Data[coord.Row, coord.Col];
                    if (indexCell == null)
                    {
                        indexCell = new GridIndexCell();
                        indexGrid.Data[coord.Row, coord.Col] = indexCell;
                    }
                    indexCell.Add(i);
                }
            }
            indexGrid.CorrectCountOverflow();

            var actualGrid = density.CreateTileCountsForInitialization(m_source);

            var regionSourcesBySegment = new List <List <Range> >();
            var tilesPerSegment        = new List <GridRange>();
            var pointDataBytes         = m_source.PointSizeBytes * m_source.Count;

            var tileOrder      = PointCloudTileSet.GetTileOrdering(actualGrid.SizeY, actualGrid.SizeX).ToArray();
            var tileOrderIndex = 0;

            while (tileOrderIndex < tileOrder.Length)
            {
                var segmentTilesFromEstimation = new HashSet <int>();
                var segmentChunks = new HashSet <int>();

                var startTile      = tileOrder[tileOrderIndex];
                var startTileIndex = new GridCoord(actualGrid.Def, startTile.Row, startTile.Col);

                var segmentProbableValidTileCount = 0;

                var segmentPointCount = 0;

                while (tileOrderIndex < tileOrder.Length)
                {
                    var tile = tileOrder[tileOrderIndex];

                    // unfortunately, I cannot check the actual counts, because they have not been measured
                    // instead, I can count the estimated area, and undershoot

                    // get unique tiles/chunks

                    var uniqueEstimatedCoords = indexGrid
                                                .GetCellCoordsInScaledRange(tile.Col, tile.Row, actualGrid)
                                                .Where(c => !segmentTilesFromEstimation.Contains(c.Index))
                                                .ToList();

                    // count probable valid tiles for low-res estimation
                    if (uniqueEstimatedCoords.Count > 0)
                    {
                        var uniquePointCount = uniqueEstimatedCoords.Sum(c => m_grid.Data[c.Row, c.Col]);

                        if (segmentPointCount + uniquePointCount > maxSegmentPointCount)
                        {
                            break;
                        }

                        var uniqueChunks = uniqueEstimatedCoords
                                           .Select(c => indexGrid.Data[c.Row, c.Col])
                                           .SelectMany(c => c.Chunks)
                                           .ToHashSet(segmentChunks);

                        // no longer limiting the chunks per segment to fit buffer.
                        // this means that the full chunk data will almost certainly
                        // *not* fit in the segment buffer, but the filtered data will.

                        // merge tiles/chunks
                        foreach (var coord in uniqueEstimatedCoords)
                        {
                            segmentTilesFromEstimation.Add(coord.Index);
                        }

                        foreach (var index in uniqueChunks)
                        {
                            segmentChunks.Add(index);
                        }

                        segmentPointCount += uniquePointCount;

                        ++segmentProbableValidTileCount;
                    }

                    ++tileOrderIndex;
                }

                if (segmentChunks.Count > 0)
                {
                    var endTile      = tileOrder[tileOrderIndex - 1];
                    var endTileIndex = new GridCoord(actualGrid.Def, endTile.Row, endTile.Col);

                    // group by sequential regions
                    var sortedCellList = segmentChunks.ToArray();
                    Array.Sort(sortedCellList);
                    var regions            = new List <Range>();
                    var sequenceStartIndex = 0;
                    while (sequenceStartIndex < sortedCellList.Length)
                    {
                        // find incremental sequence
                        int i = sequenceStartIndex;
                        ++i;
                        while (i < sortedCellList.Length && (sortedCellList[i] == sortedCellList[i - 1] + 1))
                        {
                            ++i;
                        }
                        regions.Add(new Range(sortedCellList[sequenceStartIndex], i - sequenceStartIndex));
                        sequenceStartIndex = i;
                    }

                    regionSourcesBySegment.Add(regions);
                    tilesPerSegment.Add(new GridRange(startTileIndex, endTileIndex, segmentProbableValidTileCount));
                }
            }

            var chunkRangeSumForAllSegments = regionSourcesBySegment.Sum(r => r.Sum(r2 => r2.Count));

            Context.WriteLine("chunkRangeSumForAllSegments: {0}", chunkRangeSumForAllSegments);
            Context.WriteLine("  ratio: {0}", (double)chunkRangeSumForAllSegments * BufferManager.BUFFER_SIZE_BYTES / pointDataBytes);

            return(regionSourcesBySegment.Select((t, i) => new PointCloudBinarySourceEnumeratorSparseGridRegion(t, tilesPerSegment[i], m_maxPointCountPerChunk)).ToList());
        }