# Selecting random points of a PolyData (Stratified sampling)

**URL:** <https://discourse.vtk.org/t/selecting-random-points-of-a-polydata-stratified-sampling/7003>\
**Category:** Support\
**Created:** [October 28, 2021, 11:49am UTC](https://discourse.vtk.org/t/selecting-random-points-of-a-polydata-stratified-sampling/7003 "2021-10-28T11:49:19Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![mau\_igna\_06](https://discourse.vtk.org/user_avatar/discourse.vtk.org/mau_igna_06/32/8064_2.png) [@mau\_igna\_06](https://discourse.vtk.org/u/mau_igna_06)\
**Post date:** [October 28, 2021, 11:49am UTC](https://discourse.vtk.org/t/selecting-random-points-of-a-polydata-stratified-sampling/7003/1 "2021-10-28T11:49:19Z")

</div>

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:

```auto
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

```

---

<div class="post-metadata">

**Author:** ![will.schroeder](https://discourse.vtk.org/user_avatar/discourse.vtk.org/will.schroeder/32/233_2.png) [@will.schroeder](https://discourse.vtk.org/u/will.schroeder)\
**Post date:** [October 28, 2021, 11:55am UTC](https://discourse.vtk.org/t/selecting-random-points-of-a-polydata-stratified-sampling/7003/2 "2021-10-28T11:55:30Z")

</div>

You might also try vtkPolyDataPointSampler with random point generation

---

<div class="post-metadata">

**Author:** ![mau\_igna\_06](https://discourse.vtk.org/user_avatar/discourse.vtk.org/mau_igna_06/32/8064_2.png) [@mau\_igna\_06](https://discourse.vtk.org/u/mau_igna_06)\
**Post date:** [October 28, 2021, 12:10pm UTC](https://discourse.vtk.org/t/selecting-random-points-of-a-polydata-stratified-sampling/7003/3 "2021-10-28T12:10:28Z")

</div>

> You might also try vtkPolyDataPointSampler with random point generation

I tried but I coudn’t get it to give me less samplePoints than the original number of points of the inputPolyData. Am I using it wrong?

Here is another approach I tried that the output fails (is not a random distribution of points, thresholding is not working as expected):

```auto
polydata0 = vtk.vtkPolyData()
polydata0.ShallowCopy(boneModel0.GetPolyData())
sampleRatio0 = 0.1
randomSampleArray = np.random.default_rng().uniform(0,1,polydata0.GetNumberOfPoints())

selectionArray = vtk.vtkIntArray()
selectionArray.SetName("Selection")
selectionArray.SetNumberOfValues(polydata0.GetNumberOfPoints())
selectionArray.Fill(0)

for i in range(polydata0.GetNumberOfPoints()):
    if randomSampleArray[i] < sampleRatio0:
        selectionArray.SetTuple1(i,1)

pointScalars = polydata0.GetPointData()
pointScalars.AddArray(selectionArray)

thresholdFilter = vtk.vtkThreshold()
thresholdFilter.SetInputData(polydata0)
thresholdFilter.ThresholdBetween(0.9, 1.1)
thresholdFilter.SetInputArrayToProcess(0, 0, 0,
    vtk.vtkDataObject.FIELD_ASSOCIATION_POINTS,
    "Selection")
thresholdFilter.Update()
geometryFilter = vtk.vtkGeometryFilter()
geometryFilter.SetInputData(thresholdFilter.GetOutput())
geometryFilter.Update()

polydata0.ShallowCopy(geometryFilter.GetOutput())

```

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

---

<div class="post-metadata">

**Author:** ![will.schroeder](https://discourse.vtk.org/user_avatar/discourse.vtk.org/will.schroeder/32/233_2.png) [@will.schroeder](https://discourse.vtk.org/u/will.schroeder)\
**Post date:** [October 28, 2021, 12:18pm UTC](https://discourse.vtk.org/t/selecting-random-points-of-a-polydata-stratified-sampling/7003/4 "2021-10-28T12:18:22Z")

</div>

> I tried but I coudn’t get it to give me less samplePoints than the original number of points of the inputPolyData. Am I using it wrong?

I assume that you are experimenting with the Distance parameter

---

<div class="post-metadata">

**Author:** ![mau\_igna\_06](https://discourse.vtk.org/user_avatar/discourse.vtk.org/mau_igna_06/32/8064_2.png) [@mau\_igna\_06](https://discourse.vtk.org/u/mau_igna_06)\
**Post date:** [October 28, 2021, 12:22pm UTC](https://discourse.vtk.org/t/selecting-random-points-of-a-polydata-stratified-sampling/7003/5 "2021-10-28T12:22:26Z")

</div>

> I assume that you are experimenting with the Distance parameter

yes. Is it possible to get less points that inputPolyData number of points?

---

<div class="post-metadata">

**Author:** ![will.schroeder](https://discourse.vtk.org/user_avatar/discourse.vtk.org/will.schroeder/32/233_2.png) [@will.schroeder](https://discourse.vtk.org/u/will.schroeder)\
**Post date:** [October 28, 2021, 12:30pm UTC](https://discourse.vtk.org/t/selecting-random-points-of-a-polydata-stratified-sampling/7003/6 "2021-10-28T12:30:46Z")

</div>

I have no idea, that’s what source code is for 😉 It could be the filter needs a refresh, a MR/patch would be welcome.

---

<div class="post-metadata">

**Author:** ![marcomusy](https://discourse.vtk.org/user_avatar/discourse.vtk.org/marcomusy/32/95_2.png) [@marcomusy](https://discourse.vtk.org/u/marcomusy)\
**Post date:** [October 28, 2021, 5:33pm UTC](https://discourse.vtk.org/t/selecting-random-points-of-a-polydata-stratified-sampling/7003/7 "2021-10-28T17:33:10Z")

</div>

For that I often use the `vtkCleanPolyData` filter with `SetTolerance(value)` of the order of 0.1. The subsampled points will be evenly spaced.

---

<div class="post-metadata">

**Author:** ![mau\_igna\_06](https://discourse.vtk.org/user_avatar/discourse.vtk.org/mau_igna_06/32/8064_2.png) [@mau\_igna\_06](https://discourse.vtk.org/u/mau_igna_06)\
**Post date:** [October 28, 2021, 6:29pm UTC](https://discourse.vtk.org/t/selecting-random-points-of-a-polydata-stratified-sampling/7003/8 "2021-10-28T18:29:41Z")

</div>

Thanks but it takes a too long on 200 thousand points polydata.

The reason I opened this thread was because I was developing an algorithm to register two similar bones without user inputs. Here it is if you want to check out: [SVD ModelToModel Registration Idea - #4 - Development - 3D Slicer Community](https://discourse.slicer.org/t/svd-modeltomodel-registration-idea/20388/4)

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

---

<div class="post-metadata">

**Author:** ![marcomusy](https://discourse.vtk.org/user_avatar/discourse.vtk.org/marcomusy/32/95_2.png) [@marcomusy](https://discourse.vtk.org/u/marcomusy)\
**Post date:** [October 28, 2021, 7:34pm UTC](https://discourse.vtk.org/t/selecting-random-points-of-a-polydata-stratified-sampling/7003/9 "2021-10-28T19:34:58Z")

</div>

on my mac it takes 1.45sec to go from 200k to 200 and 0.3sec to go from 200k to 1k:

```python
from vedo import *
import numpy as np
import time

pts = Points(np.random.rand(200000, 3), r=8)
t0 = time.time()
pts.clean(0.05)
t1 = time.time()
print(pts.NPoints(), t1-t0)
show(pts, axes=1)

```

maybe you can random-select a subset and then “clean” that one, not sure if that helps…

---

<div class="post-metadata">

**Author:** ![mau\_igna\_06](https://discourse.vtk.org/user_avatar/discourse.vtk.org/mau_igna_06/32/8064_2.png) [@mau\_igna\_06](https://discourse.vtk.org/u/mau_igna_06)\
**Post date:** [October 28, 2021, 8:27pm UTC](https://discourse.vtk.org/t/selecting-random-points-of-a-polydata-stratified-sampling/7003/10 "2021-10-28T20:27:59Z")

</div>

I’ll try that

---

<div class="post-metadata">

**Author:** ![Charles\_Gueunet](https://discourse.vtk.org/user_avatar/discourse.vtk.org/charles_gueunet/32/239_2.png) [@Charles\_Gueunet](https://discourse.vtk.org/u/Charles_Gueunet)\
**Post date:** [October 29, 2021, 7:54am UTC](https://discourse.vtk.org/t/selecting-random-points-of-a-polydata-stratified-sampling/7003/11 "2021-10-29T07:54:26Z")

</div>

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:

```auto
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). 

```

---

<div class="post-metadata">

**Author:** ![mau\_igna\_06](https://discourse.vtk.org/user_avatar/discourse.vtk.org/mau_igna_06/32/8064_2.png) [@mau\_igna\_06](https://discourse.vtk.org/u/mau_igna_06)\
**Post date:** [October 29, 2021, 9:51am UTC](https://discourse.vtk.org/t/selecting-random-points-of-a-polydata-stratified-sampling/7003/12 "2021-10-29T09:51:53Z")

</div>

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:

```auto
maskPointsFilter.SetRandomModeType(4)#UNIFORM_SPATIAL_SURFACE 
maskPointsFilter.SetMaximumNumberOfPoints(desiredNumberOfPoints)

```

 ![UNIFORM_SPATIAL_SURFACE_mode_doesnt_work](https://discourse.vtk.org/uploads/default/original/2X/a/a8dde37938f56ca07221f3a0c333db8c355a5b7d.png)

---

<div class="post-metadata">

**Author:** ![Charles\_Gueunet](https://discourse.vtk.org/user_avatar/discourse.vtk.org/charles_gueunet/32/239_2.png) [@Charles\_Gueunet](https://discourse.vtk.org/u/Charles_Gueunet)\
**Post date:** [October 29, 2021, 9:55am UTC](https://discourse.vtk.org/t/selecting-random-points-of-a-polydata-stratified-sampling/7003/13 "2021-10-29T09:55:06Z")

</div>

Is your mesh a clean surface with only convex polygons ?

---

<div class="post-metadata">

**Author:** ![mau\_igna\_06](https://discourse.vtk.org/user_avatar/discourse.vtk.org/mau_igna_06/32/8064_2.png) [@mau\_igna\_06](https://discourse.vtk.org/u/mau_igna_06)\
**Post date:** [October 29, 2021, 10:00am UTC](https://discourse.vtk.org/t/selecting-random-points-of-a-polydata-stratified-sampling/7003/14 "2021-10-29T10:00:17Z")

</div>

I think so, yes. Only triangles I think.

 ![convexPolygonBone](https://discourse.vtk.org/uploads/default/original/2X/0/0d7111913150ba52a2389739516adfe3af1390dd.png)

---

<div class="post-metadata">

**Author:** ![Charles\_Gueunet](https://discourse.vtk.org/user_avatar/discourse.vtk.org/charles_gueunet/32/239_2.png) [@Charles\_Gueunet](https://discourse.vtk.org/u/Charles_Gueunet)\
**Post date:** [October 29, 2021, 10:07am UTC](https://discourse.vtk.org/t/selecting-random-points-of-a-polydata-stratified-sampling/7003/15 "2021-10-29T10:07:57Z")

</div>

So indeed, this is not the expected output. Which version of VTK are you using ?

Can you share the dataset ? (or any dataset on which you observe the problem)

---

<div class="post-metadata">

**Author:** ![mau\_igna\_06](https://discourse.vtk.org/user_avatar/discourse.vtk.org/mau_igna_06/32/8064_2.png) [@mau\_igna\_06](https://discourse.vtk.org/u/mau_igna_06)\
**Post date:** [October 29, 2021, 10:21am UTC](https://discourse.vtk.org/t/selecting-random-points-of-a-polydata-stratified-sampling/7003/16 "2021-10-29T10:21:22Z")

</div>

Here is the bone:

> **[deformedBone.stl](https://drive.google.com/file/d/1xjf7FUKwjQ7rB-nSOQ9AQzcv6sEZO_Qx/view?usp=sharing)**
>
> Google Drive file.

I think Slicer uses VTK 8 version, but I’m not sure

---

<div class="post-metadata">

**Author:** ![Charles\_Gueunet](https://discourse.vtk.org/user_avatar/discourse.vtk.org/charles_gueunet/32/239_2.png) [@Charles\_Gueunet](https://discourse.vtk.org/u/Charles_Gueunet)\
**Post date:** [October 29, 2021, 12:18pm UTC](https://discourse.vtk.org/t/selecting-random-points-of-a-polydata-stratified-sampling/7003/17 "2021-10-29T12:18:50Z")

</div>

This version of VTK does not contains the UNIFORM\_\* mode yet unfortunately 😕

Here is a result with ParaView using this mode:

 ![image](https://discourse.vtk.org/uploads/default/original/2X/b/b94685089951357ca86e1a0b33ce311635f149e2.jpeg)

Maybe you can use ParaView 5.9.1 or 5.10.0-RC1 or VTK 9 to extract these points ?

---

<div class="post-metadata">

**Author:** ![mau\_igna\_06](https://discourse.vtk.org/user_avatar/discourse.vtk.org/mau_igna_06/32/8064_2.png) [@mau\_igna\_06](https://discourse.vtk.org/u/mau_igna_06)\
**Post date:** [October 29, 2021, 12:50pm UTC](https://discourse.vtk.org/t/selecting-random-points-of-a-polydata-stratified-sampling/7003/18 "2021-10-29T12:50:23Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![lassoan](https://discourse.vtk.org/user_avatar/discourse.vtk.org/lassoan/32/50_2.png) [@lassoan](https://discourse.vtk.org/u/lassoan)\
**Post date:** [November 9, 2021, 7:46pm UTC](https://discourse.vtk.org/t/selecting-random-points-of-a-polydata-stratified-sampling/7003/19 "2021-11-09T19:46:27Z")

</div>

As the [image above](https://discourse.vtk.org/t/selecting-random-points-of-a-polydata-stratified-sampling/7003/17)) 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?

> [@mau\_igna\_06](#):
>
> I think Slicer uses VTK 8 version, but I’m not sure

Current Slicer version uses VTK9. The last stable release was still created with VTK8.

---

<div class="post-metadata">

**Author:** ![Yohann\_Bearzi](https://discourse.vtk.org/user_avatar/discourse.vtk.org/yohann_bearzi/32/671_2.png) [@Yohann\_Bearzi](https://discourse.vtk.org/u/Yohann_Bearzi)\
**Post date:** [November 9, 2021, 9:17pm UTC](https://discourse.vtk.org/t/selecting-random-points-of-a-polydata-stratified-sampling/7003/20 "2021-11-09T21:17:59Z")

</div>

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.

 ![bone](https://discourse.vtk.org/uploads/default/original/2X/6/6bca2f85b238ccbb4a91fc9cd238c24c9cb17654.jpeg)

[Next page](https://discourse.vtk.org/t/selecting-random-points-of-a-polydata-stratified-sampling/7003.md?page=2)
