# Delete all the points of a mesh excepting N random ones using Geometry Nodes

I would like to, given a mesh, delete all the points of it excepting a number N of them (N any integer smaller than the number of vertices of the mesh). (Using Geometry Nodes in Blender 3.1)

• if the mesh exists, not GN generated, then Mesh > Sort Elements > Randomize would be enough to then simply select by index with a single node... porting that 'sort elements' operator would make a very useful node to have Feb 28, 2022 at 13:55

I found a good (perfect?) solution by using a pseudo random value to randomize the index (through multiply+modulo)

It is important to use a prime number as multiplier, else the module will have the same result for multiple inputs.

Explaination: The bottom Domain Size gives the upper limit for your points. The index of the larger point cloud is scrambled and every index still exists only once. When the "upper" part of the indexes is truncated, it will not take exact 200-400, but 200 random values between 0 and 400

This is the easiest way I know of to delete a certain percentage of a geometry, in this case a Suzanne with faces and edges already removed:

Maybe that's already enough for your use case. If not, thinking about how to tie that probability value to a more precise number of points to keep (not delete), I moved towards something like this:

Here's a link to its bigger static image. What it's doing:

• Getting the geometry's number of points using an Attribute Statistic node, fed with its index number (adding +1 to it since index numbers start with 0).
• Subtracting from that number the amount of vertices we'd like to keep, so we get the number of points to delete. This is linked to the Group Input so we can control it from the modifier tab. If we wanted to control the number of vertices to delete instead, we'd skip this part.
• Divide the number of points to delete by the current number of vertices to calculate the percentage of it to feed into the the Random Value node's probability so only that much is selected for deletion.

This largely works, but there's a problem: we limit it to around the numbers we want, but it's still a probability. If we have 100 points and we use a Random Value probability of %50 (0.5), it's not a guarantee that exactly 50 points get deleted. Sometimes it's 49, sometimes 55... so it's not perfectly precise. One workaround would be to play with the seed number until we get the exact number we want case by case, though admittedly not a very elegant solution. I'll keep looking to see if there's a way.

• One could instead of Delete Geometry, use a Separate Geometry and add or remove elements from either outputs depending on the case afterwards, counting the elements with an attribute statistic node Feb 27, 2022 at 21:41
• @Gorgious I thought about doing something like that, but since we're doing the "add or remove elements" part randomly, we're still limited by the imprecise nature of the probability slider so we don't know how many times we have to do that, no? If we had loops, that'd be easier—count and remove/add until you inevitably get to number N, but we don't. Or did I misunderstand you? Feb 27, 2022 at 21:48
• This is the provisional solution that I'm using, but, as you said, the number of points will fluctuate around the desire number. Feb 28, 2022 at 1:07

I am not sure whether this is possible by a "vanilla" geometry nodes solution. So i had to use python to get a random list of vertex weights.

What you need:

1. an object

3. select that object, run script

Be careful - the script is NOT bullet proof. It just takes the vertices from the active vertex group.

import bpy
import random

dict = {}
ob = bpy.context.active_object #any object will do

index = 0

shuffleList = []

for i in range(len(ob.data.vertices)):
shuffleList.append(i)

print (shuffleList)

random.shuffle(shuffleList)

print ("shuffled:",shuffleList)

index = 0

for v in range(len(ob.data.vertices)):
try:
dict[v] = ob.vertex_groups.active.weight(v)
except RuntimeError:
dict[v] = 0

print("dict before:")
print(dict)

index = 0

for v in range(len(ob.data.vertices)):

index += 1

for v in range(len(ob.data.vertices)):
try:
dict[v] = ob.vertex_groups.active.weight(v)
except RuntimeError:
dict[v] = 0

print("dict after:")
print(dict)

1. add the geometry nodes modifier with this node setup:

The script just creates random weights on the vertices from 0 to (1 / numberOfVertices).

The geometry nodes modifier just "cuts" that vertices with these weights "out".

result: