Slow Filters in Revit API

Let's cover Slow Filters in Revit API in this lesson. Most importantly I want to give you code snippets so you understand how to use them!

Slow Filters in Revit API

Let's cover Slow Filters in Revit API in this lesson. Most importantly I want to give you code snippets so you understand how to use them!

Summary

Slow Filters

We explored all Quick Filters in previous lesson, now let's look at Slow Filters.

First of all, remember - These 'slow' filters are very efficient, but they operate on properties and methods of elements that require to read all element properties.

So don't even think about ignoring them because they are categorized as such!

So what Filters are Slow Filters?

To see a list of all Slow Filters we can look in Inheritance Hierarchy of ElementSlowFilter.

So you can see a lot of different filters in this screenshot.

There are many filters that I consider useless like RoomFilter, RoomTagFilter and similar ones.

I find them useless because we can get these elements by Category instead of creating these filters.

However, you still have this option! And I will show you snippets of how to use them.

Also these filters don't have any shortcuts in FEC Class, so we only have 1 way of using them.

Let's structure all these filters in a better list below and go through each of them.

Revit API - Quick Filters

FEC Shortcut:

None

A filter used to pass curve elements which are of a specific type.

FEC Shortcut:

None

A filter used to pass curve elements which are of a specific type.

FEC Shortcut:

None

A filter used to match elements by their associated level.

FEC Shortcut:

None

A filter used to match elements by their associated level.

FEC Shortcut:

None

A filter used to find elements that are family instances of the given family symbol.

FEC Shortcut:

None

A filter used to find elements that are family instances of the given family symbol.

FEC Shortcut:

None

A filter used to match elements by one or more parameter filter rules.

FEC Shortcut:

None

A filter used to match elements by one or more parameter filter rules.

FEC Shortcut:

None

A filter to find elements that intersect the solid geometry of a given element.

FEC Shortcut:

None

A filter to find elements that intersect the solid geometry of a given element.

FEC Shortcut:

None

A filter to find elements that intersect the given solid geometry.

FEC Shortcut:

None

A filter to find elements that intersect the given solid geometry.

FEC Shortcut:

None

A filter used to match elements that have a given phase status on a given phase.

FEC Shortcut:

None

A filter used to match elements that have a given phase status on a given phase.

FEC Shortcut:

None

A filter used to find elements contained in any primary design option of any design option set.

FEC Shortcut:

None

A filter used to find elements contained in any primary design option of any design option set.

FEC Shortcut:

None

A filter used to find elements that are structural family instances (typically columns, beams or braces) of the given structural usage.

FEC Shortcut:

None

A filter used to find elements that are structural family instances (typically columns, beams or braces) of the given structural usage.

FEC Shortcut:

None

A filter used to match families that have the given structural material type.

FEC Shortcut:

None

A filter used to match families that have the given structural material type.

FEC Shortcut:

None

A filter used to match family instances that have the given structural material type.

FEC Shortcut:

None

A filter used to match family instances that have the given structural material type.

FEC Shortcut:

None

A filter used to match walls that have the given structural wall usage.

FEC Shortcut:

None

A filter used to match walls that have the given structural wall usage.

FEC Shortcut:

None

A filter that passes elements that are selectable in the given view.

FEC Shortcut:

None

A filter that passes elements that are selectable in the given view.

FEC Shortcut:

None

Get Areas or Area Tags

FEC Shortcut:

None

Get Areas or Area Tags

FEC Shortcut:

None

Get Rooms or Room Tags

FEC Shortcut:

None

Get Rooms or Room Tags

FEC Shortcut:

None

Get Spaces or Space Tags

FEC Shortcut:

None

Get Spaces or Space Tags

1️⃣CurveElementFilter
A filter used to pass curve elements which are of a specific type.

It is necessary to use the CurveElementFilter, and not an ElementIsCurveDrivenFilter because subclasses of CurveElement are not supported by that method.

