Iteration in Grasshopper (Without scripting)
Lately I have been experimenting with iteration in Grasshopper. Iteration is often thought to be synonymous with the computer programming concept of a loop, but while the concepts are related, the definition of iteration I will use requires that the results of one iteration are used as the starting point for the next iteration. A loop can simply be a way to apply the same operation to a list of elements (much like processing multiple values with a component in grasshopper), but it is an iterative loop if the results from one step are used in the calculation of the next step (something grasshopper does not directly do.)
This concept is also tightly linked with the concept of recursion. Simply stated, the definition of a recursive function includes the function itself. Fractals are among the canonical examples of recursion in mathematics and programming. Because recursion in programming describes a very particular way of setting up code, one that is not well translated into Grasshopper (without scripting), for the rest of this post I will simply use the term iteration, but it is worth bearing in mind that the processes shown can also be abstractly considered examples of recursion. (A disclaimer: I am NOT a programming expert, so if I am misrepresenting any of these concepts, please do let me know.)
Achieving either iteration or recursion in Grasshopper would seem to require the use of scripting. This post will show some of my investigations into iterative methods in Grasshopper without scripting.
The way that I approach iterative solutions in Grasshopper is so simple as to be almost dumb: I simply take groups of components and copy-paste them over and over again, such that the results from the first group are the starting points for the second. I have also developed a certain design pattern for definitions making use of this method, informed by my (admittedly limited) experience programming traditionally. Here is a simple diagram of that pattern:
What use would iteration be in Grasshopper? Let me provide a few examples to illustrate. I will start with some simple exercises, and move to examples from my own work. Some are more targeted towards direct problem solving, and others are more oriented towards the creation of formal variety and complexity. (Disclaimer: I do not believe variety and complexity are valid architectural ends-in-themselves)
Example 1: Fibonacci sequence
Grasshopper provides for us a component to calculate N terms of the Fibonacci sequence, but I will calculate it manually here to illustrate the pattern of iteration. First, some initial values are necessary: the first two terms of the sequence, 0 and 1. The function for the Nth term is simply the previous value added to the value before that. Our function thus has two inputs: the (n-2)th value and the (n-1)th value, and two outputs: the (n-1)th value and the nth (the calculated) value. Hooking up the outputs of the function to the inputs of a copy of the same function repeatedly will yield the Nth term of the sequence (with N-2 copies of the function).
Frequently in these iterative cases, we want the results of all the steps together in one place. This requires the addition of what I call a “collector” – a simple parameter that takes the results of all previous steps as input and outputs all previous steps plus the current step. This is easy to see added to the Fibonacci example:
The approach is simply to pick a V coordinate in the middle of the surface (v=0.5), calculate of the area from (0,0) to (.5,1), and then test if it is larger or smaller than the desired area. If it’s larger, pick the next v coordinate to test in the middle of the bottom half (0.25), and if it’s smaller, pick the next one in the middle of the top (0.75). Repeating this process over and over will allow the strip’s area to approach the desired value, and the more repetitions performed, the more accurate it will be. This process could easily be scripted (and in fact I have written such a script) but I show it here as a simple example of this design pattern applied to a real problem. This example does not include a “collector” because all we care about is the final strip, tuned to the proper area, and not all the intermediate steps.
Example 3: Repeat Transform
Here is a simple example of the use of iterative techniques for complex formal generation. This definition simply takes a BRep as input, and performs a transformation on that BRep, and then performs the same transformation on the result, and so on and so forth. This is another case where a collector allows us to gather the results of each successive step into a list at the end of the process.
Example 4: Sierpinski Triangle
As I mentioned earlier, fractals are a frequent example of recursion and iteration. The Sierpinski Triangle is a simple fractal that can be constructed easily using this method in Grasshopper. This example also makes more advanced use of data tree structures within a recursive function.
Example 5: Curve Approximation with Fixed Modules
As an intern for Radical Craft this summer, I developed an iterative algorithm for approximating a freeform curve with a fixed set of trapezoidal modules. There are only 9 unique shapes, indicated here by the color coding, and the definition selects a sequence of these shapes to construct the best possible approximation of the curve. I can’t share this definition or explain in detail its workings because it was done as part of my work, but as the full project reaches completion I will share more information.
Example 6: Iterative Bending
In this last example, I am using a much more complex function definition. It essentially takes a BRep as input, rotates it a certain amount around the x and z axes, and folds it across the YZ plane. The animation shown here demonstrates the result of changing some of the rotation parameters.
All the definitions shown in this post (except example 5) can be downloaded here.
Ideally, this process of repeating a group of components could be built into the GH interface. Once clusters (user-defined groups of components) are reinstated it seems to me that it would be fairly easy to design a special component that could encompass a group, and feed its outputs to a copy of the same group N times, or perhaps even until some goal condition was met. I have very little conception of how difficult this would be to add as an interface feature, but I know it would vastly increase the intuitiveness and elegance of solutions such as these, which rely on the repetition of particular processes in an iterative manner.
Filed under: Architecture, Grasshopper | 5 Comments