Add NearestToCentroid and NearestToCenter reductions to VoxelDownSample (#6807) - #7560
Open
MostafaFiroozi wants to merge 4 commits into
Open
MostafaFiroozi wants to merge 4 commits into
MostafaFiroozi wants to merge 4 commits into
Conversation
…Sample
Introduce a VoxelReduction enum with three modes:
- Centroid (default, preserves existing averaging behaviour)
- NearestToCentroid (returns the input point closest to the per-voxel
centroid, attributes copied through)
- NearestToCenter (returns the input point closest to the voxel's
geometric center, attributes copied through)
Both new modes are non-deforming: every output point is an actual input
point with its original normal, color, and covariance preserved. This
matches PDAL's VoxelCentroidNearestNeighbor and VoxelCenterNearestNeighbor
filters and CloudCompare's Spatial Subsampling.
NearestToCenter tracks the winner in a single pass since the voxel center
is known from the voxel index. NearestToCentroid uses a two-pass approach
(pass 1 computes centroids, pass 2 finds the closest input point) with the
voxel index cached per point to avoid recomputing floor((p - min)/voxel_size).
Fixes isl-org#6807
Expose VoxelReduction as a nested Python enum on PointCloud (Centroid, NearestToCentroid, NearestToCenter) using pybind11 native_enum, matching the pattern used by VoxelGrid.VoxelPoolingMode. Update voxel_down_sample binding with an optional 'reduction' argument defaulting to VoxelReduction.Centroid. Fix the docstring injector entry that previously carried a stray 'invert' key not applicable to voxel downsampling. Fixes isl-org#6807
Five new tests, co-located with the existing VoxelDownSample test: - NearestToCentroid: discriminating three-point single-voxel input, verifies point B is picked and its color copied through. - NearestToCenter: same input, verifies point A (equal to voxel center) is picked and its color copied through. - NearestToCenter_MultiVoxel: two voxels with distinct winners; confirms per-voxel accounting is not shared across voxels. - SingletonVoxel_AllModes: one-point-per-voxel degenerate case; all three modes must return the input point unchanged with attributes preserved. - InvalidVoxelSize_AllModes: voxel_size <= 0 must still throw for all three reduction modes. Input positions are chosen so that centroid, voxel center, and averaged centroid land at distinct points, letting one small cloud exercise all three modes. Fixes isl-org#6807
Added under Main / unreleased. References PDAL precedent and cites the new VoxelReduction enum. Note: PR number to be appended once the PR is opened. Fixes isl-org#6807
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #6807.
Adds a
VoxelReductionenum onPointCloud::VoxelDownSampleso callers can pick between the existing centroid averaging and two new keep-a-real-input-point modes:Centroid— the existing behaviour (default), so nothing breaks.NearestToCentroid— after computing the per-voxel centroid, returns the input point closest to it. Attributes are copied through.NearestToCenter— returns the input point closest to the voxel's geometric centre. Attributes are copied through.These are the same semantics PDAL exposes as
VoxelCentroidNearestNeighbor/VoxelCenterNearestNeighborand that CloudCompare labels "spatial subsampling — nearest to cell centre", so pipelines coming in from those tools now have a direct equivalent.The main motivation is that
Centroidaverages colour, normal and covariance across each voxel's contents. That's fine for smoothly-varying attributes but wrong for anything discrete — semantic class IDs, return numbers, colour that encodes a segmentation label. In those cases the two nearest modes preserve a real observation with its original attributes intact.A few implementation notes:
NearestToCenteris single-pass — the voxel centre is trivially known from the voxel index, so tracking the winner folds into the existing binning loop.NearestToCentroidis two-pass because centroids only settle after all points have been binned. To keep pass 2 cheap I cache each point's voxel index during pass 1 so we don't recomputefloor((p - min) / voxel_size).reductiondefaults toCentroid, so existing call sites are untouched.Tests added under
VoxelDownSampleNearestToCentroidandVoxelDownSampleNearestToCentercovering the asymmetric-cluster case where all three modes emit visibly different points. The existingVoxelDownSampletest still passes with the default parameter.