Why is GetNurbForm() not getting correct/all surfaces from brep?


I have the following code attempting to extract the NURBS surfaces I see in the Rhino viewport. I used the sample file example_3dm_files_20130711/V5/v5_rhino_logo.3dm as a reference. The NURBs surfaces I got is different from what I see in Rhino. Some of them matches but there are (1) extra surfaces (2) missing extruded-like surface

If I am purely interested in extract all the NURBS surfaces as one would see in Rhino3D viewport, what is the correct way to go about doing that ? Is there an example showing the best practice ?

` // open file containing opennurbs archive
FILE* archive_fp = ON::OpenFile( is.getFilename(), “rb”);

// create achive object from file pointer                                                                                              
ON_BinaryFile archive( ON::read3dm, archive_fp );

// read the contents of the file into "model"                                                                                          
bool model_read_status = model.Read( archive, dump );

if (model_read_status)
    int object_count = model.m_object_table.Count();
    printf("object count = %d\n",object_count);

    for (int object_index = 0; object_index < object_count; object_index++)
        // printf("object count[%d] is %s\n",object_count,model.m_object_table[object_index].m_object->ClassId()->ClassName());        

        if (model.m_object_table[object_index].m_object->IsKindOf(ON_ClassId::ClassId("ON_Brep")))
            const ON_Brep* brep = ON_Brep::Cast(model.m_object_table[object_index].m_object);
            if (brep)
                int m_S_Count = brep->m_S.Count();
                printf("m_S_Count = %d\n",m_S_Count);
                for (int m_S_index = 0; m_S_index < m_S_Count ; m_S_index++)
                    ON_BOOL32 hbf = brep->m_S[m_S_index]->HasBrepForm();
                    int hnf = brep->m_S[m_S_index]->HasNurbForm();
                    printf("HasBrepForm = %s, HasNurbForm = %d\n",(hbf?"true":"false"),hnf);
                    ON_NurbsSurface nurb_surface;
                    int get_nurb_surface_status = brep->m_S[m_S_index]->GetNurbForm(nurb_surface);
                    printf("get_nurb_surface_status = %d\n",get_nurb_surface_status);
                    if (get_nurb_surface_status!=0)



Couple of questions

  • What type is model?
  • Are you interested in untrimmed surfaces (these are in brep->m_S) or in the BRep faces (which may be trimmed, and are in brep->m_F)
  • You are talking about extrusions, these are special objects of type ON_Extrusion that can’t be cast to ON_Brep. You have to convert them (using HasBrepForm and/or ToBrep functions)

For more details on the BRep structure in OpenNURBS, visit:

Basically, each face of a BRep has one underlying surface. Its loops, edges, vertices and trims define which parts of the surface you see, and which are invisible due to trims.

` ONX_Model model;

I am interested in surfaces that I can write out for rendering by various renderer so I guess that would be trimmed surfaces, am I correct ? I am targeting RenderMan for now so with support of RiNuPatch includes trim and holes.

With regards to the extrusion, I will dig further and add additional processing steps.


Hi Nicholas,

First of all, Rhino supports several types of surfaces:


You find ON_NurbsSurface, ON_PlaneSurface, ON_RevSurface, and ON_SumSurface in an ON_Brep (ON_Brep::m_S).

All surface types can be represented as NURBS surfaces. To do so, use ON_Surface::GetNurbForm.

ON_Extrusion objects are more like ON_Brep objects then they are surfaces. You can the Brep form of an ON_Extrusion object using `ON_Extrusion::BrepForm```.

What you see in viewports are Breps, not surfaces. The term Brep, or boundary representation, indicates that there are portions of underlying surfaces that you may not see due to trimming. So what you are really seeing in a viewport is a Brep’s Faces (ON_BrepFace), not the underlying surface.

If you are not familiar with Breps, then you might spend some time reviewing the Brep Data Structure that @menno referenced. The openNURBS headers are also a wealth of information. For Breps, see opennurbs_brep.h.

You might review this thread: