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.
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-2009 jeremy tammik, autodesk inc. all rights reserved.