Sdk Brep Face User Data
Last changed: stevebaer-204.177.179.132

.
DeveloperC++, .NET
SummaryDemonstrates how to attach object user data to components of a Brep.

When attaching user data to brep components, attach the data to the underlying geometry, not the topology. For example, instead of attaching user data to an ON_BrepFace, attach it to the face's underlying ON_Surface object instead.

The following source code example demonstrates how to attach object user data to the underlying surface of a brep face.

C++

  CRhinoCommand::result CCommandTest::RunCommand( 
        const CRhinoCommandContext& context)
  {
    // Allow for picking of either a surface or a brep face.
    CRhinoGetObject go;
    go.SetCommandPrompt( L"Select surface to attach data" );
    go.SetGeometryFilter( CRhinoGetObject::surface_object );
    go.EnableSubObjectSelect( TRUE );
    go.GetObjects( 1, 1 );
    if( go.CommandResult() != CRhinoCommand::success )
      return go.CommandResult();


    // Get first object reference. Note, this reference
    // reprsents the picked surface or face, not the
    // top level brep.
    const CRhinoObjRef& objref = go.Object(0);


    // Get face on brep that was picked
    const ON_BrepFace* face = objref.Face();
    if( !face )
      return failure;


    // Get the faces underlying surface
    const ON_Surface* srf = face->SurfaceOf();
    if( !srf )
      return failure;


    // Query surface for user data
    CTestUserData* ud = CTestUserData::Cast( srf->GetUserData(ud->m_uuid) );
    if( ud )
    {
      RhinoApp().Print( L"Data already attached.\n" );
      return nothing;
    }


    // Get the top level object
    const CRhinoBrepObject* obj = CRhinoBrepObject::Cast( objref.Object() );
    if( !obj )
      return failure;


    // Duplicate the top level object.
    CRhinoBrepObject* dupe_obj = CRhinoBrepObject::Cast( obj->DuplicateObject() );
    if( !dupe_obj )
      return failure;


    // Get the brep
    ON_Brep* dupe_brep = dupe_obj->Brep();
    if( !dupe_brep )
      return failure;


    // Get the surface
    ON_Surface* dupe_srf = dupe_brep->m_S[face->SurfaceIndexOf()];
    if( !dupe_srf )
      return failure;


    // New up the user data
    ud = new CTestUserData();
    if( !ud )
    {
      delete dupe_obj;
      return failure;
    }


    // TODO: Initialize user data object here


    // Attach user data to surface, not face. Note, ud
    // is now owned by dupe_srf, not by us. So, we are
    // not responsible for deleting it;
    if( !dupe_srf->AttachUserData(ud) )
    {
      delete ud;
      delete dupe_obj;
      return failure;
    }


    // Replace object. Note, we cannot reuse objref for it references
    // the picked face, not the top level brep. 
    // Note, dupe_obj is now owned by Rhino, so we are not 
    // responsible for deleting it.
    if( !context.m_doc.ReplaceObject(CRhinoObjRef(obj), dupe_obj) )
    {
      delete dupe_obj;
      return failure;
    }


    // Done deal
    RhinoApp().Print( L"Data attached successfully.\n" );
    context.m_doc.Redraw();


    return CRhinoCommand::success;
  }

