# Bmesh bevel is inverted

This looks cool and all, but it's beveled in the wrong direction. How can I flip the direction it bevels, so it looks more like a rounded cube, rather than a rounded plus-sign?

import bpy
import bmesh

from bpy.props import (
BoolProperty,
BoolVectorProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
)

#Returns all edges parallel to x-axis:
def get_x_parallel_edges(bm):
#The returned list of edges:
e_list = []

#Look for all the edges that
#run parallel to the x-axis:
for f in bm.faces:
for e in f.edges:
#Rename the coords:
ey0 = e.verts[0].co.y
ey1 = e.verts[1].co.y
ez0 = e.verts[0].co.z
ez1 = e.verts[1].co.z
#Check them:
if ey0 == ey1 and ez0 == ez1:
#Check for duplicates:
is_duplicate = False
for el in e_list:
if el == e:
is_duplicate = True
if not is_duplicate:
e_list += [e]

return e_list

#Break a list of edges
#into a list of verts:
def get_v_from_e(edges):
#The returned list of verts:
v_list = []

#Break apart the edges into verts:
for e in edges:
for v in e.verts:
#Check for duplicates:
is_duplicate = False
for vl in v_list:
if vl == v:
is_duplicate = True
if not is_duplicate:
v_list += [v]
return v_list

bl_options = {'REGISTER', 'UNDO'}

length = FloatProperty(
name="Length",
description="Box Length",
min=0.01, max=100.0,
default=4.0,
)
width = FloatProperty(
name="Width",
description="Box Width",
min=0.01, max=100.0,
default=3.0,
)
height = FloatProperty(
name="Height",
description="Box Height",
min=0.01, max=100.0,
default=2.0,
)
bev_seg = IntProperty(
name="Segments",
description="Bevel Segments",
min=1, max=100,
default=3,
)
bev_offset = FloatProperty(
name="Offset",
description="Bevel Offset",
min=0.01, max=100.0,
default=0.125,
)

def execute(self, context):

#Rename the variables:
l = self.length
w = self.width
h = self.height
seg = self.bev_seg
b_offset = self.bev_offset

#Make the cube object stuff:
mesh = bpy.data.meshes.new("cube")
cube_obj = bpy.data.objects.new("Cube_Obj", mesh)

scene = bpy.context.scene
bm = bmesh.new()

bmesh.ops.create_cube(bm, size=0.5)
#Apply size:
bmesh.ops.scale(bm, vec=(l, w, h))

#First, get the verts and edges:
e_geom = get_x_parallel_edges(bm)
v_geom = get_v_from_e(e_geom)
#Now bevel:
bmesh.ops.bevel(bm,
geom=v_geom[:] + e_geom[:],
offset=b_offset,
offset_type=0,
segments=seg,
clamp_overlap=True)

bm.to_mesh(mesh)
mesh.update()

return {'FINISHED'}

def register():

def unregister():

if __name__ == "__main__":
register()


Set the profile

basically your issue was using the default value of 0.0 for the profile property of the bevel operator. I have set it to 0.5 below. Might be a contender for another operator property.

Test code including, what I believe are simpler, routines for finding parallel edges and the vertices they contain. also added some notes re upgrading to 2.8

import bpy
import bmesh
from mathutils import Vector

from bpy.props import (
BoolProperty,
BoolVectorProperty,
FloatProperty,
FloatVectorProperty,
IntProperty,
)

#Test if edge e parallel to vector v:
def parallel(e, v, eps=1e-6):
# normalized edge direction vector
d = (e.verts[1].co - e.verts[0].co).normalized()
return abs(v.normalized().dot(d)) >= 1 - eps

bl_options = {'REGISTER', 'UNDO'}

length = FloatProperty(
name="Length",
description="Box Length",
min=0.01, max=100.0,
default=4.0,
)
width = FloatProperty(
name="Width",
description="Box Width",
min=0.01, max=100.0,
default=3.0,
)
height = FloatProperty(
name="Height",
description="Box Height",
min=0.01, max=100.0,
default=2.0,
)
bev_seg = IntProperty(
name="Segments",
description="Bevel Segments",
min=1, max=100,
default=3,
)
bev_offset = FloatProperty(
name="Offset",
description="Bevel Offset",
min=0.01, max=100.0,
default=0.125,
)

def execute(self, context):

#Make the cube object stuff:
mesh = bpy.data.meshes.new("cube")
cube_obj = bpy.data.objects.new("Cube_Obj", mesh)

scene = context.scene
bm = bmesh.new()

bmesh.ops.create_cube(bm, size=0.5)
#Apply size:
bmesh.ops.scale(bm,
verts=bm.verts,
vec=(self.length, self.width, self.height))

#First, get the verts and edges:
x_axis = Vector((1, 0, 0))
e_geom = [e for e in bm.edges if parallel(e, x_axis)]
v_geom = set(v for e in e_geom for v in e.verts)
#Now bevel:
bmesh.ops.bevel(bm,
geom=list(v_geom) + e_geom[:],
offset=self.bev_offset,
offset_type=0,
# offset_type='OFFSET',
profile=0.5,
segments=self.bev_seg,
clamp_overlap=True)

bm.to_mesh(mesh)
mesh.update()

return {'FINISHED'}

def register():