Building a Brep in RhinoCommon

I am trying to define a new Brep object in RhinoCommon, following this Dale’s C++ sample
… but it looks like I’m missing something.
This is the code that gives me an invalid brep:
It should trim a PlaneSurface by an ArcCurve (a circle)

import Rhino
import math

def main():

define surface

surf = Rhino.Geometry.PlaneSurface(
Rhino.Geometry.Interval( -100, 100 ),
Rhino.Geometry.Interval( -100, 100 ) )

draw surface

Rhino.RhinoDoc.ActiveDoc.Objects.AddSurface( surf )

define outer curve

circ = Rhino.Geometry.Circle( 75 )
curve3d = Rhino.Geometry.ArcCurve( circ )

draw outer curve

Rhino.RhinoDoc.ActiveDoc.Objects.AddCurve( curve3d )

get curve 2D

tolr = Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance
curve2d = surf.Pullback( curve3d, tolr )
vertexpnt = curve3d.PointAtStart

surface orientation

backsurf = False

curve orientation

backedge = False

build brep:

rep = Rhino.Geometry.Brep()

add vertex

vertex = rep.Vertices.Add(
vertexpnt, Rhino.RhinoMath.UnsetValue )
vertexindex = vertex.VertexIndex

add curve 3D

cur3dindex = rep.AddEdgeCurve( curve3d )

add edge

edge = rep.Edges.Add(
vertexindex, vertexindex, cur3dindex, Rhino.RhinoMath.UnsetValue )

add surface

surfindex = rep.AddSurface( surf )

add face

face = rep.Faces.Add( surfindex )

add loop

loop = rep.Loops.Add( Rhino.Geometry.BrepLoopType.Outer, face )

add curve 2D

cur2dindex = rep.AddTrimCurve( curve2d )

add trim

trim = loop.Trims.Add( edge, backedge, loop, cur2dindex )
trim.IsoStatus = Rhino.Geometry.IsoStatus.None
trim.TrimType = Rhino.Geometry.BrepTrimType.Boundary
trim.SetTolerances( Rhino.RhinoMath.UnsetValue, Rhino.RhinoMath.UnsetValue )

set surface orientation

face.OrientationIsReversed = backsurf

print ‘Brep is valid: %s’ % str( rep.IsValid )


Any advise to help me find the error(s) ?

That seems like an awful lot of work just to create a plane surface with a hole in the middle. Why not just do something like this?

import rhinoscriptsyntax as rs

def TestPlanarSrf():
    points = []
    points.append([-100.0, -100.0, 0.0])
    points.append([100.0, -100.0, 0.0])
    points.append([100.0, 100.0, 0.0])
    points.append([-100.0, 100.0, 0.0])
    points.append([-100.0, -100.0, 0.0])
    curves = []
    curves.append(rs.AddCircle(rs.WorldXYPlane(), 75))

Thanks Dale.
My test was just a first step to try to learn how to build Brep’s.
I’d have to build less simple shapes, like a non planar surface trimmed by a curve projected onto it and a solid from an extruded curve closed by non planar surfaces.

OK, it was a tolerance problem.

It seems that using Rhino.RhinoMath.UnsetValue wasn’t working.
I had to use a numeric value.

Dilemma: this requires a 2d trim curve. In fact that’s the only type of trim curve I see available in Rhinocommon for brep construction. How do I do this in 3d then?

If I split a brep face with a simple curve loop, I often get one or two extra brep edge curves that I very much don’t want and the lack of Rhinocommon access to MergeEdge means I’m stuck with those extra curves that destroys my ability to use the new Rhino 6 WIP surface blend command. So I thought I’d construct a brep from scratch but I can’t figure out the trimming.

@dale I want to know this also. Can you please show us how to make a brep by defining its outer and inner trimming curves? And both being irregular non planar curves? In python.

@bdidier, I am curious as to what you are working on. Why do you need to build Breps by hand using Python?

@dale I am trying to create a patch but with holes.

Here is an example created in Rhino by using the _Patch and _Split commands:

But I would like to do that in python.
I can create a patch with no holes with Rhino.Geometry.Brep.CreatePatch. And I can use the Rhino.Geometry.BrepFace.Split to split that patch with two inner curves. But I do not want to use the Rhino.Geometry.BrepFace.Split function. It is one of the slowest functions, and also the index of the resulting brep faces is unpredictable, depending on the position of the two inner curves. For example, if one of the inner curves intersects with the outer curve, the brep face indices of splitted patch are in different order than if I exclude that one specific inner curve from splitting.
This is just a simple example. My actual patch may have hundreds of holes, instead of two.

So I thought that maybe there was a way of manually building a Brep and assigning all the inner curves as inner trimming curves?

Patch with holes.3dm (197.5 KB)

Have you tried this in the Rhino WIP? It should be faster when splitting with multiple curves…

I didn’t. But I assume that the index of the resulting brep faces is still somewhat unpredictable, the way it is with Rhino.Geometry.BrepFace.Split Rhino 5 function.

Even if it isn’t would creating a patch, and then assigning all the inner curves as the inner trimming curves be too difficult in Rhino 5?

Yes, probably. You could always loop through the list of curves one at a time. But that would be slow.

Rolling your own Brep isn’t for the faint of heard. There is quite a bit of work in putting together the most basic shapes, let alone a patched face with a bunch of holes.

The famous Brep data structure:

Here are a couple of samples, in C#, to chew on:



Now if you really want to trim, not split, then it is possible to create a disjoint Brep, with a bunch of extruded surfaces, and then use Brep.Trim. I can work up a sample if you want…

– Dale


I googled before asking a question and that Brep Data Structure article appears few times:

But the C++ code is not really something a python coder would understand.

Indeed those C# samples look quite scary.

What would be the difference between split and trim?

And would that Brep.Trim require a single inner curve per run? It is not possible to include all the inner curves to trim the patch at once?

Trim is basically Split and then delete the pieces you don’t want to keep.

I believe Brep.Trim wants a single oriented cutting Brep. So you’d need to extrude your curves though the target patch.

Thank you Dale !
Sorry for taking me too long to see the post.

Hi Dale,

using your examples I was almost successful on building brep trims manually. This is what I got:

I’m trying to trim a hole in the middle. As you can see, it works for the parameter lines, but somehow the brep still exists where the hole is supposed to be. Any ideas or advice on what I might be missing?

Much appreciated,

Hi @thomas.gust,

Do you have sample source I can review? Otherwise, verity the inner trimming loop clockwise around the region the hole, and the trim curves of the inner loop run clockwise.

– Dale

1 Like

Hi Dale, I called Brep.Repair() and that fixed the problem. I will still try to find out what was missing.

Here is what I did so far in short:

  • start with an existing brep (single surface)
  • add vertices
  • add 2d and 3d curves
  • add edges
  • add innner loop
  • add trims for inner loop
  • set trim type to boundary, tolerance and iso status

All validity tests were positive, but there still was the piece of brep in the middle. When I make a wireframe from that brep, I get the correct result.

I will make a code example if I can’t find the error.