Access persistent data in Grasshopper in C#

How to access the persistent data property of Grasshopper components in C#.

Say for example you want to read the value of ‘2’ which is saved internally within a ‘Num’ component.

grasshopper-persistent-data-access

We can look up the Num class and access the property from here quite easily. But what if we want to do it a bit more generically, so we can access the persistent data within any component?

We can do this by accessing the GH_PersistentParam(T) class. But because this class is in a different namespace/class hierarchy to the IGH_Param class (where we would normally be working to access component properties) it takes a little bit of work to manoeuvre data without Grasshopper having a small fit. (Read here for a forum post where David Rutten explains the class hierarchy behind Grasshopper.)

Two similar solutions I’ve produced today are:

var param2 = Component.Params.Input[0].Sources[0] as Grasshopper.Kernel.GH_PersistentParam<Grasshopper.Kernel.Types.GH_Number>;
A = param2.PersistentData[0];

…and the one-line alternative:

A = ((Grasshopper.Kernel.GH_PersistentParam<Grasshopper.Kernel.Types.GH_Number>) Component.Params.Input[0].Sources[0]).PersistentData[0];

This is a great simplification of the problem – it will only looks at the 1st component connected to the 1st input. And since PersistentData returns as GH_Structure, rather than dealing with data trees, it is easiest just to use square bracket notation to retrieve the first item (which is valid if we only have one item in our persistent data, as in this example).

Using Generics in C#

When we write a method in C#, we often want to specify an input and a return for it. Since C# is a strongly typed language, it likes to know exactly what data type these inputs and returns are.

Let’s take an example, which takes a 2D array of data and returns a specified row as a list:

public List<string> GetRowOf2dArray(string[,] array, int rowNo)
{
    List<string> rtnlist = new List<string>();
    for (int i = 0; i < array.GetLength(0); i++)
    {
        rtnlist.Add(array[i, rowNo]);
    }
    return rtnlist;
}

This is all well and good if we only want to use strings. But what happens if, later on, we want to use the function with a list of doubles?

We might decide to create a copy of the method:

public List<double> GetRowOf2dArray(double[,] array, int rowNo)
{
    List<double> rtnlist = new List<double>();
    for (int i = 0; i < array.GetLength(0); i++)
    {
        rtnlist.Add(array[i, rowNo]);
    }
    return rtnlist;
}

Now, at the interface level, we can extract a row whether we have a matrix of doubles or of strings, and return them in the correct data type.

string[,] branchPaths = new string[5, 5];
for (int i = 0; i < branchPaths.GetLength(0); i++)
{
    for (int j = 0; j < branchPaths.GetLength(1); j++)
    {
        branchPaths[i, j] = "I am cell " + i.ToString() + ", " + j.ToString() + ".";
    }
}

var rtnList = new List<string>();
rtnList = tst.GetRowOf2dArray(branchPaths, 0);

But, we’re already running into problems. We basically had to copy and paste the GetRow…() method above, which is already bad practice. What if we want to change something, or we find there’s a bug? We’d have to make the change in every copy of GetRow…(). And what if we want to use the method with yet another data type, such as an array of integers? We’d have to keep copying and pasting for every data type.

One way around this is instead to write the method using objects as the type. Since all types inherit from the object type, we can write the method once and cast the specific data types. A very simple example is:

public bool IsEqual(object v1, object v2)
{
    if (v1 == v2) return true;
    else return false;
}

double a = 2;
double b = 3;
bool areTheyEqual = IsEqual(a, b); //returns false

However, this gives a lot of problems, which are explained in more depth here. Basically, using objects means that we lose performance due to casting, and we lose control since all data types can be casted to and from objects. What we want is a way to create a method suitable for multiple data types, but where we still can feel safe that the user won’t break our method with a strange data type.

Generics

This is solved with generics. As well as feeding in parameters to our methods, we can also tell the method what kind of data type we want to use it with.

This will already be familiar if you have worked with lists:

List<double> myList = new List<double>();

myList.Add(1.5);
myList.Add(5.232);

The bit in the angle brackets is the type – we can’t create a list without telling it what kind of data the list will contain. By writing <double>, we are saying that every item in the list will be a double. And if we wanted to create a list of strings, we don’t need to call a different method or different class, but we can still do it by calling the same class by specifying the type as string.

In short, using generics allows you to write your method once for a wide range of data types.

Back to the matrix example – in our class:

public List<T> GetRowOf2dArray<T>(T[,] array, int rowNo)
{
    List<T> rtnlist = new List<T>();
    for (int i = 0; i < array.GetLength(0); i++)
    {
         rtnlist.Add(array[i, rowNo]);
    }
    return rtnlist;
}

int[,] branchPaths = new int[5, 5];
for (int i = 0; i < branchPaths.GetLength(0); i++)
{
    for (int j = 0; j < branchPaths.GetLength(1); j++)
    {
        branchPaths[i, j] = i*100 + j;
    }
}

var rtnList = new List<int>();
rtnList = tst.GetRowOf2dArray<int>(branchPaths, 2);

T is the placeholder for the type. When the user calls the method, T will hold a data type, such as string or int. In this example, both an input (T[,]) and the return type (List<T>) have data types that must be carried by the user. The place where the user specifies the data type carried by T is in GetRowOf2dArray<T>. So when the user calls the method, they only need to specify T once. T can then be used wherever necessary throughout the method.

References

MSDN – An introduction to C# generics
MSDN – Generics (C# programming guide)