Grasshopper Stairs

From TOI-Pedia



As is often the case, there are many ways of building stairs. This is just one example of creating a straight stair along the y-axis of the coordinate world system. The definition needs to be adjusted (or the stairs rotated) for other directions. This definition allows for entering possible constraints defined by Building Codes such as the maximum consecutive steps before placing a landing.


The variables are:

  • Total Rise
  • Riser Height
  • Tread Depth
  • Maximum Consecutive Steps
  • Length of the Landing

Once the basic set-up is complete, you can define the following variables:

  • Nose Length
  • Thickness Tread
  • Thickness Riser
  • Width of Treads & Risers
For a good spiral staircase tutorial see:

Basic Components

This definition is set-up to first define the total height, divided by an approximate riser height to obtain the number of steps. You could also have divided the total height by the number of steps instead. However, this way we can constrain the minimum-maximum riser height easily on the Number Slider, whereas doing this with the step count is more complicated.

So, let's set-up this first step. To visualize this, we use a Curve » Primitive » SDL Line. Define a Vector » Vector » Unit Z for the Direction and specify the Length with a Number Slider. This length will be the total height of the stairs. Define a Vector » Plane » XY Plane for the starting point of the stairs.

Defining the number of risers and calculating the riser height


Now we will calculate the number of steps by dividing the total height by the approximate riser height. Use Maths » Operators » Division for this. We get a decimal number, whereas we need an integer. Use the Maths » Operators » Round components to obtain the integer. If we divide the line by this number we get a segmented line where every segment comes close to the specified height. Use Curve » Division » Divide and plug in the Nearest Integer from the Round component into the Number of segments (Count) of the Divide Curve component.

Use Curve » Division » Shatter to break the curve into segments. Connect the original SDL line to the Curve input and the parameter t output from Divide Curve into the t input on the Shatter component.

With the Curve » Analysis » Length you can determine the length of each segment. Notice that it is quite close to the originally defined approximate riser height

Defining the number of treads and the depth of the treads


Next, using the number of steps, you generate a series to determine the depth of each step. Later we will use this series to move each of the line segments in the y-direction. Use a Number Slider to set the tread depth, this will be the step size (N) on the Sets » Sequence » Series. The Count comes from the number of steps you have calculated and used for the Divide Curve. All you have create is a list of numbers which we will use later.

Setting Up Domain

Understanding List Length and last Item in a List
Creating the start of the domain with a series
Creating Domains for Landings

If you wanted to make a simple continuous stairs, your definition would be straigthforward and almost done. What complicates this, is the necessity for a landing. This varies by code, depending on the country, exterior/interior, public/private buildings, etc. As an example, we will place a landing every 7 steps (meaning; every 7th step will be a landing).

To do this, we use the series component from the treads. We need to group the tread distances into groups of 7 steps. Then we add the length of the landing to every group. As the total number of steps needed to cover a height of 4500mm in our example we have to create the domains 0-6, 7-13, 14-20 and the leftover 21-26. To keep this parametric and working for all other instances as well, we need do some "tree gymnastics" to set up these domains.

Tree Gymnastics

First we obtain the number of steps from the Series component with Sets » List » List Length. The list counts 27 elements, but we need to retrieve the last item (26), we use an expression x-1. The we have to divide this number by the maximum number of consecutive steps to see how many groups we get. Use Maths » Operators » Division for this. Then round the number to get an integer count with Maths » Util » Round. It's better to use the ceiling in this case, always rounding it up to the nearest integer.

We create a series with Sets » Sequence » Series, using the the maximum number of consecutive steps as the stepsize (N) and the rounded number of groups for the Count. In the example the series reads (0,7,14,21) This list will function as the start of your domain.

Next, we need to create a second list for the end of the domain. This list should be (6,13,20,26). Subtract 1 from the maximum number of consecutive steps by using Maths » Operators » Subtraction and add this to the series with Maths » Operators » Addition Now the list reads (6,13,20,27) This is a problem because item 27 does not exist in your original list of steps (from 0-26 is 27 items).

Therefore we need to replace the last item in your series. Use Sets » List » Insert Items to extract the length of the series and set an expression x-1 to identify the item to be replaced (3). This will be the replacement index. Then use Sets » List » Replace Items to substitute the number of your last item with the item List Length item from your steps. This will be the Item to replace with. The Series to modify comes from the addition. Now your list will be (6,13,20,26).

Use Maths » Domain » Construct Domain to create a domain from the two lists. The start domain comes from the original series (0,7,14,21). The end domain comes from the Replace Items component (6,13,20,26). You domain will now be (0-6,7-13,14-20,21-26).

