What's New in the Revit 2012 API

This is the third instalment of a series publishing the information provided in the 'What's New' sections of the past few Revit API releases help file RevitAPI.chm.

The first instalment covering What's New in the Revit 2010 API explains my motivation for this and provides an overview of the other releases.

We now move on to the Revit 2012 API, looking at:

First, however, another update on my vacation.

Unexpected Places, and Warmer

I am still on holiday in Italy, so please do not expect any immediate responses to comments for a while.

I love adventures, and finding myself in unexpected places, and I am getting my fill of that here and now.

I found better weather further south, and a beautiful empty beach north of Bari.

Acting on a recommendation by a cyclist whom I asked about his unintelligible dialect in a bar, I also ended up enjoying the unique trulli of Alberobello.

Trulli in Alberobello

From there we continued to Lecce and started exploring the sweet and efficient little local train system connecting many of the communities on the peninsula of Salento.

We visited Galatina, continued to Nardo, and walked a long way on foot towards Santa Caterina to reach the protected natural park and beach of Porto Selvaggio.

Portoselvaggio

In spite of some rain and cold, with some warm sunshine in between, we spent a day or two in pure uninterrupted nature.

On the way out towards Nardo again, a passing car picked us up and took us to Galipoli, another surprise visit, with a direct train connection back to Lecce.

Now, to continue the promised series of 'What's New' documentation from the past few Revit API releases.

Major renovations to the Revit 2012 API

.NET 4.0 now used by the Revit API

The Revit API has been enhanced to run with the .NET 4.0 runtime. As a result, Visual Studio 2010 with a framework target of .NET 3.5 or 4.0 must be used to debug your addins. Addins compiled with Visual Studio 2008 will run normally outside the debugging environment.

All samples in the Revit API SDK have been upgraded to Visual Studio 2010.

Microsoft has not yet announced when Visual Studio Tools for Applications (VSTA) for .NET 4.0 will be available. VSTA is the technology used for Revit macros. The Microsoft VSTA debugger is not compatible with the default Revit 2012 .NET 4.0 environment. VSTA macros can run successfully in the .NET 4.0 environment, but a special Revit configuration is required for debugging. In order to use VSTA debugging, you must:

  1. Ensure you have user permissions sufficient to modify files in the Revit installation folder.
  2. Exit Revit.
  3. Run '[Revit.exe directory]\RevitVSTAConfig.exe'
  4. Click the 'Prepare Revit for VSTA' button.
  5. Restart Revit.

Note: Revit's native components continue to be compiled with the VS 2008 C++ compiler. Therefore Revit 2012 does not include the VS2010 redistributable. Third-party applications which include natively compiled C++ components should use the VS 2008 C++ compiler or must include the VS 2010 C++ redistributables with the installation.

RegenerationMode

Automatic regeneration mode has been removed. You no longer have to include the RegenerationMode attribute on your add-ins. All APIs expect that add-in code is written using manual regeneration when necessary.

Add-In registration – new required property VendorId

Two new registration properties have been added:

Here is an example of the new entries:

<?xml version="1.0" encoding="utf-16" standalone="no"?
<RevitAddIns>
  <AddIn Type="Command">
    <Assembly>Command.dll</Assembly>
    <ClientId>d7e30025-97d4-4012-a581-5f8ed8d18808</ClientId>
    <FullClassName>Revit.Command</FullClassName>
    <Text>Command</Text>
    <VendorId>ADSK</VendorId>
    <VendorDescription>Autodesk, www.autodesk.com</VendorDescription>
  </AddIn>
</RevitAddIns>

CompoundStructure and WallSweeps

The CompoundStructure class has been replaced. The old CompoundStructure class in the API was read-only and supported only the nominal layers list without support for the settings related to vertical regions, sweeps, and reveals. The new CompoundStructure class supports read and modification of all of the structure information include vertical regions, sweeps and reveals.

The CompoundStructure.Layers property has been replaced by CompoundStructure.GetLayers() and CompoundStructure.SetLayers().

The CompoundStructureLayer class has also been replaced for the same reasons as CompoundStructure.

The following table maps properties from the old CompoundStructureLayer to the new version of the class:

The property HostObjAttributes.CompoundStructure has been replaced by two methods:

Remember that you must set the CompoundStructure back to the HostObjAttributes instance in order for any change to be stored in the element.

In addition to the information on wall sweeps found in the CompoundStructure class, there is a new API representing a wall sweep or reveal. The WallSweep class is an element that represents either a standalone wall sweep/reveal, or one added by the settings in a given wall's compound structure. Standalone wall sweeps and reveals may be constructed using the static method Create().

LinePattern

The LinePattern class has been replaced. The old LinePattern class in the API represented both the line pattern itself and the element that contains it, and offered no details on the contents of the pattern beyond its name. The new classes available are:

The method

offers the ability to add new LinePattern elements to the Revit database.

The property of the Settings class:

has been removed. LinePatterns may be found by the following approaches:

  1. Use of a FilteredElementCollector filtering on class LinePatternElement
  2. Use of the static methods of LinePatternElement:

FillPattern

The FillPattern class has been replaced. The old FillPattern class in the API represented both the fill pattern itself and the element that contains it, and offered no details on the contents of the pattern beyond its name. The new classes available are:

The method

offers the ability to add new FillPattern elements to the Revit database.

The property of the Settings class:

has been removed. FillPatterns may be found by the following approaches:

  1. Use of a FilteredElementCollector filtering on class FillPatternElement
  2. Use of the static methods of FillPatternElement:

IndependentTag

A good portion of the IndependentTag class and related classes have been renovated.

Some new members were added to determine the elements referenced by the tag:

Import and Export APIs changes

The import and export APIs no longer have special argument combinations which permit use of the "active view". If you wish to export from or import to the active view, you must obtain it directly and pass it as input to the method.

The methods

provide access to predefined setups and settings from a given document for DWG and DFX export.

The method

has been replaced by

Save and Close API changes

The behaviour of these methods has been changed. Previously, they would prompt the interactive user to pick a target path name if the document's path name was not already set, or if the target file was read-only. Now they will throw an exception if the document's path name is not yet set, or if the saving target file is read-only.

The behaviour of this method has been changed. Previously, it would prompt the interactive user to pick a target path name if the document's path name was not already set, or if the target file was read-only. Now it will throw an exception if the document's path name is not set yet. In this case, it needs to be first saved using the SaveAs method instead, or when the target file is read-only.

This new method behaves identically to Document.Save(), but allows you to specify a temporary id to use to generate the file preview.

The behaviour of these methods has been changed. Previously, they would prompt the user before overwriting another file. Now an exception will be thrown in that situation.

This new method allows you to save a document, and encapsulates the options to rename the document in session, overwrite an existing file (if it exists), and temporarily assign a view id to use to generate the file preview.

This new method closes the document after saving it. If the document's path name has not been set the "Save As" dialog will be shown to the Revit user to set its name and location.

This new method saves the document to a file name and path obtained from the Revit user (via the "Save As" dialog).

Reference properties

The Reference class is being renovated to be more closely aligned with the native Revit class it wraps. Because of this change, References will no longer carry information on the document, element, or geometry object it was obtained from. The following table lists the replacement API calls for the obsolete Reference properties:

The method

is affected most by this change. The method was the only method to populate the Transform and ProximityParameter properties of Reference. You should switch to the replacement method:

This replacement method returns a list of ReferenceWithContext objects, containing the Reference plus additional members:

Note that methods which existed in Revit 2011 and earlier will continue in this release to return a fully populated Reference object (it is not necessary to change code dealing with these methods). However, methods added in Revit 2012 may not return a fully populated Reference handle and will need to be parsed using the replacement methods above. Also, affected members have been marked obsolete and planned to be removed in a future release.

Event argument changes

A few changes have been made to event argument classes as we align frameworks to generate code for events.

Note: some of these classes and methods may change again in future.

The following table of changes lists the affected property, the classes providing it, and the new member with optional notes:

Event sender changed for UI events

For some UI events on UIApplication and UIControlledApplication, the type of the "sender" object has been changed.

Move/Mirror/Rotate/Array changes

Move method replacements

The new static methods

replace the Document.Move() overloads.

Mirror method replacements

The new static methods

replace the Document.Mirror() methods. These new methods allow you to mirror one or more elements directly about a geometric plane which you may construct directly. Previously the Document.Mirror() methods required you to obtain a reference to an actual plane, or implicitly used the active view to calculate the mirror plane.

Rotate method replacements

The new static methods

replace the Document.Rotate() methods.

New Copy methods

The new static methods

allow you to copy and translate one or more physical elements and place the newly copied elements by applying the given translation vector.

LinearArray creation replacement methods

The new methods

replace the Document.Array() overloads that return LinearArray.

The new methods

replace the Document.ArrayWithoutAssociate() methods that create sets of elements based on linear translation.

RadialArray creation replacement methods

The new methods

replace the Document.Array() overloads that return RadialArray. The new methods require a view input (where previously the old overloads would use the active view implicitly, which could lead to unexpected failure in some conditions).

The new methods

replace the Document.ArrayWithoutAssociate() methods that create sets of elements based on rotation.

Structural AnalyticalModel changes

AnalyticalModel now an Element

The AnalyticalModel class is now a subclass of Element.

One consequence of this change: the AnalyticalModel of a newly created structural element can no longer be obtained without regeneration (as the AnalyticalModel element must be generated).

AnalyticalModelSelector

The following two constructors were removed from AnalyticalModelSelector:

The following method was also removed:

Instead of passing the array of curves and the index to create the selector, you should use the constructor that accepts the Curve directly (obtain the curve from the collection prior to input).

SlabFoundationType

The enumerated value SlabFoundationType.Slab is now SlabFoundationType.SlabOneWay. A new option, SlabTwoWay, is also available. Existing floors assigned the value Slab will report SlabOneWay.

Major enhancements to the Revit API

Extensible Storage

The Revit API now allows you to create your own class-like Schema data structures and attach instances of them to any Element in a Revit model. This functionality can be used to replace the technique of storing data in hidden shared parameters. Schema-based data is saved with the Revit model and allows for higher-level, metadata-enhanced, object-oriented data structures. Schema data can be configured to be readable and/or writable to all users, just a specific application vendor, or just a specific application from a vendor.

The extensible storage classes are all found in Autodesk.Revit.DB.ExtensibleStorage

The following data types are currently supported:

Simple usage of ExtensibleStorage

// Create a data structure, attach it to a wall, 
// populate it with data, and retrieve the data 
// back from the wall
public void StoreDataInWall(
  Wall wall,
  XYZ dataToStore )
{
  Transaction createSchemaAndStoreData
    = new Transaction(wall.Document, "tCreateAndStore");
  createSchemaAndStoreData.Start();
  SchemaBuilder schemaBuilder = new SchemaBuilder(
    new Guid("720080CB-DA99-40DC-9415-E53F280AA1F0"));
  // allow anyone to read the object
  schemaBuilder.SetReadAccessLevel(AccessLevel.Public);
  // restrict writing to this vendor only
  schemaBuilder.SetWriteAccessLevel(AccessLevel.Vendor);
  // required because of restricted write-access
  schemaBuilder.SetVendorId("ADSK");
  // create a field to store an XYZ
  FieldBuilder fieldBuilder = schemaBuilder
    .AddSimpleField("WireSpliceLocation", typeof(XYZ));
  fieldBuilder.SetUnitType(UnitType.UT_Length);
  fieldBuilder.SetDocumentation(
    "A stored location value representing a wiring splice in a wall.");
  schemaBuilder.SetSchemaName("WireSpliceLocation");
  // register the Schema object
  Schema schema = schemaBuilder.Finish();
  // create an entity (object) for this schema (class)
  Entity entity = new Entity(schema);
  // get the field from the schema
  Field fieldSpliceLocation
    = schema.GetField("WireSpliceLocation");
  // set the value for this entity
  entity.Set<XYZ>(fieldSpliceLocation,
    dataToStore, DisplayUnitType.DUT_METERS);
  // store the entity in the element
  wall.SetEntity(entity);
  // get the data back from the wall
  Entity retrievedEntity = wall.GetEntity(schema);
  XYZ retrievedData = retrievedEntity.Get<XYZ>(
    schema.GetField("WireSpliceLocation"),
    DisplayUnitType.DUT_METERS);
  createSchemaAndStoreData.Commit();
}

Worksharing API

Several new classes were added to provide access to worksharing information in the document:

Some related additions were made to existing classes:

In addition, there is API support for the new 2012 worksharing visualization functionality:

Setting the Active View

The new property

has both a getter and setter, so it allows you to query the currently active view of the currently active document, and also allows you to set it similarly to what an end user can do by changing a view in the Project Browser in Revit.

The setter has a number of limitations:

Opening and activating a document

A new method:

was added to the UI API. It opens a Revit document and makes it the active one. The document is opened with its default view displayed.

There are limitations preventing this method to be called at certain situations:

Adding a custom Ribbon tab

The new methods

(and the corresponding methods in UIControlledApplication) provide the ability to add a new ribbon tab to Revit, at the end of the list of static tabs (to the right of the Add-Ins tab, if shown). If multiple tabs are added, they will be shown in the order added.

There is a limit to the number of custom tabs supported in a given session of Revit (20). This limit is provided to ensure that the standard tabs remain visible and usable. Because of this, your application should only add a custom tab if it's really needed.

Construction modeling API

New functionality in Revit 2012 allows elements to be divided into sub-parts, collected into assemblies, and displayed in special assembly views. The API for dividing parts is still under development and likely to change.

Read, write and create access to assemblies in the Revit environment is provided through the classes:

A new assembly containing the selected elements can be created as follows:

  ElementId categoryId = doc.get_Element(
    uidoc.Selection.GetElementIds().
  FirstOrDefault() ).Category.Id;
 
  ElementId titleblockId
    = doc.TitleBlocks.Cast<FamilySymbol>()
      .First<FamilySymbol>().Id;
 
  AssemblyInstance instance = null;
 
  Transaction t = new Transaction( doc );
 
  if( AssemblyInstance.IsValidNamingCategory( doc,
    categoryId, uidoc.Selection.GetElementIds() ) )
  {
    t.SetName( "Create Assembly Instance" );
    t.Start();
    instance = AssemblyInstance.Create( doc,
      uidoc.Selection.GetElementIds(), categoryId );
    t.Commit();
 
    t.SetName( "Set Assembly Name" );
    t.Start();
    string assemblyName = "Assembly #1";
    if( AssemblyInstance.IsValidAssemblyName( doc,
      assemblyName, categoryId ) )
    {
      instance.AssemblyTypeName = assemblyName;
    }
    t.Commit();
  }

Other important methods include AssemblyInstance.GetMemberIds(), AssemblyInstance.SetMemberIds(), and AssemblyInstance.Disassemble().

Assembly views, that display only the elements in the assembly, are created with the AssemblyViewUtils class such as:

  if( instance.AllowsAssemblyViewCreation() )
  {
    ViewSheet viewSheet = AssemblyViewUtils
      .CreateSheet( doc, instance.Id, titleblockId );
 
    View3D view3d = AssemblyViewUtils
      .Create3DOrthographic( doc, instance.Id );
 
    ViewSection detailSectionA = AssemblyViewUtils
      .CreateDetailSection( doc, instance.Id,
      AssemblyDetailViewOrientation.DetailSectionA );
 
    View materialTakeoff = AssemblyViewUtils
      .CreateMaterialTakeoff( doc, instance.Id );
 
    View partList = AssemblyViewUtils
      .CreatePartList( doc, instance.Id );
  }

The PartUtils class provides methods to identify Part elements that are created by sub-dividing model elements. These methods describe the relationship between Parts and the elements (such as walls, floors, etc) that are divided to create the Parts.

DB-level applications

The add-in framework has been extended to support database-level add-ins. These add-ins should be used when the purpose of your application is to assign events and/or updaters to the Revit session, but not to add anything to the Revit user interface or use APIs from RevitAPIUI.dll.

To implement a DB-level application, implement the methods in the Autodesk.Revit.DB.IExternalDBApplication interface:

Within the OnStartup() method you should register events and updaters which your application will respond to during the session.

To register the DB-level application with Revit, add the appropriate registry entry to a manifest file in the Addins folder. A DB-level application has a similar structure as for a UI external application:

<?xml version="1.0" standalone="no"?>
<RevitAddIns>
  <AddIn Type="DBApplication">
    <Assembly>MyDBLevelApplication.dll</Assembly>
    <AddInId>DA3D570A-1AB3-4a4b-B09F-8C15DFEC6BF0</AddInId>
    <FullClassName>MyCompany.MyDBLevelAddIn</FullClassName>
    <Name>My DB-Level AddIn</Name>
  </AddIn>
</RevitAddIns>

Geometry API enhancements

Get original geometry of a FamilyInstance

The new method

returns the original geometry of the instance, before the instance is modified by joins, cuts, coping, extensions, or other post-processing.

Extrusion analysis of a solid

The utility class

allows you to attempt to “fit” a given piece of geometry into the shape of an extrusion. An instance of this class is a single-time use class which should be supplied a solid geometry, a plane, and a direction. The utility will calculate a base boundary parallel to the input plane which is the outer boundary of the shadow cast by the solid onto the input plane and along the extrusion direction.

After the extrusion has been calculated, the class permits a second step analysis to identify all faces from the original geometry which do not align with the faces of the calculated extrusion.

This utility works best for geometry which are at least somewhat “extrusion-like”, for example, the geometry of a wall which may or may not be affected by end joins, floor joins, roof joins, openings cut by windows and doors, or other modifications.

GeometryCreationUtilities

The new utility class GeometryCreationUtilities offers the ability to create solid geometry from input curves:

The resulting geometry is not added to the document as a part of any element. However, you may use the created Solid, and its constituent faces and edges, in several ways:

Find 3D elements by intersection

The new element filters:

pass elements whose actual 3D geometry intersects the 3D geometry of the target object. With ElementIntersectsElementFilter, the target object is another element. The intersection is determined with the same routine used to determine if an interference exists during generation of an InterferenceReport. With ElementIntersectsSolidFilter, the target object is any solid, including one created from scratch using GeometryCreationUtilities.

This example uses a created cylinder centered on the end of a wall to find other walls in close proximity (whether or not they are actually joined):

public ICollection<ElementId>
  FindWallJoinsAtEndUsingProximity(
    Wall wall, int end )
{
  // Get properties of wall at the end point 
  LocationCurve wallCurve = wall.Location
    as LocationCurve;
  XYZ endPoint = wallCurve.Curve.get_EndPoint( end );
  double height = wall.get_Parameter(
    BuiltInParameter.WALL_USER_HEIGHT_PARAM ).AsDouble();
  double elevation = wall.Level.Elevation;
  // Build cylinder centered at wall end point, 
  // extending 3' in diameter 
  CurveLoop cylinderLoop = new CurveLoop();
  XYZ arcCenter = new XYZ(
    endPoint.X, endPoint.Y, elevation );
  Application application = wall.Document.Application;
  Arc firstArc = application.Create.NewArc( arcCenter,
    1.5, 0, Math.PI, XYZ.BasisX, XYZ.BasisY );
  Arc secondArc = application.Create.NewArc( arcCenter,
    1.5, Math.PI, 2 * Math.PI, XYZ.BasisX, XYZ.BasisY );
  cylinderLoop.Append( firstArc );
  cylinderLoop.Append( secondArc );
  List<CurveLoop> singleLoop = new List<CurveLoop>();
  singleLoop.Add( cylinderLoop );
  Solid proximityCylinder = GeometryCreationUtilities
    .CreateExtrusionGeometry( singleLoop,
      XYZ.BasisZ, height );
  // Filter walls 
  FilteredElementCollector proximityCollector
    = new FilteredElementCollector( wall.Document );
  proximityCollector.OfClass( typeof( Wall ) );
  // Exclude the wall itself 
  List<ElementId> toExclude = new List<ElementId>();
  toExclude.Add( wall.Id );
  proximityCollector.Excluding( toExclude );
  // Filter only elements intersecting our target cylinder 
  proximityCollector.WherePasses(
    new ElementIntersectsSolidFilter(
      proximityCylinder ) );
  // Return matches 
  return proximityCollector.ToElementIds();
}

Boolean operations

The new methods

execute a boolean operation combining a pair of solid geometry objects. Options to the method include the operations type: Union, Difference, or Intersect.

The first method takes a copy of the input solids and produces a new solid as a result. Its first argument can be any solid, either obtained directly from a

Revit element or created via another operation like GeometryCreationUtils.

The second method performs the boolean operation directly on the first input solid. The first input must be a solid which is not obtained directly from a Revit

element. The property

can identify whether the solid is appropriate as input for this method.

In this example, the geometry of intersecting columns and walls is obtained by a Boolean intersection operation. The intersection volume and number of boundary faces is shown in the resulting dialog.

/// <summary> 
/// A data structure containing the details 
/// of each intersecting wall/column pair. 
/// </summary> 
struct Intersection
{
  public Element Wall;
  public Element Column;
  public Solid Solid;
}
 
/// <summary> 
/// A collection of all intersections. 
/// </summary> 
private List<Intersection> m_allIntersections;
 
/// <summary> 
/// Finds and posts information on wall/column intersections. 
/// </summary> 
/// <param name="doc">The document.</param> 
public void FindIntersectionVolumes( Document doc )
{
  // Find all Wall elements. 
  FilteredElementCollector collector
    = new FilteredElementCollector( doc );
  collector.OfClass( typeof( Wall ) );
  m_allIntersections = new List<Intersection>();
  foreach( Wall wall in collector.OfType<Wall>() )
  {
    // Find all intersecting columns 
    FilteredElementCollector columnIntersectionCollector
      = new FilteredElementCollector( doc );
    // Columns may be one of two different categories 
    List<BuiltInCategory> categories
      = new List<BuiltInCategory>();
    categories.Add( BuiltInCategory.OST_Columns );
    categories.Add( BuiltInCategory.OST_StructuralColumns );
    ElementMulticategoryFilter categoryFilter
      = new ElementMulticategoryFilter( categories );
    // Apply intersection filter to find matches 
    ElementIntersectsElementFilter intersectsFilter
      = new ElementIntersectsElementFilter( wall );
    columnIntersectionCollector
      .WhereElementIsNotElementType()
      .WherePasses( categoryFilter )
      .WherePasses( intersectsFilter );
    foreach( Element element in
      columnIntersectionCollector )
    {
      // Store information on intersection 
      Intersection intersection;
      intersection.Wall = wall;
      intersection.Column = element;
      Solid wallSolid = GetGeometry( wall );
      Solid columnSolid = GetGeometry( element );
      // Intersect the solid geometry of the two elements 
      intersection.Solid = BooleanOperationsUtils
        .ExecuteBooleanOperation( wallSolid,
        columnSolid, BooleanOperationsType.Intersect );
      m_allIntersections.Add( intersection );
    }
  }
  TaskDialog td = new TaskDialog( "Intersection info" );
  td.MainInstruction = "Intersections found: "
    + m_allIntersections.Count;
  StringBuilder builder = new StringBuilder();
  foreach( Intersection intersection in
    m_allIntersections )
  {
    builder.AppendLine( String.Format(
      "{0} x {1}: volume {2} faces {3}",
      intersection.Wall.Name,
      intersection.Column.Name,
      intersection.Solid.Volume,
      intersection.Solid.Faces.Size ) );
  }
  td.MainContent = builder.ToString();
  td.Show();
}
 
/// <summary> 
///  Gets the solid geometry of an element. 
/// </summary> 
/// <remarks>Makes an assumption that each element 
/// consists of only one postive-volume solid, and 
/// returns the first one it finds.</remarks> 
/// <param name="e"></param> 
/// <returns></returns> 
private Solid GetGeometry( Element e )
{
  GeometryElement geomElem = e.get_Geometry(
    new Options() );
  foreach( GeometryObject geomObj in
    geomElem.Objects )
  {
    // Walls and some columns will have a 
    // solid directly in its geometry 
    if( geomObj is Solid )
    {
      Solid solid = (Solid)geomObj;
      if( solid.Volume > 0 )
        return solid;
    }
    // Some columns will have a instance 
    // pointing to symbol geometry 
    if( geomObj is GeometryInstance )
    {
      GeometryInstance geomInst
        = (GeometryInstance) geomObj;
      // Instance geometry is obtained so that the 
      // intersection works as expected without 
      // requiring transformation 
      GeometryElement instElem
        = geomInst.GetInstanceGeometry();
      foreach( GeometryObject instObj in
        instElem.Objects )
      {
        if( instObj is Solid )
        {
          Solid solid = (Solid)instObj;
          if( solid.Volume > 0 )
            return solid;
        }
      }
    }
  }
  return null;
}

HostObject – top, bottom, side faces

The new methods

provide a shortcut to locate the faces of a given roof, floor, or wall which act as the exterior or interior boundary of the object's CompoundStructure. Top and bottom faces are applicable to roofs and floors. Side faces are applicable to walls.

Get host face of a FamilyInstance

The property

gets the reference to the host face of family instance, or if the instance is placed on a work plane, the reference to the geometry face underlying the work plane.

Element.Geometry

This property has been modified to throw an exception when attempting to read the geometry of a newly added or modified element, if the element has not yet been regenerated. Call Document.Regenerate() to regenerate the affected element and to be able to obtain the geometry.

This property now returns results for ElementType subclasses which own geometry.

GeometryObject.GraphicsStyleId

This new property allows access to the GraphicsStyle and Category of individual family primitives to be determined while working in the project environment.

Curve representation of an Edge

The methods

provide a curve that corresponds to the edge (either oriented along the edge's parametric direction, or oriented in the edge's topological direction on the specified face).

Centroid of a Solid

The method

calculates the centroid of the solid using an approximation, with an accuracy suitable for architectural purposes. This will correspond only with the center of gravity if the solid represents a homogeneous structure of a single material.

Transforming geometry

The new method

returns a copy of the geometry in the original element, transformed by the input coordinate transformation.

Instance.GetTransform() and Instance.GetTotalTransform()

These new methods provide the transform for a given Instance (which is the parent class for elements like family instances, link instances, and imported CAD content). GetTransform() obtains the basic transform for the instance based on how the instance is placed. GetTotalTransform() provides the transform modified with the true north transform, for instances like import instances.

Serialization/deserialization of References

The new methods

allow you to save a reference to a geometry object, for example a face, edge, or curve, as a string, and to obtain an identical Reference later using the String as input.

Face.HasRegions & Face.GetRegions()

This property and method provide information about the faces created by the Split Face command. HasRegions returns a boolean indicating if the face has any Split Face regions. GetRegions returns a list of faces. As the material of these faces can be independently modified through the UI with the Paint tool, the material of each face can be found from its MaterialElementId property.

Face.MaterialElementId replaces Face.MaterialElement

Face.MaterialElement has been obsoleted. Face.MaterialElementId should be used instead.

In some cases the return face will not have access to its Document, so the MaterialElement cannot be returned, but the id can.

NewHermiteSpline tangency control

A new overload takes optional XYZ inputs for the tangency at the start and end of the spline.

New NewNurbSpline overload

The new overload

creates a NurbSpline in an identical manner to how the spline sketching tool creates such a curve in the Revit UI. Remaining fields in the curve definition (Knots, Degree) are automatically assigned from the calculation.

PolyLine returned from Element.Geometry

A new geometry object called a PolyLine is exposed through the API. The PolyLine represents a set of coordinate points forming contiguous line segments. Typically this type of geometry would be seen in geometry imported from other formats (such as DWG). Previous Element.Geometry[] would skip extraction of these geometry object completely.

Analysis of Room and Space 3D geometry

The new method:

computes the 3D geometry of the input spatial element (room or space) and returns it, along with information about the elements which form the boundary of the element.

The new classes:

encapsulate the results of the geometric calculation.

The class:

provides the available options for the calculation (currently limited to an option to calculate the boundaries at the finish face or at the boundary object's centerlines and whether to include the free boundary faces in the calculation result).

Detailed Energy Analysis Model API

A new API is provided to obtain and analyze the contents of a project's detailed energy analysis model, as seen in the Export to gbXML and the Heating and Cooling Loads features:

Detailed energy analysis model

This analysis produces an analytical thermal model from the physical model of a building. The analytical thermal model is composed of spaces, zones and planar surfaces that represent the actual volumetric elements of the building.

The new classes in Autodesk.Revit.DB.Analysis namespace:

can be used to generate and analyze the contents of the detailed energy analysis model. Use

to create and populate the model (while setting up appropriate options); use

to extract the entities from the analysis; and use

to clean up the Revit database after finishing with the analysis results.

Conceptual energy analysis API

The new classes in the Autodesk.Revit.DB.Analysis namespace:

provide access to the elements and objects created by Revit to perform energy analyses on conceptual design models.

The method

supports export of a gBXML file containing conceptual energy analysis elements (mass elements) only.

Analysis visualization framework

The analysis visualization framework was improved to support multiple analysis results shown in the same view at the same time.

The new class

was added to store meta-data for each analysis result. The Results Visibilty view frame control in the user interface and the API's SpatialFieldManager.ResultsEnabledInView and AnalysisResultSchema.IsVisible properties control which results (if any) are displayed.

The class SpatialFieldManager now has new methods:

to register and access results meta-data. Corresponding methods and properties of SpatialFieldManager:

are deprecated. They can be used if SpatialFieldManager contains only one analysis result, but they throw an exception if multiple results are registered.

The method

is changed to take a result index as an additional argument; the old version is deprecated and can be used if SpatialFieldManager contains only one analysis result.

New classes allow for different types of analysis data and different appearance of results:

  // Create a SpatialFieldManager for the active view 
  SpatialFieldManager sfm = SpatialFieldManager
    .CreateSpatialFieldManager(doc.ActiveView, 1);
  int primitiveIndex = sfm.AddSpatialFieldPrimitive();
 
  // This example creates two result schema. 
  // Each schema contains a single value at the origin. 
  IList<XYZ> pts = new List<XYZ>();
  pts.Add(XYZ.Zero);
 
  FieldDomainPointsByXYZ pnts = new FieldDomainPointsByXYZ(pts);
 
  // Create the schema 
 
  AnalysisResultSchema resultSchemaA = new AnalysisResultSchema(
    "Schema A", "Time");
 
  AnalysisResultSchema resultSchemaB = new AnalysisResultSchema(
    "Schema B", "Distance");
 
  // Data in Schema A measures time and can be 
  // displayed using Hours or Minutes for units 
 
  List<string> unitsList = new List<string>();
  unitsList.Add("Hours");
  unitsList.Add("Minutes");
  List<double> unitsMultipliers = new List<double>();
  unitsMultipliers.Add(1);
  unitsMultipliers.Add(60);
  resultSchemaA.SetUnits(unitsList, unitsMultipliers);
 
  List<double> doubleList = new List<double>();
 
  // The data value in Schema A is 3.5 hours 
 
  doubleList.Add(3.5);
  IList<ValueAtPoint> valueList
    = new List<ValueAtPoint>();
  valueList.Add(new ValueAtPoint(doubleList));
  FieldValues fieldValuesA
    = new FieldValues(valueList);
 
  // Data in Schema B measures distance and can be 
  // displayed using Feet or Inches for units 
  unitsList.Clear();
  unitsMultipliers.Clear();
  unitsList.Add("Feet");
  unitsList.Add("Inches");
  unitsMultipliers.Add(1);
  unitsMultipliers.Add(12);
  resultSchemaB.SetUnits(unitsList, unitsMultipliers);
 
  doubleList.Clear();
  valueList.Clear();
  // The data value in Schema B is 5 feet 
  doubleList.Add(5);
  valueList.Add(new ValueAtPoint(doubleList));
  FieldValues fieldValuesB = new FieldValues(valueList);
 
  // Update the view's spatial field primitive with the schema 
  sfm.UpdateSpatialFieldPrimitive(primitiveIndex,
    pnts, fieldValuesA, sfm.RegisterResult(resultSchemaA));
  sfm.UpdateSpatialFieldPrimitive(primitiveIndex,
    pnts, fieldValuesB, sfm.RegisterResult(resultSchemaB));

Point Cloud API

Revit offers two sets of APIs related to Point Clouds.

The client API is capable of working with point cloud instances within Revit (creating them, manipulating their properties, and reading the points found matching a given volumetric filter).

The major classes of the client API are:

There are two methods to access the points as a client:

  1. In the traditional IEnumerable interface, you can iterate the resulting points directly from the PointCollection.
  2. In an unsafe interface usable only from C# and C++/CLI, you can get a pointer to the point storage of the collection and access the points directly in memory. Although you must deal with pointers directly, there may be performance improvements when traversing large buffers of points.

The following snippets show how to iterate part of a point cloud using both methods. The same point cloud filter is applied for both routines:

Reading point cloud points by iteration

private int ReadPointCloud_Iteration(
  PointCloudInstance pcInstance )
{
  PointCloudFilter filter = CreatePointCloudFilter(
    pcInstance.Document.Application, pcInstance );
 
  // Get points.  Number of points is 
  // determined by the needs of the client
 
  PointCollection points = pcInstance.GetPoints(
    filter, 10000 );
 
  int numberOfPoints = 0;
  foreach( CloudPoint point in points )
  {
    // Process each point
    System.Drawing.Color color
      = System.Drawing.ColorTranslator.FromWin32(
        point.Color );
 
    String pointDescription = String.Format(
      "({0}, {1}, {2}, {3}",
      point.X, point.Y, point.Z, color.ToString() );
 
    numberOfPoints++;
  }
  return numberOfPoints;
}

Reading point cloud points by pointer

public unsafe int ReadPointCloud_Pointer(
  PointCloudInstance pcInstance )
{
  PointCloudFilter filter = CreatePointCloudFilter(
    pcInstance.Document.Application, pcInstance );
 
  // Get points.  Number of points is 
  // determined by the needs of the client
 
  PointCollection points = pcInstance.GetPoints(
    filter, 10000 );
 
  int totalCount = points.Count;
  CloudPoint* pointBuffer = (CloudPoint*) points
    .GetPointBufferPointer().ToPointer();
 
  for( int numberOfPoints = 0;
    numberOfPoints < totalCount; numberOfPoints++ )
  {
    CloudPoint point = *( pointBuffer + numberOfPoints );
 
    // Process each point
 
    System.Drawing.Color color
      = System.Drawing.ColorTranslator.FromWin32(
        point.Color );
 
    String pointDescription = String.Format(
      "({0}, {1}, {2}, {3}",
      point.X, point.Y, point.Z, color.ToString() );
  }
  return totalCount;
}

Point cloud filter creation

private PointCloudFilter CreatePointCloudFilter(
  Application app, PointCloudInstance pcInstance )
{
  // Filter will match 1/8 of the overall point cloud
  // Use the bounding box (filter coordinates 
  // are in the coordinates of the model)
 
  BoundingBoxXYZ boundingBox
    = pcInstance.get_BoundingBox( null );
 
  List<Plane> planes = new List<Plane>();
 
  XYZ midpoint
    = ( boundingBox.Min + boundingBox.Max ) / 2.0;
 
  // X boundaries
  planes.Add( app.Create.NewPlane(
    XYZ.BasisX, boundingBox.Min ) );
  planes.Add( app.Create.NewPlane(
    -XYZ.BasisX, midpoint ) );
 
  // Y boundaries
  planes.Add( app.Create.NewPlane(
    XYZ.BasisY, boundingBox.Min ) );
  planes.Add( app.Create.NewPlane(
    -XYZ.BasisY, midpoint ) );
 
  // Z boundaries
  planes.Add( app.Create.NewPlane(
    XYZ.BasisZ, boundingBox.Min ) );
  planes.Add( app.Create.NewPlane(
    -XYZ.BasisZ, midpoint ) );
 
  // Create filter
 
  PointCloudFilter filter = PointCloudFilterFactory
    .CreateMultiPlaneFilter( planes );
 
  return filter;
}

There are two special API-only tools intended to help your client application interact with the user:

  1. The SetSelectionFilter() method and FilterAction property of PointCloudInstance allow you to specify a volumetric filter to be applied to the cloud. The parts of the cloud that pass this filter will be rendered differently in the user interface than the rest of the cloud. If the FilterAction is Highlight, the selected part of the cloud will show in highlight color (blue). If the action is Isolate, only the selected part of the cloud will be visible.
  2. The overloaded method Selection.PickBox() invokes a general purpose two-click editor that lets the user to specify a rectagular area on the screen. While this editor makes no changes in Revit as a result of the selections, you can use the returned box to generate a filter and apply a highlight or isolate action to the point cloud.

This example prompts the user to select a portion of the cloud, and creates a highlight filter for it.

Prompt for cloud selection and highlight

public void PromptForPointCloudSelection(
  UIDocument uiDoc, PointCloudInstance pcInstance )
{
  Application app = uiDoc.Application.Application;
  Selection currentSel = uiDoc.Selection;
 
  PickedBox pickedBox = currentSel.PickBox(
    PickBoxStyle.Enclosing,
    "Select region of cloud for highlighting" );
 
  XYZ min = pickedBox.Min;
  XYZ max = pickedBox.Max;
 
  //Transform points into filter
  View view = uiDoc.ActiveView;
  XYZ right = view.RightDirection;
  XYZ up = view.UpDirection;
 
  List<Plane> planes = new List<Plane>();
 
  // X boundaries
  bool directionCorrect = IsPointAbovePlane(
    right, min, max );
  planes.Add( app.Create.NewPlane( right,
    directionCorrect ? min : max ) );
  planes.Add( app.Create.NewPlane( -right,
    directionCorrect ? max : min ) );
 
  // Y boundaries
  directionCorrect = IsPointAbovePlane(
    up, min, max );
  planes.Add( app.Create.NewPlane( up,
    directionCorrect ? min : max ) );
  planes.Add( app.Create.NewPlane( -up,
    directionCorrect ? max : min ) );
 
  // Create filter
  PointCloudFilter filter = PointCloudFilterFactory
    .CreateMultiPlaneFilter( planes );
 
  Transaction t = new Transaction(
    uiDoc.Document, "Highlight" );
  t.Start();
 
  pcInstance.SetSelectionFilter( filter );
  pcInstance.FilterAction
    = SelectionFilterAction.Highlight;
 
  t.Commit();
}
 
private static bool IsPointAbovePlane(
  XYZ normal, XYZ planePoint, XYZ point )
{
  XYZ difference = point - planePoint;
  difference = difference.Normalize();
  double dotProduct = difference.DotProduct( normal );
  return dotProduct > 0;
}

The engine API is capable of supplying points in a point cloud to Revit. A custom engine implementation consists of the following:

Engine implementations may be file-based or non-file-based:

Regardless of the type of engine used, the implementation must supply enough information to Revit to display the contents of the point cloud. There are two ReadPoints methods which must be implemented:

Material API changes and PropertySets

The Revit Materials API is largely renovated to allow for a representation of materials that is both more compact and more extensible.

The following classes are now obsolete:

The properties on these classes are now accessible from PropertySets or the Material class itself.

All named properties on Material specific to appearance or structure (e.g. Shininess) are also obsolete.

In their place, a material will have one or more aspects pertaining to rendering appearance, structure, or other major material category. Each aspect is represented by a PropertySet or PropertySetElement. Each material can own its properties of an aspect via a PropertySet or share them with other materials as a reference to a PropertySetElement.

New enumerated types:

New classes:

New methods:

Performance Adviser

The new Revit feature Performance adviser is designed to analyze the document and flag for the user any elements and/or settings that may cause performance degradation. The Performance Adviser command executes set of rules and displays their result in a standard review warnings dialog.

The API for performance adviser consists of 2 classes (PerformanceAdviser and IPerformanceAdviserRule). PerformanceAdviser is an application-wide singleton that has a dual role: it is a registry of performance checking rules and an engine to execute them. The methods of PerformanceAdviser:

allow you to manipulate what rules are checked. Applications that create new rules are expected to use AddRule() to register the new rule during application startup and DeleteRule() to deregister it during application shutdown.

Methods of PerformanceAdviser

allow UI or API application to mark rules for execution and run them on a given document, getting report as a list of FailureMessage objects.

The new interface IPerformanceAdviserRule allows you to define new rules for the Performance Adviser. Your application should create a class implementing this interface, instantiate an object of the derived class and register it using PerformanceAdviser.AddRule(). Methods of IPerformanceAdviserRule available for override include:

which provide rule identification information;

which are executed once per check and can be used to perform checks of the document "as a whole";

which allow the rule to identify a subset of elements in the document to be checked and run the check on the individual elements.

Potentially problematic results found during rule execution are reported by returning FailureMessage(s).

External File References (Linked Files)

The API can now tell what elements in Revit are references to external files, and can make some modifications to where Revit loads external files from.

An Element which contains an ExternalFileReference is an element which refers to some external file (ie. a file other than the main .rvt file of the project.) Two new Element methods, IsExternalFileReference() and GetExternalFileReference(), let you get the ExternalFileReference for a given Element.

ExternalFileReference contains methods for getting the path of the external file, the type of the external file, and whether the file was loaded, unloaded, not found, etc. the last time the main .rvt file was opened.

The classes RevitLinkType and CADLinkType can have IsExternalFileReference() return true. RevitLinkTypes refer to Revit files linked into another Revit project. CADLinkTypes refer to DWG files. Note that CADLinkTypes can also refer to DWG imports, which are not external file references, as imports are brought completely into Revit. A property IsImport exists to let users distinguish between these two types.

Additionally, the element which contains the location of the keynote file is an external file reference, although it has not been exposed as a separate class.

There is also a class ExternalFileUtils, which provides a method for getting all Elements in a document which are references to external files.

Additionally, the classes ModelPath and ModelPathUtils have been exposed. ModelPaths can store paths to a location on disk, a network drive, or a Revit Server location. ModelPathUtils provides methods for converting between modelPath and String.

Finally, the class TransmissionData allows users to examine the external file data in a closed Revit document, and to modify path and load-state information for that data. Two methods, ReadTransmissionData, and WriteTransmissionData, are provided. With WriteTransmissionData, users can change the path from which to load a given link, and can change links from loaded to unloaded and vice versa. (WriteTransmissionData cannot be used to add links to or remove links from a document, however.)

Newly exposed classes:

Customizing IFC export

The classes

allow your custom application to override the default implementation for the IFC export process.

The interface is passed an ExporterIFC object. The ExporterIFC object is the starting point for all IFC export activities and offers access to the options selected for the given export operation. It also contains access to information cached by Revit during the export process; this information is cached to provide easy access to it later, and sometimes to write it to the file at the end of the export process.

There are several auxiliary objects provided to support implementation of an IFC export client. These are the most important:

The IFC export client for Revit 2012 represents a transitional state between the version implemented internally in Revit 2011 and the final state which should be written 100% using the Revit API. Temporary APIs are exposed to bridge the gaps between the API client code and portions of the previous implementation. As Autodesk continues to evolve this export client, temporary APIs will be changed, deprecated and/or removed in future versions of Revit.

MEP API major enhancements

Pipe settings and sizes

The following new classes provide read/write access to MEP pipe settings:

Placeholder ducts and pipes

The following new properties identify placeholder ducts and pipes:

These new static methods allows creation of placeholder ducts and pipes:

New utility methods are exposed to convert a set of placeholder ducts and pipes to real 3D entities:

Duct & pipe insulation & lining

The new classes

and related types support read/write and create access to duct & pipe insulation and lining. In Revit 2012, these objects are now accessible as standalone elements related to their parent duct, pipe, or fitting.

Small enhancements & API interface changes

SiteLocation and City TimeZone

The properties

now use Revit's TimeZone calculation engine to assign an appropriate time zone for the coordinates. (Previously the time zone was not modified when these values were changed).

SiteLocation retains the ability to set the TimeZone manually as the calculation is may not be accurate for locations near the boundaries.

The City class has been adjusted to return the more accurate TimeZone values.

The new static method

provides direct access to the results of a time zone calculation.

FamilyParameter.GUID property

Returns the GUID of a particular family parameter. Allows you to determine if family parameters are shared or not.

InternalDefintion.Visible property

Identifies if a parameter definition represents a visible or hidden parameter (hidden applies to shared parameters only).

Selection.GetElementIds() method

Returns a collection containing the ids of the selected elements. This collection can be used directly with FilteredElementCollector.

API to prompt for rubber band box

PickedBox Selection.PickBox(PickBoxStyle style);
PickedBox Selection.PickBox(PickBoxStyle style, String statusPrompt)

Save and SaveAs APIs permitted in most event handlers

The limitation against calling Save/SaveAs has been removed for most events.

The restriction against calling Save/SaveAs remains only in the following special events:

Please note that other restrictions may still prevent a successful save (e.g. save cannot be performed if a transaction group or transaction is still opened by the API client or via Revit's UI when the event handler is invoked)

Opening IFC Documents

A new method allows opening an IFC Document. This method is similar in behaviour to OpenDocumentFile rather than to standard Import methods. It opens the specified file as a newly created document rather than importing it into an existing one. The new document is retuned by the method if opening was successful.

RevitUIFamilyLoadOptions

The class RevitUIFamilyLoadOptions is no longer available for direct construction in the API. If you want to trigger the Revit UI to respond to situations when a loaded family is already found in the target project, obtain a special IFamilyLoadOptions instance from the new static method UIDocument.GetRevitUIFamilyLoadOptions() (in RevitAPIUI.dll) instead.

Reference documentation for BuiltInParameter members

The members of the BuiltInParameter enum (which are parameter "ids" for Revit use) now have automatically generated documentation. The documentation for each id includes the parameter name, as found in the Element Properties dialog in the English version of Autodesk Revit. Note that multiple distinct parameter ids may map to the same English name; in those case you must examine the parameters associated with a specific element to determine which parameter id to use.

SolidSolidCutUtils.CanTwoElemsHaveSolidSolidCut() method

This method has been removed and replaced by

The new method provides a reason why the cutting element cannot cut the other element.

Adaptive component API

The methods in the new classes

provide access to data related to adaptive component families and instances.

ViewSheet.ConvertToRealSheet()

This new method converts a placeholder sheet to a real view sheet, optionally applying a titleblock at the same time.

Initial View Settings

A new class

allows access to the initial view settings for a document that controls which view should initially be shown when the model is opened.

It has the following public methods/properties:

Document preview

The new method

gets the settings related to the stored document preview image for a given document. It returns a DocumentPreviewSettings object, whose members include:

Note that it is also possible to temporarily assign a preview view id for one save operation through the SaveOptions and SaveAsOptions classes. The id set to these classes is not stored in the saved documented.

Document identification

An override for

was added to determine if two Documents represent the same document currently opened in the Revit session.

An override for

was added to return the same hashcode for document instances that represent the same document currently opened in the Revit session.

Dynamic Update Framework API changes

There are new settings to flag an updater as optional. Optional updaters will not cause prompting the end user when they are opening a document which was modified by that updater but the updater is not currently registered. red). Optional updaters should be used only when necessary. By default, updaters are non-optional. New methods introduced to support this change are:

New methods were added to access information about currently registered updaters:

Revit now disallows any calls to UpdaterRegistry from within the Execute() method of an updater. That means any calls to RegistryUpdater(), AddTrigger(), etc. will now throw an exception. The only method of UpdaterRegistry allowed to be called during execution of an updater is UnregisterUpdater(,) but the updater to be unregistered must be not the one currently being executed.

Enclosure class renamed

The Enclosure class, introduced in Revit 2011 as the parent class for Rooms, Spaces and Areas, was renamed to SpatialElement.

Room, Area and Space boundary segments

The individual BoundarySegment properties for the Room, Space and Area classes have been marked obsolete.

The SpatialElement class contains a new method:

which works for all subclass types.

Line origin and direction

Two new properties added to Line class to get the origin and direction of a line:

TextElement properties

Five new read-only properties have been added to the TextElement class:

FaceSplitter class

The FaceSplitter class, representing the element produced by a Split Face operation, has been exposed to the API.

Use this class to identify the element whose face was split by the element (SplitElementId property).

  Autodesk.Revit.DB.Options opt
    = app.Create.NewGeometryOptions();
  opt.ComputeReferences = true;
  opt.IncludeNonVisibleObjects = true;
 
  FilteredElementCollector collector
    = new FilteredElementCollector( doc );
 
  ICollection<FaceSplitter> splitElements
    = collector.OfClass( typeof( FaceSplitter ) )
      .Cast<FaceSplitter>().ToList();
 
  foreach( FaceSplitter faceSplitter in
    splitElements )
  {
    Element splitElement = doc.get_Element(
      faceSplitter.SplitElementId );
 
    Autodesk.Revit.DB.GeometryElement geomElem
      = faceSplitter.get_Geometry( opt );
 
    foreach( GeometryObject geomObj in
      geomElem.Objects )
    {
      Line line = geomObj as Line;
      if( line != null )
      {
        XYZ end1 = line.get_EndPoint( 0 );
        XYZ end2 = line.get_EndPoint( 1 );
        double length = line.ApproximateLength;
      }
    }
  }

To find the faces created by the split, use the new Face.GetFaceRegions() method on the face of the host element for the split.

ColumnAttachment

The newly exposed ColumnAttachment class represents an attachment of the top or bottom of a column to a roof, floor, ceiling, or beam. Static methods:

provide access to the settings in this class for a given element.

Color class

The API color class may represent an invalid or uninitialized color when an instance of it is obtained from Revit. Invalid colors cannot be read; a new exception will throw from the Red, Green, and Blue properties if you attempt to read them. Setting the color properties is permitted and makes the color no longer invalid.

The property

identifies if the color is valid.

FamilyInstance: flip work plane

The new property

is a settable property capable of changing if the work plane for a particular family instance is flipped.

The new property

identifies if the family instance allows flipping of the work plane.

New NewFamilyInstance() overloads

Two new overloads are provided for creating family instances from References:

These are identical to their counterparts that accept Faces as input. Because the Reference member will not always be populated in all Face handles, these overloads allow an alternate means of creating the target family instance attached to the right face.

The new overload

provides the ability to create a line-based detail component.

Allow and disallow wall end joins

The new methods

provide access to the setting for whether or not joining is allowed at a particular end of the wall. If joins exist at the end of a wall and joins are disallowed, the walls will become disjoint. If joins are disallowed for the end of the wall, and then the setting is toggled to allow the joins, the wall will automatically join to its neighbors if there are any.

Element.Pinned property

The Element.Pinned property is no longer read-only. It now allows you to set an element to be pinned or unpinned.

ElementFilter.PassesElement

Two new overloads allow you to evaluate the result of an ElementFilter:

ElementMulticategoryFilter

This new ElementFilter subtype allows you to easily find elements whose category matches any of a given set of categories.

ElementMulticlassFilter

This new ElementFilter subtype allows you to easily find elements whose class type matches any of a given set of classes.

ElementPhaseStatus

The new method

returns the status of a given element in the input phase. Options include none (elements unaffected by phasing), new, demolished, past, future, existing and temporary.

The new element filter allows you to filter for elements which have a status matching one of the set of input statuses.

Temporary view mode information

The new method:

identifies if a particular temporary view mode is active for a view.

The new method:

identifies if an element should be visible in the indicated view mode. This applies only to the TemporaryHideIsolate and AnalyticalModel view modes.

Generalized Array, Set, Map classes removed

The Revit API classes in Autodesk.Revit.Collections:

have been removed. More flexible alternatives exist in the .NET framework System.Collections and System.Collections.Generic namespaces.

Replacement for ExternalCommandData.Data

The property

has been replaced by

The data type is now an IDictionary<String, String>.

The previous Data property has been marked Obsolete.

Replacement for Application.LibraryPaths

The property

has been replaced by two methods

The data type is now an IDictionary<String, String>.

The previous LibraryPaths property has been marked Obsolete.

LinkElementId property changes

The members of the LinkElementId class have changed in order to clarify what element is represented by an instance of this object. The new properties are:

Application properties

The new properties:

provide read access to information in the current Revit session.

RevitAddInUtility.dll

This DLL is now compiled as a compatible binary capable of execution on 32-bit or 64-bit systems.

VSTA changes

VSTA enabled for multiple Revit sessions

Macros can now be used in multiple Revit sessions launched from a single installation. Revit will no longer warn you about VSTA being disabled when the second and subsequent sessions are launched.

There are a few restrictions regarding what you can do from the second and subsequent sessions:

  1. Application level macros in the second session may be run, but not edited, until the first session is closed.
  2. Document level macros in the second session can be run and edited freely. However, edits to macro projects from a document opened in both sessions can't be saved until the document is closed by the first session.

Structure API

Track Changes UI

The track changes UI previously offered by Revit Structure has been removed. In previous releases, this offered the ability to highlight elements changed by API commands, and a limited ability to revert some or all of the changes.

Unfortunately, the functionality was limited in certain ways:

If you wish to offer some ability for your users to see what changes were made by a given transaction, you can implement something similar or more sophisticated using the DocumentChanged event. End users are best served using the Undo mechanism to revert all changes made during a given transaction, if that is their desire. The Undo mechanism is consistent and compatible with multiple API transactions, events and updaters as well as individual commands.

LineLoad.UniformLoad

This property has been corrected to be Boolean instead of integer.

NewBeamSystem() changes

The family of NewBeamSystem() methods has changed. Previously curves could be input without a sketch plane or level as input, and the orientation of the active view would determine the orientation of the resultant beam system. Now, there are overloads accepting either the sketch plane or the level and those inputs are required.

The overloads of NewBeamSystem() now check that the input profile curves lie properly in the sketch plane or level. They also check to ensure that the profile forms a closed loop.

NewTruss() change

The SketchPlane input for this method is now required. Previously null could be input, and the orientation of the active view would determine the orientation of the resultant truss.

Rebar changes

RebarShape creation and modification

RebarShape elements are no longer modifiable (except for Allowed Bar Types). Instead of changing a RebarShape, create a new one based on the old one. This change results in a simplified API that works in the same way as the UI.

Also, the syntax for RebarShape creation has been changed. In 2011, the steps were:

  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, the steps are:

  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 is the document modified.)

