How blender is Setup: In Blender I have created a triangle and extruded it. Selected an edge and created a new transform in the UI and named it "Edge.001" it is currently active. Now I have selected the edge perpendicular to it and I want to pull that edge along one of the custom defined transform's axis.

I am trying to write a python function to do the following.

  1. Make an extrusion of the selected edge.
  2. Transform the edge along a particular axis with defined length.

That is equivalent to doing:

  1. "Pressing" E to extrude and pressing "Esc" so that the duplicate is on top of the original edge
  2. With the custom user defined transform ('Edge.001") selected pressing "G" to grab and constraining along the y axis of the custom defined transform by pressing the short cut corresponding to the axis (lets say "y" axis) twice i.e. "YY".

I have the following code.

def pull_edge(axis,length):
    # Note: Please define axis before calling function
    # Extrude mesh but do not transform
    bpy.ops.mesh.extrude_region_move(MESH_OT_extrude_region={"mirror":False}, TRANSFORM_OT_translate={"value":(0, 0, 0), "constraint_axis":(False, False, False), "constraint_orientation":'GLOBAL', "mirror":False, "proportional":'DISABLED', "proportional_edit_falloff":'SMOOTH', "proportional_size":1, "snap":False, "snap_target":'CLOSEST', "snap_point":(0, 0, 0), "snap_align":False, "snap_normal":(0, 0, 0), "gpencil_strokes":False, "texture_space":False, "remove_on_cancel":False, "release_confirm":False})

# Pull along local axis
# Unclear how to do this.

I cannot understand how blender in the info panel gets those transform values they are different from the value specified while grabbing.

E.g. Grabbing an edge along y axis of the custom defined transform by a value of 0.26 seems to generate the values (-0.216937, 0.0633597, -3.36766e-009). This is what blender does.

bpy.ops.transform.translate(value=(-0.216937, 0.0633597, -3.36766e-009), constraint_axis=(False, True, False), constraint_orientation='Edge.001', mirror=False, proportional='DISABLED', proportional_edit_falloff='SMOOTH', proportional_size=1)

How do I proceed ?


1 Answer 1


I think http://web.purplefrog.com/~thoth/blender/python-cookbook/extrude-edge-along-custom-axis.html will accomplish your mission. Here's a copy in-line:

import bpy
import bmesh

def guess_edge_order(bm, edge):
    """ We need to create a new face,
    but if that face is going to have a normal consistent with an adjacent face
    we need to choose the order of the vertices carefully.
    v0 = edge.verts[0]
    v1 = edge.verts[1]
    if len(edge.link_faces) != 1:
        # it is going to be non-manifold.  balls!
        return v0, v1

    face = edge.link_faces[0]
    nverts = len(face.verts)

    i0 = [ i for i in range(nverts) if face.verts[i].index == v0.index]
    i0 = i0[0]
    #print(["indices", i0, face.verts[i0], face.verts[i1], i1])
    i1 = (i0 + 1)% nverts
    #print(["next", face.verts[i1] , "==", v1])

    # does the polarity of this edge match the order of the vertices on the face?
    if (face.verts[i1].index != v1.index):
        return v0, v1
        return v1,v0

def mission1(obj, axis, len):

    bm = bmesh.from_edit_mesh(obj.data)

    # collect a set of all the vertices from all selected edges (without duplicates)
    verts = set()
    for edge in bm.edges:
        if edge.select:

    # create new vertices "extruded" from the vertices of all the selected edges and
    # stash them in a hash so we can map from the old vertex to its extruded partner
    newverts = {}
    for v in verts:
        v2 = bm.verts.new( v.co + axis*len)
        newverts[v.index] = v2

    # for each selected edge create a new face from the original edge plus the extruded vertices
    for edge in bm.edges:
        if edge.select:
            v0,v1 = guess_edge_order(bm, edge)
            v2 = newverts[v1.index]
            v3 = newverts[v0.index]
            bm.faces.new( [v0, v1, v2, v3] )

    # if we don't do this, it will look silly in the editor, and maybe even cause problems during render

    # apply all the changes we made back to to the target mesh data
    bmesh.update_edit_mesh(obj.data, destructive=True)


obj = bpy.context.active_object
scn = bpy.context.scene
# which custom orientation are we using?
orientation = scn.orientations['Face']

m1 = obj.matrix_world.to_3x3().inverted() # this is what we need to map from world space to object space
m2 = orientation.matrix.transposed() # we transpose this so we can extract a column
global_axis = m2.row[z_axis] # this is the custom orientation axis we want in global space
axis = m1* global_axis # now we have the necessary extrusion vector in the object's local coordinate space

if True:
    print (m1*m2.row[x_axis])
    print (m1*m2.row[y_axis])
    print (axis)

mission1(obj, axis, 1.5)
  • $\begingroup$ Thank you seems to work did not understand the code. Will work towards extending its functionality. I am new to stack exchange not sure how to accept your answer. $\endgroup$
    – Aiena
    Commented Nov 12, 2015 at 8:08

You must log in to answer this question.

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