# Fail to join faces with python

I would like to join two faces which are in the same mesh by using bmesh.utils.face_join(faces, remove=True), and the details from blender 2.78c API documentation show:

Firstly, I had a square plane whose vertices are((-1, -1, 0), (1, -1, 0), (1, 1, 0), (-1, 1, 0)) Secondly, I used the following codes to add a triangle plane whose vertices are ((0, 0, 0), (2, 2, 0), (2, -2, 0)) to the mesh containing the square plane.

And then joined the square plane and the triangle plane together.

import bpy
import bmesh
from mathutils import Vector

# Setting scene and camera
scene = bpy.context.scene

# All objects in Scene
objects_in_scene = scene.objects
# get the square plane
for obj in objects_in_scene:
if (hasattr(obj.data, "vertices")):
squareObj = obj
break

# vertices of the triangle plane
verts2 = [(0, 0, 0), (2, 2, 0), (2, -2, 0)]
squareObj.data.vertices[-3].co = verts2[0]
squareObj.data.vertices[-2].co = verts2[1]
squareObj.data.vertices[-1].co = verts2[2]

# change mode to editmode
bpy.ops.object.mode_set(mode='EDIT')
bm = bmesh.from_edit_mesh(squareObj.data)

# add the triangle face
bm.verts.ensure_lookup_table()
set_of_verts = set(bm.verts[i] for i in range(4,7))
bm.faces.new(set_of_verts)

# update the bmesh
bmesh.update_edit_mesh(squareObj.data)

# join the two faces and print the new face
print(bmesh.utils.face_join(bm.faces, remove=True))


However, I got the error message bellow:

TypeError: face_join() takes no keyword arguments

I modified the codes in the end line and use print(bmesh.utils.face_join(bm.faces)) instead.

The script could run but I got feedback, "None", which meant failure according to blender API documentation.

In fact, I am trying to merge two faces into one face with python like this.

I found this operation in blender 2.78c API documentation and tried it.

Please tell me if you have any suggestion about why can't use bmesh.utils.face_join(faces) and bmesh.utils.face_join(faces, remove=True), or how to merge two faces into one face with python.

Thank you in advanced.

• As the answer below noted. bmesh.utils.face_join(faces, remove=True) doesn't work as you think it does. It looks at the faces in question, and removes the inner-connecting edges and verts. If you use F2 plugin, you can try selecting 5 connected faces and press 'F' to see what it actually does. What you wanted to do is combining 2 separated meshes into one, while changing their topology. Boolean is the only thing I can think of that does what you want, but it works in volumes, probably won't work well in 2D. You can try the tinyCAD addon and see how it does that. Jul 23 '17 at 2:10
• i totally did not think about what the user actually wanted to do in my answer. Thanks for that! Jul 23 '17 at 9:14

okay so here is the information I can give you:

1. bmesh.utils.face_join(faces, remove=True) only works (in my tests) if the faces you provide are actually connected by an edge. If there is any other face involved that is not connected, the function will fail. This is the problem you are experiencing

therefore you need to programmatically select linked faces. (see 3.)

1. The indexes for the vertices are not guaranteed to be the same indexes. So range(4, 7) in your code in bmesh does not necessarily give you the same vertices you added earlier to the mesh.

I suggest, you add the face the same way you add the vertices, to the mesh datablock. Or, better, you should add the vertices to the bmesh like this:

v1 = bm.verts.new((2.0, 2.0, 2.0))
v2 = bm.verts.new((-2.0, 2.0, 2.0))
v3 = bm.verts.new((-2.0, -2.0, 2.0))

new_face = bm.faces.new((v1, v2, v3))


Edit: your new face might actually not share an edge with the existing faces. you should check that probably

1. Now that you have your face properly set up, you can try to feed linked faces into the bmesh.utils.face_join(linked_faces)

this is a function i wrote to get linked faces:

def get_linked_faces(f):

if f.tag:
return []

f.tag = True
# Select edges that link two faces
edges = [e for e in f.edges if len(e.link_faces) == 2]
for e in edges:
faces = [elem for elem in e.link_faces if not elem.tag]

if not len(faces) == 0:
for elem in faces:



you will get an array of linked face groups:

f_link_map = []
for face in bm.faces:
if not face.tag:

1. in the end of your operations it's also good practise to add

bm.free()

i hope that helps you. it took me quite a while to find out what the problem is in your case. also sorry, python formatting is quite an annoyance.

• Thanks a lot, it is really helpful. I tried your code and found two tiny problems. First one is f_linked.extend(get_linked_faces(elem)) in the line 13 in function get_linked_faces(f). I suggest to replace it with f_linked.extend(faces) because elem is not defined here. Second one is add f_link = [] for face in f_link_map: if face not in f_link: f_link.append(face)  after finding f_link_map because some faces were multiply added in f_link_map. Anyway, you did me a great favor, this problem has confused me a few days. Jul 23 '17 at 9:34
• i accidentally removed a line. i corrected it now. sorry for that Jul 23 '17 at 9:36
• Extra info: you can't replace it with f_linked.extend(faces) because it needs to be a recursive call. i will publish the commented code snippet and post it here later - so anyone can understand the code better Jul 23 '17 at 9:43