Select Group

Does anyone have code snippet how to

  1. select multiple groups in rhino
  2. return output would be a list of lists where each list contains the guids of objects in a group

?

Problem is, objects can be in several groups and groups can be nested… Gets complicated.

And there is no way to get a tree or nested list of lists representations?

I have hard time to understand how to even reference in python the top most main groups. Since all the group are selected:

go = Rhino.Input.Custom.GetObject()
go.GroupSelect = True
print(go.GetMultiple(1, 0))

For example how can I select groups: A, C, D and store all their child objects in lists.

Hi @Petras_Vestartas ,

import rhinoscriptsyntax as rs
import itertools
def build_universal_group_dict(selected_objects):
    group_dict = {}
    object_group_map = {}  
    def update_group(full_name, simple_name, parent):
        if full_name not in group_dict:
            group_dict[full_name] = {
                'name': simple_name,
                'parent': parent,
                'children': set(),
                'objects': set()
            }
        else:
            if parent and group_dict[full_name]['parent'] is None:
                group_dict[full_name]['parent'] = parent
    for obj in selected_objects:
        groups = rs.ObjectGroups(obj)
        object_group_map[obj] = set()
        if groups:
            for grp in groups:
                grp_name = grp if grp.strip() != "" else "(unnamed)"
                parts = [p if p.strip() != "" else "(unnamed)" for p in grp_name.split("\\")]
                full_chain = []
                parent = None
                for part in parts:
                    if full_chain:
                        full_chain.append(part)
                        full_name = "\\".join(full_chain)
                    else:
                        full_chain.append(part)
                        full_name = part
                    update_group(full_name, part, parent)
                    if parent:
                        group_dict[parent]['children'].add(full_name)
                    group_dict[full_name]['objects'].add(obj)
                    object_group_map[obj].add(full_name)
                    parent = full_name
        else:
            ungrouped = "Ungrouped"
            update_group(ungrouped, "Ungrouped", None)
            group_dict[ungrouped]['objects'].add(obj)
            object_group_map[obj].add(ungrouped)
    return group_dict, object_group_map
def compute_shared_elements(object_group_map):
    shared_dict = {}
    for obj, groups in object_group_map.items():
        if len(groups) > 1:
            sorted_groups = sorted(groups)
            for combo in itertools.combinations(sorted_groups, 2):
                if combo not in shared_dict:
                    shared_dict[combo] = set()
                shared_dict[combo].add(obj)
    return shared_dict
def print_universal_structure(group_dict, shared_dict):
    print("Universal Group Structure:")
    for group_full, info in sorted(group_dict.items()):
        print("--------------------------------------------------")
        print("Group: " + group_full)
        print("  Simple Name: " + info['name'])
        print("  Parent: " + (info['parent'] if info['parent'] is not None else "None"))
        if info['children']:
            print("  Children: " + ", ".join(sorted(info['children'])))
        else:
            print("  Children: None")
        print("  Objects: " + str(list(info['objects'])))
    print("\nShared Elements Between Groups:")
    if shared_dict:
        for groups_pair, objs in sorted(shared_dict.items()):
            print("Groups: " + " & ".join(groups_pair) + " share objects: " + str(list(objs)))
    else:
        print("No shared elements found among groups.")
def infer_group_hierarchy(group_dict):
    inferred_parents = {}
    groups = list(group_dict.keys())
    for group in groups:
        inferred_parents[group] = None
        objs = group_dict[group]['objects']
        candidates = []
        for other in groups:
            if other == group:
                continue
            other_objs = group_dict[other]['objects']
            if objs.issubset(other_objs) and objs != other_objs:
                diff = len(other_objs) - len(objs)
                candidates.append((other, diff))
        if candidates:
            parent = min(candidates, key=lambda x: x[1])[0]
            inferred_parents[group] = parent
    return inferred_parents
def build_inferred_tree(inferred_parents):
    tree = {group: {"children": []} for group in inferred_parents}
    roots = []
    for group, parent in inferred_parents.items():
        if parent:
            tree[parent]["children"].append(group)
        else:
            roots.append(group)
    return roots, tree
def print_inferred_tree(tree, node, group_dict, indent=0):
    print(" " * indent + "- " + node + " (" + group_dict[node]['name'] + ")")
    for child in sorted(tree[node]["children"]):
        print_inferred_tree(tree, child, group_dict, indent + 4)
def main():
    objs = rs.GetObjects("Select objects")
    if not objs:
        print("No objects selected.")
        return
    group_dict, object_group_map = build_universal_group_dict(objs)
    shared_dict = compute_shared_elements(object_group_map)
    print_universal_structure(group_dict, shared_dict)
    inferred_parents = infer_group_hierarchy(group_dict)
    roots, tree = build_inferred_tree(inferred_parents)
    print("\nHierarchical Group Tree (inferred based on object inclusion):")
    for root in sorted(roots):
        print_inferred_tree(tree, root, group_dict)

Keep up the good work with OpenNest, you’re awesome :slight_smile:

Petras.3dm (68.7 KB)

Farouk

2 Likes

Wow! :tada: :balloon: :raised_hands:

Thank you a lot :slight_smile:

This will be very useful for me.