Skip to main content

This is modified version of TLousky answer in this script we use three factors to decide merging edges :

  • distance between their centers.
  • difference in length.
  • the angle between these edges.

you can drop any of them if it's not necessary in your scene, and this is the script :


import bpy, bmesh
from math import sin

bm = bmesh.from_edit_mesh( bpy.context.object.data )
bm.edges.ensure_lookup_table()

lt = 0.2 #length difference + -
dt = 0.2  #max distance 
at = 0.16  #max sin(angle)  (30°)

center  = lambda e : ( e.verts[0].co + e.verts[1].co ) / 2
length  = lambda e : ( e.verts[0].co - e.verts[1].co ).length
dist    = lambda v1, v2: (  v2 -  v1 ).length
sinAngle   = lambda e1, e2: abs(sin((e1.verts[1].co - e1.verts[0].co).angle(e2.verts[1].co - e2.verts[0].co))) 

i =-1
while i < len(bm.edges)-1:
    i +=1
    e = bm.edges[i]
    i = e.index 
    l = length(e)
    lmin = l-lt
    lmax = l+lt
    c = center(e)
    for oe in  bm.edges[i+1:]:
        if  lmin < length(oe) < lmax  and dist( center(oe), c) < dt and sinAngle(e, oe)<at :
            ev1, ev2 = e.verts[:]
            oev1, oev2 = oe.verts[:]
            print( ev2, oev2 )
            if dist(ev1.co, oev1.co ) < dist(ev1.co, oev2.co ) :
                if ev1 != oev1 : bmesh.ops.pointmerge( bm, verts = [ ev1, oev1 ], merge_co = ev1.co )
                if ev2 != oev2 : bmesh.ops.pointmerge( bm, verts = [ ev2, oev2 ], merge_co = ev2.co )
            else :
                if ev1 != oev2 : bmesh.ops.pointmerge( bm, verts = [ ev1, oev2 ], merge_co = ev1.co )
                if ev2 != oev1 : bmesh.ops.pointmerge( bm, verts = [ ev2, oev1 ], merge_co = ev2.co )
            bm.edges.ensure_lookup_table()
            i=-1
            break    

bmesh.update_edit_mesh(bpy.context.object.data ,True)
Chebhou
  • 19.7k
  • 54
  • 100