Ice-Ray Lattice – Basic Recursion – Example 8.1

This script is a fairly basic introduction to the concept of recursion in Grasshopper, which is only really possible with one of two add-ons, Anemone or Hoopsnake, unless you want to try writing your own code with one of the scripting components! I derived this example initially from the page DesignCoding.net which has many very good examples of other scripts, and which I can definitely recommend. The example from Design coding used Hoopsnake to make the Ice-ray Lattice but I decided to use the Anemone component for this example.

Both components (Hoopsnake and Anemone) allow you to do things that would otherwise only be possible with traditional scripting, but be aware they have their limitations and might get very slow or crash altogether if what you are trying to do is very complicated. But they are very good tools once you understand their logic.

So what is Recursion, you might ask. That’s what google (and Wikipedia) is for 😉  I will give my best definition here, and hopefully it will become clearer through the examples. It is basically applying a rule to a problem, and then repeating that rule again and again in a similar way upon the results of the previous application of the rule, either infinitely (bad idea with a computer!) or until certain end conditions are met. The end condition could be simple, such as, do this only ten times. I’m not a fan of boxing, but maybe the example will help in understanding. A boxing match has “rounds” and the rules are the same each round. The exit condition is either a set limit of rounds (15?), a knockout, or a TKO. But the thing is the boxers in each round are different people. They are not 100%, they have been beat up, knocked around in the previous rounds, so each round can only be considered in light of the results of the previous round. OK, that made no sense. Let’s move forward…

Before I get into the script, I will explain some of the logic of the Chinese-Ice Ray algorithm. The rules are actually very simple for this first example, but more complexity can be added later.  There is really only one rule for this example, and after each “round” or recursion, the rule repeats on the previous results.

Rule: Find the midpoint of a shape, and then draw a random line at any angle to divide the shape in two.”

Rule 1 – Possible subdivisions after the first recursion

You can see in the image above some of the possible results of applying this rule. This is round 1. Recursion 1.

Now we have two shapes. We apply the same rule, but now we apply it twice. So after round 2, Recursion 2, we will have 4 shapes. Round 3 will give us 8 shapes, round 4 16 shapes, Round 5 32 shapes…. and by round 10 we will have over 1000 shapes…

Possible subdivisions after each round, applying recursively the same rule.

This will be quite fun for a few minutes, but eventually you might want to vary the rules a bit to generate more interesting, or at least more original outcomes. I will show some more ways to vary the rule in the next script, but one thing you could do now is limit the random angle from our rule to a specified interval to create quite different end effects.

Possible variations with cutting angle range limited

And there’s nothing to stop you from changing the rules of the game every so often… although this might be considered cheating…

Variations where Recursion rules change at fixed intervals.

So I think that’s enough background on the rules and recursion. Now for the grasshopper. We will basically only be using a few components with Anemone, but getting these integrated into your first loop is the most important thing.

Step One: Create a surface. Use your favorite method. Later we will try recursion with some irregular surfaces, but for now, I would recommend just using something flat.

Step Two: Set up your loop. The loop in Anemone is like a set of brackets. Your loop will have these basic components.

A Start (Loop Start) an End (Loop End) the arrows at the top should be connected first to loop the data back and forth.

A Data Input (D0). This can be a number, surface, point, vector…  you can have multiple sets of data looping, which is an Advantage of Anemone over Hoopsnake

A Loop Count (N).  When you are developing your loop, start with this set to zero, then once that works, SLOWLY work your way up. Don’t try 100 loops at the start or everything is sure to crash!

A Reset (T).  This is a boolean toggle (T/F) Which allows you to reset and start again.

The data comes out of D0 and then you mess around with it, in this case apply our rules for dividing surfaces, and then feed the data back into D0 at the Loop End.

Another output of “Loop Start” is a counter. If you put a panel coming out of this you can quickly see how many rounds you’ve done. The counter is handy for other operations, for example, resetting the random number generator each round…I will show an example.

Step Three – Setup Round 1So once the loop is set up, now it is time to fill in the “blue” area. In this case, it will be fairly straightforward. We find the center of the surface with the “Area” component. From there we want to draw a line in a random direction. For this I have a random angle generator, which then is used to move points in a positive and negative direction (a distance larger than the surface in question…I use a measure tool to make sure this number is always bigger than my surface), which in turn generates a line.

Finally, this line is used in the “Split Surface” component.

So that is round 1

Step Four – Try Round 2. So if everything seems to be working after round 1 (actually round 0), push the slider up to the next round. You will probably need to fix your data structure now since you are now executing your script on multiple objects. You can see how I did my data structure, but it can be a bit tricky. Basically I need to flatten my surfaces at first because I want a unique angle for every division. If the surfaces are grafted initially, I will get the same angle for each. Once I get my cutting lines though, now I need to graft those lines (and the surfaces) otherwise they will cut any surface they cross. In this example, i want the lines to only cut one surface…the surface which it bisects. That is why I initially flatten the data structure, but then graft it at the end before splitting. After the surfaces are split, you can flatten again.

One other thing to notice, I am using my counter to randomly reset my number generator after every round. Why? If I do not, it will recycle random numbers and you will get lines at the same angle repeating themselves. You basically need a new list after every round. And I can’t just use the count as my seed since I still want to try many variations in each round. So I am adding the count to an arbitrary number (151…it could be any number, just not 0) and then multiplying this by a seed value that i can change.

Step Five – Let it roll! If it is working after the second round the way you expect, it will probably continue to work as you increase the number of loops. Just be careful not to make the number too high too fast. After 14 rounds there will be 16,000 surface slit operations being done, and anything more than this and crashes will definitely start to happen. I found this particular script after 9 or 10 rounds the results are the best anyways. The variations below are all 10 rounds.

Some variations of the script with the different sets of rules.

As far as the Ice-Rays, it might be worth searching around the web for some writings on this, if you want some ideas to try and generate some rules of your own. A couple of Articles I found:

MIT – Shape Grammars of Ice-Rays

Xiaofang Yuan (2011) “A new perspective to look at ice-ray grammar”

And for design applications, here is a writeup on how Min|Day architects applied some of the principles of the Ice-Ray on a couple of projects, one on some custom cut wood screens, and another to develop a site plan.

And finally an image of the script…