Specifically, the following methods are removed:

and replaced by:

The ability to modify hook angle, hook orientation, and style has been removed. These can only be set at creation.

Rebar Shape Parameters

The interface for Rebar Shape Parameters has changed. Throughout the Rebar API, all methods now use ElementId to stand for a shared parameter, instead of ExternalDefinition. Methods are provided in the new RebarShapeParameters class to convert between ElementId and ExternalDefinition:

The following RebarShape properties were replaced with get methods:

The ability to modify hook angle, hook orientation, and style has been removed.

The return type of RebarShape.GetCurvesForBrowser() was changed from CurveArray to IList<Curve>.

RebarHookType

The method

was replaced by

New members were added to the RebarHookType class are new (its properties were only available through the Parameters interface before).

RebarHostData class

The RebarHostData class has the following changes:

Rebar class

The two methods Creation.Document.NewRebar() were replaced by:

The new methods are similar to the old ones, except that they no longer return null for invalid arguments, and they no longer regenerate the document.

The new class RebarBendData is to support functionality that is not part of Alpha 3.

MEP API small enhancements and changes

Spare and space circuits

The new property

identifies the type of an electrical circuit (circuit, spare or space).

The method ElectricalSystem.AddToCircuit now throws an exception when the system is a spare or space circuit.

Cable tray and conduit domain

The enum class

adds a new enum value to represent cable tray & conduit.

Connector

New read-only properties have been added:

MEPSystem

The new property

identifies if the system currently contains no components.

Graphical warnings for disconnects

The new properties:

and the matching setters control whether Revit MEP will highlight disconnects in systems graphically.

Space properties

The new property

indicates if the value of Space.LatentHeatGainperPerson and Space.SensibleHeatGainperPerson properties is the default value or if it is user-defined.

To accomodate this property, the namespace of enum BaseLoadOn has changed from Autodesk.Revit.DB.Electrical to Autodesk.Revit.DB.

Fitting methods

The following methods no longer remove unused or dangling curve connectors:

Please use ConnectorManager.UnusedConnectors.Erase to remove unused connectors after creating a new fitting.


End of document


That was the news in the Revit 2012 API back in the year 2011.

Please be aware that some of the changes mentioned above have been updated yet again since.

Stay tuned for the next installment, coming soon, leading up towards the current day.