The Revit Structure 2012 API

Sangsen recently submitted a couple of comments which made it clear that a short overview of the new features of the Revit Structure 2012 API is overdue (see below for the Q & A).

Here is a description written by Joe Ye for our Spring 2011 ADN AEC newsletter:

Autodesk Revit Structure 2012 API Migration Tips

This article discusses changes made to the Revit Structure 2012 API. We will quickly go over the list of items which have been changed, and look at the changes around rebar API in more detail.

Overview of Revit Structure 2012 API Changes

The following is the list of changes made to the Revit Structure 2012 API:

Below, we discuss rebar changes.

Migrating Rebar API Codes

If you have a code that creates a rebar shape in Revit Structure 2011, you will need to migrate it to use it in Revit Structure 2012. Here are the main changes in the steps to create a rebar shape:

In 2011,

  1. Create a RebarShape inside the Document.
  2. Create a RebarShapeDefinition inside the RebarShape.
  3. Add data to the RebarShapeDefinition.
  4. Commit the RebarShape.

In 2012,

  1. Create a RebarShapeDefinition. It refers to the Document, but is not inside the document.
  2. Add data to the RebarShapeDefinition.
  3. Create a RebarShape inside the Document based on the RebarShapeDefinition. Only now the document is modified.

In addition, the following methods are replaced by new ones:

Example: Migrating the RST Labs Code

Now, let's take a look at how to apply these changes to the rebar shape code, using our RST training labs code as an example. Here is the code for 2011, omitting some parameter definitions for simplicity:

//  RstLab 4.1 code in Revit Structure 2011
 
[Transaction(TransactionMode.Manual)]
[Regeneration(RegenerationOption.Manual)]
public class RstLab4_1_CreateSimpleRebarShape : IExternalCommand
{
public Result Execute(
  ExternalCommandData commandData,
  ref string messages,
  ElementSet elements)
{
  UIApplication uiApp = commandData.Application;
  Application app = uiApp.Application;
  Document doc = uiApp.ActiveUIDocument.Document;
 
  Transaction trans = new Transaction( doc, "Lab4_2" );
  trans.Start();
 
  // Create a newrebarshape.
 
  RebarShape oRebarShape = doc.Create.NewRebarShape();
 
  oRebarShape.Name = RstUtils.msRebarShapeName;
 
  RebarShapeDefinitionBySegments shapeDef 
    = oRebarShape.NewDefinitionBySegments( 5 );
 
  // Add parameters with default value.
  // GetOrCreateSharedParameter() is a helper function.
 
  ExternalDefinition def 
    = GetOrCreateSharedParameter("A");
 
  Parameter pA = shapeDef.AddParameter(def, 280);
 
  // . . .
 
  shapeDef.AddConstraintParallelToSegment( 
    0, pA, false, false );
 
  oRebarShape.set_HookAngle(0, 180);
 
  // . . .
 
  shapeDef.Commit();
  trans.Commit();
  shapeDef.CheckDefaultParameterValues( 0, 0 );
 
  return Result.Succeeded;
}

Several lines above require changes in 2012.

First, remove the lines with Create.NewRebarShape(). We will add code of creating rebar shape later on via new method later:

  RebarShape oRebarShape
    = doc.Create.NewRebarShape(); // Remove these lines
 
  oRebarShape.Name = RstUtils.msRebarShapeName;

Replace the code creating RebarShapeDefinitionBySegments instance to use the constructor:

  RebarShapeDefinitionBySegments shapeDef
    = oRebarShape.NewDefinitionBySegments( 5 ); // 2011

with this:

  RebarShapeDefinitionBySegments shapeDef
    = new RebarShapeDefinitionBySegments( doc, 5 ); // 2012

The steps to create each shape segment are unchanged. However, in 2012, methods used to define rebar segment only accept ElementId as an argument instead of External Definition in 2011. Methods in RebarShapeParameters class provide a utility method to retrieve an element id of an external definition. We need to get the corresponding element id, and replace the reference to the parameter value (e.g., 'pA') with its corresponding ElementId variable (e.g., 'idA') in AddParameter() method a shape definition. For instance, original code like this:

  //  Add parameters with default value in 2011.
 
  ExternalDefinition def = GetOrCreateSharedParameter( "A" );
 
  Parameter pA = shapeDef.AddParameter( def, 280 );

Will be modified like this:

  //  Add parameters with default value in 2012.
 
  ExternalDefinition def = GetOrCreateSharedParameter( "A" );
 
  ElementId idA = RebarShapeParameters
    .GetOrCreateElementIdForExternalDefinition( doc, def );
 
  shapeDef.AddParameter( idA, 280 );

The RebarShape class provides a static method to create a RebarShape instance in 2012. This method accommodates parameters to define the rebar shape's hook and hook angle. The methods to set hook properties are removed. Put all the rebar shape properties in the call to the Create method. After you have defined the rebar segment, add the following line to create the rebar shape:

  RebarShape oRebarShape
    = RebarShape.Create( doc,
      shapeDef, null, RebarStyle.Standard,
      StirrupTieAttachmentType.InteriorFace,
      180, RebarHookOrientation.Left,
      180, RebarHookOrientation.Left,
      0 );

The RebarShapeDefinitionBySegments.Commit method is removed in Revit 2012. You can simply delete it:

  shapeDef.Commit(); // take out this line

That's it! Here is the final code in 2012, again keeping only one parameter to emphasize the changes we made:

//  RstLab 4.1 code in 2012
//
[Transaction(TransactionMode.Manual)]
public class RstLab4_1_CreateRebarShape : IExternalCommand
{
  public Result Execute(
    ExternalCommandData commandData,
    ref string messages,
    ElementSet elements )
  {
    UIApplication uiApp = commandData.Application;
    Application app = uiApp.Application;
    Document doc = uiApp.ActiveUIDocument.Document;
 
    Transaction trans = new Transaction(doc, "Lab4_1");
    trans.Start();
 
    RebarShapeDefinitionBySegments shapeDef 
      = new RebarShapeDefinitionBySegments(doc, 5);
 
    // Add parameters with default value.
 
    // GetOrCreateSharedParameter() is a helper function.
 
    ExternalDefinition def = GetOrCreateSharedParameter("A");
 
    ElementId idA = RebarShapeParameters
      .GetOrCreateElementIdForExternalDefinition(
        doc, def);
 
    shapeDef.AddParameter(idA, 280);
 
    // . . .
 
    // Add constraints
 
    shapeDef.AddConstraintParallelToSegment(0, idA, false, false);
 
    // . . .
 
    // Create a newrebarshape.
 
    RebarShape oRebarShape = RebarShape
      .Create( doc, shapeDef, null, 
        RebarStyle.Standard,
        StirrupTieAttachmentType.InteriorFace,
        180, RebarHookOrientation.Left,
        180, RebarHookOrientation.Left,
        0 );
 
    trans.Commit();
 
    shapeDef.CheckDefaultParameterValues(0, 0);
 
    return Result.Succeeded;
  }
}

All the API changes are documented in the 'Revit Platform API Changes and Additions.docx' and the 'What's New' section of the Revit API help file RevitAPI.chm provided with the Revit 2012 SDK. Please refer to those for more information about the usage of individual classes and methods.

Many thanks to Joe for this overview!

Some of the Revit Structure API changes were also discussed in the Revit 2012 API webcast and the associated materials.

Sangsen's Questions

Last but not least, Joe also took the time to answer Sangsen's questions:

Thank you very much again, Joe!