2
$\begingroup$

I want to split a mesh with random_selection.

My question is: How do I make sure that the "random_selection", selects the faces in a mesh to exact no. as specified by percentage. for example: A 10*10 Mesh contains 100 faces, so 50% of random selection should select exactly 50 faces, but in reality it selects sometime 48, 51, and so on. here is my noob Code:

import bpy
import bmesh

myob = bpy.ops.mesh
m = bpy.context.object
me = m.data

bpy.ops.mesh.select_all(action='TOGGLE')
bm = bmesh.from_edit_mesh(m.data)
face = bm.faces
myob.select_random(percent=50.0)
if len(bm.faces.select) == 100*50/100:
    bpy.ops.mesh.split
else:
    Pass 

I am newbei in Python scripting and blender APIs does not helping me in understanding it clearly on 'How to get access the face information in a mesh'

len(bm.faces) # Will tell the total faces in a mesh
bm.faces[i].select = true # Will select one face at a time

but, how do I know, How much faces are exactly been selected. Any suggestion:

Here is some code I tried:

for i in range(100):
    if bm.faces[i].select:
        fac.append(bm.faces[i])
        count += 1        
if len(fac) < 50:
    for i in range(50):
        if bm.faces[i].select == False:
            bm.faces[i].select = True
            fac.append(bm.faces[i])
        continue
    bmesh.update_edit_mesh(m.data, True)        
elif len(fac) > 50:
    print (count - 50, "are extra faces." )
    for j in range(100):
        if bm.faces[j].select == True:
            bm.faces[j].select = False
            if bm.faces[j] in fac:
                del fac[j] #problem here
        continue    
    bmesh.update_edit_mesh(m.data, True)
else:
    print ("Exactly 50 faces are selected")

I somehow manage to select missing faces to make them 50 faces, but how do I deselect and remove them from list of selected faces.

$\endgroup$
  • $\begingroup$ Is this different from your other 'splitting' question? $\endgroup$ – Ray Mairlot Oct 22 '16 at 17:46
  • $\begingroup$ If I get the answer of this question then this will help me solving my previous question. I thought to just break down my questions into small parts, so that I can easily get the response from genies. $\endgroup$ – mGm Oct 23 '16 at 0:27
  • $\begingroup$ Yes, random value will give expected value and not the exact. That's why I thought to iterate as long as it will select exactly 50 faces. <br/> I want to select exact portion specified by a percent and split it to make new mesh. I am also open to any other alternative other than random. The newly created meshes should not contain a chunk of consecutive faces. $\endgroup$ – mGm Oct 23 '16 at 11:24
  • $\begingroup$ A couple of things, can the mesh simply be created rather than using an existing mesh. To make sure you don't get large islands split down into smaller chunks, eg a 10 by 10 can be split into 25 lots of 2x2 meshes each with 2 randomly selected faces (for 50%) $\endgroup$ – batFINGER Oct 24 '16 at 11:30
  • $\begingroup$ Yes, to create a mesh with any method is acceptable. What I want to achieve is to split the mesh. I am trying to create a pattern of different objects that will be face duplicated on these split meshes. The pattern should be completed mixed in N by N mesh. $\endgroup$ – mGm Oct 24 '16 at 21:36
2
$\begingroup$

Here is another take, that randomly selects from all faces using randint(0, len(faces)) pops the selected face from faces list and adds to selected until the desired length is achieved.

import bpy
from random import randint

context = bpy.context
obj = context.edit_object
mesh = obj.data
# check that percent is between 0 and 100.
percent = 40
# test code to run in edit mode
import bmesh
bm = bmesh.from_edit_mesh(mesh)
# deselect all
for f in bm.faces:
    f.select = False
# amount that need to be selected (to nearest int)
select_count = int(percent * len(bm.faces) / 100)
# unselected 
faces = [f for f in bm.faces] # could use f.index
# selected
selected = []

while len(selected) < select_count:
    # choose randomly from faces
    i = randint(0, len(faces) - 1)

    # pop and select
    f = faces.pop(i)
    f.select = True
    selected.append(f) # or use f.index
bmesh.update_edit_mesh(mesh)

print("Selected %d of %d" % (len(selected), len(bm.faces)))
$\endgroup$
  • $\begingroup$ You might try str.format() instead of the old formatting at the end... stackoverflow.com/a/13452357/6655092 $\endgroup$ – JakeD Nov 1 '16 at 11:20
  • $\begingroup$ Your code is just half of the length of my version. I do not understand, why did you use Swap. If I omit swap line and insert 'i' in f = faces.pop(i). This will do still the same. $\endgroup$ – mGm Nov 2 '16 at 11:30
  • $\begingroup$ Yes you're right... forgot about indexing pop instead of swap n pop, will edit accordingly, $\endgroup$ – batFINGER Nov 2 '16 at 11:51
1
$\begingroup$
import bpy
import bmesh
myob = bpy.ops.mesh
m = bpy.context.object # objects in the context
me = m.data
bpy.ops.mesh.select_all(action='TOGGLE') #unselect all

bm = bmesh.from_edit_mesh(m.data) # bmesh represention of context data
face = bm.faces     #face coordinates and their indices

def selection(p):
    count = 0
    fac = [] # selected faces are stored in a list
    total = 0
    myob.select_random(percent=p) # random selection
    bmesh.update_edit_mesh(m.data, True) #update to see selection in viewport

 #make sure to iterate each face in a mesh

    for i in range(len(bm.faces)):
        if bm.faces[i].select:
        fac.append(bm.faces[i])
        count += 1        
    total += 1    
    #print ("total faces in the object are: ",total)

    percent = round(total * p / 100)

    if count < percent:
    #print (50 - count, "faces are missing.")
        diff  = int(percent - count)
        cont = 0
        ind = 0

        while (cont < diff):
            if bm.faces[ind].select == False:
                bm.faces[ind].select = True
                #fac.append(bm.faces[i])
                cont += 1
            else:    
                ind += 1
        bmesh.update_edit_mesh(m.data, True)
        print ("%s"%p, "percent of faces, in total",percent, "are selected")

     elif count > percent:
         #print (count - 50, "are extra faces." )
         diff = int(count - percent) #example 5, the next loop should remove these 5 selections from the mesh
         cont = 0
         ind = 0

         while (cont < diff):
             if bm.faces[ind].select == True:
                 bm.faces[ind].select = False
                 cont += 1
             else:
                 ind += 1   
         bmesh.update_edit_mesh(m.data, True)
         print ("%s"%p, "percent of faces, in total",percent, "are selected")
     else:
         print ("%s"%p, "percent of faces, in total",percent, "are selected")

 selection(40)

This chunk of code will select exact faces as specified by the percentage.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.