Copy Groups

Demonstrates how to duplicate objects with grouping.

partial class Examples
{
  public static Result CopyGroups(RhinoDoc doc)
  {
    var go = new Rhino.Input.Custom.GetObject();
    go.SetCommandPrompt("Select objects to copy in place");
    go.GroupSelect = true;
    go.SubObjectSelect = false;
    go.GetMultiple(1, 0);
    if (go.CommandResult() != Result.Success)
      return go.CommandResult();

    var xform = Transform.Identity;
    var group_map = new Dictionary<int, int>();

    foreach (var obj_ref in go.Objects())
    {
      if (obj_ref != null)
      {
        var obj = obj_ref.Object();
        var duplicate = doc.Objects.Transform(obj_ref.ObjectId, xform, false);
        RhinoUpdateObjectGroups(ref obj, ref group_map);
      }
    }
    doc.Views.Redraw();
    return Result.Success;
  }

  static void RhinoUpdateObjectGroups(ref RhinoObject obj, ref Dictionary<int, int> group_map)
  {
    if (obj == null) return;

    int attrib_group_count = obj.Attributes.GroupCount;
    if (attrib_group_count == 0) return;

    var doc = obj.Document;
    if (doc == null) return;

    var groups = doc.Groups;

    int group_count = groups.Count;
    if (group_count == 0) return;

    if (group_map.Count == 0)
      for (int i = 0; i < group_count; i++)
        group_map.Add(i, -1);

    var attributes = obj.Attributes;
    var group_list = attributes.GetGroupList();
    if (group_list == null) return;
    attrib_group_count = group_list.Length;

    for (int i = 0; i < attrib_group_count; i++)
    {
      int old_group_index = group_list[i];
      int new_group_index = group_map[old_group_index];
      if (new_group_index == -1)
      {
        new_group_index = doc.Groups.Add();
        group_map[old_group_index] = new_group_index;
      }
      group_list[i] = new_group_index;
    }

    attributes.RemoveFromAllGroups();
    for (int i = 0; i < attrib_group_count; i++)
      attributes.AddToGroup(group_list[i]);

    obj.CommitChanges();
  }
}
Partial Friend Class Examples
  Public Shared Function CopyGroups(ByVal doc As RhinoDoc) As Result
	Dim go = New Rhino.Input.Custom.GetObject()
	go.SetCommandPrompt("Select objects to copy in place")
	go.GroupSelect = True
	go.SubObjectSelect = False
	go.GetMultiple(1, 0)
	If go.CommandResult() <> Result.Success Then
	  Return go.CommandResult()
	End If

	Dim xform = Transform.Identity
	Dim group_map = New Dictionary(Of Integer, Integer)()

	For Each obj_ref In go.Objects()
	  If obj_ref IsNot Nothing Then
		Dim obj = obj_ref.Object()
		Dim duplicate = doc.Objects.Transform(obj_ref.ObjectId, xform, False)
		RhinoUpdateObjectGroups(obj, group_map)
	  End If
	Next obj_ref
	doc.Views.Redraw()
	Return Result.Success
  End Function

  Private Shared Sub RhinoUpdateObjectGroups(ByRef obj As RhinoObject, ByRef group_map As Dictionary(Of Integer, Integer))
	If obj Is Nothing Then
		Return
	End If

	Dim attrib_group_count As Integer = obj.Attributes.GroupCount
	If attrib_group_count = 0 Then
		Return
	End If

	Dim doc = obj.Document
	If doc Is Nothing Then
		Return
	End If

	Dim groups = doc.Groups

	Dim group_count As Integer = groups.Count
	If group_count = 0 Then
		Return
	End If

	If group_map.Count = 0 Then
	  For i As Integer = 0 To group_count - 1
		group_map.Add(i, -1)
	  Next i
	End If

	Dim attributes = obj.Attributes
	Dim group_list = attributes.GetGroupList()
	If group_list Is Nothing Then
		Return
	End If
	attrib_group_count = group_list.Length

	For i As Integer = 0 To attrib_group_count - 1
	  Dim old_group_index As Integer = group_list(i)
	  Dim new_group_index As Integer = group_map(old_group_index)
	  If new_group_index = -1 Then
		new_group_index = doc.Groups.Add()
		group_map(old_group_index) = new_group_index
	  End If
	  group_list(i) = new_group_index
	Next i

	attributes.RemoveFromAllGroups()
	For i As Integer = 0 To attrib_group_count - 1
	  attributes.AddToGroup(group_list(i))
	Next i

	obj.CommitChanges()
  End Sub
End Class
import Rhino
from Rhino.Commands import *
from scriptcontext import doc

def RhinoUpdateObjectGroups(obj, group_map):
    if obj == None: return

    attrib_group_count = obj.Attributes.GroupCount
    if attrib_group_count == 0: return

    doc = obj.Document
    if doc == None: return

    groups = doc.Groups

    group_count = groups.Count
    if group_count == 0: return

    if group_map.Count == 0:
        for i in range(0, group_count):
            group_map.append(-1)

    attributes = obj.Attributes
    group_list = attributes.GetGroupList()
    if group_list == None: return
    attrib_group_count = group_list.Length

    for i in range(0, attrib_group_count):
        old_group_index = group_list[i]
        new_group_index = group_map[old_group_index]
        if new_group_index == -1:
            new_group_index = doc.Groups.Add()
            group_map[old_group_index] = new_group_index
        group_list[i] = new_group_index

    attributes.RemoveFromAllGroups()
    for i in range(0, attrib_group_count):
        attributes.AddToGroup(group_list[i])

    obj.CommitChanges()

def RunCommand():
    go = Rhino.Input.Custom.GetObject()
    go.SetCommandPrompt("Select objects to copy in place")
    go.GroupSelect = True
    go.SubObjectSelect = False
    go.GetMultiple(1, 0)
    if go.CommandResult() != Result.Success:
        return go.CommandResult()

    xform = Rhino.Geometry.Transform.Identity
    group_map = []

    for obj_ref in go.Objects():
        if obj_ref != None:
            obj = obj_ref.Object()
            duplicate = doc.Objects.Transform(obj_ref.ObjectId, xform, False)
            RhinoUpdateObjectGroups(obj, group_map)
    doc.Views.Redraw()
    return Result.Success

if __name__ == "__main__":
    RunCommand()