7
$\begingroup$

There is "remove doubles" function for removing overlapping vertices and it works nice. But sometimes I'd like to see which vertices will be merged in order to decide whether I actually need to remove them or not. So in this case selecting them first (specifying distance threshold) to highlight would be useful. Unfortunately I have not found any such option in "select all by trait"

$\endgroup$
1
  • $\begingroup$ I have been using Blender for years, never even thought about that feature. I'll be super interested in any answers that are posted. $\endgroup$
    – J Sargent
    Commented Nov 30, 2016 at 23:35

1 Answer 1

8
$\begingroup$

Ok, here the script that adds button with such function to "Select" > "Select All by Trait" menu. Feel free to improve.

Edit: Updated to blender 3.4.1

bl_info = {
    "name": "Select Doubles",
    "author": "Lambdadelta",
    "version": (1, 1),
    "blender": (3, 4, 1),
    "location": "(Edit Mode) Select > Select All by Trait",
    "description": "Select all overlapped vertices.",
    "warning": "",
    "tracker_url": "https://blender.stackexchange.com/questions/68326",
    "category": "Mesh",
}


import bpy, bmesh
from mathutils import kdtree


def select_by_distance(context, distance):
    ob = context.object
    me = ob.data
    bm = bmesh.from_edit_mesh(me)
    verts = bm.verts

    verts.ensure_lookup_table()

    size = len(verts)
    kd = kdtree.KDTree(size)
    for i, v in enumerate(verts):
        kd.insert(v.co, i)
    kd.balance()

    for v in verts:
        v.select = False

        vert_in_range_ids = [index for co, index, dist in kd.find_range(v.co, distance)]

        if len(vert_in_range_ids) > 1:
            for i in vert_in_range_ids:
                verts[i].select = True

    context.tool_settings.mesh_select_mode = True, False, False
    bm.select_flush_mode()
    bmesh.update_edit_mesh(me, loop_triangles=False, destructive=False)

class MESH_OT_select_by_distance(bpy.types.Operator):
    """Select duplicate vertices"""

    bl_idname = "mesh.select_doubles"
    bl_label = "Select by Distance"
    bl_options = {'REGISTER', 'UNDO'}

    distance: bpy.props.FloatProperty(
        name="Distance",
        subtype='DISTANCE',
        default=0.0001,
        min=0.0,
        max=50.0,
        description="Minimum distance between elements to select",
        unit='LENGTH',
    )

    @classmethod
    def poll(cls, context):
        ob = context.active_object
        return ob and context.mode == 'EDIT_MESH'

    def execute(self, context):
        select_by_distance(context, self.distance)
        return {'FINISHED'}

    def invoke(self, context, event):
        select_by_distance(context, self.distance)
        return {'FINISHED'}


def menu_func(self, _):
    self.layout.operator(MESH_OT_select_by_distance.bl_idname, text="Verts by Distance")


def register():
    bpy.utils.register_class(MESH_OT_select_by_distance)
    bpy.types.VIEW3D_MT_edit_mesh_select_by_trait.append(menu_func)


def unregister():
    bpy.utils.unregister_class(MESH_OT_select_by_distance)
    bpy.types.VIEW3D_MT_edit_mesh_select_by_trait.remove(menu_func)


if __name__ == "__main__":
    register()
$\endgroup$
2
  • $\begingroup$ First - Thx for creating this script. Can you update it, for working with Blender 3.4.1? :) $\endgroup$
    – jedrzej_s
    Commented Jan 23, 2023 at 10:42
  • $\begingroup$ @jedrzej_s Updated $\endgroup$ Commented Jan 24, 2023 at 19:24

You must log in to answer this question.

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