How to get a specific component after a cluster is exploded? C#

Hello there,

I wonder what is the best way to catch specific component derived from a exploded cluster in C#? I noticed that .ExplodeCluster method doesnt have a return type. Therefore, I tried to get a list of GUID from the cluster which hasnt been exploded first in order to catch a specific component. However, this approach doesnt seem to work as component GUIDs will be regenerated after a cluster is exploded. (not sure if this is the right way to do.)

Another approach I can think of but Im not quite sure how to do it at the moment is checking the latest components added to the gh document and select the one I need within the list. However, with this approach, I’m not sure how GH defines the latest components added to the document as once a cluster is exploded, there will be many added at the same time.

Does anyone know a solution? Thanks in advance.

Hey,

It really depends what you want to filter by in this case I chose by component NickName
Also you should eventually replace my expCltrGuids for the actual guids of the components in your cluster. In addition, please note that the ComponentGuid is the unique ID of a component, so it will never change if you have many instances of the same type in the canvas.

Below the code and attahced the gh file.

  private void RunScript(List<Guid> expCltrGuids, string nickName, ref object AllComponents, ref object AllComponentGuids, ref object ClusterComponents, ref object ClusterComponentsGuids, ref object Selected)
  {

    // Only get components which implement the IGH_Component interface. Will ignore panels for example
    // Will also ignore this C# component
    var allComponents = GrasshopperDocument.Objects.Where(c => c is IGH_Component &&
      c.ComponentGuid != this.Component.ComponentGuid).ToList();

    var allComponentsGuids = allComponents.Select(c => c.ComponentGuid).ToList();

    List<IGH_Component> clusterComponemts = new List<IGH_Component> ();

    // Data Matching stuff
    if(allComponentsGuids.Count > expCltrGuids.Count)
    {
      for (int i = 0; i < expCltrGuids.Count; i++)
      {
        for (int j = 0; j < allComponentsGuids.Count; j++)
        {
          // Check if guid of exploded cluster equals guid of comp in canvas
          if(expCltrGuids[i] == allComponentsGuids[j])
          {
            // if true add to cluster component list
            clusterComponemts.Add(allComponents[j] as IGH_Component);
          }
        }
      }
    }

      // Data Matching stuff
    else if(allComponentsGuids.Count < expCltrGuids.Count)
    {
      for (int i = 0; i < allComponentsGuids.Count; i++)
      {
        for (int j = 0; j < expCltrGuids.Count; j++)
        {
          // Check if guid of exploded cluster equals guid of comp in canvas
          if(allComponentsGuids[i] == expCltrGuids[j])
          {
            // if true add to cluster component list
            clusterComponemts.Add(allComponents[i] as IGH_Component);
          }
        }
      }
    }

      // Data Matching stuff
    else
    {
      for (int i = 0; i < allComponentsGuids.Count; i++)
      {
        // Check if guid of exploded cluster equals guid of comp in canvas
        if(allComponentsGuids[i] == expCltrGuids[i])
        {
          // if true add to cluster component list
          clusterComponemts.Add(allComponents[i] as IGH_Component);
        }
      }
    }

    // Select cluster components based on nickname
    List<IGH_Component> selectedComp = clusterComponemts.Where(c => c.NickName == nickName).ToList();




    AllComponents = allComponents;
    AllComponentGuids = allComponentsGuids;
    ClusterComponents = clusterComponemts;
    ClusterComponentsGuids = expCltrGuids;
    Selected = selectedComp;
  }

Select_ToForum.gh (12.4 KB)

1 Like

The cluster component inherits IGH_InstanceGuidDependent, which exposes the method:

void InstanceGuidsChanged(SortedDictionary<Guid, Guid> map);

If you inherit it in a class, you can access that map (which relates old id with new id) that handles the document when it change the IDs. Not sure which document (cluster owner document or cluster document) will handle this, the owner I guess.

Not technically, the cpu works in sequence (it is not a parallel operation). If there are no changes of the order by the user, I suppose that the order is always the same in which the components have been placed on the canvas. So if you explode a cluster of N components, the last N components belonged to the cluster. If you are looking for a specific one, you will need some data that only belongs to that component.

Components have two ids, the component id, that gives it individual and unique identity, and the instance id, which allows two components of the same type to be differentiated in the same context (document).

1 Like

Hello Nicholas,

Thanks for your reply. I just quickly look through your code. The only thing I’m not sure about is the matching part. I’m getting a cluster from a file location, so reading and exploding happens at the same time. If I pre-check the instanceID of the components inside the cluster. It will change once it’s exploded, however, if I use componentID, then if there are multiple same components, they will all be extracted. (maybe using another condition to filter it out may work, but if it’s in complex script and the same cluster is called several times, not sure if this is the best method.)

I will try to go through you code in details later and let you know. Thanks!

Yep, I am aware, ComponentGuid returns the unique id of a component, thats why I used it

Hi Dani, thanks for your reply. Yes, I’m aware the inheritance nature of the methods. However, I think that the instance GUID has to be created a new one if a cluster is called twice. This is where I get stuck. The document I referred to is cluster.document(). The idea is to have the ability to call the same cluster several times in the gh file and whenever it’s called, some components from the exploded cluster can automatically work with other components preset up in the grasshopper document.

If you can show me where is the ExplodeCluster method in the GH SDK that would be awesome. Yeah My code is pretty much boiler plate, since I don’t have the correct scenario to test it against. And I am also aware that there can be many instances of the same component in the cluster as well. But we can easily make the filtering more robust and turn everything in to some nice methods.

Also, it would be great if you can tell us explicitly what you are trying to achieve

Not sure if it’s documented in the SDK. You can explode a cluster using ExplodeCluster(). The return type is void, so it will just do the action of unpacking.

Okay the objective of the exercise is as following.

  1. read a cluster file from a file location when a toggle is triggered.
  2. unpack the cluster file ( unpack version is important as say if I want to keep the capability of changing some of the parameters from a component like graph mapper. If I pack it, I cannot change it.)
  3. auto connect some of the components from an unpacked cluster to other components existing in a pre-set up grasshopper file when a condition is satisfied.

Is there a better way in your mind to achieve this?

Well I am actually not sure about the best steps to take to achieve what you want because I have never tried to do something similar before. But some time ago I saw a post by @nathanletwory recreating a grasshopper file from code. Maybe he can be more useful in this case.

But I am curious to know about ExplodeCluster what class does this method belong to? I have not been able to find anything about it.

Cheers

1 Like