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()