This method takes an argument - CurveElementType enumeration.
It has the following options:

  • Invalid - An invalid curve element type.

  • ModelCurve - A model curve.

  • DetailCurve - A detail curve.

  • SymbolicCurve - A symbolic curve.

  • ReferenceLine - A reference line.

  • SpaceSeparation - A space separation curve.

  • RoomSeparation - An room separation curve.

  • AreaSeparation - An area separation curve.

  • CurveByPoints - A curve created by connecting a set of points.

  • RepeatingDetail - The profile of a repeating detail set.

  • Insulation - A detail curve representing insulation.

  • Cloud - A portion of a revision cloud.

  • AreaBasedLoadBoundary - An Area Based Load Boundary curve.

Here is a snippet to get only Room Separation Lines using this Filter:

# Create Filter for RoomSeparation Curves
filter     = CurveElementFilter(CurveElementType.RoomSeparation)
room_lines = FilteredElementCollector(doc).WherePasses(filter).ToElements()

#👀 Print Results
for line in room_lines:
    print('Type: {} | LineStyle: {}'.format(type(line), line.LineStyle.Name))

# This Filter Can Be inverted
inverted_filter = CurveElementFilter(CurveElementType.RoomSeparation, True) # inverted filter
2️⃣ElementLevelFilter

A filter used to match elements by their associated level.
Very easy to use as we only need ElementId of a Level.

Here is a snippet to get Rooms and Walls associated with a random level. Feel free to select specific level for your testing!

# Get Random Level
random_level = FilteredElementCollector(doc)\
                    .OfClass(Level)\
                    .FirstElement()

# Create LevelFilter
lvl_filter   = ElementLevelFilter(random_level.Id)

# Get Rooms on Level
rooms_on_lvl = FilteredElementCollector(doc)\
                    .OfCategory(BuiltInCategory.OST_Rooms)\
                    .WherePasses(lvl_filter)\
                    .ToElements()
# Get Walls on Level
walls_on_lvl = FilteredElementCollector(doc)\
                    .OfCategory(BuiltInCategory.OST_Walls)\
                    .WherePasses(lvl_filter)\
                    .ToElements()

#👀 Print Results
print('There are {} Rooms on Level: {}'.format(len(rooms_on_lvl),
                                               random_level.Name))

print('There are {} Walls on Level: {}'.format(len(walls_on_lvl),
                                               random_level.Name))
3️⃣FamilyInstanceFilter

A filter used to find elements that are family instances of the given family symbol.

Let's make an example where we will take all FamilySymbols from the project and count how many instances are placed in the project.

1️⃣ Get All FamilySymbols
2️⃣ Create FamilyInstanceFilter
3️⃣ Apply filter to the collector
👀 Print Results.

#1️⃣ Get All FamilySymbols (Types)
all_symbols = FilteredElementCollector(doc).OfClass(FamilySymbol)

for symbol in all_symbols:
    #2️⃣ Create a FamilyInstance filter with the FamilySymbol Id
    filter = FamilyInstanceFilter(doc, symbol.Id)

    #3️⃣ Apply the filter to the elements in the active doc
    family_instances = FilteredElementCollector(doc).WherePasses(filter).ToElements()

    #👀 Print Results
    family_name = symbol.Family.Name
    symbol_name = Element.Name.GetValue(symbol)
    print("Family: {} - Type '{}' has {} instances in the project.".format(family_name,
                                                                           symbol_name,
                                                                            len(family_instances)))
4️⃣ElementParameterFilter (see Lesson 07.05)

A filter used to match elements by one or more parameter filter rules.

This filter can be really useful, as we can check Parameter values. There are multiple steps in creating this filter, because we need to define:

  • Parameter

  • Evaluator

  • RuleValue

  • Tollerance / CaseSensetivity

And while these are the same steps as creating a View Filter, it might be overwhelming first time you do it.

So there will be a whole lesson about this filter in-depth, so you can understand all the steps necessary to create these filters!

👇 Meanwhile, I will provide here a code snippet on how it can be used:

app = __revit__.Application

#1️⃣ Parameter
p_fam_id = ElementId(BuiltInParameter.SYMBOL_FAMILY_NAME_PARAM)
f_param  = ParameterValueProvider(p_fam_id)

#2️⃣ Evaluator
evaluator = FilterStringContains()

#3️⃣ Value
value = 'FE TUER'

#4️⃣ Rule
rvt_year = int(app.VersionNumber)
if rvt_year >= 2023:
    f_rule = FilterStringRule(f_param, evaluator, value)
else:
    f_rule = FilterStringRule(f_param, evaluator, value, False)


