Hi. I would like to know how to get a sample of points of my polydata that are evenly distributed on the mesh surface. My input is a longBonePolyData.
Here is my code till now:
desiredNumberOfPoints = 1000
ratio = int(longBonePolyData.GetNumberOfPoints()/desiredNumberOfPoints)
sampleSource = vtk.vtkSphereSource()
sampleSource.SetRadius(1)
maskPointsFilter = vtk.vtkMaskPoints()
maskPointsFilter.SetInputData(longBonePolyData)
#This works but the sampling could be biased spatially I think
maskPointsFilter.SetOnRatio(ratio)
maskPointsFilter.RandomModeOn()
#This doesn't work the output is clustered spatially not evenly distributed.
#maskPointsFilter.SetRandomModeType(2)#SPATIALLY_STRATIFIED
#maskPointsFilter.SetMaximumNumberOfPoints(desiredNumberOfPoints)
maskPointsFilter.Update()
sampleGlyph3D = vtk.vtkGlyph3D()
sampleGlyph3D.SetInputConnection(maskPointsFilter.GetOutputPort())
sampleGlyph3D.SetSourceConnection(sampleSource.GetOutputPort())
sampleGlyph3D.ScalingOff()
sampleGlyph3D.Update()
#Visualize the glyph
But for this way the only improvement to the script I posted firstly is that the ratio can be any real number between 1 and 0.
I might have to stay with the first script because is the only one that works till now but my algorithm that uses those points as input would benefit if the points where evenly distributed over the mesh
It works, although the algorithm would make a little bit better registrations if the points of the meshes were evenly sampled from the meshes surface instead of randomly sampled like right now
If you keep using the vtkMaskPoint, I think you may be interested in the UNIFORM_SPATIAL_SURFACE that you can enable with a SetRandomModeType(4). It should do what you want.
Here is the corresponding doc extracted from ParaView for all random modes for this filter:
Randomized Id Strides picks points with random id increments starting at
Offset (the output probably isn't a statistically random sample). Random
Sampling generates a statistically random sample of the input, ignoring Offset
(fast - O(sample size)). Spatially Stratified Random Sampling is a variant of
random sampling that splits the points into equal sized spatial strata before
randomly sampling (slow - O(N log N)). The Uniform Spatial Distribution (Bound
based) samples points using random poisitions inside the bounds of the data
set and a point locator. The Uniform Spatial Distribution (Surface Sampling)
samples points randomly via an inverse transform on surface area of each cell
(3D cells are ignored). The Uniform Spatial Distribution (Volume Sampling)
samples points randomly sampled via an inverse transform on volume area of
each cell (2D cells are ignored).
Hi Charles. Thank for the answer but it doesn’t work. The points are clustered over the metaphysis and sparse around the diaphysis of the bone using the script I posted firstly with this options:
That result looks good. Although I think I’ll have to wait to Slicer to update its VTK version and try it. The idea is to launch the registration script inside Slicer or in the Slicer’s python interactor.
As the image above) shows (and I experienced this outside of VTK, too), surface-weighted random sampling produces highly non-uniform point distribution on surface meshes: points are often clumped together in small groups and there are huge empty areas between these clumps.
Can someone explain this? Is it just because the number of samples is relatively small (and the distribution would eventually become uniform when you reach hundreds of thousands of samples)?
Is there a solution in VTK that would provide more uniform distribution for few hundred or few thousand points? Is there a point sampler or a post-processing filter that would try to maximize distance between sample points on the surface?
Current Slicer version uses VTK9. The last stable release was still created with VTK8.
You can use vtkPoissonDiskSampler if you want evenly spaced points in your output. This filter guarantees that the output cannot have 2 points closer than Radius.
BTW. I just discovered a bug that can make the filter crash… I’ll push a fix.