Normal of point? Rotate geometry perpendicular to curve

Hi all,

I’m having some issues with a simple staircase that I’m trying to create. I’ve made it in such a way that from a single starting point I can control all of the key dimensions of the staircase up to the next floor, while also cutting a hole equivalent to the staircase footprint out of the floor above. When done in isolation the stairs work as I’d like, but when I put them into the context of a building it works less successfully.

I want to be able to select the starting point from an offset of the boundary edge, so that in theory I could rotate the stairs around to any edge. However, the stairs are done relative to the world XYZ, and I would like them to be perpendicular to the curve so that at any point they are facing in towards the centre of the plan. I can create a Rotate Axis component (green stairs in image) with a slider to achieve this manually, but know there must be a more efficient solution to have the X and Y values that I put in at the beginning of the script relative to the curve.

Rotate (30.7 KB)

I couldn’t open your file due to missing plugins (Pufferfish Offset Curves), but you might want to look at the ‘Orient Direction’ component using the Point and Tangent output from Curve Eval of the profile as targets.

Sorry, I hadn’t realised I was using a non-standard component. I’ve swapped it out for the normal offset component.

I’ve tried two different approaches; orientating my geometry, and rotating my geometry. When I orientate it appears to work without error, except I then can’t actually see the rotated stair as an object in rhino (not talking about baking, I just want to see the representation of it).

When I rotate it, it works some of the time. I calculated the angle between the start point and the x axis (as this is the direction of the stairs) and then the angle between the strt point and the floor centroid. I then feed that into a rotate component, and this works fine so long as it doesn’t need to rotate more than 180 degrees.

Is there a better way to do this or am I just missing something to restrict the rotation beyond 180?Rotate (67.9 KB)

You are still using Pufferfish:


A little difficult to guess how to fix it?

Any reason for your geometry being so far away from the origin?

Digging a little bit, I found that your ground floor and upper floors params both have an empty branch that causes errors. Flattening both params fixes the errors.

I’m not going to bust my chops trying to make your stairs work but perhaps this yellow group will be helpful? Similar to what @qythium suggested, this rotates the tangent from Eval 90 degrees (actually -0.5*Pi).

Rotate (68.9 KB)

Any reason for your geometry being so far away from the origin?

Similar to my data tree issues yesterday, I have inherited the base of the model from elsewhere. Had I started the model from scratch I would have gone about things differently, but I’m just trying to work with what’s in front of me.

I had missed the second pufferfish offset command, that should be it removed now.

As you can see in the image, the stairs are still rotating funny above 180 degrees. I’m trying to get that edge to align with the centroid.

Rotate (64.1 KB)

Does the yellow group (previous post) help? Being so far away from the origin makes it very difficult to rotate and inspect the model so I’m having a hard time seeing the geometry in your version ‘b’.
(Rhino Note, to center zoom/rotation: ‘View | Viewport Properties | Target | Place | OK’)

OK, this is getting close. In the “Stair Profile” group (brown?), I replaced the ‘X’ and ‘Y’ vectors with the rotated tangent (“X”) and tangent (“Y”), respectively. Not sure yet what’s up with the tread length but the stairs are created with the correct orientation so they don’t need to be re-oriented or rotated.

Got it! Needed a vector Amplitude component for ‘Tread Depth’:

Rotate (73.3 KB) (updated cosmetically)

I looked into why the stairs were so slow and was able to avoid the culprit (CapEx) by using EdgeSrf instead to create a “Closed Brep” solid much faster.

Rotate (73.3 KB)

Check this as well…

Rotate (23.7 KB)

1 Like

Off, but slightly on topic. My Pufferfish offset is able to to offset both sides as well as have multiple end cap conditions like straight, rounded, ect. If you need just to regular offset just use the gh offset. (Also, you are using an old version of the plugin)

Your rotation works oddly for angles above 180º because you’re calculating the angle between vectors without specifying a plane (WorldXY), this will return the minimum angle between the vectors cos⁻¹(û•v̂) which is always less than 180º. It’s a really common mistake to trip up on, which is why I usually avoid calculating angles directly and use the Orient direction or Plane-to-plane commands.

The GH component treats its direction inputs as a scaling factor (unlike the behaviour of the Rhino commands), so be sure to unitize them first if you don’t want your geometry to be scaled.


I would also construct the stairs independently in a arbitrary convenient reference frame first before orienting them at their final destination

Rotate (72.1 KB)


That’s all good advice but the stairs in your model are not oriented perpendicular to the edge?

And CapEx isn’t needed since the Extr is already a “Closed Brep”.

What’s wrong with constructing the stairs at the correct location and orientation in the first place, as my last post does? (version ‘d’)

Apparently @stu92’s requirement was to orient the stairs towards the room’s centroid as illustrated in post #5… I had initally assumed edge-perpendicular orientation too.

Nothing wrong with doing it in place of course, just my preferred way of going about such things as it makes the initial construction cleaner, and it’s likely that the same set of stairs will be copied to multiple locations afterwards.

Thanks also for pointing out the technique of using EdgeSrf , I hadn’t realised it could be used that way with offset curves :slight_smile:

Well, he seems to have said two different things. The thread title and first post says this:

And then later in post #5 he refers to the area centroid. @stu92, which is it?

I normally do the same thing myself, constructing geometry at the origin and orienting it later, often many copies. In this case, I saw a shortcut and took it. :sunglasses:

I accidentally zoomed out on the GH canvas to see a three story building that looks like a basis for this project? A nice toy to play with… Seeing it, I wanted to have separate controls for where the stairs would be located on each floor. Another application for an old UI widget idea.

I struggled for too long with the “construct stairs in place method” (which has potential advantages) and resorted to Orient copies of a set constructed at the origin (0,0,0).

Rotate (71.8 KB)

Real stairs have landings, fire exit standards railings, and other concerns, and must adapt to different heights between floors.

Rotate (77.4 KB)

Thanks everyone for all of your input. I’m still fairly new to grasshopper, so seeing as many different ways as possible to do something really helps me learn!

@Joseph_Oster Yeah the generic house is just for me to get to grips with how such tools could be used in a real project. Thanks sharing your ‘mulitple location’ stair solution :slight_smile: