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:
- Analytical model – analytical model class is now a subclass of Element. As a consequence of this change, when you create a new structural element, you will need to call Documentation.Regenerate() method before accessing its analytical model; i.e., the analytical model needs to be created first. Methods to access properties of an analytical model stay the same.
- AnalyticalModelSelector – two constructors that take an index as an argument has been removed. You should use the version that accepts the curve directly.
- SlabFoundationType – the enumeration value SlabFoundationType.Slab is now renamed as SlabOneWay. An additional option, SlabTwoWay has been added.
- Track changes UI – Track change UI has been removed. If you wish to offer a similar functionality, you can implement a similar or more sophisticated functionality using transactions, events and updaters, aligning the Undo mechanism that the end user is familiar with.
- NewBeamSystem() – this method accepts either sketch planes or the level.
- NewTruss() – this method requires sketch plane as an argument.
- Rebars and rebar shapes - syntaxes for creating rebar and rebar shape have been changed. The changes results in a simplified API, which is aligned to the UI.
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,
- Create a RebarShape inside the Document.
- Create a RebarShapeDefinition inside the RebarShape.
- Add data to the RebarShapeDefinition.
- Commit the RebarShape.
In 2012,
- Create a RebarShapeDefinition. It refers to the Document, but is not inside the document.
- Add data to the RebarShapeDefinition.
- 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:
- Autodesk.Revit.Creation.Document.NewRebarShape method
> RebarShape.Create(Document, RebarShapeDefinition, ... ) - RebarShape.NewDefinitionBySegments method
> RebarShapeDefinitionBySegments constructor - RebarShape.NewDefinitionByArc method
> RebarShapeDefinitionByArc constructors
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:
- Q:
In Revit Structure 2012, BoundaryConditions.HostElement returns analytical model instead of family instance.
Can you help me how to obtain the host element family instance?
A: After getting the analytical model from the BoundaryConditions instance, you can call the AnalyticalModel.GetElementId method to retrieve the id of the Host element family instance.
- Q:
Please explain the details about Analytical Changes option in Analytical Alignment property.
A: The big change to the analytical model in RST 2012 is the split of analytical model and its host physical model. The latter are now standalone elements.
Accordingly, the change of analytical model in Revit 2012 is that the AnalyticalModel class is derived from the Element class instead of the IDisposable interface. This means in Revit 2012, each AnalyticalModel instance is persistent and database resident. Previously, AnalyticalModel instances lived in transient memory only.
This affects the way to get the analytical model object. Now we can retrieve them using the element filtering mechanism via FilteredElementCollecotr. Previously the analytical model could only be retrieved from the host element.
With regard to the functionality of the AnalyticalModel class, new methods about alignment operation were introduced: GetAlignmentMethod, HasAlighment and SetAlignmentMethod.
The alignment option should work for a 2011 model opened in RST 2012.
- Q:
In Revit 2012, how can I access an entity with its Analytical model details. Please post changes to the analytical model class.
A: The host physical component of a given analytical model can be obtained by the AnalyticalModel.GetElementId method. It returns the element id of the physical component.
Thank you very much again, Joe!