BoundingBox Tolerance
Overview
The BoundingBoxIntersectsFilter
is a powerful tool in the Revit API that allows you to filter elements based on their intersection with a specified bounding box. This guide will walk you through its usage, from basic applications to advanced techniques, including the use of tolerance and filter inversion.
Basic Concepts
What is a Bounding Box?
A bounding box is the smallest rectangular cuboid that completely encloses an element or a set of elements in 3D space. In Revit, it's represented by two XYZ points: the minimum and maximum corners of the box.
What is BoundingBoxIntersectsFilter?
BoundingBoxIntersectsFilter
is a spatial filter that selects elements whose bounding boxes intersect with a specified outline (another bounding box). This filter is particularly useful for selecting elements within a certain region of your model.
Basic Usage
Creating a Simple Filter
To create a basic BoundingBoxIntersectsFilter
, you need to define an outline (bounding box) and then apply the filter to a FilteredElementCollector
.
# Import necessary modules
from Autodesk.Revit.DB import *
# Define the outline (bounding box)
min_point = XYZ(0, 0, 0)
max_point = XYZ(10, 10, 10)
outline = Outline(min_point, max_point)
# Create the filter
filter = BoundingBoxIntersectsFilter(outline)
# Apply the filter to collect elements
elements = FilteredElementCollector(doc, doc.ActiveView.Id).WherePasses(filter).ToElements()
# Print the number of elements found
print(f"Number of elements intersecting the bounding box: {len(elements)}")
This code snippet creates a bounding box from (0,0,0) to (10,10,10), then finds all elements in the active view that intersect with this box.
Advanced Usage
Using Tolerance
Tolerance allows for a more flexible intersection check. It's particularly useful when dealing with imprecise modeling or when you want to include elements that are very close to, but not strictly intersecting, the bounding box.
# Define tolerance (in the document's units, e.g., feet)
tolerance = 0.1
# Create the filter with tolerance
filter = BoundingBoxIntersectsFilter(outline, tolerance, False)
# Apply the filter
elements = FilteredElementCollector(doc, doc.ActiveView.Id).WherePasses(filter).ToElements()
print(f"Number of elements intersecting the bounding box (with {tolerance} tolerance): {len(elements)}")
In this example, elements within 0.1 feet of the bounding box will be included in the results.
Inverting the Filter
Sometimes, you might want to find elements that do NOT intersect the bounding box. This is where the invert parameter comes in handy.
# Create an inverted filter
inverted_filter = BoundingBoxIntersectsFilter(outline, tolerance, True)
# Apply the inverted filter
non_intersecting_elements = FilteredElementCollector(doc, doc.ActiveView.Id).WherePasses(inverted_filter).ToElements()
print(f"Number of elements NOT intersecting the bounding box: {len(non_intersecting_elements)}")
This code finds all elements that do not intersect (or come within the tolerance of) the specified bounding box.
Practical Examples
Example 1: Finding Columns in a Specific Area
Let's say you want to find all columns within a certain area of your building:
# Define the area of interest
min_point = XYZ(0, 0, 0)
max_point = XYZ(50, 30, 100) # Assuming a 50x30 feet area, 100 feet high
outline = Outline(min_point, max_point)
# Create the filter
filter = BoundingBoxIntersectsFilter(outline)
# Find columns
columns = FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Columns).WherePasses(filter).ToElements()
print(f"Number of columns in the specified area: {len(columns)}")
Example 2: Excluding Small Elements with Dynamic Tolerance
Sometimes, you might want to exclude very small elements from your selection. Here's how you can do that using a dynamic tolerance:
def get_element_size(element):
bbox = element.get_BoundingBox(None)
if bbox:
diagonal = bbox.Max.DistanceTo(bbox.Min)
return diagonal
return 0
# Define the outline
outline = Outline(XYZ(0, 0, 0), XYZ(100, 100, 100))
# Collect all elements
all_elements = FilteredElementCollector(doc).WhereElementIsNotElementType().ToElements()
# Filter elements based on dynamic tolerance
result_elements = []
for elem in all_elements:
size = get_element_size(elem)
tolerance = size * 0.1 # 10% of element size
filter = BoundingBoxIntersectsFilter(outline, tolerance, False)
if filter.PassesFilter(doc, elem.Id):
result_elements.append(elem)
print(f"Number of elements intersecting (with dynamic tolerance): {len(result_elements)}")
This script calculates a tolerance for each element based on its size, effectively excluding very small elements that might technically intersect but are likely not significant for the analysis.
Best Practices and Tips
-
Performance:
BoundingBoxIntersectsFilter
is generally fast, but for very large models, consider narrowing your initial collection (e.g., by category) before applying the filter. -
Tolerance Units: Always be aware of your document's units when setting tolerance. A tolerance of 1 means different things in a document set to feet versus one set to millimeters.
-
Combining Filters: You can combine
BoundingBoxIntersectsFilter
with other filters usingLogicalAndFilter
orLogicalOrFilter
for more complex queries. -
Visualization: Consider creating temporary geometry to visualize your bounding box in Revit, especially when debugging.
Conclusion
The BoundingBoxIntersectsFilter
is a versatile tool in the Revit API toolkit. By mastering its use, including the application of tolerance and filter inversion, you can create powerful and precise element selection logic in your Revit add-ins and scripts. Remember to always consider the specific needs of your project and the performance implications when working with large models.
Exercise Project
To solidify your understanding, try creating a Revit add-in that does the following:
- Allows the user to draw a rectangle in a view to define a bounding box.
- Uses
BoundingBoxIntersectsFilter
to find all elements intersecting this box. - Implements a slider for adjusting tolerance.
- Provides an option to invert the filter.
- Highlights the selected elements in the view.
This project will give you hands-on experience with all aspects of BoundingBoxIntersectsFilter
and help you understand its practical applications in a real-world scenario.