Returning once again to freshen up a few of our favourite recurring topics:
A new version of RevitLookup is available.
RevitLookup release 2023.1.0 includes the following enhancements:
ElementId
was -1They are discussed in more depth in the enhancements discussion #124.
Thank you very much, Roman, Роман @Nice3point Карпович, for your great ideas and diligent maintenance work!
A short note from the Revit API discussion forum thread on filtering different built-in categories at the same time:
Question: Is it possible to filter different BuiltInCategories at same time?
Because I want to improve my code efficiency in my big Revit file, so I only want to filter once.
Or is there any other way to get instances of these built-in categories in a list?
bic_beam = DB.BuiltInCategory.OST_StructuralFraming bic_collumn = DB.BuiltInCategory.OST_StructuralColumns bic_beam_tag = DB.BuiltInCategory.OST_StructuralFramingTags bic_collumn_tag = DB.BuiltInCategory.OST_StructuralColumnTags
So far, I only know the basic collector and filtering for one BuiltInCategory:
collector = DB.FilteredElementCollector(doc, doc.Active.Id) beam_filter = DB.ElementCategoryFilter(DB.BuiltInCategory.OST_StructuralFraming) beam_elements = collector.WherePasses(beam_filter ).ToElementIds()
Answer: First, a comment on your second code snippet: it is always advisable to use the filter shortcuts.
In this case, use OfCategory
instead of ElementCategoryFilter
+ WherePasses
.
It is shorter, clearer, and guarantees that you are using a quick filter.
Second, the answer to your question is yes.
I think this is the one and only purpose of
the FilterCategoryRule
class.
Read the article on how to use FilterCategoryRule for more info.
It also mentions how you can easily achieve the same without using FilterCategoryRule, by using a Boolean OR combination filter of ElementCategoryFilter instances, showing how that approach can be used to:
For yet more info, please refer to The Building Coder topic group on filtering for elements.
Last but not least, you can also use
the ElementMulticategoryFilter
class,
a filter used to find elements whose category matches any of a given set of categories, e.g.:
cat_list = [BuiltInCategory.OST_Walls, BuiltInCategory.OST_Windows, BuiltInCategory.OST_Doors, BuiltInCategory.OST_Floors, BuiltInCategory.OST_Ceilings] types = List[BuiltInCategory](cat_list) multiCat = ElementMulticategoryFilter(types) Elements = FilteredElementCollector(doc).WherePasses(multiCat).WhereElementIsNotElementType().ToElements()
Response: Thank you! That is exactly what I need!
Two questions to clarify:
So, the two approaches OfCategory
and ElementCategoryFilter
+ WherePasses
both achieve the same goal.
In addition, both ways are quick filters.
However, using OfCategory
directly can be more readable and clearer.
Is that right?
I will compare using FilterCategoryRule
with ElemenetMulticategoryFilter
.
Answer: Yes, that is absolutely correct.
I prefer ElementMulticategoryFilter
myself, now I think about it.
It is clearer and more direct.
It did not exist when I originally implemented the samples
to retrieve MEP elements
and structural elements,
or I would have opted for that back then.
Mark de Vries of ICN Development shared
some important real-world considerations in the discussion
about how to get all the outermost walls in the model
that we edited and shared here four years ago in the article
on FilterRule
use and retrieving exterior walls:
This algorithm to create a room around the building and let it determine its boundary walls is the most reliable and fastest solution to this particular problem of finding the exterior walls of a building. It also works better with, e.g., Dutch drawing practice, where compound walls are split into individual walls for its layers, making approaches that rely on isExternal
properties or the count of bounded rooms unreliable at best.
There is however one caveat that is important to keep in mind. This is essentially a 2D approach to finding boundaries, as you are working with boundary lines, and not planes. This appears to be a fundamental limitation of the Revit API. This is not normally a problem for this particular algorithm, but it will become one if your model has vertically stacked walls within a single level. In that case, only one wall of that stack will be found, usually the one closest to the bottom of the temporary room.
There are of course workarounds to this: Determine the z-heights of each wall in the stack and create a separate room for each of those heights. This of course has to be done for every wall that falls into or crosses a particular z-height range that you are interested in, so the scan for finding all the z-heights that need to be checked separately can be time consuming for large designs.
I am guessing the BuildingEnvelopeAnalyzer
needs a cell size variable to solve this same problem (though they are more likely to internally use a horizontal section plane to find intersecting walls and determine the exterior walls from a much smaller set of candidates).
So, the room around the entire design is probably the best solution with the least requirements, but it will need some non-trivial modifications to be able to handle designs with stacked walls.
Thank you, Mark, for sharing your valuable knowledge and experience.
An unusual and beautiful two-and-a-half-hour full-length feature film with beautiful views on how to build Gmail-like UI with React Native at the Zen temple Koshoji is chockful of information and calming at the same time.