Retrieve Structural Elements

I recently discussed the retrieval of all Revit

MEP elements and their connectors
.
Here is a similar question on retrieving structural elements:

Question: How can I get all the structural elements like structural walls, slabs, columns, and beams from the model?
I have a problem with the columns and beams because they are family instances and I cannot just check only their type.
I currently have to go through all the family instances and check whether they are a column or beam to be modified in my model.

Answer: Yes, certainly you can efficiently and directly retrieve all structural elements from a Revit model database.
The key to doing so is to use the filtered element collectors.
All you need to do is identify certain criteria by which to identify all your elements and encode these into filters to apply to the collector.

One approach to achieve this is described for the

retrieval of MEP elements
,
which shows how to set up a combined filtered element collector which restricts the categories of the family instances.

In that solution, some elements such as ducts and pipes that can be directly identified by their System.Type.

Others such as equipment and fittings are represented by family instances and can be further identified by their category. For instance, for the MEP elements, we specified both the System.Type FamilyInstance as well as categories such as duct fitting, duct terminal, and pipe fitting.

To set up a similar filter for your structural elements, you will have to analyse your model to determine exactly which categories your columns and beams have.

Here is an example to retrieve certain structural elements that I make use of for the RST link application:


FilteredElementCollector GetStructuralElements(
  Document doc )
{
  // what categories of family instances
  // are we interested in?
 
  BuiltInCategory[] bics = new BuiltInCategory[] {
    BuiltInCategory.OST_StructuralColumns,
    BuiltInCategory.OST_StructuralFraming,
    BuiltInCategory.OST_StructuralFoundation
  };
 
  IList<ElementFilter> a
    = new List<ElementFilter>( bics.Count() );
 
  foreach( BuiltInCategory bic in bics )
  {
    a.Add( new ElementCategoryFilter( bic ) );
  }
 
  LogicalOrFilter categoryFilter
    = new LogicalOrFilter( a );
 
  LogicalAndFilter familyInstanceFilter
    = new LogicalAndFilter( categoryFilter,
      new ElementClassFilter(
        typeof( FamilyInstance ) ) );
 
  IList<ElementFilter> b
    = new List<ElementFilter>( 6 );
 
  b.Add( new ElementClassFilter(
    typeof( Wall ) ) );
 
  b.Add( new ElementClassFilter(
    typeof( Floor ) ) );
 
  b.Add( new ElementClassFilter(
    typeof( ContFooting ) ) );
 
  b.Add( new ElementClassFilter(
    typeof( PointLoad ) ) );
 
  b.Add( new ElementClassFilter(
    typeof( LineLoad ) ) );
 
  b.Add( new ElementClassFilter(
    typeof( AreaLoad ) ) );
 
  b.Add( familyInstanceFilter );
 
  LogicalOrFilter classFilter
    = new LogicalOrFilter( b );
 
  FilteredElementCollector collector
    = new FilteredElementCollector( doc );
 
  collector.WherePasses( classFilter );
 
  return collector;
}

You will have to analyse your model and see whether this filtering really suits your needs and whether all elements you are interested in are covered.

In addition to the explicit filtering demonstrated here, which gives you full and detailed control over what exactly is retrieved, the StructuralInstanceUsageFilter might fit your needs more exactly with less effort.
You might also find the StructuralMaterialTypeFilter useful.
In any case, you will have to test them in your specific models.

Please refer to the

MEP element retrieval
for
links to further discussions and examples of filtered element collectors.


Comments

6 responses to “Retrieve Structural Elements”

  1. Hi Jeremy,
    I am trying to Add Railing and Ramp instances to the ElementFilter, like:
    b.Add(new ElementClassFilter(typeof(Railing)));
    b.Add(new ElementClassFilter(typeof(Ramp )));
    b.Add(new ElementClassFilter(typeof(Stair)));
    However, that does not work. I studied the project with DB Lookup. It seems that I need an Element or something to reach these objects. Or do I have to solve it in a different way?
    Greetings, Renzo

  2. Dear Renzo,
    What is the problem that you run into, then?
    Do you get an exception saying “Input type is of an element type that exists in the API, but not in Revit’s native object model”?
    Are the classes you list possibly so-called non-native classes?
    We discussed that issue several times in the past:
    http://thebuildingcoder.typepad.com/blog/2010/08/filtering-for-a-nonnative-class.html
    Even the Revit SDK sample developers ran into it:
    http://thebuildingcoder.typepad.com/blog/2010/10/measurepanelarea-update.html
    I am not sure that that is what you mean, though.
    Cheers, Jeremy.

  3. Hi Jeremy,
    I was using your example…When I tried to add these objecttypes (Railing, Ramp, Stair) they are not recognized by the API… So I have to create a workaround for that…
    Now, this works:
    FilteredElementCollector collActive3 = new FilteredElementCollector(doc);
    FilteredElementCollector coll4 = new FilteredElementCollector(doc);
    collActive3.OfCategory(BuiltInCategory.OST_StairsRailing );
    coll4.OfCategory(BuiltInCategory.OST_Ramps);
    collActive3.UnionWith(coll4);
    collActive3.WhereElementIsNotElementType() ; //takes care to select only instances!!!
    Greetins, Renzo

  4. Dear Renzo,
    Congratulations on solving your issue. Actually, you can probably achieve the same thing a little bit simpler and more efficiently by using a logical Boolean OR filter instead of instantiating four separate collectors and using UnionWith.
    For instance, have a look at the method GetStructuralElements in
    http://thebuildingcoder.typepad.com/blog/2010/07/retrieve-structural-elements.html
    Or look at the even more extreme example to retrieve MEP elements:
    http://thebuildingcoder.typepad.com/blog/2010/06/retrieve-mep-elements-and-connectors.html
    Cheers, Jeremy.

  5. Hi Jeremy,
    I will share my solution. Finally, I got it to work.
    I had some difficulties understanding the filter mechanism.
    In this way I select all instances of the Categories I want…
    Thanks for your help, Renzo
    === === ===
    FilteredElementCollector collector = new FilteredElementCollector(doc);
    IList elFilter = new List(bics.Length);
    foreach (BuiltInCategory bic in bics)
    {
    elFilter.Add(new ElementCategoryFilter(bic));
    }
    LogicalOrFilter logOrFilter = new LogicalOrFilter(elFilter);
    collector.WherePasses(logOrFilter);
    collector.WhereElementIsNotElementType(); //takes care to select only instances!!!

  6. Dear Renzo,
    Looks great now! Thank you!
    Cheers, Jeremy.

Leave a Reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading