Iterating through groups of objects

I wrote a script that is working on a single selected group of curves. It’s for exporting nested sheets to dxf for CNC use. It copies the group, moves it to the origin, rotates, exports and then deletes the copy.

What I’m after is the ability to select multiple groups and have them each processed into individual files. I think I might be on the right track, however, all I’ve actually managed to achieve so far is that the groups all export into a single file with all the file names concatenated. Sooo… Maybe I’m not as close as I think!

It may be worth mentioning that the groups often contain other sub-groups but all of them have a rectangular outline on the “CNC” layer that I’m using to get the top level group name.

Here’s the original single use script for reference:

import Rhino
import scriptcontext as sc
import rhinoscriptsyntax as rs
import System.Guid, System.Drawing.Color

objectIDs = rs.GetObjects("Select objects for export as .DXF", 4 + 512, True, True, True)

objNames=[]

def RotateSelected(deg):
    geo = copy
    if copy:
        plane=rs.ViewCPlane()
        bb=rs.BoundingBox(geo,plane)
        if bb:
            rs.EnableRedraw(False)
            rs.RotateObjects(geo,(bb[0]),deg,copy=False)

for singleID in objectIDs:
    objName = rs.ObjectName(singleID)
    objNames.append(objName)

name = {x for x in objNames if x != None}
sheetnum = " ".join(name)
path = rs.DocumentPath()
exportcmd = '_-Export "' + path + "CNC\\" + sheetnum + '.dxf" _Enter'

if objectIDs:
    bbox = rs.BoundingBox(objectIDs)
    dir = rs.VectorCreate([0,0,0], bbox[0])
    copy = rs.CopyObjects(objectIDs, dir)
    rs.UnselectAllObjects()
    rs.SelectObjects(copy)
    RotateSelected(270)
    rs.Command(exportcmd)
    rs.DeleteObjects(copy)

Here’s the latest attempt at a multi-group version:

import Rhino
import scriptcontext as sc
import rhinoscriptsyntax as rs
import System.Guid, System.Drawing.Color

objs = rs.GetObjects("Select objects for export as .DXF", 4 + 512, True, True, True)

names = []
sheets = []
gnames = []
grps = []

#populate lists
for i in objs:
    if rs.ObjectLayer(i) == "CNC":
        sheets.append(i)
for i in sheets:
    gnames.append(rs.ObjectTopGroup(i))
for i in gnames:
    grps.append(rs.ObjectsByGroup(i))
for i in sheets:
    names.append(rs.ObjectName(i))

def exportdxf(objs):
#create save name    
    name = {x for x in names if x != None}
    sheetnum = " ".join(name)
    path = rs.DocumentPath()
    exportcmd = '_-Export "' + path + "CNC\\" + sheetnum + '.dxf" _Enter'
#operations
    if objs:
        bbox = rs.BoundingBox(objs)
        dir = rs.VectorCreate([0,0,0], bbox[0])
        copy = rs.CopyObjects(objs, dir)
        rs.UnselectAllObjects()
        rs.SelectObjects(copy)
    if copy:
        plane=rs.ViewCPlane()
        bb=rs.BoundingBox(copy,plane)
        if bb:
            rs.EnableRedraw(False)
            rs.RotateObjects(copy,(bb[0]),270,copy=False)
        rs.Command(exportcmd)
        rs.DeleteObjects(copy)
#try to get it to loop
for i in grps:
    exportdxf(i)

Any help is greatly appreciated!
Thanks!

Hi @ainsley,

The following sample script will allow you to select groups of curve. Once selected, the curves are organized into a dictionary of lists, with the dictionary key being the group index, and the dictionary value being a list that contains the ids of selected curves that belong to the group.

import Rhino
import scriptcontext as sc

def test_group_curves():
    # Select some grouped curves
    go = Rhino.Input.Custom.GetObject()
    go.SetCommandPrompt("Select grouped curves to export")
    go.GeometryFilter = Rhino.DocObjects.ObjectType.Curve
    go.GroupSelect = True
    go.SubObjectSelect = False
    go.GetMultiple(1, 0)
    if go.CommandResult() != Rhino.Commands.Result.Success: return
    
    # Create an an empty dictionary
    dict = {}
    
    # Iterate the selection
    for objref in go.Objects():
        obj = objref.Object()
        if obj:
            obj_groups = obj.Attributes.GetGroupList()
            if obj_groups:
                # Get the top group
                group_index = obj_groups[0]
                # Is the group in the dictionary?
                if dict.has_key(group_index):
                    # Append the curve id to the list
                    dict[group_index].append(obj.Id)
                else:
                    # Add a key and initial list
                    dict[group_index] = [obj.Id]
    
    for group_index in dict.keys():
        print(sc.doc.Groups.GroupName(group_index))
        for id in dict[group_index]:
            print(id)

if __name__ == "__main__":
    test_group_curves()

Now that the curve are organized, it should be fairly easy to transform the groups and export.

– Dale

1 Like

Thanks Dale!

This was almost exactly what I was after. For future reference if anyone is looking for the same result that I needed, all you have to do is add in one line to reverse the group list:

    # Iterate the selection
    for objref in go.Objects():
        obj = objref.Object()
        if obj:
            obj_groups = obj.Attributes.GetGroupList()
            obj_groups = obj_groups[::-1] #<---Reverse List

This changes the output so all the curve guids are keys in only their top level group. The original output listed all of the groups (incl. subgroups) and omitted any objects in subgroups from the parent group.

Cheers!