/// <summary> /// The internal implementation for point cloud read requests from Revit. /// </summary> /// <remarks>Both IPointCloudAccess.ReadPoints() and IPointSetIterator.ReadPoints() are served by this method.</remarks> /// <param name="rFilter">The point cloud filter.</param> /// <param name="buffer">The point cloud buffer.</param> /// <param name="nBufferSize">The maximum number of points in the buffer.</param> /// <param name="startIndex">The start index for points. Pass 0 if called from IPointCloudAccess.ReadPoints() or if this is the first /// call to IPointSetIterator.ReadPoints(). Pass the previous cumulative number of read points for second and successive calls to /// IPointSetIterator.ReadPoints().</param> /// <returns>The number of points read.</returns> protected unsafe int ReadSomePoints(PointCloudFilter rFilter, IntPtr buffer, int nBufferSize, int startIndex) { // Get the pointer to the buffer. CloudPoint *cpBuffer = (CloudPoint *)buffer.ToPointer(); int pointIndex = 0; int currentIndex = startIndex; int totalPoints = 0; int startCell = 0; Outline fullOutline = GetOutline(); // Test each cell until the first cell with needed points is found. for (int i = 0; i < m_storedCells.Count; i++) { PointCloudCellStorage cell = m_storedCells[i]; // Pass the cell outline to the filter. int filterResult = rFilter.TestCell(cell.LowerLeft, cell.UpperRight); // Filter result == -1 means the cell is completely out of scope for the filter. if (filterResult == -1) { continue; } // The cell is at least partially in scope. If the cell has more points than // the number read in previous calls, we should start with this cell. // If it has less points than the number read, the cell was already processed and we // should move to the next one. totalPoints += cell.NumberOfPoints; if (currentIndex < totalPoints) { startCell = i; currentIndex = Math.Max(0, startIndex - totalPoints); break; } } // Start with the current candidate cell and read cells until there are no more to read. for (int i = startCell; i < m_storedCells.Count; i++) { // Test the cell against the filter. PointCloudCellStorage cell = m_storedCells[i]; int filterResult = rFilter.TestCell(cell.LowerLeft, cell.UpperRight); // Filter result == -1 means the cell is entirely out of scope, skip it. if (filterResult == -1) { continue; } // Filter result == 0 means some part of the cell is in scope. // Prepare for cell is called to process the cell's points. if (filterResult == 0) { rFilter.PrepareForCell(fullOutline.MinimumPoint, fullOutline.MaximumPoint, cell.NumberOfPoints); } // Loop through all points in the cell. for (int j = currentIndex; j < cell.NumberOfPoints; j++) { // If we need to test the point for acceptance, use the filter to do so. // If filter result == 1 the entire cell was in scope, no need to test. if (filterResult == 0) { if (!rFilter.TestPoint(cell.PointsBuffer[j])) { continue; } } // Add the point to the buffer and increment the counter *(cpBuffer + pointIndex) = cell.PointsBuffer[j]; pointIndex++; // Stop when the max number of points is reached if (pointIndex >= nBufferSize) { break; } } // Stop when the max number of points is reached if (pointIndex >= nBufferSize) { break; } currentIndex = 0; } return(pointIndex); }
public IntPtrCloudPointBuffer(IntPtr buffer, int buffer_size) { m_buffer = (CloudPoint *)buffer; m_buffer_size = buffer_size; }