Let's dive into efficiently retrieving visible elements in the active Revit view. You're right, VisibleInViewFilter
and WhereElementIsViewIndependent
alone aren't sufficient when crop regions or other visibility overrides are in play. They indicate potential visibility, not actual, rendered visibility within the current view's context. We need a more robust approach.
Here's a breakdown of the problem and a practical solution, combining best practices and leveraging the Revit API:
The Challenge:
The Revit API doesn't offer a single, direct method to get precisely what's visually rendered in the active view, especially considering crop regions, temporary view templates, and element overrides. VisibleInViewFilter
only checks if an element could be visible in some view, not the current one with its specific settings. WhereElementIsViewIndependent
filters elements that are view-specific, but it doesn't filter based on visibility.
The Solution: Combining Filters and Bounding Box Intersections
The most reliable approach involves a combination of filtering and geometric checks. We'll use the view's crop box (or its equivalent if it's not rectangular) to define the visible region and then check if element bounding boxes intersect with this region. This approach is accurate and handles crop boxes effectively.
Explanation and Key Improvements:
-
Crop Box Retrieval: We retrieve the CropBox
of the active view. For non-rectangular crop regions, you'll need to get the CurveLoop
representing the crop boundary and use more advanced geometric intersection methods.
-
Efficient Element Collection: The FilteredElementCollector
with the activeView.Id
is crucial. This limits the initial collection to elements in the view, significantly improving performance compared to collecting all elements in the model. You can further refine this collector with additional filters (e.g., OfClass
, OfCategory
) to target specific element types for even better performance.
-
Bounding Box Intersection: The core logic uses Outline.Intersects
. This checks if the element's bounding box intersects with the view's crop box. This is a robust way to determine visibility within the cropped region.
-
Null Bounding Box Handling: The code now includes a check for elementBox != null
. Some elements (like annotation elements far from the view) might have null bounding boxes. Handling this prevents exceptions.
-
Example Usage: The provided Execute
method demonstrates how to use the GetVisibleElements
function within a Revit command.
Further Considerations:
-
Performance: For extremely large models, you might consider spatial partitioning techniques (e.g., using the SpatialElement
classes) to further optimize the intersection checks.
-
Non-Rectangular Crops: For complex crop shapes, you'll need to work with the CurveLoop
of the crop region and implement more sophisticated geometric intersection tests (e.g., using the XYZ.DistanceTo
method or other geometric utilities).
-
Temporary View Modes: Be aware that temporary view modes (like Reveal Hidden Elements) can affect visibility. You might need to adjust your logic based on the current view's temporary view mode if your add-in needs to handle these cases.
This approach provides a practical and reliable way to get truly visible elements in the active Revit view, addressing the limitations of simpler visibility filters. Remember to adapt the crop region handling for non-rectangular shapes if needed. Let me know if you have any other questions!
I hope that this explanation can prove useful in your further research. Please let us know how it goes. Thank you and good luck!