next previous home

2-2 Model Elements

Model elements are generally part of the building and have geometry. In this lab we will develop a reusable utility to retrieve all model elements, i.e. Revit element instances with a 3D geometrical representation. We encapsulate it in the previously created utility class LabUtils.

To retrieve all model elements, we ensure that the element has non-empty geometry. We also do some checks beforehand to optimize the looping.

  /// <summary>
  /// Helper to get all geometrical elements.
  /// </summary>
  public static ElementSet GetAllModelElements( Autodesk.Revit.Application revitApp )
  {
    ElementSet elems = revitApp.Create.NewElementSet();
    Geo.Options opt = revitApp.Create.NewGeometryOptions();
    opt.DetailLevel = Geo.Options.DetailLevels.Fine;
    // IEnumerator iter = revitApp.ActiveDocument.Elements // this would also be sufficient
    ElementIterator iter = revitApp.ActiveDocument.Elements;
    while( iter.MoveNext() )
    {
      Autodesk.Revit.Element elem = iter.Current as Autodesk.Revit.Element;
      // This single line would probably work if all system families were
      // exposed as HostObjects, but they are not yet:
      // if( elem is FamilyInstance }} elem is HostObject )
      if( !( elem is Symbol || elem is FamilyBase ) )
      {
        if( null != elem.Category )
        {
          if( null != elem.get_Geometry( opt ) )
          {
            elems.Insert( elem );
          }
        }
      }
    }
    return elems;
  }
    ' Helper to get all geometrical elements
    Shared Function GetAllModelElements(ByVal revitApp As Revit.Application) As ElementSet

        Dim elems As ElementSet = revitApp.Create.NewElementSet
        Dim opt As Geometry.Options = revitApp.Create.NewGeometryOptions
        opt.DetailLevel = Geometry.Options.DetailLevels.Fine

        'Dim iter As IEnumerator = revitApp.ActiveDocument.Elements ' this would also be sufficient
        Dim iter As ElementIterator = revitApp.ActiveDocument.Elements
        Do While (iter.MoveNext())
            Dim elem As Revit.Element = iter.Current

            ' This single line would probably work if all system families were exposed as HostObjects, but they are not yet
            'If TypeOf elem Is FamilyInstance Or TypeOf elem Is HostObject Then
            If Not (TypeOf elem Is Symbol OrElse TypeOf elem Is FamilyBase) Then
                If Not (elem.Category Is Nothing) Then
                    Dim geo As Geometry.Element = elem.Geometry(opt)
                    If Not (geo Is Nothing) Then
                        elems.Insert(elem)
                    End If
                End If
            End If

        Loop

        Return elems

    End Function

Add a standard external command implementation to the Labs2 module and call the utility function, then loop over the returned elements and display their data:

  #region Lab2_2_ModelElements
  /// <summary>
  /// List all model elements.
  /// </summary>
  public class Lab2_2_ModelElements : IExternalCommand
  {
    public CmdResult Execute(
      ExternalCommandData commandData,
      ref string message,
      ElementSet elements )
    {
      string s = string.Empty;
      ElementSet modelElems = LabUtils.GetAllModelElements( commandData.Application );
      s += "There are " + modelElems.Size + " model elements:";
      foreach( Element elem in modelElems )
      {
        s += "\r\n  Category=" + elem.Category.Name + "; Id=" + elem.Id.Value.ToString();
      }
      LabUtils.InfoMsg( s );
      return CmdResult.Succeeded;
    }
  }
  #endregion // Lab2_2_ModelElements
#Region "Lab2_2_ModelElements"
    ''' <summary>
    ''' List all model elements.
    ''' </summary>
    Public Class Lab2_2_ModelElements
        Implements IExternalCommand

        Public Function Execute( _
            ByVal commandData As ExternalCommandData, _
            ByRef message As String, _
            ByVal elements As ElementSet) _
            As IExternalCommand.Result _
            Implements IExternalCommand.Execute

            ' Call the utility
            Dim modelElems As ElementSet = LabUtils.GetAllModelElements(commandData.Application)

            ' List all elems
            Dim sMsg As String = "There are " & modelElems.Size & " model elements:"
            Dim elem As Revit.Element
            For Each elem In modelElems
                sMsg += vbCrLf & "  Category=" & elem.Category.Name & "; Id=" & elem.Id.Value.ToString
            Next
            MsgBox(sMsg)

            Return IExternalCommand.Result.Succeeded

        End Function
    End Class
#End Region

Compile and link the project and update the Revit.ini file accordingly (cf. 'Add_to_Revit_ini.txt'), or load the command with the help of Add-in Manager.

Run the command and examine and discuss the information displayed in the dialogue with the course instructor and your peers.

next previous home copyright © 2007-2008 jeremy tammik, autodesk inc. all rights reserved.