Need help Generating Stairs on a Non-Planar Surface in Grasshopper

Hello all,
I’m working with a non-planar ribbon surface in Rhino and exploring how to generate stairs along it using Grasshopper. I previously followed a youtube tutorial method that visually aligned somewhat with my design https://www.youtube.com/watch?v=GEbOh_v91zY , and while it worked on a small portion, it turned out to be inefficient and ultimately unusable.

The main issues were:

It only runs along a single curve, whereas my ramp is defined by two edge curves.
It requires a planar input curve, but in my workflow, I use rebuilt non-planar curves that exist in 3D space.

Ideally, I want to:

  • Input two non-planar curves (the ramp edges),
  • Define the rise and run values,
  • And generate stair treads that stay within the ribbon boundaries.

Any tips or existing scripts that handle this kind of setup would be much appreciated! I have attached my rhino file with the surface and curves as well as a grasshopper script that needs help extruding up 15cm incrementally for the stairs.
20250515_Curved Sloped Stair zk.gh (10.5 KB)


slope srf with edge curves.3dm (456.0 KB)
slope srf with edge curves.3dm (474.2 KB)

But your “ribbon surface” is generated from one curve in the Rhino file and its offset :interrobang:

P.S. And the offset curve is self-intersecting:

And the edges of the ramp are not fair. :man_facepalming:

@Joseph_Oster oh, I am so sorry. Here is another file with the proper geometry
slope srf with edge curves.3dm (474.2 KB)

Try this solution.
20250515_Curved Sloped Stair zk a.gh (61.3 KB)



2 Likes

Way too late for me. I used the single curve from your Rhino file (internalized in this GH file), rebuilt and offset it to create the ramp and moved on from there. I see a section near the top that ignores the ramp boundaries but won’t bother to fix it. Interesting problem though. :thinking:

I used only “Rise(a slider in meters = 7.25 inches) and ignored “Run(tread).


stairs_2025May15a.gh (30.4 KB)

Can be opened in R7 because curve is internalized. (cyan group)

1 Like

@leopoldomonzani Very nice solution, thank you so much! I think for the time being it will work, only issue with this Im facing is that the risers are not consistent some are 15cm but some go up to 30cm.

@Joseph_Oster thank you so much for the help. In your version the risers are working perfectly, its just the issue of the input curve being single curve that is rebuilt and offset that changes shape too much from what I am working with currently. (which is the double edge ribbon). But thank you for you time, it is definitely an interesting take on the solution.

So add a ‘Count’ slider and increase the control points for Rebuild Curve from the default 10. Top View is best to see that the rebuilt curve matches the original.



stairs_2025May15b.gh (35.8 KB)

White group is a silly fix to “preseve ramp boundaries”; wish I had thought of it earlier, could maybe have been less code.

It’s up to you to define initial geometry - don’t forget GIGO :bangbang:

In my experience, the issue with this is when tutorials show a more general or common example, such as making stairs along an ascending curve, whereas your geometry goes up and down. I’m sure you know what I’m talking about.

This approach is inspired by what @leopoldomonzani tried plus some tweaks:
stairs.gh (22.9 KB)

Main thing here is that rather than dividing the surface, you divide its ‘medial axis’ (tween curve from both ‘rail’ curves) by a length you specify, then use isocurves for the surface divisions. Highest and Lowest points from each division surface are used as a quick way to gauge top and bottom planes for each step. Nonetheless, this could be adjusted based on more specific directions from you––for example, the lowest points per step could be replaced with an overall ‘depth’ of the entire mass under the surface, which remains a question at the moment:

1 Like

In this definition the risers are uniform.
20250515_Curved Sloped Stair zk b.gh (70.8 KB)

3 Likes

This thread reminds me of another one four years ago, long and complex with parametric landings, max steps between landings, etc. I don’t recall it going up and down though.

I was thinking about having another try at this, wishing I had done some things differently, but have only just now realized some things…

  • Your first post has two Rhino files with the same name: slope srf with edge curves.3dm

  • The one I opened (456.0 KB) matches the GH file, the other one doesn’t (474.2 KB) :interrobang:

  • The larger file you re-posted later has multiple peaks (goes up and down) while the smaller one I saw (that matches the GH file) only goes up (or down). VERY DIFFERENT :bangbang:

So nah, I’ll skip the re-try.

thank you all for the help, all solutions with super interesting approaches. Definitely going with @leopoldomonzani’s most recent solution as I get the smoothest set of steps that match my surface geometry.

Did you notice that all steps (@leopoldomonzani and my own) are planar? That makes for some surprises, which is why steps are normally grouped between landings and defined by “run” (or “going”, which is tread length). Real trails often have non-planar segments where gentle slopes follow the terrain.

Yes, that’s a great point. I noticed the planarity too. I think that’s what made the rhythm feel quite regular, even when the trail suggested more variation. In real terrain following stairs, those non-planar segments add a kind of softness or adaptability. I will definitely have to tweak some of the landing moments but overall this was quite an interesting problem to work on. Thanks for all the help.

Would be interesting to insert this path (centerline of your ribbon surface?) into GH code from the old thread I linked to (scaled appropriately) and see how it looks.

Unfortunately I can’t easily get that to work because I don’t remember how the old code works. :thinking: Based on the ‘Step Rise’ slider value, it appears that both are the same scale.


terrain_steps_2025_May16a.gh (51.1 KB)