Accessing only one group member

(Paul Poinet) #1

Hi all,

I have a Rhino file with plenty of groups. Each group contains a considerable number of objects.
Those objects have the same name. I try to access quickly the name of one object in each group.
This is my code so far:

    // All groups in doc
    Rhino.DocObjects.Tables.GroupTable groupTableDoc = doc.Groups;

    // Iterate through the group table
    // and retrieve the name of the first object for each group
    List<string> objName = new List<string>();
    int groupCount = groupTableDoc.Count;
    for (int i = 0; i < (groupCount); i++){
      Rhino.DocObjects.RhinoObject groupObject = groupTableDoc.GroupMembers(i)[0];

    A = objName;

This method works but if one does that within a large rhino file containing more than 400 groups and each containing around 20-50 objects, it takes quite a long time (around 30sec) since it goes through all group members for each group.
Unfortunately, there is no .Item method within the GroupTable class in order to access only one specific group member.
Is there any other alternative you might think of?



(Radovan Grmusa) #2

Hi Paul

I think that there is no faster way because you have to populate your List by calling method GroupMembers(index) to get array of RhinoObject belonging to each group.
Later in your code you can use your list to manipulate RhinoObjects but once any group is changed (group deleted, new group created, items added/removed from group…) you will have to populate your list again.
And you should check if group is deleted otherwise an exception in your code may occur.
You may also consider of using shorter syntax (LINQ, lambda-expresions,…) - is is not faster, only code is more compact. Here is example of method:

    private Result TestGroupSelect(RhinoDoc doc)
        var docGroupTable = doc.Groups;
        var groupCount = docGroupTable.Count;
        if (groupCount < 1)
            Rhino.RhinoApp.WriteLine("There si no groups in the document.");
            return Result.Nothing;

        var indexRange = Enumerable.Range(0, groupCount );
        var allGroups = (from groupIndex in indexRange
                         where !docGroupTable.IsDeleted(groupIndex)
                         select docGroupTable.GroupMembers(groupIndex)

        Rhino.RhinoApp.WriteLine("Total {0} groups will be processed.", allGroups.Count);
        // Now we can read names of first element (RhinoObject) in each group:
        var namesOfFirstObjectInEveryGroup = allGroups.Select(objects => objects[0].Name).ToList();
        Rhino.RhinoApp.WriteLine("Total {0} names aquired.", namesOfFirstObjectInEveryGroup.Count);

        //But we can also perform different operatrions on object based on some criterias we defiene.
        //For example we can search for objects in all groups that have particualr Name
        string particularName = "sq123";
        var objectsWithParticualrName = allGroups.SelectMany(RHObjects => RHObjects)
                                                 .Where(rhObject => rhObject.Name == particularName);
        Rhino.RhinoApp.WriteLine("Total {0} objects found with name={1}.", objectsWithParticualrName.Count(), particularName);

        //or you can count how many curves you have in groups  
        int noOfCurves = allGroups.SelectMany(RHObjects => RHObjects).Count(rhObject => rhObject.Geometry.ObjectType== ObjectType.Curve );
        Rhino.RhinoApp.WriteLine("Total {0} curves found within groups.", noOfCurves);

        //or how many extrusions
        var allObjects= allGroups.SelectMany(RHObjects => RHObjects); //extract all RhinoObjects into one collection
        var extrusionsInGroups = allObjects.OfType<ExtrusionObject>();//and find extrusions
        Rhino.RhinoApp.WriteLine("Total {0} extrusion objects found within groups.", extrusionsInGroups.Count());

        //or more specific filtering
        var filteredObjects = from rhObj in allObjects
                              where rhObj.IsLocked == false
                              where rhObj.Geometry.ObjectType== ObjectType.Curve 
                                   && ((Curve)rhObj.Geometry).IsClosed
                              select rhObj;
        Rhino.RhinoApp.WriteLine("Total {0} objects with specific filter found within groups...", filteredObjects.Count());

        return Rhino.Commands.Result.Success;