Applying Filters

Filters can be applied to a FilteredElementCollector using ElementFilters. An ElementFilter is a class that examines an element to see if it meets a certain criteria. The ElementFilter base class has three derived classes that divide element filters into three categories.

Most filters may be inverted using an overload constructor that takes a Boolean argument indicating to invert the filter so that elements that would normally be accepted by the filter will be rejected, and elements that would normally be rejected will be accepted. Filters that cannot be inverted are noted in their corresponding sections below.

There is a set of predefined filters available for common uses. Many of these built-in filters provide the basis for the FilteredElementCollector shortcut methods mentioned in the FilteredElementCollector section above. The next three sections provide more information on the built-in filters.

Once a filter is created, it needs to be applied to the FilteredElementCollector. The generic method WherePasses() is used to apply a single ElementFilter to the FilteredElementCollector.

Filters can also be applied using a number of shortcut methods provided by FilteredElementCollector. Some apply a specific filter without further input, such as WhereElementIsCurveDriven(), while others apply a specific filter with a simple piece of input, such as the OfCategory() method which takes a BuiltInCategory as a parameter. And lastly there are methods such as UnionWith() that join filters together. All of these methods return the same collector allowing filters to be easily chained together.

Quick filters

Quick filters operate only on the ElementRecord, a low-memory class which has a limited interface to read element properties. Elements which are rejected by a quick filter will not be expanded in memory. The following table summarizes the built-in quick filters, and some examples follow for a few of the filters.

Table 13: Built-in Quick Filters

Built-in Filter What it passes Shortcut Method(s)
BoundingBoxContainsPointFilter Elements which have a bounding box that contains a given point None
BoundingBoxIntersectsFilter Elements which have a bounding box which intersects a given outline None
BoundingBoxIsInsideFilter Elements which have a bounding box inside a given outline None
ElementCategoryFilter Elements matching the input category id OfCategoryId()
ElementClassFilter Elements matching the input runtime class (or derived classes) OfClass()
ElementDesignOptionFilter Elements in a particular design option ContainedInDesignOption()
ElementIdSetFilter Elements whose ElementIds are included in a collection
ElementIsCurveDrivenFilter Elements which are curve driven WhereElementIsCurveDriven()
ElementIsElementTypeFilter Elements which are "Element types" WhereElementIsElementType() WhereElementIsNotElementType()
ElementMulticategoryFilter Elements matching any of a given set of categories None
ElementMulticlassFilter Elements matching a given set of classes (or derived classes) None
ElementOwnerViewFilter Elements which are view-specific OwnedByView() WhereElementIsViewIndependent()
ElementStructuralTypeFilter Elements matching a given structural type None
ExclusionFilter All elements except the element ids input to the filter Excluding()
FamilySymbolFilter Symbols of a particular family
VisibleInViewFilter Elements that are most likely visible in the given view
Note: The FamilySymbolFilter cannot be inverted.
Note: The bounding box filters exclude all objects derived from View and objects derived from ElementType.

The following example creates an outline in the document and then uses a BoundingBoxIntersectsFilter to find the elements in the document with a bounding box that intersects that outline. It then shows how to use an inverted filter to find all walls whose bounding box do not intersect the given outline. Note that the use of the OfClass() method applies an ElementClassFilter to the collection as well.

Code Region 6-2: BoundingBoxIntersectsFilter example
public void IntersectsFilterSample(Document document)
{
        // Use BoundingBoxIntersects filter to find elements with a bounding box that intersects the given Outline in the document.

        // Create a Outline, uses a minimum and maximum XYZ point to initialize the outline. 
        Outline myOutLn = new Outline(new XYZ(0, 0, 0), new XYZ(100, 100, 100));

        // Create a BoundingBoxIntersects filter with this Outline
        BoundingBoxIntersectsFilter filter = new BoundingBoxIntersectsFilter(myOutLn);

        // Apply the filter to the elements in the active document
        // This filter excludes all objects derived from View and objects derived from ElementType
        FilteredElementCollector collector = new FilteredElementCollector(document);
        IList<Element> elements = collector.WherePasses(filter).ToElements();

        // Find all walls which don't intersect with BoundingBox: use an inverted filter to match elements
        // Use shortcut command OfClass() to find walls only
        BoundingBoxIntersectsFilter invertFilter = new BoundingBoxIntersectsFilter(myOutLn, true);
        collector = new FilteredElementCollector(document);
        IList<Element> notIntersectWalls = collector.OfClass(typeof(Wall)).WherePasses(invertFilter).ToElements();
}

The next example uses an exclusion filter to find all walls that are not currently selected in the document.

Code Region 6-3: Creating an exclusion filter
public void FindNotSelectedWalls(UIDocument uiDocument)
{
        // Find all walls that are not currently selected, 
        // Get all element ids which are current selected by users, exclude these ids when filtering
        ICollection<ElementId> selectedIds = uiDocument.Selection.GetElementIds();

        // Use the selection to instantiate an exclusion filter
        ExclusionFilter filter = new ExclusionFilter(selectedIds);
        // For the sake of simplicity we do not test here whether the selection is empty or not,
        // but in production code a proper validation would have to be done to avoid an argument
        // exception from the filter's consructor.

        // Apply the filter to the elements in the active document,
        // Use shortcut method OfClass() to find Walls only
        FilteredElementCollector collector = new FilteredElementCollector(uiDocument.Document);
        IList<Element> walls = collector.WherePasses(filter).OfClass(typeof(Wall)).ToElements();
}
Note: The ElementClassFilter will match elements whose class is an exact match to the input class, or elements whose class is derived from the input class. The following example uses an ElementClassFilter to get all loads in the document.
Code Region 6-4: Using an ElementClassFilter to get loads
public void MakeLoadFilter(Document document)
{
        // Use ElementClassFilter to find all loads in the document
        // Using typeof(LoadBase) will yield all AreaLoad, LineLoad and PointLoad
        ElementClassFilter filter = new ElementClassFilter(typeof(LoadBase));

        // Apply the filter to the elements in the active document
        FilteredElementCollector collector = new FilteredElementCollector(document);
        ICollection<Element> allLoads = collector.WherePasses(filter).ToElements();
}
There is a small subset of Element subclasses in the API which are not supported by the element class filter. These types exist in the API, but not in Revit's native object model, which means that this filter doesn't support them. In order to use a class filter to find elements of these types, it is necessary to use a higher level class and then process the results further to find elements matching only the subtype.
Note: Dedicated filters exist for some of these types.

The following types are affected by this restriction:

Type Dedicated Filter
Subclasses of Autodesk.Revit.DB.Material None
Subclasses of Autodesk.Revit.DB.CurveElement CurveElementFilter
Subclasses of Autodesk.Revit.DB.ConnectorElement None
Subclasses of Autodesk.Revit.DB.HostedSweep None
Autodesk.Revit.DB.Architecture.Room RoomFilter
Autodesk.Revit.DB.Mechanical.Space SpaceFilter
Autodesk.Revit.DB.Area AreaFilter
Autodesk.Revit.DB.Architecture.RoomTag RoomTagFilter
Autodesk.Revit.DB.Mechanical.SpaceTag SpaceTagFilter
Autodesk.Revit.DB.AreaTag AreaTagFilter
Autodesk.Revit.DB.CombinableElement None
Autodesk.Revit.DB.Mullion None
Autodesk.Revit.DB.Panel None
Autodesk.Revit.DB.AnnotationSymbol None
Autodesk.Revit.DB.Structure.AreaReinforcementType None
Autodesk.Revit.DB.Structure.PathReinforcementType None
Autodesk.Revit.DB.AnnotationSymbolType None
Autodesk.Revit.DB.Architecture.RoomTagType None
Autodesk.Revit.DB.Mechanical.SpaceTagType None
Autodesk.Revit.DB.AreaTagType None
Autodesk.Revit.DB.Structure.TrussType None

Slow Filters

Slow filters require that the Element be obtained and expanded in memory first. Thus it is preferable to couple slow filters with at least one ElementQuickFilter, which should minimize the number of Elements that are expanded in order to evaluate against the criteria set by this filter. The following table summarizes the built-in slow filters, while a few examples follow to provide an in-depth look at some of the filters.

Table 14: Built-in Slow Filters

Built-in Filter What it passes Shortcut Method(s)
AreaFilter Areas None
AreaTagFilter Area tags None
CurveElementFilter CurveElements None
ElementLevelFilter Elements associated with a given level id None
ElementParameterFilter Elements passing one or more parameter filter rules None
ElementPhaseStatusFilter Elements with a given phase status on a given phase None
FamilyInstanceFilter Instances of a particular family instance None
FamilyStructuralMaterialTypeFilter Family elements of given structural material type None
PrimaryDesignOptionMemberFilter Elements owned by any primary design option None
RoomFilter Rooms None
RoomTagFilter Room tags None
SpaceFilter Spaces None
SpaceTagFilter Space tags None
StructuralInstanceUsageFilter FamilyInstances of given structural usage None
StructuralMaterialTypeFilter FamilyInstances of given structural material type None
StructuralWallUsageFilter Walls of given structural wall usage None
Element Intersection Filters Elements that intersect the solid geometry of a given element None
Element Intersection Filters> Elements that intersect the given solid geometry None

The following slow filters cannot be inverted:

As mentioned in the quick filters section, some classes do not work with the ElementClassFilter. Some of those classes, such as Room and RoomTag have their own dedicated filters.

Code Region 6-5: Using the Room filter
public void MakeRoomFilter(Document document)
{
        // Use a RoomFilter to find all room elements in the document. It is necessary to use the RoomFilter and not an ElementClassFilter or the shortcut method OfClass() because the Room class is not supported by those methods.
        RoomFilter filter = new RoomFilter();

        // Apply the filter to the elements in the active document
        FilteredElementCollector collector = new FilteredElementCollector(document);
        IList<Element> rooms = collector.WherePasses(filter).ToElements();
}

The ElementParameterFilter is a powerful filter that can find elements based on values of parameters they may have. It can find elements whose parameter values match a specific value or are greater or less than some value. ElementParameterFilter can also be used to find elements that support a specific shared parameter.

The example below uses an ElementParameterFilter to find rooms whose size is more than 100 square feet and rooms with less than 100 square feet.

Code Region 6-6: Using a parameter filter
public void FindRooms(Document document)
{
        // Creates an ElementParameter filter to find rooms whose area is greater than specified value
        // Create filter by provider and evaluator 
        BuiltInParameter areaParam = BuiltInParameter.ROOM_AREA;
        // provider
        ParameterValueProvider pvp = new ParameterValueProvider(new ElementId((long)areaParam));

        // Create an ElementParameter filter to filter rooms whose area is greater than 100 SF
        var ruleGreater100 = new FilterDoubleRule(pvp, new FilterNumericGreater(), 100, 1E-6);
        ElementParameterFilter filterGreater100 = new ElementParameterFilter(ruleGreater100);

        // Apply the filter to the elements in the active document
        IList<Element> roomsGreater100 = new FilteredElementCollector(document)
         .OfCategory(BuiltInCategory.OST_Rooms)
         .WherePasses(filterGreater100).ToElements();

        // Find rooms whose area is less than or equal to 100: 
        // Use inverted filter to match elements
        ElementParameterFilter filterLessthan100 = new ElementParameterFilter(ruleGreater100, true); 
        IList<Element> roomsLessthan100 = new FilteredElementCollector(document)
         .OfCategory(BuiltInCategory.OST_Rooms)
         .WherePasses(filterLessthan100).ToElements();
}

The following example shows how to use the FamilyStructuralMaterialTypeFilter to find all families whose material type is wood. It also shows how to use an inverted filter to find all families whose material type is not wood.

Code Region 6-7: Find all families with wood material
public void FindWoodFamilies(Document document)
{
        // Use FamilyStructuralMaterialType filter to find families whose material type is Wood
        FamilyStructuralMaterialTypeFilter filter = new FamilyStructuralMaterialTypeFilter(StructuralMaterialType.Wood);

        // Apply the filter to the elements in the active document
        FilteredElementCollector collector = new FilteredElementCollector(document);
        ICollection<Element> woodFamiles = collector.WherePasses(filter).ToElements();

        // Find families are not Wood: Use inverted filter to match families
        FamilyStructuralMaterialTypeFilter notWoodFilter = 
                new FamilyStructuralMaterialTypeFilter(StructuralMaterialType.Wood, true);
        collector = new FilteredElementCollector(document);
        ICollection<Element> notWoodFamilies = collector.WherePasses(notWoodFilter).ToElements();
}

The last two slow filters derive from ElementIntersectsFilter which is a base class for filters used to match elements which intersect with geometry. See Code Region: Find Nearby Walls in the section Geometry Utility Classesfor an example of the use of this type of filter.

Logical filters

Logical filters combine two or more filters logically. The following table summarizes the built-in logical filters.

Table 15: Built-in Logical Filters

Built-in Filter What it passes Shortcut Method(s)
LogicalAndFilter Elements that pass 2 or more filters WherePasses()- adds one additional filter

IntersectWith() - joins two sets of independent filters

LogicalOrFilter Elements that pass at least one of 2 or more filters UnionWith() - joins two sets of independent filters

In the example below, two quick filters are combined using a logical filter to get all door FamilyInstance elements in the document.

Code Region 6-8: Using LogicalAndFilter to find all door instances
public void FindDoors(Document document)
{
        // Find all door instances in the project by finding all elements that both belong to the door category and are family instances.
ElementClassFilter familyInstanceFilter = new ElementClassFilter(typeof(FamilyInstance));

// Create a category filter for Doors
ElementCategoryFilter doorsCategoryfilter = 
        new ElementCategoryFilter(BuiltInCategory.OST_Doors);

// Create a logic And filter for all Door FamilyInstances
LogicalAndFilter doorInstancesFilter = new LogicalAndFilter(familyInstanceFilter, 
        doorsCategoryfilter);

// Apply the filter to the elements in the active document
FilteredElementCollector collector = new FilteredElementCollector(document);
IList<Element> doors = collector.WherePasses(doorInstancesFilter).ToElements();
}