# how to create and extrude a bmesh face

I would like to programmatically create and extrude polygons. I've found several examples of code (e.g. here), but none of them are currently working for me. As a simple example, I am trying to get things working first with a defined circular face and then extrude that face. Here is the code defining the circular bmesh:

import bpy, bmesh
from math import *

NUMVERTS = 1000
Dphi = 2*pi/NUMVERTS
# calculate x,y coordinate pairs
coords = [(cos(i*Dphi),sin(i*Dphi),0) for i in range(NUMVERTS)]

bm = bmesh.new()
for v in coords:
bm.verts.new(v)
bm.faces.new(bm.verts)

bm.normal_update()

me = bpy.data.meshes.new("circle")
bm.to_mesh(me)
ob = bpy.data.objects.new("circle",me)
bpy.context.scene.update()


Which results in a 2D circle

I then want to extrude that face in z by some amount resulting in something like:

I would like to do everything in a python script without having to select anything in the GUI. Also, I'm using a circle as a placeholder example here -- I ultimately want to import much more complicated 2D (XY) polygons and extrude them in Z by some amount. Thanks!

Here is the extrusion part filled in:

import bpy, bmesh
from math import *
from mathutils import Vector

NUMVERTS = 1000
Dphi = 2*pi/NUMVERTS
# calculate x,y coordinate pairs
coords = [(cos(i*Dphi),sin(i*Dphi),0) for i in range(NUMVERTS)]

bm = bmesh.new()
for v in coords:
bm.verts.new(v)

# think of this new vertices as bottom of the extruded shape
bottom = bm.faces.new(bm.verts)

# next we create top via extrude operator, note it doesn't move the new face
# we make our 1 face into a list so it can be accepted to geom
top = bmesh.ops.extrude_face_region(bm, geom=[bottom])

# here we move all vertices returned by the previous extrusion
# filter the "geom" list for vertices using list constructor
bmesh.ops.translate(bm, vec=Vector((0,0,1)), verts=[v for v in top["geom"] if isinstance(v,bmesh.types.BMVert)])

bm.normal_update()

me = bpy.data.meshes.new("circle")
bm.to_mesh(me)
ob = bpy.data.objects.new("circle",me)
bpy.context.scene.update()


The hard part is grasping the habit of having this dictionary return type from the operations. It's a dictionary containing definition for "geom" that contains a single list where all the verts, edges and faces are listed one after another. You are then supposed to make a list of the verts, edges or faces with python list construction where you check for the element type using isinstance(), depending on what you need for each operation.

Similarly to the link in your q, can use bmesh operators, in this case I've used solidify, Note you must set the normal before calling the operator to get the desired result. Also note that face.normal = (0, 0, -1) (commented out) could (preferably?) be used in place of bm.normal_update().

import bpy, bmesh
from math import radians, sin, cos

NUMVERTS = 100
# calculate x,y coordinate pairs
coords = [(cos(i * Dphi), sin(i * Dphi), 0) for i in range(NUMVERTS)]

bm = bmesh.new()
verts = [bm.verts.new(v) for v in coords]

face = bm.faces.new(verts)
bm.normal_update()
# or face.normal = (0, 0, -1)
bmesh.ops.solidify(bm, geom=[face], thickness=1.0)

me = bpy.data.meshes.new("circle")
bm.to_mesh(me)
ob = bpy.data.objects.new("circle",me)


However I've found if you are going to do for multiple faces then making the "wall" faces is significantly faster. (that's my experience using similar to create 1000's of OSM buildings that are basically an extrusion of an ngon.)

import bpy, bmesh
from math import radians, cos, sin

from mathutils import Vector

NUMVERTS = 100
height = 1.0
# calculate x,y coordinate pairs
coords = [(cos(i * Dphi), sin(i * Dphi), 0) for i in range(NUMVERTS)]

bm = bmesh.new()
verts = [bm.verts.new(v) for v in coords]
roofverts = [bm.verts.new(v.co + Vector((0, 0, height))) for v in verts]
# pop one on the end to make ring
roofverts.append(roofverts[0])
verts.append(verts[0])
for i in range(len(roofverts) - 1):
wall = bm.faces.new([verts[i], roofverts[i], roofverts[i+1], verts[i+1]])
#wall.material_index = matidx
# pop off to remove.
verts.pop()
roofverts.pop()
floor = bm.faces.new(verts)
top = bm.faces.new(roofverts)

me = bpy.data.meshes.new("circle")
bm.to_mesh(me)