NOTE: The riser height determines the number of steps. If you want to have equal groups of steps, the divisor (maximum number of consecutive steps) needs to be a multiple of the number of steps and the remainder needs to be 0. For example, if you have 24 steps in groups of 8, the remainder is 0 and you get 3 groups of 8 steps with 2 landings in between. Instead, if you have groups of 7, the remainder is 3 and you get 3 groups of 7 steps, and 1 group of 3 steps with 3 landings in between.

Subset List

Using Sublist to "group" maximum consecutive steps

Now we apply the domain onto the series that generated the steps with Sets » List » Sublist. Plug the series into the List input and the constructed domain into the Domain input. The component has created the groups of 7 steps accordingly.

So far we have only grouped the steps, or more precisely; the distances of the thread depth. We will use this to move each of the risers along the y-direction. But first we need to add a landing length to each of the groups. If the landing length is 1000mm, we need to create a series of (0,1000,2000,3000) to place the landings in between the groups. To clarify, we need to add 0 to the 1st group, 1000 to the 2nd group, 2000 to the 3rd group, etc.

We use another Sets » Sequence » Series for this. To obtain the number of groups that came from the Sublist component, we use the Count output of the Sets » Tree » Tree Statistics component. Make sure to simplify the tree first by right-clicking and selecting Simplify. In our case, this is (4). The stepsize is the Landing Length, which you could define with a Number Slider (1000mm in example). Make sure to Graft this tree to ensure the data matches the groups as described above. By adding the two components with Maths » Operators » Addition you get exactly what we need.

Since we haven't applied any transformations yet, none of the previous steps are visible. That's why we call it tree gymnastics, we've only altered the structure of the data. In the following steps we will use this to actually transform the geometry and complete the stairs.

Create Risers and Treads

Using Sublist to "group" maximum consecutive steps
Adding an additional point to finish the last step of the stairs
Matching the points for the treads and drawing a line in between

First we have to place the list of risers in the same data structure as the list of distances from the last step by applying the same Sublist component. Copy and paste the Sublist and replace the List input with the output from the Shatter component.

Next we will apply a move transformation to the line we've shattered in the beginning. We will move the risers with the distances from the last step. Use Transform » Euclidian » Move and a Vector » Vector » Unit Y for the direction for this.

Now you can connect the shattered lines from the Sublist component into the Geometry input of the move component. Then you can add the Y-vector to the Translation vector. You will see that all the risers have moved according to the correct grouped distances.

To draw the horizontal threads we can use the start and end points and connect them with again some tree gymnastics. Get the endpoints with Curve » Analysis » Endpoints. From the Startpoints we have to remove the first point, as it is not needed. If we want to end with a thread, we also have to create an additional point moved horizontally along the y-axis.

First, let's remove the 1 starting point with Sets » Sequence » Cull Index. Select Set integer to 0 by right clicking on the Index input.

Now, let's add the last thread endpoint. Use Sets » List » List Item and once again Sets » List » List Length to obtain the last item. Set an expression x-1 by right-clicking on the List Length output. Then with Transform » Euclidian » Move you can move the item again along the y-direction with a Vector » Vector » Unit Y. Be sure to use the thread depth as your number slider for this move.

All that is left now is to add this point to the end of the list of starting points. For this we use Sets » List » Insert Items. This works similarly to the Replace Items component we used in the domain. The list comes from the Cull Index component. We take the length of the list to feed the insertion index and the moved point into the Items to insert input.

To finish the threads draw a line between the new list of starting points and the list of endpoints.

Finalizing Stairs

Adding thickness to the treads and risers and adding a nosing
Final Stairs

If you've made it this far, the last part is easy. We are going to extrude the stairs in the x-direction to generate surfaces. We will add a nose length and thickness to the steps and risers. These are the 4 additional variables mentioned at the beginning of this exercise.

For the nose, we can extend the thread line on one side. Use Curve » Util » Extend Curve. Define the extension of the correct side with a Number Slider, the other side requires an input of 0 by setting an integer.

Extrude the extended line into the x-direction by using Surface » Freeform » Extrude and Vector » Vector » Unit X. Do the same for the risers with a new extrude component. This way you can select the threads and risers independently, which may be useful when baking (for different materials for example).

Lastly we extrude the surface of the threads vertically to give them thickness, again with Surface » Freeform » Extrude and Vector » Vector » Unit Z this time. To extrude the risers, we need to extrude in the y-direction. You can vary the thickness with Number Sliders.

Personal tools