Is there a way to trim multiple objects using as cutting object a closed polysrf so that all surfaces that standing outside of a closed polysrf are removed?
I have attached an example. The blue color is the cutting object and with red are the surfaces that i would like to trim.
Thanks in advance!
Well, in this particular case I would select the red surfaces, run _Split, split them with the blue volume. Then use SelLast to select all the split surface parts, from the front view crossing deselect the inside surfaces (ctrl+crossing window) and Delete (the outside surfaces).
That’s exactly what i currently do! However, as the same or the surfaces may be more closer to the boundary of the surface and also if we assume the closed polysrf that represents a ship hull shape the fore part wiil be way more narrow and then this approach is not efficient. That’s why i would like to setup a python script (or grasshopper ) to execute this task.
Well, it’s not too complicated, but there is a bit of work involved. Basically:
Split the surfaces with the volume
Find a point somewhere on each of the split parts and test for inclusion inside the volume
Delete any parts that are outside the volume
The main challenge in this is finding a point on each split surface part which is not on one of the edges touching the volume, which might produce a wrong inclusion choice.
@Jarek - I actually tried SelVolumeObject on his file manually yesterday - it doesn’t work after the split. Apparently it is too strict, and anything actually touching the volume surfaces (like after a split) is not selected…
You are right Mitch, I did not try the file at first, it’s a bit tricky with this tight overlap, so SelVolume as it is does not pick it up.
The script it using extracted render mesh as the Volume in SelVolume, therefore we have an option to set a tolerance there, which helps. But only if we increase the mesh quality of the cutting volume first, the default one in the file is crude. So with better mesh and script tolerance set to 5 (mm) all works OK over here:
OK, thanks for that Jarek! I am going to make a youtrack item for SelVolumeObject to have a tolerance option or something that can handle touch-intersection cases. For simple volumes one could also offset the volume by a tiny amount to the outside, but as we know, OffsetSrf is not all that reliable, so I wouldn’t want to depend on that.
Yeah, that’s why I was using RenderMesh in the script since they are less tricky to offset; that’s how the “tolerance” is implemented (offsetting the mesh). This solution is not perfect but works ok 99% of the times and in some cases is a huge time-saver. I, too, wish for a native Rhino BooleanTrim/Split or at least SelVolume tolerance or an option for “touch” condition.
I think that something like the following could work better.
Is it possible to use the Rhino Command SelVolumeObject to check if the center of area of the trimmed parts is inside the volume object (see the if statements at the end of the code)
filter = rs.filter.surface + rs.filter.polysurface
breps = rs.GetObjects("Select brep to split", filter)
cutter = rs.GetObjects("Select cutting brep", filter)
rs.EnableRedraw(False)
for brep in breps:
splits = rs.SplitBrep ( brep, cutter )
for obj in splits:
cog = rs.SurfaceAreaCentroid(obj)
#if cog is inside closed volume pass
#else delete obj
rs.EnableRedraw(True)
P.S I realised that this will not work for symmetric surfaces. But i could potentially split them on x-axis
I believe that’s what I indicated in post #4 - using point inclusion.
Just beware that certain surface geometry may have their area/volume centroids that lie outside the surface/volume. A more or less 100% reliable solution would be to mesh the surface, get the mesh vertices, test to find a point that is not coincident with the edge of the surface and use that to test for “insideness”.
Indeed i got inspired from your post!
With the volumes that i m planning to use, i dont foresee any surface to have the cog outside
What i dont know however is how to pass the rhino SelVolumeObject commnand in the script.
No need… with your volume and your test point, I would use the Rhinoscriptsyntax method rs.IsPointInSurface(). If it returns True, the point is inside the volume, that is a surface part to keep. If it returns False, the point is outside, and that is a split part to be collected for later deletion.
I place the code here for future reference.
One thing that i would do is to search for symmetry along x-axis (i.e if y-coordinate of srf = 0 ) and split it because right now the outside of boundary symmetric surfaces are not removed.
import rhinoscriptsyntax as rs
filter = rs.filter.surface + rs.filter.polysurface
breps = rs.GetObjects("Select brep to split", filter)
cutter = rs.GetObjects("Select cutting brep", filter)
rs.EnableRedraw(False)
for brep in breps:
splits = rs.SplitBrep ( brep, cutter )
for obj in splits:
cog = rs.SurfaceAreaCentroid(obj)
if not rs.IsPointInSurface(cutter,cog[0]):
rs.DeleteObject(obj)
rs.DeleteObject(brep)
rs.EnableRedraw(True)