VB.NET (Rhino 4)

  Public Overrides Function RunCommand(ByVal context As IRhinoCommandContext) _
    As IRhinoCommand.result
    ' Allow for picking of either a surface or a brep face.
    Dim go As New MRhinoGetObject()
    go.SetCommandPrompt("Select surface to attach data")
    go.SetGeometryFilter(IRhinoGetObject.GEOMETRY_TYPE_FILTER.surface_object)
    go.EnableSubObjectSelect(True)
    go.GetObjects(1, 1)
    If (go.CommandResult() <> IRhinoCommand.result.success) Then
      Return go.CommandResult()
    End If


    ' Get first object reference. Note, this reference
    ' reprsents the picked surface or face, not the
    ' top level brep.
    Dim objref As MRhinoObjRef = go.Object(0)


    ' Get face on brep that was picked
    Dim face As IOnBrepFace = objref.Face()
    If (face Is Nothing) Then Return IRhinoCommand.result.failure


    ' Get the faces underlying surface
    Dim srf As IOnSurface = face.SurfaceOf()
    If (srf Is Nothing) Then Return IRhinoCommand.result.failure


    ' Query surface for user data
    Dim key As String = "MyVBUserData"
    Dim userdata As String = ""
    If (srf.GetUserString(key, userdata)) Then
      RhUtil.RhinoApp().Print("Data already attached." + vbCrLf)
      RhUtil.RhinoApp().Print("USERDATA = " + userdata + vbCrLf)
      Return IRhinoCommand.result.nothing
    End If


    ' Get the top level object
    Dim obj As IRhinoBrepObject = MRhinoBrepObject.ConstCast(objref.Object())
    If (obj Is Nothing) Then Return IRhinoCommand.result.failure


    Dim orig_brep As IOnBrep = obj.Brep()


    Dim dupe_brep As New OnBrep(orig_brep)


    ' Get the surface
    Dim dupe_srf As OnSurface = dupe_brep.m_S(face.SurfaceIndexOf())
    If (dupe_srf Is Nothing) Then Return IRhinoCommand.result.failure


    ' Attach user data to surface, not face.
    ' Set our user data string. This can be any type of string. In this example, we
    ' just set up some text, but this could be a serialized .NET class
    dupe_srf.SetUserString(key, "my custom user data")


    ' Replace object. Note, we cannot reuse objref for it references
    ' the picked face, not the top level brep.
    If (context.m_doc.ReplaceObject(New MRhinoObjRef(obj), dupe_brep) IsNot Nothing) Then
      RhUtil.RhinoApp().Print("Data attached successfully" + vbCrLf)
      context.m_doc.Redraw()
      Return IRhinoCommand.result.success
    End If


    Return IRhinoCommand.result.nothing
  End Function

C# (Rhino 4)

  public override IRhinoCommand.result RunCommand(IRhinoCommandContext context)
  {
    // Allow for picking of either a surface or a brep face.
    MRhinoGetObject go = new MRhinoGetObject();
    go.SetCommandPrompt("Select surface to attach data");
    go.SetGeometryFilter(IRhinoGetObject.GEOMETRY_TYPE_FILTER.surface_object);
    go.EnableSubObjectSelect(true);
    go.GetObjects(1, 1);
    if(go.CommandResult() != IRhinoCommand.result.success)
      return go.CommandResult();


    // Get first object reference. Note, this reference
    // reprsents the picked surface or face, not the
    // top level brep.
    MRhinoObjRef objref = go.Object(0);


    // Get face on brep that was picked
    IOnBrepFace face = objref.Face();
    if( face == null )
      return IRhinoCommand.result.failure;


    // Get the faces underlying surface
    IOnSurface srf = face.SurfaceOf();
    if( srf == null )
      return IRhinoCommand.result.failure;


    // Query surface for user data
    string key = "MyCSUserData";
    string userdata = "";
    if( srf.GetUserString(key, ref userdata) )
    {
      RhUtil.RhinoApp().Print("Data already attached.\n");
      RhUtil.RhinoApp().Print("USERDATA = " + userdata + "\n");
      return IRhinoCommand.result.nothing;
    }
    // Get the top level object
    IRhinoBrepObject obj = MRhinoBrepObject.ConstCast(objref.Object());
    if( obj == null )
      return IRhinoCommand.result.failure;


    IOnBrep orig_brep = obj.Brep();
    OnBrep dupe_brep = new OnBrep(orig_brep);


    // Get the surface
    OnSurface dupe_srf = dupe_brep.m_S[face.SurfaceIndexOf()];
    if( dupe_srf == null )
      return IRhinoCommand.result.failure;


    // Attach user data to surface, not face.
    // Set our user data string. This can be any type of string. In this example, we
    // just set up some text, but this could be a serialized .NET class
    dupe_srf.SetUserString(key, "my custom user data");


    // Replace object. Note, we cannot reuse objref for it references
    // the picked face, not the top level brep.
    if(context.m_doc.ReplaceObject(new MRhinoObjRef(obj), dupe_brep) != null)
    {
      RhUtil.RhinoApp().Print("Data attached successfully\n");
      context.m_doc.Redraw();
      return IRhinoCommand.result.success;
    }
    return IRhinoCommand.result.nothing;
  }