The Ol' Perforated Pipe - Looking for feedback


I tried tackling this today. It was my first script. I believe it can be much simpler - by the end I took some odd turns with culling the initial grid to achieve a diagonal grid. I considered “Diaggrid” but I wanted the option to adjust the rotation. Still struggling to get the normals of the cylinder voids to orient themselves well.

Would appreciate anyone taking a look and offering any suggestions!

M (48.8 KB)

I didn’t want to rewrite most of your code but am not that comfortable with Split Tree (which I left in place for the ‘Filtered Points’ group) but felt that it would be easier to scrap the ‘Filtered Normals’ group, combine the two sets of points and get surface normals all over again (white group). (28.9 KB)

SDiff was way too slow for me so I borrowed a recent Python contribution from @kev.r which is MUCH FASTER, though still takes 40 secs. for this (so is disabled in the GH file).

1 Like

By the way, very impressive for your first GH model, congratulations! Well done.

Here are a few more simplifications, primarily avoiding Split Tree by rotating every other row using Repeat Data, along with a few minor shortcuts. (25.6 KB)

P.S. Slightly simpler yet, your don’t need DeBrep since Cylinder is a surface. (20.7 KB)

1 Like

Do you want the perforation oriented normal to the cylinder or are you looking for some kind of variation?

1 Like

Version ‘d’ - Replaced SDivide with SFrames. (22.0 KB)

1 Like

How about a perforated twisted ellipse? :sunglasses:

I got to this by considering that rotating points or surface frames only works on round things. So I thought about adjusting seams on contour lines but soon realized that rotated ellipses alone provide staggered separation of holes. The Python ‘SDiff’ is slow on this though, taking 1.2 minutes. (27.0 KB)

The rotation angles on these three are 180, 120 and 90 degrees, left to right.

1 Like

Hi! Still exploring this - initially I just wanted it to be a simple normal, but as I got into scripting I now want the ability to change the rotation.

Joseph thank you for all of your input!

I’m going to study your simplifications. The twisted one looks incredible.

My next research phase is looking at how to provide rotational parameters to augment the normal of the perforating extrusion. Interested in seeing how each perforated hole can only be visible from a special angle, and becomes more tunnel like when the tube becomes thicker.

Just playing around. Get an idea, implement it, rinse, wash, repeat.

The “big idea” on this one is to get staggered holes on a shape that isn’t round or twisted… The “trick” is to divide each horizontal curve (used to loft the “vase”) by twice as many points as I really want, then cull every other point while alternating the ‘True/False’ cull pattern on each row. Works a treat! (29.1 KB)

Glad you enjoy it. Many ways to do things, hope you’re not overwhelmed.

As to making holes that are not “normal” to the surface, that could get tricky. Will watch with interest.

1 Like

FYI, two things:

  1. When I tried a thicker shell, the capped “rods” that make the holes did not penetrate the outer shell. So I coupled the “Thickness” slider to an Amplitude component for the normal vectors that do the extrude and modified the expression on the Move ‘T’ input.

  2. I noticed that the holes appear farther apart on the smaller radius bulges and realized that I’m offsetting the lofted surface outward instead of inward. This makes the holes evenly spaced on the inside only.

If I offset inwards instead, some holes are likely to intersect before reaching the inner surface, which isn’t ideal and might cause the Python ‘BooleanDifference’ to fail? This model increases the number of rows (‘Height Density’ slider) from 30 to 40, which contributes to the issue and slows the “SDiff”. (29.7 KB)

You’re flying on this thing.

@Joseph_Oster Your use of the Merge/Repeat node confounded me at first…but now I’m starting to understand. (Rotate first index X, Rotate second index 0, repeat) So simple. For some reason the term “Merge” makes me think that the result would be additive, not alternating.

@Joseph_Oster For some reason i can’t get the python script to preview or bake on your scripts.

I downloaded the “” script and that works for me.

The Sdiff node works for your scripts but not the python node on any of the scripts you just shared. Running Rhino 7.1.20299.23101.

Any thoughts?

Merge does the deceptively simple job of combining branches from multiple data trees. It gives the same result as connecting multiple wires to the same input but with the distinct advantage of being able to specify the sequence of wires.

merge_2021_Jul10a (8.8 KB)

Depending on which wire is connected first, second and third (etc.), you can get the same result but using Merge makes that sequence unambiguous.

It’s deceptive in the sense that when data trees don’t match, the results may not be what you expect, though they are predictable. Sometimes ‘Simplify’ or Suirify (or Flatten) can resolve differences so data trees merge as you want.

merge_2021_Jul10b (6.2 KB)

Some (including me) would say that GH would be easier to work with if all components produced results that were ‘Suirifed’ but that discussion is for another thread.

Oh dear… what a drag. I’m using R6, not R7. It might be a Rhino document tolerance issue?
In Rhino, ‘View | Display Options | Units | Absolute tolerance’. I use 0.001.

If changing that doesn’t help, I don’t know what to say? Maybe @kev.r can help? Welcome to the tower of Babel world that McNeel has produced for us. :frowning: If you connect a text panel to the Python ‘out’ output, you might see an error message?

1 Like

Look what happens when you ‘Simplify’ the first (‘D1’) input to Merge in this case:


Can you see why that happens? It might be easier if you ‘Simplify’ the Data component instead of the ‘D1’ input:


A thorough understanding of Merge and Entwine (including Entwine’s ‘Flatten Inputs’ option) is crucial to understanding GH data trees.

If you look at the output of the Cap component, with Tree/List Viewer by @Joseph_Oster (thanks for this great tool Joseph, I use it frequently) you will see that the last branch is a duplicate of the first branch.

Culling the last branch produces a closed brep from the python script component.

The grasshopper component probably checks for problems like this (part of the reason it’s slower?). (23.4 KB)

Here’s a link to the Tree/List viewer from @Joseph_Oster if you don’t have it:


1 Like

That probably happens because the start and end points of the curves are the same, causing two rods in the same place where only one is needed? It occurred to me that might be a problem but only after the fact, and it worked for me.

Thank you for the fix and for the excellent Python component! Cheers.

Thanks again Kevin for spotting and fixing this duplicate branch problem. At the time I replied, I was too distracted to look at the code. Now that I have reviewed all the GH models I posted yesterday, it appears to be only the cylinder models that are affected?

Starting with the twisted ellipse (, the rest of them look OK because they use a different method to get the points. @mendler, do they work for you?

Here are three fixed versions of ‘Perforate_Cylinder’ that include a copy of ‘Tree/List Viewer’. Glad to hear you find that tool useful, I use it every day. (35.6 KB) (36.7 KB) (34.0 KB)

Mahalo. (“thank you” in Hawaiian)

I changed the tolerance in rhino and that worked :wink: