next previous home

3-3 Determine instance type and family

In this section, we determine the family and type of a family instance element. We look at two simple scenarios. In Lab 3-1, we listed all symbols by looping over the contents of the symbols property for each family found in the model. Here, we first list all loaded standard family symbols belonging to a category, such as 'Windows'. For this we can use the new filter type called NewLogicAndFilter, which lists all elements based on filter criteria which matches the 'Windows' category AND the 'FamilySymbol' type. Once we have the loaded family symbols, we can directly access the Family and Name properties to display them.

  /// <summary>
  /// For a selected family instance in the model, determine
  /// its type and family using Revit 2009 filtering.
  /// </summary>
  public class Lab3_3_DetermineInstanceTypeAndFamily : IExternalCommand
  {
    public IExternalCommand.Result Execute(
      ExternalCommandData commandData,
      ref string message,
      ElementSet elements)
    {
      Application app = commandData.Application;
      Document doc = app.ActiveDocument;

      // Use the filtering mechanism to report all FamilySymbol objects of "Windows" category.
      BuiltInCategory bic = BuiltInCategory.OST_Windows;
      List<Element> familySymbols = new List<Element>();

      Filter filterCategory = app.Create.Filter.NewCategoryFilter( bic );
      Filter filterType = app.Create.Filter.NewTypeFilter( typeof( FamilySymbol ) );
      Filter filterAnd = app.Create.Filter.NewLogicAndFilter( filterCategory, filterType );
      app.ActiveDocument.get_Elements( filterAnd, familySymbols );

      string sMsg = "The loaded windows family symbols in the model are:";
      foreach( Element elem in familySymbols )
      {
        FamilySymbol symb = elem as FamilySymbol;
        sMsg += "\r\n    " + symb.Name + ", Id=" + symb.Id.Value.ToString();
        Family fam = symb.Family;
        sMsg += "; Family name=" + fam.Name + ", Family Id=" + fam.Id.Value.ToString();
      }
      LabUtils.InfoMsg( sMsg );
      return IExternalCommand.Result.Succeeded;
    }
  }
    Public Class Lab3_3_DetermineInstanceTypeAndFamily
        Implements IExternalCommand

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

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

            ' Use the filtering mechanism to report all FamilySymbol objects of "Windows" category.
            Dim sMsg As String = " Windows Family Symbols in the model are:"
            Dim bic As BuiltInCategory = BuiltInCategory.OST_Windows

            Dim familySymbols As New List(Of Element)
            Dim filterCategory As Filter = app.Create.Filter.NewCategoryFilter(bic)
            Dim filterType As Filter = app.Create.Filter.NewTypeFilter(GetType(FamilySymbol))
            Dim filter As Filter = app.Create.Filter.NewLogicAndFilter(filterCategory, filterType)
            Dim rVal As Integer = app.ActiveDocument.Elements(filter, familySymbols)

            Dim elem As Element
            For Each elem In familySymbols
                Dim symb As FamilySymbol = elem
                sMsg += vbCrLf & "  " & symb.Name & ", Id=" & symb.Id.Value.ToString
                Dim fam As Family = symb.Family
                sMsg += "; Family name=" & fam.Name & ", Family Id=" & fam.Id.Value.ToString
            Next
            MsgBox(sMsg)

            Return IExternalCommand.Result.Succeeded
        End Function
     End Class

Build the project, adjust the ini file and examine the output in a model with a few windows instances. Notice the intriguing fact that some of the family symbols are listed multiple times if used for any instances.

Why do two different family symbols have the same name?

In Revit, a symbol represents geometry, and we have the concept of master and slave family symbols.

Consider two window instances of the same type, but inserted into walls of different types. Now, these two window instances refer to the same family symbol and count as being of the same type, but it is clear that they cannot possibly use the same symbol geometry, since they have different thickness. Hence master and slave symbols are used.

For instance, if there is no door instance in project, there will be only one master symbol for 36"x84" doors. Now, if the user draws a wall and places a door into it, Revit will create a slave symbol for 36"x84". If she then draws a different type of wall and places a new door of the same type in this new wall, Revit will create another slave symbol for 36"x84". Then there will be one master symbol and two slave symbols in the project.

There is currently no API to query the symbol whether it is master or slave.

Both of the symbols have the same parent family class instance and either are usable for editing existing or creating new instances, so there is no issue with this.

Let us add some code that shows the symbol and family for any selected windows:

  // Now loop the selection set and check for standard Family Instances of "Windows" category
  Categories categories = doc.Settings.Categories;
  Category catWindows = categories.get_Item( bic );
  foreach( Element elem2 in doc.Selection.Elements )
  {
    if( elem2 is FamilyInstance )
    {
      FamilyInstance inst = elem2 as FamilyInstance;
      if( null != inst.Category && inst.Category.Id.Equals( catWindows.Id ) )
      {
        sMsg = "Selected window Id=" + elem2.Id.Value.ToString();
        FamilySymbol fs = inst.Symbol;
        sMsg += "\r\n  FamilySymbol = " + fs.Name + "; Id=" + fs.Id.Value.ToString();
        Family f = fs.Family;
        sMsg += "\r\n  Family = " + f.Name + "; Id=" + f.Id.Value.ToString();
        LabUtils.InfoMsg( sMsg );
      }
    }
  }
    ' Now loop the selection set and check for standard
    ' family instances of "Windows" category
    Dim categories As Categories = doc.Settings.Categories
    Dim catWindows As Category = categories.Item(bic)
    For Each elem In doc.Selection.Elements
        If TypeOf elem Is FamilyInstance Then
            Dim inst As FamilyInstance = elem
            Dim catInst As Category = Nothing
            If (inst.Category Is Nothing) Then
                catInst = Nothing
            Else
                catInst = inst.Category
            End If
            ' Check if the element category id is same as Windows category id
            If (Not catInst Is Nothing) AndAlso catInst.Id.Equals(catWindows.Id) Then

                sMsg = "Selected Window Id=" & elem.Id.Value.ToString & vbCrLf
                Dim fs1 As FamilySymbol = inst.Symbol
                sMsg += "  FamilySymbol = " & fs1.Name & "; Id=" & fs1.Id.Value.ToString & vbCrLf
                Dim f1 As Family = fs1.Family
                sMsg += "  Family = " & f1.Name & "; Id=" & f1.Id.Value.ToString
                ' Report each Window data
                MsgBox(sMsg)
            End If
        End If
    Next

Rebuild the solution, preselect some window instances and run the command again. Discuss the code with the course instructor and your peers.

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