Find close to identical meshes

Hi,

I’m trying to take a set of meshes with the same vertex order (same mesh, just differently deformed by shape keys and an armature) compare them, find ones that are either identical or close to identical (preferably with user defined tolerance) and merge the nearly identical ones together.

My initial idea is just to loop through mesh vertices / polys, compare positions and average that out to a single value.

What I’m interested in is if there’s any built in functionality or available scripts that already does some part of this? Could be geometry nodes or even some other software besides Blender also. Just need to try it out for a larger proof of concept.

Edit:
This could also be rephrashed as “remove almost identical shape keys”.

Edit 3:
After some copy and pasting from internet. Seems to give correct average difference. Now just to loop through objects and store similar.

import bpy, bmesh
import numpy as np

#Get average of list
def Average(lst):
    return np.mean(lst, axis=None)

#Get Difference
def subtractTheMatrix(matrix1, matrix2):
    matrix1Rows = len(matrix1)
    matrix2Rows = len(matrix2)
    matrix1Col = len(matrix1[0])
    matrix2Col = len(matrix2[0])

    #base case
    if(matrix1Rows != matrix2Rows or matrix1Col != matrix2Col):
        return "ERROR: dimensions of the two arrays must be the same"

    #make a matrix of the same size as matrix 1 and matrix 2
    matrix = []
    rows = []

    for i in range(0, matrix1Rows):
        for j in range(0, matrix2Col):
            rows.append(0)
        matrix.append(rows.copy())
        rows = []

    #loop through the two matricies and the subtraction should be placed in the
    #matrix
    for i in range(0, matrix1Rows):
        for j in range(0, matrix2Col):
            matrix[i][j] = matrix1[i][j] - matrix2[i][j]
            
    return matrix

#---------------------------------- MAIN -------------------------------------
#Get verts of active object
#obj = bpy.context.active_object

obj_A = bpy.data.objects['Cube_A']
verts_A = [vert.co for vert in obj_A.data.vertices]
obj_B = bpy.data.objects['Cube_B']
verts_B = [vert.co for vert in obj_B.data.vertices]
#print("Coordinates of verts =", verts, "\n")

#Compare lists
li1 = verts_A
li2 = verts_B
li3 = subtractTheMatrix(li1, li2)
print("Difference of lists =", li3, "\n")

#Average list
average = abs(Average(li3))

#print("Average delta =", round(average, 2), "\n")
print("Average delta =", average, "\n")


Updated version with some fixes. Loops through objects and sets duplicates to hidden. No averaging and grouping yet.

import bpy, bmesh
import numpy as np

#Get average of list
def Average(lst):
    return np.mean(lst, axis=None)

#Get Difference
def SubtractTheMatrix(matrix1, matrix2):
    matrix1Rows = len(matrix1)
    matrix2Rows = len(matrix2)
    matrix1Col = len(matrix1[0])
    matrix2Col = len(matrix2[0])

    #base case
    if(matrix1Rows != matrix2Rows or matrix1Col != matrix2Col):
        return "ERROR: dimensions of the two arrays must be the same"

    #make a matrix of the same size as matrix 1 and matrix 2
    matrix = []
    rows = []

    for i in range(0, matrix1Rows):
        for j in range(0, matrix2Col):
            rows.append(0)
        matrix.append(rows.copy())
        rows = []

    #loop through the two matricies and the subtraction should be placed in the
    #matrix
    for i in range(0, matrix1Rows):
        for j in range(0, matrix2Col):
            matrix[i][j] = matrix1[i][j] - matrix2[i][j]
            
    return matrix

           

def SimpleSetReducer():
    print("Starting - Reduce Set - find deltas \n")
    #deltas under this will be processed
    delta_threshold = 0.05

    # store selection in list
    input = [obj for obj in bpy.context.selected_objects if obj.type == 'MESH']

    for obj_a in input:
        if obj_a.hide_viewport == False:
            #Define object to comapare to and get verts to list
            verts_a = [vert.co for vert in obj_a.data.vertices]
        
            for obj_b in input:
                if obj_a != obj_b:
                    if obj_b.hide_viewport == False:
                        
                        verts_b = [vert.co for vert in obj_b.data.vertices]
                        difference = SubtractTheMatrix(verts_a, verts_b)
                        difference_absolute = np.abs(difference)
                        average = Average(difference_absolute)
                        
                        #If delta under threshold
                        if average < delta_threshold:
                            print("A:", obj_a.name, "B:", obj_b.name)
                            print("Found delta under threshold:", average ," - hiding for deletion")
                            #Add to deletion list
                            obj_b.hide_viewport = True
                    
#---------------------------------- MAIN -------------------------------------
#FindSimilar()
#ReduceSet()
SimpleSetReducer()