Split Brep with curves

Having a brain block here… I am trying to create a function that splits a brep with any number of curves (that might or might not actually split the brep).

Test file:
Split_Brep_Test.3dm (37.7 KB)

The following fails when selecting the surface and all 4 curves:

import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino, System
from System.Collections.Generic import IEnumerable

def SplitBrepWCrvs(brepID,crvIDs,tol,del_orig=True):
    brep=rs.coercebrep(brepID)
    crvs=[rs.coercecurve(crvID) for crvID in crvIDs]
    splits=brep.Split.Overloads[IEnumerable[Rhino.Geometry.Curve],System.Double](crvs, tol)
    if splits and len(splits)>1:
        sc.doc.Objects.Delete(brepID,True)
        return [sc.doc.Objects.AddBrep(brep) for brep in splits]

brepID=rs.GetObject("Select brep to split",8+16)
crvIDs=rs.GetObjects("Select splitting curves",4)
result=SplitBrepWCrvs(brepID,crvIDs,sc.doc.ModelAbsoluteTolerance,True)

because of this bug I previously reported, which will not be fixed until V7. Interestingly enough if you use only one of the two green curves and the red one which lies on the surface, it still does not do what it is supposed to do - it also looks like it fails if any curves cross each other. Only the two green ones work together.

So, I thought I’d try to “roll my own” , but I’m still not succeeding completely - I am still not getting all the splits I am supposed to, even though it is better.

import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino, System
from System.Collections.Generic import IEnumerable

def SplitBrepWCrvs(brepID,crvIDs,tol,del_orig=True):
    orig_brep=rs.coercebrep(brepID)
    crvs=[rs.coercecurve(crvID) for crvID in crvIDs]
    split_parts=[orig_brep]
    for crv in crvs:
        for brep in split_parts:
            splits=brep.Split.Overloads[IEnumerable[Rhino.Geometry.Curve],System.Double]([crv], tol)
            if splits and len(splits)>1:
                split_parts.remove(brep)
                for split in splits:
                    split_parts.append(split)
    if split_parts:
        sc.doc.Objects.Delete(brepID,True)
        return [sc.doc.Objects.AddBrep(brep) for brep in split_parts]

brepID=rs.GetObject("Select brep to split",8+16)
crvIDs=rs.GetObjects("Select splitting curves",4)
result=SplitBrepWCrvs(brepID,crvIDs,sc.doc.ModelAbsoluteTolerance,True)

Somehow it seems like this should work, but I’m at a loss as to why it is not 100%. Did I miss something dumb here, or do I need to make an excursion into recursion?

TIA, --Mitch

Hi Mitch,

Your scripting is too advanced for me to understand all the details, but I am wondering if it is the same problem that you and I discussed briefly about splitting a curve in multiple places, i.e have you allowed for the fact that the split off parts of the brep with the first curve have a new identity, and you have to use that to make the second split?

Max.

Edit: I understand a bit more now, and I think you have. But the way I understand it is you are appending the new parts to the list, and expect those to still be considered at the next splitting operation. I am surprised you can do that, querying a list while adding items at the same time.

M.

Well, actually, if I got it right, I am not. Any surface that gets split is replaced with the split parts, but for each new curve, the list is parsed from the beginning…

Ah yes, I can see that now, the new breps do not have to be reconsidered in the “for brep in split_parts:” loop, and they will be considered in the next run of the “for crv in crvs:” loop.

Sorry for my bit of static…

Max.

No biggie, nice to see that you are following the logic. Still can’t figure out why it fails though. :confounded:

Hi Mitch,

You were altering the split_parts list while iterating over it.
The below version will collect the result of the splits in a separate list
Only after the iteration, the split results are copied for splitting with the next curve.

import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino, System
from System.Collections.Generic import IEnumerable

def SplitBrepWCrvs(brepID,crvIDs,tol,del_orig=True):
    orig_brep=rs.coercebrep(brepID)
    crvs=[rs.coercecurve(crvID) for crvID in crvIDs]
    split_parts=[orig_brep]
    for crv in crvs:
        new_splits = [] # collect split results in this container
        for brep in split_parts:
            splits = brep.Split.Overloads[IEnumerable[Rhino.Geometry.Curve],System.Double]([crv], tol)
            if splits :
                new_splits.extend(splits)
            else:
                new_splits.append(brep)
        
        split_parts = new_splits[:] #copy new_splits as split_parts
        
        sc.doc.Objects.Delete(brepID,True)
        return [sc.doc.Objects.AddBrep(brep) for brep in split_parts]

brepID=rs.GetObject("Select brep to split",8+16)
crvIDs=rs.GetObjects("Select splitting curves",4)
result=SplitBrepWCrvs(brepID,crvIDs,sc.doc.ModelAbsoluteTolerance,True)

After typing my reply I realized the list duplication could also be a solution to pass in the for loop

for brep in split_parts[:]: iso for brep in split_parts:
This makes it save t alter the original list within the loop:

import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino, System
from System.Collections.Generic import IEnumerable

def SplitBrepWCrvs(brepID,crvIDs,tol,del_orig=True):
    orig_brep=rs.coercebrep(brepID)
    crvs=[rs.coercecurve(crvID) for crvID in crvIDs]
    split_parts=[orig_brep]
    for crv in crvs:
        for brep in split_parts[:]:
            splits=brep.Split.Overloads[IEnumerable[Rhino.Geometry.Curve],System.Double]([crv], tol)
            if splits and len(splits)>1:
                split_parts.remove(brep)
                for split in splits:
                    split_parts.append(split)
    if split_parts:
        sc.doc.Objects.Delete(brepID,True)
        return [sc.doc.Objects.AddBrep(brep) for brep in split_parts]

brepID=rs.GetObject("Select brep to split",8+16)
crvIDs=rs.GetObjects("Select splitting curves",4)
result=SplitBrepWCrvs(brepID,crvIDs,sc.doc.ModelAbsoluteTolerance,True)

Nice, I learned something new today!
-Willem

1 Like

Thanks Willem! I was absolutely convinced that I could simply replace the original brep with the split brep parts within the main list, but that was incorrect. Thanks for taking the time to look!

–Mitch

1 Like