# #5️⃣ Filter
filter_fam_name = ElementParameterFilter(f_rule)

#6️⃣ Apply Filter to FEC
element_ids = FilteredElementCollector(doc)\
                .WherePasses(filter_fam_name)\
                .WhereElementIsNotElementType()\
                .ToElementIds()

#👉 Select Elements
uidoc.Selection.SetElementIds(element_ids)

The code is doing the following:

1️⃣ Select Parameter
2️⃣ Select Evaluator (Contains, Equal, Greater…)
3️⃣ Rule Value
4️⃣ Create Rule
5️⃣ Create FIlter
6️⃣ Apply Filter to collector
👉 Set Selection in Revit to visually see collector's elements


💡 NB! There are different classes for Rules depending on parameter's StorageType!

5️⃣ElementIntersectsElementFilter (see Lesson 07.06 for more)

A filter to find elements that intersect the solid geometry of a given element.

💪 This is an amazing filter and it's very easy to use!

We need to select an element and then provide it to create this filter. And it will find all intersecting elements.

💡I Highly recommend you to try it out, it has a lot of potential!

Here is a code snippet:

from Autodesk.Revit.UI.Selection import ObjectType

#👉 Choose Element
ref  = uidoc.Selection.PickObject(ObjectType.Element)
elem = doc.GetElement(ref)

#🔽 Create a ElementIntersectsElementFilter
filter = ElementIntersectsElementFilter(elem)

#✅ Get Intersecting Elements
inter_el_ids = FilteredElementCollector(doc)\
                                .WherePasses(filter)\
                                .ToElementIds()

#👀 Set Revit UI Selection
uidoc.Selection.SetElementIds(inter_el_ids)

When you use this filter, you might see this message (I got it with Rooms):

⚠️ 'The category of the element is not supported for element intersection filters.'

So in this case we would need to use the next filter, where we should use Geometry instead of an Element.

6️⃣ElementIntersectsSolidFilter (see Lesson 07.06 for more)

A filter to find elements that intersect the given solid geometry.

This filter is similar to the previous one, but we use the Geometry instead of Elements to look for intersections.

I would recommend sticking to ElementIntersectsElementFilter when possible, but sometimes you might want to work with geometry instead.

So here is an example on how to use, This snippet will:

  • Pick and Element

  • Ensure it's FilledRegion Selected

  • Create Solid from FilledRegion

  • Create ElementIntersectsSolidFilter

  • Apply Filter to Collector

  • Set Selection to elements in the collector

from Autodesk.Revit.UI.Selection import ObjectType

#👉 Choose Element
ref  = uidoc.Selection.PickObject(ObjectType.Element)
elem = doc.GetElement(ref)

#✅ Ensure FilledRegion Selected
if type(elem) != FilledRegion:
    import sys
    sys.exit()
    
# Create Solid Geometry from Region
region     = elem
boundaries = region.GetBoundaries()
solid      = GeometryCreationUtilities.CreateExtrusionGeometry(boundaries, XYZ(0,0,1), 1000) #10 - height

#🔽 Create a ElementIntersectsElementFilter
filter = ElementIntersectsSolidFilter(solid)

#✅ Get Intersecting Elements
inter_el_ids = FilteredElementCollector(doc)\
                                .WhereElementIsNotElementType()\
                                .WherePasses(filter)\
                                .ToElementIds()

#👀 Set Revit UI Selection
uidoc.Selection.SetElementIds(inter_el_ids)
7️⃣ElementPhaseStatusFilter

A filter used to match elements that have a given phase status on a given phase.

It takes ElementOnPhaseStatus Enumeration as an argument, and has the following options

  • None - Phase status is undefined (e.g., for annotations)

  • Past - Created and demolished before the given phase

  • Existing - Created in a previous phase, existing through the end of the given phase

  • Demolished - Created before the given phase, to be demolished on the given phase

  • New - Created on this phase (and not demolished)

  • Temporary - Created and demolished during this phase

  • Future - Created after this phase

# Select Phase and PhaseStatus
phases       = FilteredElementCollector(doc).OfClass(Phase).ToElements()
last_phase   = list(phases)[-1]
phase_status = ElementOnPhaseStatus.New

# Create Filter
filter_phase = ElementPhaseStatusFilter(last_phase.Id, phase_status)

# Apply Filter
elements = FilteredElementCollector(doc).WherePasses(filter_phase).ToElements()
print('There are {} New Elements on Phase: {}'.format(len(elements), 
													last_phase.Name))
8️⃣PrimaryDesignOptionMemberFilter

A filter used to find elements contained in any primary design option of any design option set.

#1️⃣ Create a PrimaryDesignOptionMember filter 
filter = PrimaryDesignOptionMemberFilter()

#2️⃣ Apply Filter to Get Walls from Primary DesignOption
walls_of_primary_opt = FilteredElementCollector(doc).OfClass(Wall).WherePasses(filter).ToElements()

#👀 Print Walls
print('There are {} Walls on PrimaryDesignOptions'.format(len(walls_of_primary_opt)))
9️⃣StructuralInstanceUsageFilter

Constructs a new instance of a filter to match structural family instances (typically columns, beams, or braces) of the given structural usage.

This Filter takes StructuralInstanceUsage Enumeration and it has the following options:

  • Undefined - indicates automatic

  • Wall - Structural usage is as wall.

  • Column - Structural usage is as column.

  • Girder - Structural usage is as girder.

  • Joist - Structural usage is as joist.

  • Purlin - Structural usage is as purlin.

  • Other - Structural usage is as "other".

  • Brace - Structural usage is as brace.

  • HorizontalBracing - Structural usage is as horizontal bracing.

  • KickerBracing - Structural usage is as kicker bracing.

  • Automatic - Structural usage is automatic.

  • TrussChord - Structural usage is as truss chord.

  • TrussWeb - Structural usage is as truss web.

💡 Also remember that this filter and enumeration are from Revit.DB.Structure !

from Autodesk.Revit.DB.Structure import StructuralInstanceUsageFilter, StructuralInstanceUsage

#🔽 Create a StructuralInstanceUsageFilter for beams
filter_str_wall = StructuralInstanceUsageFilter(StructuralInstanceUsage.Wall)
filter_str_col  = StructuralInstanceUsageFilter(StructuralInstanceUsage.Column)
filter_str_gir  = StructuralInstanceUsageFilter(StructuralInstanceUsage.Girder)

#✅ Apply the filter to the elements in the active document
elements = FilteredElementCollector(doc).WherePasses(filter_str_gir).ToElements()

#👀 Show Results
count = len(elements)
print("Number of Elements in the document: {}".format(count))
🔟FamilyStructuralMaterialTypeFilter

A filter used to match families that have the given structural material type.
It will get you families that have a built-in parameter Material for Model Behaviour.

This filter takes StructuralMaterialType Enumeration argument.
It has the following options to choose from:

  • Undefined - Structural material type is undefined.

  • Steel - Structural material type is steel.

  • Concrete - Structural material type is concrete.

  • Wood - Structural material type is wood.

  • Other - Structural material type is other.

  • PrecastConcrete - Structural material type is precast concrete.

  • Generic - Structural material type is generic.

  • Aluminum - Structural material type is aluminum.\

💡 Make sure you import these classes from DB.Structure!

#🔽 Import classes from DB.Structure
from Autodesk.Revit.DB.Structure import (FamilyStructuralMaterialTypeFilter, \
                                        StructuralMaterialType)

#1️⃣ Use FamilyStructuralMaterialType filter to find families whose material type is Wood
filter_wood     = FamilyStructuralMaterialTypeFilter(StructuralMaterialType.Wood)
filter_not_wood = FamilyStructuralMaterialTypeFilter(StructuralMaterialType.Wood, True)

#2️⃣ Apply the filter to the elements in the active doc
wood_families     = FilteredElementCollector(doc).WherePasses(filter_wood).ToElements()
not_wood_families = FilteredElementCollector(doc).WherePasses(filter_not_wood).ToElements()

#👀 Print Results
print(wood_families)
print(not_wood_families)

1️⃣1️⃣StructuralMaterialTypeFilter

A filter used to match family instances that have the given structural material type.

