Streamlining your Filters

by Guy Robinson 5. December 2008 14:28

As I’ve said before on AUGI, if you aren’t using Filters in your command development then you should be with Revit 2009. However as you start to use them in more complicated scenarios your code can get a little unwieldy.

In this post I’m going to show you some methods to tidy up your code a little. In the following example we’re going to get all doors where the sill is less than 0.0 above the floor level and all windows where the sill is less than 760mm above the floor level. Here is the standard filter approach.

   1: Autodesk.Revit.Application rvtApp = commandData.Application;
   2: //Doors
   3: Filter doors = rvtApp.Create.Filter.NewCategoryFilter(BuiltInCategory.OST_Doors);
   4: // get all instances with sill less than zero
   5: Filter sillLTZeroFilters = rvtApp.Create.Filter.NewParameterFilter(BuiltInParameter.INSTANCE_SILL_HEIGHT_PARAM,CriteriaFilterType.LessThan, 0.0);
   6: Filter doorSillsFilter = rvtApp.Create.Filter.NewLogicAndFilter(doors, sillLTZeroFilters);
   7: //Windows
   8: Filter windows = rvtApp.Create.Filter.NewCategoryFilter(BuiltInCategory.OST_Windows);
   9: Filter window760Filter = rvtApp.Create.Filter.NewParameterFilter(BuiltInParameter.INSTANCE_SILL_HEIGHT_PARAM, CriteriaFilterType.LessThan, 760.0);
  10: Filter windowSillsFilter = rvtApp.Create.Filter.NewLogicAndFilter(windows, window760Filter);
  11: // finished filter
  12: Filter completeFilter = rvtApp.Create.Filter.NewLogicOrFilter(windowSillsFilter, doorSillsFilter);
  13: ElementIterator itor = rvtApp.ActiveDocument.get_Elements(completeFilter);

Here’s 3 techniques for  simplifying your code:

1.. Class libraries

You can combine standard filter functionality in your own libraries. For example I’ve defined one that &&’s a Category Filter with a Parameter Filter which allows the code to be simplified to:

   1: Filter doorSillsFilter = myfilters.CategoryParameterFilter(BuiltInCategory.OST_Doors,
   2:                                                            BuiltInParameter.INSTANCE_SILL_HEIGHT_PARAM,
   3:                                                            CriteriaFilterType.LessThan, 0.0);
   4: //Windows
   5: Filter windowSillsFilter = myfilters.CategoryParameterFilter(BuiltInCategory.OST_Windows,
   6:                                                             BuiltInParameter.INSTANCE_SILL_HEIGHT_PARAM,
   7:                                                             CriteriaFilterType.LessThan, 760.0);
   8: // finished filter
   9: Filter completeFilter = rvtApp.Create.Filter.NewLogicOrFilter(windowSillsFilter, doorSillsFilter);
  10: ElementIterator itor = rvtApp.ActiveDocument.get_Elements(completeFilter);

2.. Enumerating Filters

Although not useful in this example ,you can use an IEnumerable method to build filters. Useful for building Filters that combine a large number of filters, for example:

   1: Filter allFilters = myfilters.BuildCategoryFilters(
   2:                     new BuiltInCategory[] { BuiltInCategory.OST_Doors,BuiltInCategory.OST_Windows });

3.. Filter Logic Operators

This one requires at a minimum .NET3.0, if you don’t use .NET3.0 I’d suggest .NET 3.5SP1. You need >.NET3.0  because it uses extension methods which allow you to tidy up logic filters. Allowing you to write the example code like this:

   1: Autodesk.Revit.Application rvtApp = commandData.Application;
   2: //Doors
   3: Filter doors = rvtApp.Create.Filter.NewCategoryFilter(BuiltInCategory.OST_Doors)
   4:                .And(rvtApp.Create.Filter.NewParameterFilter(BuiltInParameter.INSTANCE_SILL_HEIGHT_PARAM, CriteriaFilterType.LessThan, 0.0));
   5: //Windows
   6: Filter windows = rvtApp.Create.Filter.NewCategoryFilter(BuiltInCategory.OST_Windows)
   7:                  .And(rvtApp.Create.Filter.NewParameterFilter(BuiltInParameter.INSTANCE_SILL_HEIGHT_PARAM, CriteriaFilterType.LessThan, 760.0));
   8:  
   9: ElementIterator itor = rvtApp.ActiveDocument.get_Elements(doors.Or(windows));

If you’re wondering why I didn’t use Operator overloading, they can’t be implemented on static methods which excludes extension methods unfortunately. Would be cool being able to write  .getElements(doors && windows).

BTW, although the RevitAPI help suggests this is possible because Autodesk.Revit.Filter is an abstract class. You need to implement Autodesk.Revit.Filter.elementPassesFilter(ElemRecAccess**, ADocument*) .Which we’ll leave for now ;-)

You can find all the code and an example Revit project for these techniques here.

Comments are closed

About the Author

A .NET software Developer providing custom applications and commands for architecture firms exclusively working with Autodesk Revit and integration with any associated applications. All from a little place north of Whitianga, New Zealand.

Page List

Disclaimer

I'm self employed so the opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway☺

© Copyright2008

Creative Commons License
Blog content is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License.

With the following exception. All code snippets, application and libraries are licensed under a a Apache License Version 2.0

Autodesk Revit®

Autodesk: Revit is a product that is wholly owned by Autodesk. Any reference to Revit,Revit API, Revit Architecture, Revit MEP or Revit Structure on this site is made acknowledging this ownership. Refer to Autodesk's own web site and product pages for specific trademark and copyright information. Autodesk represents a great many products and every attempt will be made to respect their ownership whenever one of these other products is mentioned on this site.