Retrieving 3D Model Elements
next previous home

Model elements are generally part of the building and have geometry. In this lab we will implement a filter to retrieve all model elements, i.e. Revit element instances with a 3D geometrical representation. There are several possible approaches to retrieving these elements. Here, we will present a method that loops over all document elements uses a combination of different criteria to ensure that only valid model elements are selected. The criteria applied to each element are:

The preview legend components inadvertently acquired geometry that is accessible through the API in Revit 2010. Previously, that check was not neccessary.

The comparison of the element category with the built-in preview legend components one can be achieved by simply comparing the former's element id value with the latter cast to an integer.

Add a standard external command implementation to the Labs2 module to iterate over all document elements:

  #region Lab2_2_ModelElements
  public class Lab2_2_ModelElements : IExternalCommand
  {
    public CmdResult Execute(
      ExternalCommandData commandData,
      ref string message,
      ElementSet elements )
    {
      Application app = commandData.Application;
      Document doc = app.ActiveDocument;

      ElementIterator it = doc.Elements;
      string s = string.Empty;
      int count = 0;
      
      while( it.MoveNext() )
      {
        Element e = it.Current as Element;
      }
      
      s = "There are " + count.ToString() + " model elements:" + s;
      LabUtils.InfoMsg( s );
      
      return CmdResult.Failed;
    }
  }
  #endregion // Lab2_2_ModelElements
#Region "Lab2_2_ModelElements"
    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

            Dim app As Application = commandData.Application
            Dim doc As Document = app.ActiveDocument

            Dim it As ElementIterator = doc.Elements
            Dim s As String = String.Empty
            Dim count As Integer = 0

            Do While (it.MoveNext())
                Dim e As Element = it.Current
            Loop

            s = "There are " & count & " model elements:" & s

            MsgBox(s)

            Return IExternalCommand.Result.Failed

        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.

Once this is up and running, you can explore how to add the filter criteria discussed above to skip all the thousands of unwanted non-model elements. Here is one example of the while loop enhanced to apply that filter. First, we need to declare a gloabl variable or two to compare the preview legend components category:

  public class Lab2_2_ModelElements : IExternalCommand
  {
    BuiltInCategory _bicPreviewLegendComponent = BuiltInCategory.OST_PreviewLegendComponents;

    public CmdResult Execute(
      ExternalCommandData commandData,
      ref string message,
      ElementSet elements )
    {
      Application app = commandData.Application;
      Document doc = app.ActiveDocument;

      ElementIterator it = doc.Elements;
      string s = string.Empty;
      int count = 0;

      Geo.Options opt = app.Create.NewGeometryOptions();

      int iBic = (int) _bicPreviewLegendComponent;

      while( it.MoveNext() )
      {
        Element e = it.Current as Element;

        if ( !(e is Symbol)
          && !(e is FamilyBase)
          && (null != e.Category)
          && ( iBic != e.Category.Id.Value )
          && (null != e.get_Geometry( opt )) )
        {
          ++count;
          s += string.Format( "\r\n  Category={0}; Name={1}; Id={2}",
            e.Category.Name, e.Name, e.Id.Value.ToString() );
        }
      }

      s = "There are " + count.ToString() + " model elements:" + s;
      LabUtils.InfoMsg( s );

      return CmdResult.Failed;
    }
  }
    Public Class Lab2_2_ModelElements
        Implements IExternalCommand

        Dim _bicPreviewLegendComponent As BuiltInCategory = BuiltInCategory.OST_PreviewLegendComponents

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

            Dim app As Application = commandData.Application
            Dim doc As Document = app.ActiveDocument

            Dim it As ElementIterator = doc.Elements
            Dim s As String = String.Empty
            Dim count As Integer = 0

            Dim opt As Geometry.Options = app.Create.NewGeometryOptions

            Dim iBic As Integer = _bicPreviewLegendComponent

            Do While (it.MoveNext())
                Dim e As Element = it.Current

                If Not (TypeOf e Is Symbol) _
                    And Not (TypeOf e Is FamilyBase) _
                    And Not (e.Category Is Nothing) _
                    And Not (iBic = e.Category.Id.Value) Then

                    Dim geo As Geometry.Element = e.Geometry(opt)
                    If Not (geo Is Nothing) Then
                        count = count + 1
                        s += vbCrLf & "  Category=" & e.Category.Name & "; Id=" & e.Id.Value.ToString
                    End If
                End If

            Loop

            s = "There are " & count & " model elements:" & s

            MsgBox(s)

            Return IExternalCommand.Result.Failed

        End Function
    End Class

Run the command, examine and discuss the elements obtained before and after filtering, and what the various items in the filter statement mean, with the course instructor and your peers.

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