This filter takes StructuralMaterialType Enumeration as an argument.
And it has the following options:

  • Undefined - Structural material type is undefined.

  • Steel - Structural material type is steel.

  • Concrete - Structural material type is concrete.

  • Wood - Structural material type is wood.

  • Other - Structural material type is other.

  • PrecastConcrete - Structural material type is precast concrete.

  • Generic - Structural material type is generic.

  • Aluminum - Structural material type is aluminum.

💡 Also remember that this filter and enumeration are from Revit.DB.Structure !

from Autodesk.Revit.DB.Structure import StructuralMaterialType, StructuralMaterialTypeFilter

#🔽 Create a StructuralMaterialTypeFilter for beams
filter_concrete = StructuralMaterialTypeFilter(StructuralMaterialType.Concrete)
filter_wood     = StructuralMaterialTypeFilter(StructuralMaterialType.Wood)
filter_steel    = StructuralMaterialTypeFilter(StructuralMaterialType.Steel)

#✅ Apply the filter collector
concrete_elements = FilteredElementCollector(doc).WherePasses(filter_concrete).ToElements()

#👀 Show Results
count = len(concrete_elements)
print("Number of concrete elements in the document: {}".format(count))
1️⃣2️⃣StructuralWallUsageFilter

A filter used to match walls that have the given structural wall usage.

This filter need StructuralWallUsage Enumeration argument
And it has the following options:

  • NonBearing - Structural usage is non-bearing.

  • Bearing - Structural usage is bearing.

  • Shear - Structural usage is shear.

  • Combined - Structural usage is combined.

💡 Also remember that this filter and enumeration are from Revit.DB.Structure !

from Autodesk.Revit.DB.Structure import StructuralWallUsage, StructuralWallUsageFilter

#🔽 Create a StructuralWallUsageFilter 
bearing_wall_filter = StructuralWallUsageFilter(StructuralWallUsage.Bearing)

#✅ Apply the filter collector
bearing_walls = FilteredElementCollector(doc).WherePasses(bearing_wall_filter).ToElements()

#👀 Show Results
bearing_wall_count = len(bearing_walls)
print("Number of bearing walls in the document: {}".format(bearing_wall_count))
1️⃣3️⃣ SelectableInViewFilter ❌

A filter that passes elements that are selectable in the given view.

I don't know what's the point of this filter, because it gave me the same result as VisibleInViewFilter Quick filter or using 2nd constructor of FilteredElementCollector. Maybe there is some exception case, but I am not sure about it.

So I would recommend ignoring it and sticking to the constructor to get elements in a view.

elements_in_view = FilteredElementCollector(doc,active_view.Id).ToElements()
1️⃣4️⃣AreaFilter / AreaTagFilter

We can't get Area and AreaTag with OfClass method.

So there is a separate filters for that.

💡However, we can always us OfCategory to get Area or AreaTags.

# Apply filters
areas     = FilteredElementCollector(doc).WherePasses(AreaFilter()).ToElements()
area_tags = FilteredElementCollector(doc).WherePasses(AreaTagFilter()).ToElements()
1️⃣5️⃣RoomFilter / RoomTagFilter

We can't get Room and RoomTag with OfClass method.

So there is a separate filters for that.

💡However, we can always us OfCategory to get Rooms or RoomTags.

# Apply filters
rooms     = FilteredElementCollector(doc).WherePasses(RoomFilter()).ToElements()
room_tags = FilteredElementCollector(doc).WherePasses(RoomTagFilter()).ToElements()
1️⃣6️⃣SpaceFilter / SpaceTagFilter

We can't get Space and SpaceTag with OfClass method.

So there is a separate filters for that.

💡However, we can always us OfCategory to get Spaces or SpaceTags.

# Apply filters
spaces     = FilteredElementCollector(doc).WherePasses(SpaceFilter()).ToElements()
space_tags = FilteredElementCollector(doc).WherePasses(SpaceTagFilter()).ToElements()

Questions:

What if I haven't found filter I need?

What if I haven't found filter I need?

Discuss the lesson:

P.S. Sometimes this chat might experience connection issues.
Please be patient or join via Discord app so you can get the most out of this community and get access to even more chats.

P.S. Sometimes this chat might experience connection issues.
Please be patient or join via Discord app so you can get the most out of this community and get access to even more chats.

© 2023-2024 EF Learn Revit API

© 2023-2024 EF Learn Revit API

© 2023-2024 EF Learn Revit API