Sdk Create Block
Last changed: dale@mcneel.com-204.177.179.125

.
DeveloperC++, .NET
VersionRhino 4
SummaryDemonstrates how to create an instance definition using the Rhino 4.0 SDK.

Also See

How To: Insert a Block

Dynamically Inserting Blocks

Overview

Rhino blocks, known in the SDK as instances, are single objects that combines one or more objects. Using blocks lets you:

More Information

The process for creating instance definitions using the Rhino SDK requires two steps:

  1. Define the instance definition objects. Instance definition objects are similar to regular Rhino objects - the ones that you see on the screen. The difference is that instance definition objects reside in a different location in the document. To add instance definition objects to the document, use CRhinoDoc::AddObject and make sure you set the bInstanceDefinition parameter to true.
  2. Add a new instance definition object to Rhino's instance definition table, which is located on the Rhino document. An instance definition defines the name of the instance and the instance definition objects used by it.

Note, an instance definition's base point is always the world origin (0,0,0). Knowing this, you need to orient your instance definition geometry around the world origin. The Block command does this by prompting the user for a base point and then transforming the selected objects from the user's picked point to the world origin. If you adding your own geometry on the fly, and not picking it, just create your objects knowing that the base point for your instance definition will be the world origin.

Example

The following example code demonstrates how to select one or more object and create a block definition with them. Note, unlike Rhino's Block command, this example code does not delete the selected objects, nor does it automatically insert a block instance at the location defined by the user.

C++

  CRhinoCommand::result CCommandTest::RunCommand( const CRhinoCommandContext& context )
  {
    // Select objects to define block
    CRhinoGetObject go;
    go.SetCommandPrompt( L"Select objects to define block" );
    go.EnableReferenceObjectSelect( false );
    go.EnableSubObjectSelect( false );
    go.EnableGroupSelect( true );


    // Phantoms, grips, lights, etc., cannot be in blocks.
    const unsigned int forbidden_geometry_filter 
                  = CRhinoGetObject::light_object
                  | CRhinoGetObject::grip_object
                  | CRhinoGetObject::phantom_object;
    const unsigned int geometry_filter = forbidden_geometry_filter 
                                 ^ CRhinoGetObject::any_object;
    go.SetGeometryFilter( geometry_filter );
    go.GetObjects( 1, 0 );
    if( go.CommandResult() != success )
      return go.CommandResult();


    // Block base point
    CRhinoGetPoint gp;
    gp.SetCommandPrompt( L"Block base point" );
    gp.GetPoint();
    if( gp.CommandResult() != success )
      return gp.CommandResult();


    ON_3dPoint base_point = gp.Point();


    // Block definition name
    CRhinoGetString gs;
    gs.SetCommandPrompt( L"Block definition name" );
    gs.GetString();
    if( gs.CommandResult() != success )
      return gs.CommandResult();


    // Validate block name
    ON_wString idef_name = gs.String();
    idef_name.TrimLeftAndRight();
    if( idef_name.IsEmpty() )
      return nothing;


    // See if block name already exists
    CRhinoInstanceDefinitionTable& idef_table = context.m_doc.m_instance_definition_table;
    int idef_index = idef_table.FindInstanceDefinition( idef_name );
    if( idef_index >= 0 )
    {
      RhinoApp().Print( L"Block definition \"%s\" already exists.\n", idef_name );
      return nothing;
    }


    // Create new block definition
    ON_InstanceDefinition idef;
    idef.SetName( idef_name );


    // Gather all of the selected objects
    ON_SimpleArray<const CRhinoObject*> objects( go.ObjectCount() );
    int i;
    for( i = 0; i < go.ObjectCount(); i++ )
    {
      const CRhinoObject* obj = go.Object(i).Object();
      if( obj )
        objects.Append( obj);
    }


    ON_Xform xform;
    xform.Translation( ON_origin - base_point );


    // Duplicate all of the selected objects and add them
    // to the document as instance definition objects
    ON_SimpleArray<const CRhinoObject*> idef_objects( objects.Count() );
    for( i = 0; i < objects.Count(); i++ )
    {
      const CRhinoObject* obj = objects[i];
      if( obj )
      {
        CRhinoObject* dupe = context.m_doc.TransformObject( obj, xform, false, false, false );
        if( dupe)
        {
          context.m_doc.AddObject( dupe, false, true );
          idef_objects.Append( dupe );
        }
      }
    }


    if( idef_objects.Count() < 1 )
    {
      RhinoApp().Print( L"Unable to duplicate block definition geometry.\n" );
      return failure;
    }


    idef_index = idef_table.AddInstanceDefinition( idef, idef_objects );
    if( idef_index < 0 )
    {
      RhinoApp().Print( L"Unable to create block definition \"%s\".\n", idef_name );
      return failure;
    }


    return success;
  }

C# (Rhino 4)

  public override IRhinoCommand.result RunCommand(IRhinoCommandContext context)
  {
    // Select objects to define block
    MRhinoGetObject go = new MRhinoGetObject();
    go.SetCommandPrompt( "Select objects to define block" );
    go.EnableReferenceObjectSelect( false );
    go.EnableSubObjectSelect( false );
    go.EnableGroupSelect( true );


    // Phantoms, grips, lights, etc., cannot be in blocks.
    uint forbidden_geometry_filter = (uint)(IRhinoGetObject.GEOMETRY_TYPE_FILTER.light_object |
                                            IRhinoGetObject.GEOMETRY_TYPE_FILTER.grip_object |
                                            IRhinoGetObject.GEOMETRY_TYPE_FILTER.phantom_object );
    uint geometry_filter = forbidden_geometry_filter ^ (uint)IRhinoGetObject.GEOMETRY_TYPE_FILTER.any_object;
    go.SetGeometryFilter( geometry_filter );
    go.GetObjects( 1, 0 );
    if( go.CommandResult() != IRhinoCommand.result.success )
      return go.CommandResult();


    // Block base point
    MRhinoGetPoint gp = new MRhinoGetPoint();
    gp.SetCommandPrompt( "Block base point" );
    gp.GetPoint();
    if( gp.CommandResult() != IRhinoCommand.result.success )
      return gp.CommandResult();


    On3dPoint base_point = gp.Point();


    // Block definition name
    MRhinoGetString gs = new MRhinoGetString();
    gs.SetCommandPrompt( "Block definition name" );
    gs.GetString();
    if( gs.CommandResult() != IRhinoCommand.result.success )
      return gs.CommandResult();


    // Validate block name
    string idef_name = gs.String().Trim();
    if( string.IsNullOrEmpty(idef_name))
      return IRhinoCommand.result.nothing;


    // See if block name already exists
    MRhinoInstanceDefinitionTable idef_table = context.m_doc.m_instance_definition_table;
    int idef_index = idef_table.FindInstanceDefinition( idef_name );
    if( idef_index >= 0 )
    {
      string msg = "Block definition \"" + idef_name + "\" already exists.\n";
      RhUtil.RhinoApp().Print( msg );
      return IRhinoCommand.result.nothing;
    }


    // Create new block definition
    OnInstanceDefinition idef = new OnInstanceDefinition();
    idef.SetName( idef_name );


    // Gather all of the selected objects
    List<IRhinoObject> objects = new List<IRhinoObject>();
    for( int i = 0; i < go.ObjectCount(); i++ )
    {
      IRhinoObject obj = go.Object(i).Object();
      if( obj != null )
        objects.Add( obj );
    }


    OnXform xform = new OnXform();
    xform.Translation( new On3dPoint(OnUtil.On_origin) - base_point );


    // Duplicate all of the selected objects and add them
    // to the document as instance definition objects
    List<IRhinoObject> idef_objects = new List<IRhinoObject>();
    for( int i = 0; i < objects.Count; i++ )
    {
      IRhinoObject obj = objects[i];
      if( obj != null )
      {
        MRhinoObject dupe = context.m_doc.TransformObject(obj, xform, false, false, false);
        if( dupe != null )
        {
          // Transform the geometry to the world origin so
          // they insert in the location the user expects.
          context.m_doc.AddObject( dupe, false, true);
          idef_objects.Add( dupe );
        }
      }
    }


    if( idef_objects.Count < 1 )
    {
      RhUtil.RhinoApp().Print( "Unable to duplicate block definition geometry.\n" );
      return IRhinoCommand.result.failure;
    }


    idef_index = idef_table.AddInstanceDefinition( idef, idef_objects.ToArray() );
    if( idef_index < 0 )
    {
      RhUtil.RhinoApp().Print( "Unable to create block definition \""+idef_name+"\"\n" );
      return IRhinoCommand.result.failure;
    }
    return IRhinoCommand.result.success;
  }

VB.NET (Rhino 4)

  Public Overrides Function RunCommand(ByVal context _
    As RMA.Rhino.IRhinoCommandContext) As RMA.Rhino.IRhinoCommand.result
    ' Select objects to define block
    Dim go As New MRhinoGetObject()
    go.SetCommandPrompt("Select objects to define block")
    go.EnableReferenceObjectSelect(False)
    go.EnableSubObjectSelect(False)
    go.EnableGroupSelect(True)


    ' Phantoms, grips, lights, etc., cannot be in blocks.
    Dim forbidden_geometry_filter As UInteger = _
        CType(IRhinoGetObject.GEOMETRY_TYPE_FILTER.light_object Or _
              IRhinoGetObject.GEOMETRY_TYPE_FILTER.grip_object Or _
              IRhinoGetObject.GEOMETRY_TYPE_FILTER.phantom_object, UInteger)


    Dim geometry_filter As UInteger = _
       (forbidden_geometry_filter Xor CType(IRhinoGetObject.GEOMETRY_TYPE_FILTER.any_object, UInteger))
    go.SetGeometryFilter(geometry_filter)
    go.GetObjects(1, 0)
    If (go.CommandResult() <> IRhinoCommand.result.success) Then
      Return go.CommandResult()
    End If


    ' Block base point
    Dim gp As New MRhinoGetPoint()
    gp.SetCommandPrompt("Block base point")
    gp.GetPoint()
    If (gp.CommandResult() <> IRhinoCommand.result.success) Then
      Return gp.CommandResult()
    End If


    Dim base_point As On3dPoint = gp.Point()


    ' Block definition name
    Dim gs As New MRhinoGetString()
    gs.SetCommandPrompt("Block definition name")
    gs.GetString()
    If (gs.CommandResult() <> IRhinoCommand.result.success) Then
      Return gs.CommandResult()
    End If


    ' Validate block name
    Dim idef_name As String = gs.String().Trim()
    If (String.IsNullOrEmpty(idef_name)) Then
      Return IRhinoCommand.result.nothing
    End If


    ' See if block name already exists
    Dim idef_table As MRhinoInstanceDefinitionTable = context.m_doc.m_instance_definition_table
    Dim idef_index As Integer = idef_table.FindInstanceDefinition(idef_name)
    If (idef_index >= 0) Then
      Dim msg As String = "Block definition """ + idef_name + """ already exists."
      RhUtil.RhinoApp().Print(msg + vbCrLf)
      Return IRhinoCommand.result.nothing
    End If


    ' Create new block definition
    Dim idef As New OnInstanceDefinition()
    idef.SetName(idef_name)


    ' Gather all of the selected objects
    Dim objects As New List(Of IRhinoObject)()
    For i As Integer = 0 To go.ObjectCount() - 1
      Dim obj As IRhinoObject = go.Object(i).Object()
      If (obj IsNot Nothing) Then objects.Add(obj)
    Next


    Dim xform As New OnXform()
    xform.Translation(New On3dPoint(OnUtil.On_origin) - base_point)


    ' Duplicate all of the selected objects and add them
    ' to the document as instance definition objects
    Dim idef_objects As New List(Of IRhinoObject)()
    For i As Integer = 0 To objects.Count - 1
      Dim obj As IRhinoObject = objects(i)
      If (obj IsNot Nothing) Then
        Dim dupe As MRhinoObject = context.m_doc.TransformObject(obj, xform, False, False, False)
        If (dupe IsNot Nothing) Then
          ' Transform the geometry to the world origin so
          ' they insert in the location the user expects.
          context.m_doc.AddObject(dupe, False, True)
          idef_objects.Add(dupe)
        End If
      End If
    Next


    If (idef_objects.Count < 1) Then
      RhUtil.RhinoApp().Print("Unable to duplicate block definition geometry." + vbCrLf)
      Return IRhinoCommand.result.failure
    End If


    idef_index = idef_table.AddInstanceDefinition(idef, idef_objects.ToArray())
    If (idef_index < 0) Then
      RhUtil.RhinoApp().Print("Unable to create block definition """ + idef_name + """" + vbCrLf)
      Return IRhinoCommand.result.failure
    End If
    Return IRhinoCommand.result.success
  End Function