Confusion creating brep


I am using opennurbs to write 3dm files to transfer geometry between applications. To that end, I am trying to transfer a trimmed surface by creating a brep. To help develop a procedure I have referred to example_brep.cpp, cmdSampleTwistedCube.cpp, cmdSampleTrimmedPlane.cpp, cmdSampleFaceWithHole.cpp, and Brep Data Structure with C/C++.

My interpretation is that brep edge and trim curves are just two different representations of the same curves (edges being the 3d space representation, and trim curves being the 2d surface parameter space representation). However, this would mean there is redundancy in the brep structure, and it would difficult to have them exactly equal (for example, the RhinoSDK ON_Surface Pullback and Pushup functions can only convert between 3d and 2d representations to within a tolerance), which makes me suspect I have misinterpreted trim and edge curves. Can you please correct my understanding?

I need to understand this as in my application I have a surface and 3d edge curves, but not edges defined in 2d surface parameter space. In the example code the procedure for creating a brep seems to be:

  1. Create vertices
  2. Create 3d edge curves
  3. Create faces
  4. Create loops
  5. Create 2d trim curves

The brep NewTrim() function used in the final step takes both a 3d edge curve and trim curve index as arguments, yet the example code appears to create the trim curve prior in a way such that either it is relying on the geometry in the example for the edge and trim to be equivalent, or it needn’t be equivalent to the edge curve at all, or perhaps the trim curve is just created to have an object that the NewTrim() function then sets appropriately to match the edge curve in 2d space. Clearly I am confused.

As a final question, Brep Data Structure with C/C++ shows the brep structure with four edge/trim curves in each loop. Is it limited to four? I suspect not as it does not explicitly state this, but another library I use, the Sintef GoTools library, does limit the boundary to four curves, which may be a coincidence, but want to be sure.


Hi @stephen.banks,

You are correct, the edge curve / trim curve combination is redundant. Since nearly every operation requires both 3d and 2d information, ON_Brep requires that both are provided.

You are also correct that you can rarely have the edge and trim agree exactly. ON_BrepEdge::m_tolerance is a measure of the maximum 3d difference.

Also, there is no fixed order of objects that a Brep must be created in. The samples follow a simple order because all the information is already known.

Generally, you’d add the surfaces, the 3d curves and then the rest. But again, there not rule.

Finally, there is no limit on the number of edges in a boundary.

– Dale

Thanks, @dale.

Given that is the case, for what it’s worth, I would like to make a recommendation to add back in the ON_Surface::Pullback() and ON_Surface::Pushup() functions to opennurbs. These functions were included in older versions of opennurbs to at least as late as OPENNURBS_VERSION 201102025.

The reasons that immediately come to mind, of which I am sure there are others (albeit I appreciate you would have had your reasons for removing them), are (i) people can find older versions of opennurbs and get access to the code for these functions; (ii) the redundancy of having both the 3d and 2d representations suggests both will not always be exposed in applications/libraries, with the Sintef GoTools library being one example; and (iii) given the intention of opennurbs is to be able to transfer geometry between applications, and my point that not all applications/libraries expose both representations, presumably due to this redundancy, offering a standardised approach to convert between these representations so that breps can be created and transferred between applications would seem to make sense.

Kind regards,

Hi @stephen.banks,

We won’t be implementing ON_Surface::Pullback or ON_Surface::Pushup in the free openNURBS toolkit.

The partial implementations, found in older versions, didn’t work well if they worked at all. They never worked on NURBS surfaces, for example. Thus, they were removed so as not to mislead developers.

Perhaps you should be developing with the full-featured version of openNURBS, the one included with Rhino?

– Dale

Hi @dale,

Is the “full-featured version of openNURBS” the one bundled with RhinoSDK? I’m wondering as when I looked at it I didn’t, for example, see the pullback and pushup functions in the header file for nurbs surfaces. An additional consideration for me is that I don’t want to write a plugin for Rhino (that is, whilst I have a licence for Rhino, I’d prefer it be at the discretion of my users whether they use Rhino or not, rather than force them to purchase a licence for it so that my code will work).

Regarding tolerances, I was curious and read a 3dm file written by Rhino and found ON_BrepTrim::m_tolerance and ON_BrepEdge::m_tolerance equal to zero for the model. Does Rhino always set these to zero, or did it just happen for the particular model I inspected that it was able to determine these curves exactly with zero uncertainty?




There is a lot you get when running in Rhino, including file I/O, the display pipeline, and API’s not included in the free openNURBS.

ON_BrepTrim::m_tolerance and ON_BrepEdge::m_tolerance are saved in the 3dm file. ON_BrepEdge::m_tolerance should have been computed correctly before the file was saved. If you see a zero edge tolerance, the either the construction created exact edges from surface boundaries, the geometry was not created by native Rhino commands, or perhaps the the computation failed.

– Dale

I just thought I’d follow up to correct a previous remark of mine in case anyone comes across this post in the future that in actual fact the open source Sintef GoTools library does have functionality to compute a 2d parametric curves on surface given a 3d space curve on surface, and vice versa, in contrast to my previous remark that it doesn’t.