Brep.GetConnectedComponents not working?

I’ve got a brep made up of separate joined Polysurfaces. I’m trying to get the separate polysurfaces using Brep.GetConnectedComponents() but I get 6 separate surfaces instead of the 3 separate polysurfaces I would expect. Am I missing something?

220813 GetConnectedComp.3dm (194.6 KB)
220813 GetConnectedComp.py (353 Bytes)

import rhinoscriptsyntax as rs
import Rhino
import scriptcontext as sc

def TestSplit():
    obj = rs.GetObjects()
    
    if not obj:
        return
    
    brep = rs.coercebrep(obj)
    
    breps = brep.GetConnectedComponents()
    
    for i in breps:
        sc.doc.Objects.AddBrep(i)
    
    rs.DeleteObject(obj)

TestSplit()

try this

import rhinoscriptsyntax as rs
import Rhino
import scriptcontext as sc

def TestSplit():
    obj = rs.GetObjects()
    
    if not obj:
        return
    
    brep = rs.coercebrep(obj)
    
    breps = brep.GetConnectedComponents()
    breps = Rhino.Geometry.Brep.JoinBreps(breps,0.01)
    for i in breps:
        sc.doc.Objects.AddBrep(i)
    
    rs.DeleteObject(obj)
    sc.doc.ActiveDoc.Views.Redraw()

TestSplit()

Hi @603419608 , the example I gave just highlights the problem with the method not working as expected. I know I could just explode and join, but I need to return the separate brep parts without changing them like JoinBreps() does. I have polysurfaces with faces pointing in different direction like so:


brown shows the backface of a surface

I’d like to retrieve each separate polysurface without changing the direction of each face. I guess I should have mentioned that being problem I’m trying to solve. Here’s the file with the faces pointing in different direction:
220813 GetConnectedComp 2.3dm (194.9 KB)

Brep.GetConnectedComponents is returning 6 monoface breps because all the of the original brep’s edges are naked.

This script can separate the breps of joinable sets of faces.
import rhinoscriptsyntax as rs
import Rhino
import scriptcontext as sc

def TestSplit():
    obj = rs.GetObject(preselect=True)
    
    if not obj:
        return
    
    brep_In = rs.coercebrep(obj)
    
    brep_TaggedSrfs = brep_In.DuplicateBrep()
    
    key = '_FaceIndex'
    
    for face in brep_TaggedSrfs.Faces:
        face.UnderlyingSurface().SetUserString(key, str(face.FaceIndex))
    
    breps_GCC = brep_TaggedSrfs.GetConnectedComponents()
    
    if len(breps_GCC) < 2:
        print "Brep does not have multiple 'shells'."
        return
    
    breps_Joined = Rhino.Geometry.Brep.JoinBreps(
        breps_GCC, 2.0*sc.doc.ModelAbsoluteTolerance)
    
    if len(breps_Joined) < 2:
        print "Brep does not have multiple 'shells'."
        return
    
    bDeleteOK = True
    
    for brep in breps_Joined:
        idxs = [int(face.UnderlyingSurface().GetUserString(key))
                for face in brep.Faces]
        
        brep_Out = brep_In.DuplicateBrep()
        
        for i in xrange(brep_In.Faces.Count-1, -1, -1):
            if i in idxs: continue
            brep_Out.Faces.RemoveAt(i)
        
        gOut = sc.doc.Objects.AddBrep(brep_Out)
        if gOut == gOut.Empty:
            print "Subset of brep could not be added."
            bDeleteOK = False
    
    if bDeleteOK: rs.DeleteObject(obj)
    
    sc.doc.Views.Redraw()

TestSplit()
1 Like

Good point! Thanks! Do you know if there’s a way to joining those polysurfaces without getting any naked edges in the touching edges and while keeping their face direction? @spb

_NonmanifoldMerge and Brep.MergeBreps Method will do it, although the latter creates invalid breps with your geometry that can be repaired with Brep.Repair.

Script with MergeBreps
import rhinoscriptsyntax as rs
import Rhino.Geometry as rg
import scriptcontext as sc

def TestSplit():
    obj = rs.GetObject(preselect=True)
    
    if not obj:
        return
    
    brep_In = rs.coercebrep(obj)
    
    brep_TaggedSrfs = brep_In.DuplicateBrep()
    
    key = '_FaceIndex'
    
    for face in brep_TaggedSrfs.Faces:
        face.UnderlyingSurface().SetUserString(key, str(face.FaceIndex))
    
    breps_GCC = brep_TaggedSrfs.GetConnectedComponents()
    
    if len(breps_GCC) < 2:
        print "Brep does not have multiple 'shells'."
        return
    
    breps_Joined = rg.Brep.JoinBreps(
        breps_GCC, 2.0*sc.doc.ModelAbsoluteTolerance)
    
    if len(breps_Joined) < 2:
        print "Brep does not have multiple 'shells'."
        return
    
    bDeleteOK = True
    
    for brep in breps_Joined:
        idxs = [int(face.UnderlyingSurface().GetUserString(key))
                for face in brep.Faces]
        
        breps_ToMerge = [rg.BrepFace.DuplicateFace(
                brep_In.Faces[i], duplicateMeshes=True)
                for i in xrange(brep_In.Faces.Count)
                if i in idxs]
        
        brep_Out = rg.Brep.MergeBreps(
            breps_ToMerge,
            2.0*sc.doc.ModelAbsoluteTolerance)
        
        bValid, sLog = brep_Out.IsValidWithLog()
        if not bValid:
            #print sLog
        
            if brep_Out.Repair(sc.doc.ModelAbsoluteTolerance):
                #print "Brep.Repair succeeded."
                pass
            else:
                print "Brep.Repair failed."
                bDeleteOK = False
                continue
        
        gOut = sc.doc.Objects.AddBrep(brep_Out)
        if gOut == gOut.Empty:
            print "Subset of brep could not be added."
            bDeleteOK = False
    
    if bDeleteOK: rs.DeleteObject(obj)
    
    sc.doc.Views.Redraw()

TestSplit()
1 Like

Thanks a lot @spb. This works like a charm.