Water runoff script – Example 8.6


In example 4.1 I mentioned a custom VB component I had used to analyze the flow of water across a surface. I recently tried to recreate this using the Anemone looping component to use with meshes (for various reasons) and it was actually very easy to do. The logic is similar in some ways to example 8.5 which I used to find a path through the landscape, but in some ways this example is pretty simple.

I will be using meshes this time instead of surfaces, partly because I haven’t talked about them too much, but meshes do have some advantages (and disadvantages) over surfaces which I will not get into here. To create this particular mesh, I imported topographic data from SRTM using Elk, and then used the point output from Elk to create a Delauney mesh.

Step One – Populate Geometry and setup a loop


To get started, we will use the populate Geometry component, and initially I will use only one point, but we will scale this up to around 2000 points by the end. What’s important is for the loop to work properly at the end is that the output of populate geometry be GRAFTED. While not 100% necessary, you should also simplify, otherwise you will get messy indexing at the end.

While we are at it, we will set up a basic loop using Anemone as explained in prior examples.

Step Two – Find curve for possible movement directions


The logic of this loop is after each round, we want to find out if what direction water would flow in if it were at a specific point on site. Using a similar logic to the last example, we will intersect two shapes together to find a curve of possible directions of movement. We will then identify one point on this curve for the actual direction of movement.

To accomplish this, I first draw a mesh sphere with a radius equal to a “Step Size”. Decreasing the step size will increase accuracy at the expense of looping time. You will need to find an appropriate step size based on the overall size of the landscape you are analyzing. In this case I have a fairly large area (around 8km x 8km) so I am using an 80m step size. I find around 1% of the overall dimensions of the landscape usually gives scale appropriate results. This can be changed later if you want more accuracy. If you are testing this on a smaller model, you will need to adjust appropriately.


I then add a Mesh | Mesh Intersection component, which outputs a curve of where the water could possibly go if it flows 80 m in any direction. this is basically a circle sketched on the surface of the mesh.

Step Three – Find lowest point on curve to determine actual water movement direction


So you probably already know where the water will go, but you might not know how to get there. If there is any doubt, water is an agent, a very dumb agent, but it has one goal. To follow gravity to get to the ocean as fast as possible. So it will always flow down. Well, there are minor exceptions if you take forces like momentum, cohesion, and friction into account, but we won’t do that today 😉

To find this point, we need to know the “lowest point” on the curve we just drew in the last step. There is no such component in grasshopper, but we can use “curve closest point” and then use a point at sea level, or the center of the earth, as a comparison point.

In this case, I deconstruct my sphere’s center point, and reconstruct it with a “Z” value equal to zero. If I am working close to sea-level (in this case I am 1000 m up) it may make sense to set the “Z” value with “Construct Point” to a negative number, like -1000 m (or the center of the earth if you like).

I then use this point together with the Intersect curve from the last step to find the “lowest point.” This is where the water will head next.

Step Four – Finish the loop and draw a connecting line


So this is an image of the whole loop. I use the “Insert Item” component to reinsert the new “Lowest Point” into the list, which after 0 rounds is 1 item long. This is why I use the “Counter + 1” expression to determine the insertion index. once the item is added, I can plug this list into the end of my loop. You may want to use “the simplify toggle” to keep your list clean. Pay attention to where I placed these in the image. Last, I add an “Interpolate Curve” component at the end.


Once the loop is complete, you want to increase the looping counter gradually to see if everything is working. Run 1, then 5, then 10 rounds, etc. to get started. While it doesn’t look impressive yet, if you get a series of points and a connecting line going downhill and following the valleys, everything should be fine once you scale up!

Step Five – Scale Up!


So go big or go home the boss says? Well, all we need to do is add a few more points to our populate geometry and we’ll have a nice stormwater runoff analysis. First try 3-5 points, not too big. If this isn’t working, maybe you forgot to graft? If its working, scale up quickly. Here I have 200 points, run over 20 rounds.


Looking at it from above, you will notice that even after a couple of rounds, the initially random cloud of points will find a structure. By 20 rounds, almost all the water has accumulated into resting points. This is where the script stops really working. We know the water actually keeps flowing, but in this case, our data isn’t precise enough to account for the horizontal transport of water in rivers, where water might only drop a couple of meters over the course of many many kilometers. But it IS good at showing how water moves on steeper sites.


You can speculate about where the rivers are, however, based on your data. If you have a series of still clusters or beads, bets are good that there is a river connecting them. Above I have the GH output, and below I sketched in the river lines in Photoshop.

Anyways, from this basic analysis, all sorts of further analyses can be done. More on that soon…