0
$\begingroup$

I would like to create a simple 3d shape from a list of vertices, so I wrote a Python script which subdivides a cube and uses the Shrinkwrap modifier.

After the shape is created, I would like to be able to select the faces and/or edges of the new shape. If I go into edit mode in the 3d view, I can select an entire face on the object I called "Final". However, if I look at the number of edges or faces in the Python console, I get a large number (in the case of my example, it says 96 faces). I am including an example using vertex points from a triangular prism, but I would like to do this with a polygon with an arbitrary number of vertices. I would like to be able to find the entire face for each of the sides of my object in Python.

import bpy
import bmesh
from mathutils import Vector,Euler
from bpy_extras.object_utils import AddObjectHelper, object_data_add

w = 2
h = 3
length = 4
        
verts = [
   Vector((w/2,0,0)),Vector((-w/2,0,0)),Vector((-w/2,0,-h)),
   Vector((0,length,0)),Vector((w/2,0,-h)),Vector((0,length,-h))]
   
mesh = bpy.data.meshes.new(name="New Object Mesh")
mesh.from_pydata(verts, [], [])
objpoints=object_data_add(bpy.context, mesh)
objsize=objpoints.dimensions
bpy.ops.mesh.primitive_cube_add()
objmod=bpy.context.active_object
objmod.dimensions=[1.3*objsize.x,1.3*objsize.y,1.3*objsize.z]
bpy.ops.object.mode_set(mode='EDIT')
bpy.ops.mesh.subdivide(number_cuts=3)
bpy.ops.object.mode_set(mode='OBJECT')
bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)

wrapmod = objmod.modifiers.new(name='shapefrompoints', type='SHRINKWRAP')
wrapmod.target = objpoints
wrapmod.wrap_method = 'NEAREST_VERTEX'
# apply the modifier so we have a real object
depsgraph = bpy.context.evaluated_depsgraph_get()
# apply modifier using depsgraph (dependency graph
# https://blender.stackexchange.com/questions/146559/how-do-i-get-a-mesh-data-block-with-modifiers-and-shape-keys-applied-in-blender
object_eval = objmod.evaluated_get(depsgraph)
obj=bpy.data.objects.new("Final",object_eval.data.copy())
bpy.context.collection.objects.link(obj)
$\endgroup$

1 Answer 1

2
$\begingroup$

1.The object which is created "Final" has to be selected before applying the modifier. Hence added the following: objf=bpy.data.objects.new("Final",object_eval.data.copy()) bpy.context.collection.objects.link(objf) bpy.context.view_layer.objects.active = objf objf.select_set(True)

  1. To remove doubles the following lines are added: bpy.ops.object.mode_set(mode='EDIT') bpy.ops.mesh.remove_doubles() bpy.ops.object.mode_set(mode='OBJECT')

  2. Modifier has to me named for it to effect: bpy.ops.object.modifier_apply(modifier='shapefrompoints')

  3. To verify the result: print("No of vertices",len(objf.data.vertices)," No of edges =",len(objf.data.edges),"No of polygons",len(objf.data.polygons))

the above after running the full code gives: Info: Removed 50 vertice(s) No of vertices 6 No of edges = 9 No of polygons 5 which is correct for the triangular prism.

=============================== Full code given below:

 import bpy
 import bmesh
 from mathutils import Vector,Euler
 from bpy_extras.object_utils import AddObjectHelper, object_data_add
 
 w = 2
 h = 3
 length = 4    
 verts = [
 Vector((w/2,0,0)),Vector((-w/2,0,0)),Vector((-w/2,0,-h)),
 Vector((0,length,0)),Vector((w/2,0,-h)),Vector((0,length,-h))]

 mesh = bpy.data.meshes.new(name="New Object Mesh")
 mesh.from_pydata(verts, [], [])
 objpoints=object_data_add(bpy.context, mesh)
 objsize=objpoints.dimensions

 bpy.ops.mesh.primitive_cube_add()
 objmod=bpy.context.active_object
 objmod.dimensions=[1.3*objsize.x,1.3*objsize.y,1.3*objsize.z]
 bpy.ops.object.mode_set(mode='EDIT')
 bpy.ops.mesh.subdivide(number_cuts=2)
 bpy.ops.object.mode_set(mode='OBJECT')
 bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)

 wrapmod = objmod.modifiers.new(name='shapefrompoints', type='SHRINKWRAP')
 wrapmod.target = objpoints
 wrapmod.wrap_method = 'NEAREST_VERTEX'
 # apply the modifier so we have a real object
 depsgraph = bpy.context.evaluated_depsgraph_get()
 # apply modifier using depsgraph (dependency graph
 # https://blender.stackexchange.com/questions/146559/how-do-i-get-a-mesh-data- 
 block-with-modifiers-and-shape-keys-applied-in-blender
 object_eval = objmod.evaluated_get(depsgraph)
 objf=bpy.data.objects.new("Final",object_eval.data.copy())
 bpy.context.collection.objects.link(objf)
 bpy.context.view_layer.objects.active = objf
 objf.select_set(True)
 bpy.ops.object.mode_set(mode='EDIT')
 bpy.ops.mesh.remove_doubles()
 bpy.ops.object.mode_set(mode='OBJECT')


 bpy.ops.object.modifier_apply(modifier='shapefrompoints')

 print("no of vertices",len(objf.data.vertices)," no of edges 
 =",len(objf.data.edges),"no of polygons",len(objf.data.polygons))   
$\endgroup$
1
  • $\begingroup$ Thank you. Your correction allows me to identify each of the sides of an arbitrary shape. Correctly using remove_doubles is the main part. However, if I understand modifiers correctly, I don't need to use both the dependency graph and modifier_apply., and the depsgraph method is more efficient. $\endgroup$
    – SJK
    Aug 30, 2021 at 15:20

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .