Usually, calculation in Grasshopper goes from left to right along the wires. The components on the left get calculated first, then they trigger components downstream to the right. This continues until the canvas has been fully calculated. After many months using Grasshopper, this is so obvious that it doesn’t even need thinking about.
Until, that is, you try to use Grasshopper contravening this fundamental logic. I recently had a task where I needed to calculate the glare using Honeybee. The glare calculation component uses the Rhino camera, meaning that the camera has to be moved into the correct position if the glare is going to be calculated correctly.
I decided to use the Horster camera control to adjust the camera. This gave me something like this:
The calculations are dependent upon the camera having already been placed in the correct position here. In other words, the camera must be set before the calculations are done. See the problem? Without an output on the camera component, the calculation geometry must come from the ‘building’ component. It’s therefore impossible to ensure that the camera is moved before the calculations are done.
Which component does Grasshopper calculate first?
A bit of background first. When Grasshopper calculates components, it has a property called expired. If a component needs calculating, it is marked as expired=true. If it is up to date and doesn’t need calculating, it is marked as expired=false. When you make a change to a component (such as changing its input values) it is marked as expired. And when a component is marked as expired, everything downstream (i.e. to the right) is also marked as expired.
In short, ‘expired’ means that the component is waiting to be re-calculated.
Once Grasshopper has a list of expired components, it must then choose how it is going to re-calculate them. It does this by working from left to right, starting with a component that has no un-expired inputs.
For most Grasshopper documents, this explanation is quite sufficient. But, in reality, there is a much more complicated algorithm going on. Notice in my diagram that there is more than one valid order it can choose to calculate the components:
- Building, setCam, DoCalcs, result
- Building, DoCalcs, setCam, result
So Grasshopper has two possible choices in what it wants to calculate first. And since, at the end of the day, it does choose one option, there must be some kind of further logic in the background on how it chooses calculation order. Without much else to go on, I head to the Grasshopper forums, where I read this older post and also asked this post.
What the calculation order does NOT depend on
The calculation order in Grasshopper does not depend on any of the following:
- Component position (i.e. its x and y coordinates)
- Order of inputs or outputs
- The data contained within a component
- The type of component *
So what does the calculation order depend on?
The draw order in Grasshopper
The calculation order is driven by one key thing: the draw order. In the background, Grasshopper saves a copy of all the components in your document in a list. The order of this list is the draw order.
It is called the ‘draw order’ as it is this that governs which components are ‘drawn’ on top of each other. See how the panels below are drawn one on top of the other? That’s the draw order in action.
You can easily change the draw order by using keyboard shortcuts:
- CTRL+B sends the component to the back
- CTRL+F sends the component to the front
How Grasshopper does calculations using the draw order
The draw order does more than help to prettify your Grasshopper canvas – it is a primary driver in the calculation order too. Essentially, when Grasshopper is solving the canvas, what is happening is:
- Grasshopper makes a list of all components in your canvas. The order of these is the same as the draw order. The component drawn at the back of everything else is item 0 in the draw order, and the draw order increases to the front as you go down the list.
- Grasshopper finds the back-most expired component. It asks this component to solve itself.
- Before this component actually calculates anything, first it looks to see if any of its inputs are also expired. If they are, it asks these to solve themselves too.
- Again, these components also check their inputs before doing any calculations. This continues until a component is found which is expired, but which has no expired inputs. This component then calculates itself and marks itself as not expired.
- Go back to number 2. Repeat until nothing is expired.
How to check the draw order
The easiest way to check the draw order, and thus the calculation order, is simply to drag the components each other and see what appears on top. The component on the bottom will be calculated first. And if we aren’t happy with the order, we can use CTRL+B and CTRL+F to change them.
Looks like setCam is being calculated first. Yay!
But wait – it’s not quite as simple as that! What if the setCam component is behind DoCalcs, but ‘result’ is behind both setCam and DoCalcs? ‘Result’ will be triggered first by Grasshopper, and this will then trigger DoCalcs to solve itself. So what will happen is that, even though setCam is behind doCalcs, setCam will be calculated after doCalcs because of the influence of ‘result’.
We need to be completely sure that setCam is therefore behind everything, not just DoCalcs. We can use the CTRL+B shortcut to do this, but how can we be sure it’s working properly? There’s no visual feedback that the shortcut has sent the component behind everything else without checking manually for every component.
How to check the draw order – for geeks
And again, it’s C# to the rescue! With a quick C# component, we can get a list of all objects in the Grasshopper document – all in the draw order. And with a timer and a panel attached, we can add a bit of extra functionality – click on any component and it will be shown as ‘selected’ in the panel.
To use this yourself, copy the code below into a C# component, and set up as in the diagram. To use, turn on the timer and select any component (or components) in your Grasshopper document.
var rtnlist = new List<string>();
foreach (IGH_DocumentObject obj in GrasshopperDocument.Objects)
{
if(obj.Attributes.Selected) rtnlist.Add(obj.NickName + " (" + obj.Name + ") SELECTED");
else rtnlist.Add(obj.NickName + " (" + obj.Name + ")");
}
A = rtnlist;
Using this component, we can verify that we have successfully moved our setCam to the back of the draw order list:
Our selected component is item 0 in the list, and so is right at the back of all components in the canvas. Great news!