Search code examples
arraysduplicatesmaxscript

Delete Duplicates (same polycount) Maxscript


I want to remove all duplicate objects from a scene, I want to find the duplicates by comparing polycount of all objects.

When I've found the polycount of each object i want to group all objects with same polycount together and delete all but 1 of them. Should be simple, i am having trouble building an array with all duplicate objects in it though...

My code throws no errors but doesn't add any objects to #(duplicates) array. My code does determine polycount for all objects and puts it in objs_info array.

-- Remove object duplicates
clearselection()
select geometry
deselect helpers
objs = selection as array

objS_info = #()
objS_info2 = #()

dups = #()
for obj in objs do(

    obj_info = #()
    obj_dups = #()

    ConvertTo obj Editable_Poly
    PolyCount_src = polyop.getNumFaces obj
    --resetxform obj ; maxOps.CollapseNodeTo obj 1 true --reset Xform + collapse stack
    delta_x_src =  ((-1 * obj.min.x) + obj.max.x) 
    delta_z_src = ((-1 * obj.min.z) + obj.max.z)
    append obj_info PolyCount_src
    delta_ratio_src = delta_x_src/delta_z_src 
    for i in 1 to objs.count do(

        obj_dups = #()

        if objs[i] != obj do(
            ConvertTo obj Editable_Poly
            PolyCount = polyop.getNumFaces obj
            --resetxform obj ; maxOps.CollapseNodeTo obj 1 true --reset Xform + collapse stack
            delta_x =  ((-1 * obj.min.x) + obj.max.x) 
            delta_z = ((-1 * obj.min.z) + obj.max.z)
            delta_ratio = delta_x/delta_z 
            if(delta_ratio == delta_ratio_src and PolyCount == PolyCount_src) do(
                append obj_dups objs[i]
                )

            )
    )
append dups obj_dups
)

format "dups = % \n " obj_dups

Any help will be greatly appreciated, thank you!


Solution

  • Many ways to skin a cat. Note that testing floats for equality (what you do when comparing the bounding box size ratios is rather risky (see for example comparing float values if you want to keep that check). Grouping by the size can be done for example like this:

    objsByNumFaces = for obj in geometry where canConvertTo obj mesh collect
    (
        local snapshot = snapshotAsMesh obj
        local data = dataPair obj:obj numFaces:snapshot.numFaces
        delete snapshot
        data
    )
    
    qsort objsByNumFaces (fn _ x y = x.numFaces - y.numFaces)
    
    counter = 0
    prevCount = -1
    objsPartitioned = #()
    
    for pair in objsByNumFaces do
    (
        if pair.numFaces == prevCount then
            append objsPartitioned[objsPartitioned.count] pair.obj
        else
        (
            prevCount = pair.numFaces
            append objsPartitioned #(pair.obj)
        )
    )
    

    The objsPartitioned array will then contain objects grouped by number of faces.