Vastly improve Grasshopper component performance by NOT using data types??

Scripting components in Grasshopper can be a great way to get extra power and functionality for those comfortable with C# or VB. It can also be a much tidier way of doing certain tasks than using components, such as using mathematical formulae on a list of values.

Calculating the minimum value in a list of numbers is a great example of this – difficult to do using Grasshopper but dead easy with a few lines of script. The algorithm is simple – look through every item in the list, keeping track of the smallest item found. When we are at the end of the list, simply return this smallest value.

To implement this in Grasshopper, we can use the C# component. We’d start by specifying the input data types by right-clicking on the input, selecting ‘list’ and selecting ‘double’.

GH_component_right_click

Then we’d go into the component and add our code.

  private void RunScript(List<double> x, ref object A)
  {

    double minsofar = x[0];

    foreach(double val in x)
    {
      minsofar = Math.Min(val, minsofar);
    }

    A = minsofar;

  }

This works fine and gives the expected result.

But try and run this code for quite a large list, say 100000 items. This takes around a second to compute. Not an especially long time, but for such a simple calculation it still adds a noticeable lag to the canvas. I just accepted it for what it was, thinking maybe that’s simply how long it actually takes to run a bit of code.

One day, I was writing another simple component and was feeling especially lazy. I couldn’t be bothered to do the right-clicking malarkey, and decided to just cast the data types in the Grasshopper component itself. Again, there was a large list going into the component, but to my surprise it calculated in mere milliseconds. Investigating further, I found that this speed difference occurs time and time again, and can be easily demonstrated:

GH_double_cast

Here, we have a list of 100000 numbers (a series of doubles) and we’re trying to find the smallest value among them. (Of course, with an ascending series it’s going to be the first value, but the algorithm doesn’t know that.) The code for the first C# component is:

    double minsofar = x[0];

    foreach(double val in x)
    {
      minsofar = Math.Min(val, minsofar);
    }

    A = minsofar;

This is the same as before – we have set the input data type (called x) as double, and assumed that x is a double in the code. This consistently takes 1.2s to calculate on my laptop.

The code for the second C# component is:

    double minsofar = (double) x[0];

    foreach(object val in x)
    {
      minsofar = Math.Min((double) val, minsofar);
    }

    A = minsofar;

The only difference here is that we don’t tell the component input to expect a particular data type – we leave it set as ‘object’. (We still have to tell it it’s going to be a list.) Then, in the code, whenever we want to do something with this list that can only be applied as numbers, we cast the item in the list we are looking at as a double, e.g. x[0] becomes (double)x[0].

The difference this makes is astonishing – we go from a calculation time of 1.2s to a tiny 7 milliseconds.

Why this is I don’t know. Whether it works for other data types I am still investigating, and it would be great to hear if this technique is repeated elsewhere in different scenarios.

In the meantime, the lesson is clear: if you are looking to optimise your canvas as much as possible, it is worth trying to cast your variables inside your component instead.

Download the example file:

Changing input names for custom C# Grasshopper components

Edit input names of a GH component

The two components above look similar but are actually the same. What’s the difference? When a single item is connected to the first input, saving is enabled in the bottom input. When a list is connected to the first input, saving is disabled.

When we are writing custom Grasshopper components in C# in Visual Studio, this is very easy. All we do is, somewhere within the SolveInstance method, modify the input properties to change the name, then manually add some code to allow for our desired saving behaviour.

protected override void SolveInstance(IGH_DataAccess DA)
{
   if(Input0.Count == 1)
   {
       Params.Input[6].NickName = "save";
       Params.Input[6].Name = "Save";
   }
   else if (Input0.Count > 1)
   {
       Params.Input[6].NickName = "----";
       Params.Input[6].Name = "Save (Disabled)";
   }
}

In fact, by going to

Params.Input[i].something

where i is the index of the input we are interested in, we can access lots of interesting properties and methods to bring new interesting behaviour to our Grasshopper components. We can even do the same to our outputs with Params.Output[i].

And it’s not just limited to the parameter inputs and outputs either. By using

this.something

we can browse the properties and methods which affect the whole component. For example, we can add a warning to our component by adding the line below to our SolveInstance code:

this.AddRuntimeMessage(GH_RuntimeMessageLevel.Warning, "You did a booboo.");

Custom error message on a Grasshopper component

Keyboard reader for Grasshopper

A prototype way of interacting with Grasshopper with the keyboard. Press any character key on the keyboard to send true/false values to Grasshopper.

It uses the Global Mouse and Keyboard Hook classes by George Mamaladze to intercept key up/down events. I have written two components that turns these key events into true/false commands – if a key is raised, ‘false’ is sent, and if pressed, ‘true’ is sent.

Keyboard reader with 6 pre-filled keys
Keyboard reader with 6 pre-filled keys

In the component above, 6 keys have been hard-coded. (I have been using this as part of video game-like WASD camera control in Rhino.) The component below accepts any character (and possibly any key on the keyboard if you’re lucky enough to find the correct character code for each key.)

Keyboard reader with any letter of the keyboard
Keyboard reader with any letter of the keyboard

Install

To install, download the file at the bottom of this page. Unzip and copy the two files (one GHA and one DLL) into your Grasshopper components folder. To use, set up as in the images above, and remember to attach a timer with a short interval. You may need to unblock the file within Windows if you are having problems. (Right click each of the two files in Windows Explorer, click Properties, and click Unblock.)


Source code

The source code of the Grasshopper components is available at GitHub.

The classes for interacting with the keyboard must (at least for the moment) be downloaded separately, and are available here.

Adding names and descriptions to C# components in Grasshopper

Adding names and descriptions to inputs in custom components makes it easier for other users to understand your component. You can add these even within the C# component within Grasshopper by adding a few lines somewhere within your code:

componentdescription

Then, when the user hovers over an input, it should look like this:

descriptionpreview

Rendering cities in Rhino with OpenStreetMap data

This slideshow requires JavaScript.

Using the freely available map data from OpenStreetMap (OSM), it is possible to create maps and renders of towns and cities within Rhino.

Most of the hard work was done by the creators of Elk, a plugin for Grasshopper that parses OSM data files and returns geometry sorted into roads, rivers, railway lines and so on. It’s then just a matter of taking that geometry and modifying it to suit your visual requirements.

And once the data’s in Grasshopper, we can do all the usual crazy Grasshoppery stuff to it. In the last image above, I connected the buildings up to a bit of C# to show its distance to a given point using colour. I think I like this version of Bath more…

2015/03/31 Update: How to do this yourself

Great news! After some digging around I have stumbled upon the Grasshopper definition I used to create this. If you want to do this for your own town, it is quite simple:

  1. Visit OpenStreetMap. Zoom into the area of interest, click ‘Export’ at the top, and then the blue ‘Export’ button on the left. The file size should be much less than 10MB for decent performance. If the file is too big then zoom in and try again.
  2. Download Elk – which provides the Grasshopper components to parse the OSM file
  3. Download my Grasshopper definition and open it in Grasshopper. At the very left, import the OSM file.

This definition was made many months ago when my knowledge of meshes (and how to make them faster) was much less. I’ve since become more proficient in making really lightweight meshes. I think that Grasshopper can handle much larger maps than this current definition will allow, and one day I plan to see how far I can take it. But this will have to do for now 🙂

2015/07/11 Update 2

As promised, I have had another go at this, and I have now modelled the entire centre of my city York. Take a look and download the GH file here.

How to offset a curve in Grasshopper using the C# component

An example offset curve in Grasshopper
How to generate an offset curve in Grasshopper using only C#, either in the C# component or with Visual Studio:

NurbsCurve crv = new NurbsCurve(inputCurve.ToNurbsCurve()); //input curve to use as offset base
Point3d origin = new Point3d(0, 0, 0);
Vector3d vectxy = new Vector3d(0, 0, 1);
Plane xy = new Plane(origin, vectxy);
Curve[] crv4 = crv.Offset(xy, 1, 0.01, 0); //Get the offset curve array
NurbsCurve[] crv3 = new NurbsCurve[crv4.Count()]; //Make a new array with the size of crv4.count
for (int x = 0; x < crv4.Count(); x++)
{
    //Loop through the Curve[]
    crv3[x] = new NurbsCurve(crv4[x].ToNurbsCurve()); //Convert each Curve into a NurbyCurvey
}

Note that the offset function returns as a Curve[], and that the ToNurbsCurve() method can’t be used directly with arrays. The above code attempts to get around these limitations.

The mesh data structure in Grasshopper

Understanding meshes in Grasshopper can be a little tricky. They have a somewhat unintuitive data structure that can make it hard to handle meshes in C# code.

You probably already know a little about meshes. They are a form of geometry that contain a collection of faces, and that each face can have no more than 4 corners. How does Grasshopper handle this?

The basics

A mesh is a collection of faces. Each face is defied by 3 or 4 vertices. A vertex is a 3D point. A single mesh can contain as many faces and vertices as you want.

A mesh sphere in Grasshopper, indicating mesh points (vertices) and mesh faces

 

In terms of data structures, a mesh contains 2 lists:

  • A list of faces
  • A list of vertices

Firstly, we define a list of vertices. This is a list of 3D points. For each point, we can also imagine an index. For example, the fourth point in the list has an index of 4.

Then, we define each face. For each face, we define three vertices for triangles called A, B and C, or four vertices for quads, A, B, C and D. In the face list, the vertices contain the indices for the vertices, and not the coordinates of the vertices themselves. This is important to remember!

What does this mean when Rhino reads this data and tries to display a mesh? Take the example in the image below.

A table with an example showing how mesh faces and mesh vertices are held in the mesh data structure

The mesh contains 3 faces. For the first face, we have three values and therefore three vertices, so face 1 is a triangle. What are the coordinates of these three vertices? To do this, we need to also look at the vertices list. Face 1 contains vertices 4, 5 and 3. Remember, these are the indices for our vertices. We take these three values and cross-reference them with the vertex list – reading the coordinates for vertices 3, 5 and 4.

Why is it so complicated?

The above system actually makes sense from a data efficiency point of view. Of course, in most meshes, multiple faces will share vertices. With the sphere above, each vertex is shared between 4 neighbouring faces. With the above data structure, we only need to define our mesh points once.

Furthermore, if we want to move a point on our sphere, we just have to update our vertex list. We don’t have to search for every copy of a node or worry about ‘breaking’ our mesh when we move mesh points about.

Manipulating meshes: A C# example

Create a C# component in Grasshopper. Create an input called ‘mesh’ and set its data type to Mesh.

  private void RunScript(Mesh mesh, ref object A)
  {
    //1) Let's read from an existing mesh

    //get faces from mesh
    List faces = new List();
    foreach(MeshFace face in mesh.Faces)
    {
      faces.Add(face);
    }

    //get vertices from mesh
    List vertices = new List();
    foreach(Point3d vertex in mesh.Vertices)
    {
      vertices.Add(vertex);
    }

    //2) Let's get the coordinates for a mesh face
    
    //get the indices for the 10th face
    int[] indices = new int[4];
    indices[0] = mesh.Faces[10].A;
    indices[1] = mesh.Faces[10].B;
    indices[2] = mesh.Faces[10].C;
    indices[3] = mesh.Faces[10].D;

    //We can now get the coordinates for the 10th face from these indices
    Point3d[] facepts = new Point3d[4];
    for (int i = 0; i < 4; i++)
    {
      facepts[i] = mesh.Vertices[indices[i]];
    }


    //3) Let's make a new mesh from scratch
    
    Mesh rtnmesh = new Mesh();
    //for the new mesh, we first need to define the vertices
    //we can add any points we like - let's just copy over the vertices list
    rtnmesh.Vertices.AddVertices(vertices);
    //now let's make a face and add it to the (currently empty) face list
    MeshFace tempface = new MeshFace(0, 1, 12, 11);
    rtnmesh.Faces.AddFace(tempface);

  }

Download an example

The code above is available in the file below.

Download

How to automatically get the measurement units in Grasshopper/Rhino

How to automatically find out if your Rhino document is set to millimetres or metres:

private void RunScript(ref object scale)
  {
    int rtnval = 1;
    Rhino.RhinoDoc  doc = Rhino.RhinoDoc.ActiveDoc;
    Rhino.UnitSystem  system = doc.ModelUnitSystem;
    if(system.ToString() == "Meters") rtnval = 1;
    else rtnval = 1000;
    scale = rtnval;
  }

This script returns a value of 1 if the document is in metres, or 1000 otherwise. (I assume that the user will only be using mm or m.)

To use, create a C# component in Grasshopper and copy the part between the curly brackets to the code of the C# component. Make sure that the component has an output called ‘scale’.

mm or m component

…or download the component from below:

Download

How to colour a mesh in Grasshopper

Let’s say that you have a mesh and a point. You want to colour the mesh according to how far the different parts of the mesh are from the point.

To do this, we need to:

  1. Import the mesh and the point into Grasshopper
  2. Calculate the distance between the different points on the mesh
  3. Apply these colours to the mesh

Colour a mesh with smooth gradients

Colour a mesh in Grasshopper - smooth

 

Colour a mesh with one colour per face

Colour a mesh in Grasshopper - discrete

Note that here I am using the ‘Mesh Explode’ component to break a mesh into its faces, which is part of the MeshEdit plugin for Grasshopper.

I also have grafted both inputs to ‘Mesh Colour’ – don’t forget to do this! You should quickly see why if you don’t…

If you don’t want to use MeshEdit, you can recreate the behaviour using the slightly more clunky method below:

Colour a mesh with one colour per face - Grasshopper

Finally, if you are writing script, it is also possible to colour a mesh using the C# component. See this post for more information.

Creating a relaxed grid on a mesh dome roof with Rhino/Grasshopper and SmartForm

Something I’ve found in my archives – one of the first projects I did when starting my EngD in 2013. We had received a domed roof from the architect, and we had been asked to optimise the form and experiment with different gridding options.

The problem was that the model we received was nothing more than a collection of lines arranged into one grid pattern and lots of little mesh faces between these lines – no NURBS surfaces or anything else nice to work with! The challenge was therefore threefold: recreate the NURBS surface, manipulate the surface into a structurally more efficient form (think lots of non-zero Gaussian curvature) and then apply a range of grids to it.

In hindsight, the methodology presented below certainly isn’t the most efficient or effective, but the important thing (as is usually the case in engineering) is that it got the job done!

Continue reading Creating a relaxed grid on a mesh dome roof with Rhino/Grasshopper and SmartForm