BrepFaceList.RemoveAt overload

Hello,

I have a list of BrepFaces that I would like to remove from a Brep.

The way I do it at the moment is: loop through all brep’s BrepFaces;
take only those which are not in the upper mentioned list;
convert each of taken BrepFace to a Brep;
join all those new Breps to a single Brep;

Is it possible to get an overload method of BrepFaceList.RemoveAt, which would have a list of BrepFace indices as an input, instead of just a single BrepFace index?

With the current one, I can’t simply loop through the initial list of BrepFaces and call BrepFaceList.RemoveAt on each of them, because the BrepFaceList indices are recomputed (changed), each time BrepFaceList.RemoveAt is called.

I am somewhat making the same parallel we at the moment have with Brep.RemoveHoles overload, which also accepts a list as an input.

How about you make a list of indices to remove, sort it and remove faces in descending order?

1 Like

Hi @menno ,
I apologize for the late reply. Thank you very much for your help and suggestion!
BrepFaceList.RemoveAt always returns a brep, not an array of breps. Which means that if my (sorted in descending order) BrepFace indices, “split” the brep in half - BrepFaceList.RemoveAt will still return a single brep.
This creates an unusual brep which resembles more of a mesh than a brep (its BrepFaces are physically separated). Here is an example:

:thinking:

I haven’t tried it, but could Brep.GetConnectedComponents help here?

2 Likes

Thank you again @menno ,
I don’t have Rhino 7 at the moment, but I assume your Brep.GetConnectedComponents suggestion will probably work.

In any case, I can still use the initial workaround of filtering the needed BrepFaces, converting them to a Brep, then joining all these Breps. My comment was that BrepFaceList.RemoveAt may have a overload to accept a list of BrepsFace indices. Which would shrink the whole workaround to a single line of code.

My gut feeling is that multiple calls to RemoveAt followed by GetConnectedComponents will be significant more performant than getting individual breps for each face, and then joining those.

1 Like

Hi @djordje and @menno,

there is Brep.DuplicateSubBrep() which accepts multiple face indices. Maybe it can be used before Brep.GetConnectedComponents to create the desired results and avoid joining eg:

import Rhino
import scriptcontext
import rhinoscriptsyntax as rs

def DoSomething():
    
    brep_id = rs.GetObject("Brep", rs.filter.polysurface, True, False)
    if not brep_id: return
    
    brep = rs.coercebrep(brep_id, True)
    
    # faces to remove (a) and to keep (b)
    face_indices_a = set([3,4,5])
    face_indices_b = set(range(brep.Faces.Count)) - face_indices_a
    
    brep_a = brep.DuplicateSubBrep(face_indices_a)
    brep_b = brep.DuplicateSubBrep(face_indices_b)
    
    print "A: {}".format(brep_a.GetConnectedComponents().Count)
    print "B: {}".format(brep_b.GetConnectedComponents().Count)
    
DoSomething()

if one of the resulting sub-breps has connected components they can be added and replace eg. the brep with faces 0,1,2,6,7,8. In case of no connected components, the brep can be used as is. I think the function @menno suggests might be useful to test both resulting breps if disjoint breps need to be avoided.

_
c.

2 Likes

Thank you very much for the useful suggestion @clement !
I was not aware of the DuplicateSubBrep method.
I will use both Menno’s and your suggestions on Rhino 8. At the moment, I don’t have GetConnectedComponents on Rhino 6. But in any case both of you two helped me a lot.

2 Likes

These methods can separate non-contiguous sets of faces into multiple breps:
https://developer.rhino3d.com/api/rhinocommon/rhino.geometry.brep/createbooleanunion
https://developer.rhino3d.com/api/rhinocommon/rhino.geometry.brep/joinbreps

The argument for tolerance can be 0.0

1 Like