In RhinoCommon, I want to be able to split a Brep with multiple Brep cutters and get all the split parts. The thing is when I split the Brep with the first cutter, it can produce two or more parts (if there is an intersection) or none (if not). If the split does happen, the original Brep needs to be replaced by the list of split parts for the next cutter, and then I need to iterate through that list and do the same for each item in the list… etc. So the function needs to be recursive.
But I can’t seem to get my head around how to feed the split parts back into the original list and continue…
At this point I need to get on with other stuff, but if anyone can toss out a coupe of clues, it would be greatly appreciated…
Hmmm… How about first calculating all the intersection curves (Intersection.BrepBrep); then use all resulting curves to split all the BRep faces (BrepFace.Split(curves)). No need for recursion.
Hey Menno,
Thanks! That was my first thought as well, but I didn’t go down that road because it seems that you can’t split multiface Breps with curves, only individual faces… So then, as everything is exploded, I would have to figure out how to join the right faces back together to reconstitute the split bits correctly…
HI @dale,
Wow, I’m amazed…! So you can just create a single empty Brep and then throw a bunch of disjoint breps into it and that will pass into Brep.Split()… I’d never have thought of that approach. I’ll have a go at testing tomorrow, thanks!
Edit - This is indeed working and very cool, thanks again @dale !
@dale - I did however discover a limitation of this method… The disjoint breps that make up the cutter may not intersect each other, otherwise the operation fails…
import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino
def testDJBrepSplit():
cutter_IDs=rs.GetObjects("Select cutters",8)
to_cut_ID=rs.GetObject("Select object to cut",8+16)
cutters=[rs.coercebrep(ID) for ID in cutter_IDs]
to_cut=rs.coercebrep(to_cut_ID)
#make disjoint Brep
dj_brep=Rhino.Geometry.Brep()
for cutter in cutters: dj_brep.Append(cutter)
#try to cut brep object with disjoint cutter
if isinstance(to_cut,Rhino.Geometry.Extrusion): to_cut=to_cut.ToBrep()
split_result=to_cut.Split(dj_brep,sc.doc.ModelAbsoluteTolerance)
if not split_result: print "Failed!"
else:
for brep in split_result: sc.doc.Objects.AddBrep(brep)
rs.DeleteObject(to_cut_ID)
sc.doc.Views.Redraw()
testDJBrepSplit()
In the file below, you can split the blue box with all three green cutters or just the one red cutter, but not with all four at the same time, or any combination of the red plus a green (which cross). I suppose there isn’t a real workaround to this… The native Rhino command does work, so I imagine there is a different method used.
import scriptcontext as sc
tol = sc.doc.ModelAbsoluteTolerance
def split(input_geo, cutters):
collector = []
for g in input_geo:
res = g.Split(cutter, tol)
if res:
collector.extend(res)
else:
collector.append(g)
return collector
geos = [geo]
for count, cutter in enumerate(cutters):
# split with the first cutter
# and collect the new splitted geos
geos = split(geos, cutter)
print('round %d: input geometry is splitted into %d pieces.' % (count + 1, len(geos)))
Hi Chuck,
Thanks, that doesn’t seem to be available via RhinoCommon - at least I didn’t find it. I’m mainly trying to avoid scripting a Rhino command - otherwise this would be easy, I could just use Split…
That’s exactly what I was trying to do at first… I’ll have to look at your code to see how it differs from mine, as I couldn’t get mine working for some reason… Thanks!
I modified the script so it works in both V5 and V6, still calling Split with named arguments, but I’m letting you know in case this change wasn’t intentional.
IronPython’s support for overloaded methods can be somewhat manual. In the case of Brep.Split, you will need to use the .Overloads property to access a method’s overloads:
import System
import System.Collections.Generic.IEnumerable as IEnumerable
import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino
def test():
id = rs.GetObject( filter = 8+16, preselect = True)
if not id: return
brep = rs.coercebrep(id)
ids = rs.GetObjects(filter = 8+16,)
if not ids: return
cutters = [rs.coercebrep(item) for item in ids]
pass
out = brep.Split.Overloads[IEnumerable[Rhino.Geometry.Brep], System.Double]( cutters, .001)
rs.DeleteObject(id)
for item in out:
sc.doc.Objects.AddBrep(item)
sc.doc.Views.Redraw()
test()