Split script creating unwanted surfaces, how to delete within script?

i have a script here that splits objects by the construction plane. when i split a solid the script sometimes creates a planar surface that i don’t want. (possible bug?)

is there a way within the script to have it filter the output and delete those surfaces?

the function are called SplitObjectsWithLine but it actually uses the cplane, i just haven’t cleaned it up yet

"""Splits selected objects with the CPlane of the active viewport. 
Objects can be curves, surfaces, polysurfaces or meshes.
Script by Mitch Heynick version 29.01.17."""

import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino

def FixDegenerateBB(bb,plane,tol):
    #expands degenerate (0 length side) bounding box in the required direction(s)
    #returns fixed bounding box or original if nothing needs to be done
    if bb[1].DistanceTo(bb[2])<tol:
        t_vec=plane.YAxis
        bb[2]+=t_vec ; bb[3]+=t_vec ; bb[6]+=t_vec ; bb[7]+=t_vec
        bb[0]-=t_vec ; bb[1]-=t_vec ; bb[4]-=t_vec ; bb[5]-=t_vec
    if bb[0].DistanceTo(bb[1])<tol:
        t_vec=plane.XAxis
        bb[1]+=t_vec ; bb[2]+=t_vec ; bb[5]+=t_vec ; bb[6]+=t_vec
        bb[0]-=t_vec ; bb[3]-=t_vec ; bb[4]-=t_vec ; bb[7]-=t_vec
    if bb[0].DistanceTo(bb[4])<tol:
        t_vec=plane.ZAxis
        bb[4]+=t_vec ; bb[5]+=t_vec ; bb[6]+=t_vec ; bb[7]+=t_vec
        bb[0]-=t_vec ; bb[1]-=t_vec ; bb[2]-=t_vec ; bb[3]-=t_vec
    return bb

def SplitObjsWithLine():
    msg="Select curves, surfaces or meshes to split with CPlane"
    objIDs=rs.GetObjects(msg,4+8+16+32,preselect=True)
    if not objIDs: return
    
    tol=sc.doc.ModelAbsoluteTolerance
    cut_plane=rs.ViewCPlane()
    sf=1.1 #scale factor for enlarging cut plane - can be changed
    #principal problem from here is can't split breps or meshes with plane object
    #need to create a planar *surface* or *mesh* to use as cutter
    
    #create cutting objects
    #get objs bb relative to cutting plane
    bb=rs.BoundingBox(objIDs,cut_plane)
    #need to expand 0 length sides to work with completely planar situations
    bb=FixDegenerateBB(bb,cut_plane,tol)
    #create planar projection to cut plane
    xform_cut=rs.XformPlanarProjection(cut_plane)
    #create bb bottom rectangle(points), project to cut plane
    corners=rs.PointArrayTransform([bb[0],bb[1],bb[2],bb[3],bb[0]],xform_cut)
    #get center point for uniform scale 
    ctr_pt=(corners[0]+corners[2])/2
    #create cutting plane rectangle
    cut_rect=Rhino.Geometry.PolylineCurve(corners)
    #scale rectangle a bit larger to ensure full cut
    xform_scale=Rhino.Geometry.Transform.Scale(ctr_pt,sf)
    cut_rect.Transform(xform_scale)
    
    #create plane brep for cutter
    cut_srf=Rhino.Geometry.Brep.CreatePlanarBreps(cut_rect)[0]
    #create mesh plane for cutter
    mp=Rhino.Geometry.MeshingParameters.Coarse
    cut_mesh=Rhino.Geometry.Mesh.CreateFromPlanarBoundary(cut_rect,mp)
    #sc.doc.Objects.AddBrep(cut_srf)  #debug
    #sc.doc.Objects.AddMesh(cut_mesh)  #debug
    #sc.doc.Views.Redraw() ; return  #debug
    
    #main loop
    rs.EnableRedraw(False)
    split_result=[]
    no_split=0
    for objID in objIDs:
        rhobj=rs.coercerhinoobject(objID,True,True)
        attrs=rhobj.Attributes
        obj=rhobj.Geometry
        if rs.IsCurve(objID):
            split_res=obj.Split(cut_srf,tol)
            if split_res:
                for crv in split_res:
                    split_result.append(sc.doc.Objects.AddCurve(crv,attrs))
                rs.DeleteObject(objID)
            else: no_split+=1
        elif rs.IsBrep(objID):
            if isinstance(obj,Rhino.Geometry.Extrusion):
                if obj.HasBrepForm:
                    obj=obj.ToBrep()
                else:
                    no_split+=1 ; continue
            split_res=Rhino.Geometry.Brep.Split(obj,cut_srf,tol)
            if split_res:
                for brep in split_res:
                    cap=brep.CapPlanarHoles(tol)
                    if cap: brep=cap
                    split_result.append(sc.doc.Objects.AddBrep(brep,attrs))
                rs.DeleteObject(objID)
            else: no_split+=1
        elif rs.IsMesh(objID):
            split_res=Rhino.Geometry.Mesh.CreateBooleanSplit([obj],[cut_mesh])
            if split_res:
                for mesh in split_res:
                    split_result.append(sc.doc.Objects.AddMesh(mesh,attrs))
                rs.DeleteObject(objID)
            else: no_split+=1
            
    #reporting
    if split_result:
        splits=len(objIDs)-no_split
        if splits>1: s="s"
        else: s=""
        msg="{} object{} split into {} parts.".format(splits,s,len(split_result))
        if no_split>0: msg+=" {} objects unable to be split".format(no_split)
        #rs.SelectObjects(split_result) #optional
    else:
        msg="No objects were split"
    print msg
SplitObjsWithLine()

Hi @kleerkoat,

Is there a sample .3dm file that accompanies this script?

– Dale

here you go dale, thanks for replying.

Untitled.3dm (5.3 MB)

sidenote, this file is huge considering the geometry?

@dale any ideas? thanks

If you purge the unused block definitions, the file will be smaller…

I have not look into this, by the way.

– Dale

Hi @kleerkoat,

You might want to check with @Helvetosaur as this looks like something he wrote. But if you don’t want the planar surface, just delete it - it’s the only surface in the scene.

– Dale

in this case it’s simple but when i split a bunch of objects it’s kind of a pain. is there a way to select last and deselect everything but surfaces scripting wise?

@Helvetosaur do you have any ideas? thanks

Not in front of my computer just now, will look later…

thank you

So, yeah, what I see is that the RhinoCommon Brep.Split() function is returning 3 objects when your object is split - the two split halves plus the surface that coincides with the split plane. Looks like it will happen with any object that has one or more surfaces that lie exactly on the split plane, that’s just what the function seems to do right now - in both V6 and the WIP.

I’ll look into filtering out single surfaces that lie on the split plane - get back to you in awhile…

1 Like

is that a bug or by design?

No idea…

OK, try this one - let me know if it fails anywhere…

Found one semi-edge-case issue, this will need another small revision…

OK, fixed… I hope.

SplitObjsWithCPlane.py (5.6 KB)

1 Like

nailed it! thank you so much!