Growing and Branching Lines – Example 10.4
This script is probably the most complex I have written about so far, but it turned out to be highly flexible and capable of generating a wide range of different possibilities in the end. Before trying this out, I would highly recommend looking at the previous Example 10.3 – Growing Lines since it uses the same logic, with a few additions. If you didn’t understand that example, this one will be pretty hard to manage. Also, i will only plan on explaining the major new concepts, and not spending time on basic concepts you should already have a grasp of. If you aren’t there yet, though, please read on and at least look at the pictures… 🙂
This script uses a looping process using the Anemone plug-in to grasshopper. Before any looping script, you need to design the initial setup conditions. I actually made two versions of the initial setup for this script, and was going to explain both in one blog post, but it was getting out of control, so I decided to split it into 2 separate posts. The next example, Example 10.5, has another version of the setup that will produce very different results, but you should try this one first. In this version, before Starting the looping, I drew a square “Curve” in Rhino and a few semi-randomly placed points in the middle. The edge curve is divided into using the “Divide Curve” component to generate evenly spaced points, in this case, 50. From each of these edge points, a line is drawn to the closest of the semi-random points in the middle, its length being one-third of the total distance to the closest point. These points can be tweaked a bit to manipulate the initial conditions.
All these lines are put into a container which I am calling “Live Lines” which will grow in the looping process. The edge curve is placed in a container called “Dead Lines”. The live lines will be contained in the channel “D0” of the Anemone component, while the dead lines will be in channel “D1”
One of the most important aspects of this loop will be to adequately manage which lines are “Live” and hence subject to further growth, and which ones are “Dead” and will not grow, but will still be used for proximity tests, as in the last example. Understanding this concept is half of the key to success on this loop!
Note I identify two additional “variables” indicated with a lavender color, that will be used in the loop. The first is called the “Average Initial Length”, obtained using the “Average” component. This will be used later to determine how long a line needs to be before it can divide into branches.
The second variable I am calling the “Extension Rate” This is a percentage of the “Average Initial Length”, which determines how much the lines will grow each line. The lower the extension rate, the slower the simulation will run, but the more accurate the results will be. More on this later. While testing the loop, I recommend a slightly higher rate (maybe 5%) to keep things from running TOO slow, but once you are happy with how it is working, you can lower this to get a more precise drawing. For now I will use a 5% extension rate.
Starting the Loop
In the loop, the “Live Lines” in channel “D0” will go through a series of tests, one after the other, to determine if they will stay in the “Live Lines” category, and keep growing, if they will split and branch, or if they will “Die” and move into the dead pile (Channel D1). As the loop progresses, more and more geometry will be considered dead. Eventually, all geometry will die, in which case the “Live Lines” channel will be empty. You will notice at the top of the image below, I put in a simple “Equality” test to see if the “Live Lines” container is empty. If the List is empty, the list length will = 0, returning a “True” value. This is input into the “E” channel at the end of the loop to stop the whole process. There is no point in continuing the loop if there is no more geometry to grow.
If the “Live Lines” pile still has geometry in it, the geometry is subjected to the first test! Much like in the last example, the distance from the endpoint of EACH live line is measured to the closest point on EACH piece of geometry in the simulation (live or dead). This is done with the proper “grafting” of points and “flattening” of lines as shown in the image above. In the bottom right, the dashed grey lines show what these distance measurement look like for just one endpoint. The second illustration shows all the total measurements. It is quite a few! I then sort these distance measurements using the “Sort List” component. The closest distance is always “0” since it will measure the distance from the endpoint of the line to the line it is an endpoint of… that is why when we use the “List Item” component next, we take Item “1” (not Item “0”) which will be the distance to the nearest piece of geometry that is not itself, if the list was properly sorted.
This distance is then tested against the variable “Extension Rate” (marked in Lavender) which I identified and explained in the Initial Setup. If the distance between the endpoint and the nearest piece of geometry is LESS THAN the extension rate, the line will die. It is too close to a neighbor. This early in the game, in round 0, no piece of geometry fails this particular test, but soon pieces will start to fail. I do a “Dispatch” to move the pieces whose endpoint is to close into the morgue…the geometry that passes the first test stays alive, but will be subjected to more tests coming up… Life is TOUGH…
Last Gasp of Dying Geometry
Well, the geometry sent to the morgue isn’t quite dead yet. It doesn’t want to go quietly into the night. As a last, dying gasp, it grows… a little bit…before it is truly dead. This is a completely optional step…but I like it enough. Basically, every line grows by the “Distance” between itself and the nearest piece of geometry. I remeasure from the endpoint of the dying lines to EACH piece of geometry (Living and Dead) like in the previous step, Sort the List, and use the distance of Item “1” as in the “Extend” component for the dying lines. After this last extension, they move into the “Dead Curves” pile, never to grow again…
Tests for Division into Branches
The geometry that is still Living now has to go through some more tests (3 actually) to see if it will branch or if it will simply grow more in its current direction. The first test. Is it long enough? Only once a line has reached a certain length is it eligible for branching. You can change the final outcome of your drawing by playing with this parameter, but in this case, the minimum length that makes you eligible for branching is being 1.15 times (115%) of the Average Initial Length. You will notice this early in the growth process, only 8 lines out of our initial 50 are eligible, and these ones are in the corners, since the corner lines tended to be longer because of the way we set up our script. Anyways, the 8 lines which have reached sufficient maturity are put into one group called “Possible Division”, while the rest is sent back to school to do a little more growing up.
So you’re mature enough to divide? Good for you. The next test is pure random luck. Just like some things in life. In this case, your chances of dividing are pretty high (30%), but probability sometimes goes against you. In this case, only one of the 8 lines passed the test. It could have easily swung the other way, with 4 or 5 of the lines passing. But the lines that failed don’t have to loose hope yet. They will be eligible for this test again in the next round (if they don’t die >:-) ) since they are assured to pass the minimum growth test again, and will have another 30% chance next round. As far as the final design expression, a high division probability (like 30%) will have most eligible lines dividing roughly around the same time, creating a more regular pattern, while a very low probability (like 1-2%) will tend to create a more irregular final pattern. Anyways, the lines that passed this test (in this case 1) are again dispatched into one pile, while the lines that don’t pass are sent back to school to do a little more growing up.
There is one more test to see if the line is eligible for branching. It has to have some growing room. This was a fine tunement I put into the script later to solve a few minor issues, but basically, it keeps you from getting too many “micro” branches that are destined to end too soon. A distance is measured that is more than the incremental growth distance, in this case a bit more than twice as much. The circle shown in the image above is just a graphic illustration of this distance…the circle is not actually drawn. If the line passes this test…most will, it will branch in the next step. Those branches that don’t pass will be allowed to keep growing…but with a dark cloud over their head. Their time left is short, and destiny is calling at their door.
Spring! New Life, Growth, and Branching
So all the tests are complete. We have three stacks now. Those who failed the first test are long buried with the rest in the dead pile and forgotten. Those who passed the branching tests are ready to multiply! And the smaller stems or unlucky mature ones at least get to keep growing! But as we will soon see, the young and the unlucky may have the last laugh.
You will see in the image above, before the branching happens, the “stems” that will divide are unceremoniously moved into the “Dead” pile. It doesn’t even get to grow in its dying last gasp. All this effort…and for what! At least it will live on though…in its children. Two new tiny stems will be drawn at its endpoint, whose direction and vector is determined from a branching angle parameter. in this case, the angle is 90°, which will lead to two branches at 45° angles from the vector of the parent branch. The kids get a slight spurt in life…growing a bit more than the typical “Extension Rate”… to be exact, halfway between the “Extension Rate” variable and the “Room for Growth” parameter from the last test. This is a fine tune to the script I added later, otherwise the new line will be too short and will be too close to another line (his dead parent!) and will die before life even gets started when the loop starts again. So the children need a bit of a head start in life…Also note…if the “branching angle” is too low, the two sibling branches will also be too close to each other in the next loop, and both will die… But for now, the two new lines are welcomed into the world of the living.
The lines that did not branch grow a little bit…equal to the extension rate, and unlike those who ended up multiplying, live to see another day. After being extended, they are grouped together with the young new branches, and are all put back into channel “D0” on the loop.
The dead are shuffled along at the bottom of the script, with the long dead, the newly dead, and the dead parents all dumped together into a common grave, and placed into channel “D1” on the loop.
Let it Roll! Looping
If everything was setup correctly in the loop, you can now just sit back and relax and watch your patterns form. The image above shows a snapshot of what the pattern looks like after every 10 rounds. With the dead geometry shown in black, the living geometry in grey, and the new growth and new branching in red. The saga of life/death/and reproduction continues until round 157, when the last piece of geometry “dies” ending the loop. The final pattern is the final fossil record of our little game of life.
You can now play around with the variables and parameters, or the initial setup if you’d like, to see what other kinds of patterns emerge. When you see a pattern you think is promising, it is probably worthwhile to slow the simulation down to get a more precise drawing.
In the image above, you will see the results of running the loop with various extension rates. 1%, 2%, 5%, and 10% You can see that the quickly growing drawing is much less precise, but it can capture pretty closely at least the “feel” of a variation. 10%, however, while going by in a zip, is probably too imprecise even for quick tests, but 5% in this case works pretty well. You can try even less than 1%, but the returns are increasingly minimal, and the number of rounds to generate the pattern increasingly high.
The script can generate quite a few variations. We will explore some variations in the initial setup in the next blog posting, but for now, you can see some of the results of changing the number of initial points (1-3), changing the branching angle (4-6), moving the initial points (7), or changing the minimum division length parameter and/or branching probability (8 and 9) You can do a bit of post processing after the lines are generated. here I just gave them some thickness and made them white on a black background.
Anyways, I will show some more possible variations in the next Example 10.5. For now though, here is an overview of the full script (very large!) if you want to try and recreate it yourself.