# Extract and save trimmed surfaces from brep (solid)

**URL:** <https://discourse.mcneel.com/t/extract-and-save-trimmed-surfaces-from-brep-solid/162020>\
**Category:** CPython\
**Tags:** windows, rhinocommon, rhino7\
**Created:** [June 26, 2023, 2:00pm UTC](https://discourse.mcneel.com/t/extract-and-save-trimmed-surfaces-from-brep-solid/162020 "2023-06-26T14:00:44Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![Victor4](https://sea3.discourse-cdn.com/mcneel/user_avatar/discourse.mcneel.com/victor4/32/478469_2.png) [@Victor4](https://discourse.mcneel.com/u/Victor4)\
**Post date:** [June 26, 2023, 2:00pm UTC](https://discourse.mcneel.com/t/extract-and-save-trimmed-surfaces-from-brep-solid/162020/1 "2023-06-26T14:00:44Z")

</div>

Hi,

There is a solid as closed solid polysurface prepared in Rhino 7 in three steps:

- Surfaces have been created.
- The surfaces have been trimmed on each other.
- The remained trimmed surfaces have been Union in final closed solid polysurface object (see picture “Source solid.png” and file “T2\_closed\_solid\_polysurface.3dm”).

Using rhinoinside (RhinoCommon API) in Python 3.7 the idea was:

1. To read the “T2\_closed\_solid\_polysurface.3dm”).
2. Extract all faces with their real boundaries (not surfaces extended outside the solid object).
3. Then analyze if the one face intersects other one. (In this request it can be omitted).
4. Finally output all faces in a new 3dm file for further processing.

Unfortunately, the below code provides a result with untrimmed surfaces (see “Result\_1.png”):

```auto
import rhinoinside
rhinoinside.load()
import System
import Rhino

def extract_faces_of_solid(file_path, output_filename):
    model = Rhino.FileIO.File3dm.Read(file_path)
    output_file = Rhino.FileIO.File3dm()

    for obj in model.Objects:
        brep = Rhino.Geometry.Brep.TryConvertBrep(obj.Geometry)
        if brep:
            for face in brep.Faces:
                if isinstance(face, Rhino.Geometry.BrepFace):
                    trimmed_surface = face.ToNurbsSurface()
                    output_file.Objects.AddSurface(trimmed_surface)

    output_file.Write(output_filename, 6)
    model.Dispose()
    output_file.Dispose()

if __name__ == " __main__":
    file_path = "T2_closed_solid_polysurface.3dm"
    output_filename = 'output.3dm'
    extract_faces_of_solid(file_path, output_filename)

```

More complicated code gives us the same result - surfaces extended outside the solid object.

The second code is:

```auto
import rhinoinside
rhinoinside.load()
import System
import Rhino

def extract_trimmed_surfaces(file_path, output_filename):

    model = Rhino.FileIO.File3dm.Read(file_path)
    output_file = Rhino.FileIO.File3dm()

    layers = {}
    for layer in model.Layers:
        layers[layer.Name] = []

    for obj in model.Objects:
        if obj.Attributes.LayerIndex != -1:
            layer_name = model.Layers[obj.Attributes.LayerIndex].Name
            layers[layer_name].append(obj)

    for layer_name, objs in layers.items():
        for obj1 in objs:
            print(f"Objects on layer {layer_name}:")
            print(f" {obj1.Geometry.ObjectType} with ID {obj1.Attributes.ObjectId}")
            brep = Rhino.Geometry.Brep.TryConvertBrep(obj1.Geometry)
            if brep:
                for face in brep.Faces:
                    if isinstance(face, Rhino.Geometry.BrepFace):
                        print("face is a BrepFace")
                        # Add each face (not right shape. It is an untrimmed surface).
                        boundary_curves = brep.DuplicateEdgeCurves(False)
                        split_breps = brep.Split(boundary_curves, 0.0000001)
                        print(f"split_breps = {repr(split_breps)}")
                        for split_brep in split_breps:
                            for split_face in split_brep.Faces:
                                print(f"split_face = {repr(split_face)}")
                                if isinstance(split_face, Rhino.Geometry.BrepFace):
                                    trimmed_surface = split_face.ToNurbsSurface()
                                    print(f"trimmed_surface = {repr(trimmed_surface)}")
                                    if output_file.Objects.AddSurface(trimmed_surface):
                                        print(f"trimmed_surface has been added to output_file!")
                    else:
                        print("face is not a BrepFace")
    output_file.Write(output_filename, 6)
    model.Dispose()
    output_file.Dispose()

if __name__ == " __main__":
    file_path = "T2_closed_solid_polysurface.3dm"
    output_filename = 'Output.3dm'
    extract_trimmed_surfaces(file_path, output_filename)

```

Which function is more suitable to extract surfaces (or faces of brep object) with their real trimmed shapes? (It seems to be few lines of code only to do this).

 ![Source solid](https://global.discourse-cdn.com/mcneel/uploads/default/original/4X/c/7/1/c718080038b3d0275e2b484b704caa687304e230.png)  
[T2\_closed\_solid\_polysurface.3dm](https://discourse.mcneel.com/uploads/short-url/cbKgZlJiUYVA4BhNaVGVfOkVzeI.3dm) (69.5 KB)  
 ![Result_1](https://global.discourse-cdn.com/mcneel/uploads/default/original/4X/6/c/9/6c9fd7775e67e9d4ccad6aed9ebe12a7ad94e706.png)

---

<div class="post-metadata">

**Author:** ![farouk.serragedine](https://sea3.discourse-cdn.com/mcneel/user_avatar/discourse.mcneel.com/farouk.serragedine/32/768228_2.png) [@farouk.serragedine](https://discourse.mcneel.com/u/farouk.serragedine)\
**Post date:** [June 26, 2023, 3:05pm UTC](https://discourse.mcneel.com/t/extract-and-save-trimmed-surfaces-from-brep-solid/162020/2 "2023-06-26T15:05:48Z")

</div>

Hi Victor,  
I believe the issue you’re encountering is due to the `ToNurbsSurface()` method. This method takes a BrepFace and returns a NurbsSurface, but it doesn’t preserve the trimming information.  
Instead of using `ToNurbsSurface()` you should use the `DuplicateFace()` method which duplicates the face as a new Brep preserving the trimming information.  
Try and let me know, I’m not sure but I believe this is the issue.

---

<div class="post-metadata">

**Author:** ![dale](https://sea3.discourse-cdn.com/mcneel/user_avatar/discourse.mcneel.com/dale/32/685184_2.png) [@dale](https://discourse.mcneel.com/u/dale)\
**Post date:** [June 26, 2023, 3:19pm UTC](https://discourse.mcneel.com/t/extract-and-save-trimmed-surfaces-from-brep-solid/162020/3 "2023-06-26T15:19:03Z")

</div>

Hi @farouk.serragedine,

Try using [BrepFace.DuplicateFace](https://developer.rhino3d.com/api/rhinocommon/rhino.geometry.brepface/duplicateface).

– Dale

---

<div class="post-metadata">

**Author:** ![farouk.serragedine](https://sea3.discourse-cdn.com/mcneel/user_avatar/discourse.mcneel.com/farouk.serragedine/32/768228_2.png) [@farouk.serragedine](https://discourse.mcneel.com/u/farouk.serragedine)\
**Post date:** [June 26, 2023, 3:32pm UTC](https://discourse.mcneel.com/t/extract-and-save-trimmed-surfaces-from-brep-solid/162020/4 "2023-06-26T15:32:11Z")

</div>

Guess I was right then 🤣 @dale

---

<div class="post-metadata">

**Author:** ![Victor4](https://sea3.discourse-cdn.com/mcneel/user_avatar/discourse.mcneel.com/victor4/32/478469_2.png) [@Victor4](https://discourse.mcneel.com/u/Victor4)\
**Post date:** [June 27, 2023, 6:01am UTC](https://discourse.mcneel.com/t/extract-and-save-trimmed-surfaces-from-brep-solid/162020/5 "2023-06-27T06:01:48Z")

</div>

> [@dale](#):
>
> Try using [BrepFace.DuplicateFace](https://developer.rhino3d.com/api/rhinocommon/rhino.geometry.brepface/duplicateface).

Hi Farouk,  
Thank you very much for your reply. The code is working:

```auto
import rhinoinside
rhinoinside.load()
import System
import Rhino

def extract_faces_of_solid(file_path, output_filename):
    model = Rhino.FileIO.File3dm.Read(file_path)
    output_file = Rhino.FileIO.File3dm()

    for obj in model.Objects:
        brep = Rhino.Geometry.Brep.TryConvertBrep(obj.Geometry)
        if brep:
            for face in brep.Faces:
                if isinstance(face, Rhino.Geometry.BrepFace):
                    trimmed_surface = face.DuplicateFace(True)
                    output_file.Objects.AddBrep(trimmed_surface)

    output_file.Write(output_filename, 6)
    model.Dispose()
    output_file.Dispose()

if __name__ == " __main__":
    file_path = "T2_closed_solid_polysurface.3dm"
    output_filename = 'output.3dm'
    extract_faces_of_solid(file_path, output_filename)

```

Two lines have been changed.

```auto
 trimmed_surface = face.DuplicateFace(True)
 output_file.Objects.AddBrep(trimmed_surface)

```

**Many thanks to Dale and the entire community for taking the time to read the long post and support.**
