C# Revit二次开发基础/核心编程---元素过滤器

一、本节课程
C# Revit二次开发基础/核心编程---元素过滤器

二、本节要讲解的知识点

    元素Element过滤器的概念和使用

  • 具体内容

Revit API 提供了元素过滤器,用来遍历元素以及元素的ID。这些过滤器为各种不同的应用程序获取元素提供了更灵活更实用的接口。

(1)收集FilteredElementCollector

用来迭代以及过滤元素的主要类是收集器,有三种构造方式。

构造函数

描述

FilteredElementCollector(Document document)

一个文档构造,迭代会从文档的所有元素来进行

FilteredElementCollector(Document document,ICollection<ElementId> elementIds)

一个文档和ElementId集合来构造,迭代会从传入集合中进行

FilteredElementCollector(Document ElementId viewId)

一个文档和一个视图来构建,迭代从所有在传进来的视图中所见的元素中进行

FilteredElementCollector提供了一系列的方法,允许用户设置查询和过滤用户感兴趣的元素集:

  1. 通用方法WherePasses(),收集器中应用单一的ElementFilter,可以在结果中重复使用来增加不同的过滤器。
  2. 快捷方法,OfClass(),OfCategoryId(),OwnedByView()
  3. 并集、交集等的运算方法UnionWith(),IntersectWith()

例子:

public Result Execute(ExternalCommandData revit, ref string message, ElementSet elements)

        {

            try

            {

                Document document = revit.Application.ActiveUIDocument.Document;

                //创建一个类别过滤器来过滤出所有的内建类型为OST_StackedWalls的元素

                ElementCategoryFilter wallsCategoryFilter = new ElementCategoryFilter(BuiltInCategory.OST_StackedWalls);

                FilteredElementCollector collector = new FilteredElementCollector(document);

                collector.OfClass(typeof(Wall)).WherePasses(wallsCategoryFilter);

                ICollection<ElementId> foundIds = collector.ToElementIds();

                string prompt = "The ids of the StackedWalls in the current document are:";

                foreach (ElementId id in foundIds)

                {

                    prompt += "\n\t" + id.IntegerValue;

                }

                TaskDialog.Show("Revit", prompt);

            }

            catch (Exception e)

            {

                message = e.Message;

                return Autodesk.Revit.UI.Result.Failed;

            }

            return Autodesk.Revit.UI.Result.Succeeded;

        }

收集器设置完必须的过滤器之后,就可以获取符合条件的元素了,有几种方式:

  1. 获取元素的ID或者元素本身的迭代器。
  2. 获取符合过滤器条件的元素ID或者元素本身集合
  3. 获取符合条件的第一个元素的ID或者元素本身。如果只需要一个元素的话这种方式很有用,因为不需要再去遍历了。

FilteredElementCollector支持foreach语法:

Document document = revit.Application.ActiveUIDocument.Document;

                FilteredElementCollector collector = new FilteredElementCollector(document);

                collector.WherePasses(new ElementCategoryFilter(BuiltInCategory.OST_Levels))

                    .WhereElementIsNotElementType();

                foreach(Level level in collector)//收集器直接支持c# foreach语法。

                {

                    TaskDialog.Show("Level Name", level.Name);

                }

FilteredElementCollector支持LINQ:FilteredElementCollector实现了IEnumerable接口,所以支持LINQ查询语句和查询

Document document = revit.Application.ActiveUIDocument.Document;

                FilteredElementCollector collector = new FilteredElementCollector(document);

                collector.WherePasses(new ElementCategoryFilter(BuiltInCategory.OST_Levels));

                //LINQ查询:找到名字为“Level 1”的标高

                var levelElements = from element in collector

                                    where element.Name == "Level 1"

                                    select element;

                List<Autodesk.Revit.DB.Element> levels = levelElements.ToList<Autodesk.Revit.DB.Element>();

                ElementId level1Id = levels[0].Id;

2)元素过滤器的层次

快速过滤器只检查记录的元素并防止元素在内存中展开,可以提高效率减少内存开销。

慢速过滤器先在内存中获取和展开元素,再进行查询,在效率上比较低,推荐的方法是慢速过滤器和快速过滤器结合起来,会减少展开元素的数量。

逻辑过滤器由两个或者两个以上的过滤器逻辑组成的过滤器。

3)内建的过滤器

为了方便使用,Revit提供了一些内置(预制)的过滤器,有些提供了FileterElementCollector的快捷方法:

内建过滤器

类型

符合条件值

快捷方法

LogicalAndFilter

逻辑

必须符合两个或者两个以上的过滤器元素

WherePasses():添加另外过滤器。

IntersectWith():合并两个独立的过滤器的集合

LogicalOrFilter

逻辑

必须符合两个或者两个以上的过滤器其中一个过滤器的元素

UnionWith():合并两个独立的过滤器集合。

ElementCategoryFilter

符合传入类别ID的元素

OfCategoryId()

ElementMulticategoryFilter

符合任意一个传入类别ID的元素

ElementClassFilter

符合传入类的元素

OfClass()

ElementMulticlassFilter

符合任意一个传入类的元素

ElementIsElementTypeFilter

是元素类型的元素

WhereElementIsElementType(),

WhereElementIsNotElementType()

ElementOwnerViewFilter

是视图相关的元素

OwnedByView(),

WhereEmlementIsViewIndependent()

ElementDesignOptionFilter

符合在特定设定选项的元素

ContainedInDesignOption()

ElementIsCurveDrivenFilter

是由线驱动的元素

WhereElementIsCurveDriven()

ElementStructuralTypeFilter

符合给定结构驱动的元素

ElementWorksetFilter

符合在给定工作集里面的元素

FamilySombolFilter

特定的族类型

ExclusionFilter

除传入过滤器的元素外的所有元素

Excluding()

BoundingBoxIntersectsFilter

其边界盒与给定的轮廓(outline)相交的元素

BoundingBoxIsInsideFilter

其边界盒在给定的轮廓(outline)内的元素

BoundingBoxContainsPointFilter

其边界盒包含了给定点的元素

FamilyInstanceFilter

特定族类型的实例

ElementLevelFilter

和指定标高(level)联系的元素

ElementFhaseStatusFilter

和指定阶段状态联系的元素

ElementParamterFilter

符合一个或多个参数集的元素

ElementIntersectsElementFilter

使用冲突检测来查找符合与传入的元素在几何上相交的元素

ElementIntersectsSolidFilter

使用接口检测来查找符合与传入的实体在几何Solid上相交的元素

PrimaryDesignOptionMemberFilter

主选项所拥有的元素

StructuralInstanceUsageFilter

属于传入的结构实例用法StructuralInstanceUsage的族实例

StructuralWallUsageFilter

属于传入的结构墙用法StructrualWallUsage的墙

StructuralMaterialTypeFilter

属于传入的结构材料类型的族实例

RoomFilter

房间元素

SpaceFilter

空间元素

AreaFilter

面积元素

RoomTagFilter

房间标签元素

SpaceTagFilter

空间标签元素

AreaTagFilter

面积标签元素

CurveElementFilter

属于或者不属于inverted传入线类型的线型元素

4)快速过滤器ElementQuickFilter

1) ElementCategoryFilter

2)  ElementClassFilter

3)  ElementIsElementTypeFilter

4)  FamilySymbolFilter

5)  ExclusionFilter

5)慢速过滤器ElementSlowFilter

1) ElementLevelFilter

2) ElementParameterFilter

3) CurveElementFilter

6)逻辑过滤器ElementLogicalFilter

1) LogicalOrFilter

2) LogicalAndFilter

//============代码片段3-37:元素过滤器============

/// <summary>

/// 使用ElementCategoryFilter过滤元素

/// </summary>

void TestElementCategoryFilter(Document doc)

{

   // 找到所有属于墙类别的元素:墙实例和墙类型都将会被过滤出来

   FilteredElementCollector collector = new FilteredElementCollector(doc);

   ElementCategoryFilter filter = new ElementCategoryFilter(BuiltInCategory.OST_Walls);

   ICollection<Element> founds = collector.WherePasses(filter).ToElements();

   foreach (Element elem in founds)

   {

     Trace.WriteLine(String.Format("  Element id: {0}, type: {1}", elem.Id.IntegerValue, elem.GetType().Name));

   }

}

 

//============代码片段3-38:元素过滤器============

/// <summary>

/// 使用ElementClassFilter过滤元素

/// </summary>

void TestElementClassFilter(Document doc)

{

  // 找到所有属于FamilySymbol的元素:元素的子类也将被过滤出来

  FilteredElementCollector collector = new FilteredElementCollector(doc);

  ElementClassFilter filter = new ElementClassFilter(typeof(FamilySymbol));

  ICollection<ElementId> founds = collector.WherePasses(filter).ToElementIds();

  Trace.WriteLine(String.Format("  Found {0} FamilySymbols.", founds.Count));

}

 

//============代码片段3-39:元素过滤器============

/// <summary>

/// 使用ElementIsElementTypeFilter过滤元素

/// </summary>

void TestElementIsElementTypeFilter(Document doc)

{

  // 找到所有属于ElementType的元素

  FilteredElementCollector collector = new FilteredElementCollector(doc);

  ElementIsElementTypeFilter filter = new ElementIsElementTypeFilter();

  ICollection<ElementId> founds = collector.WherePasses(filter).ToElementIds();

    Trace.WriteLine(String.Format("  Found {0} ElementTypes.", founds.Count));

}

 

//============代码片段3-40:元素过滤器============

/// <summary>

/// 使用FamilySymbolFilter过滤元素

/// </summary>

void TestFamilySymbolFilter(Document doc)

{

  // 找到当前文档中族实例所对应的族类型

  FilteredElementCollector collector = new FilteredElementCollector(doc);

  ICollection<ElementId> famIds = collector.OfClass(typeof(Family)).ToElementIds();

  foreach (ElementId famId in famIds)

  {

    collector = new FilteredElementCollector(doc);

    FamilySymbolFilter filter = new FamilySymbolFilter(famId);

    int count = collector.WherePasses(filter).ToElementIds().Count;

    Trace.WriteLine(String.Format("  {0} FamilySybmols belong to Family {1}.", count, famId.IntegerValue));

  }

}

 

//============代码片段3-41:元素过滤器============

/// <summary>

/// 使用ExclusionFilter过滤元素

/// </summary>

void TestExclusionFilter(Document doc)

{

  // 找到所有除族类型FamilySymbol外的元素类型ElementType

  FilteredElementCollector collector = new FilteredElementCollector(doc);

  ICollection<ElementId> excludes = collector.OfClass(typeof(FamilySymbol)).ToElementIds();

    

  // 创建一个排除族类型FamilySymbol的过滤器

  ExclusionFilter filter = new ExclusionFilter(excludes);

  ICollection<ElementId> founds = collector.WhereElementIsElementType().WherePasses(filter).ToElementIds();

  Trace.WriteLine(String.Format("  Found {0} ElementTypes which are not FamilySybmols", founds.Count));

}

 

//============代码片段3-42:元素过滤器============

/// <summary>

/// 使用ElementLevelFilter过滤元素

/// </summary>

void TestElementLevelFilter(Document doc)

{

  // 找到当前所有标高对应的所有元素

  FilteredElementCollector collector = new FilteredElementCollector(doc);

  ICollection<ElementId> levelIds = collector.OfClass(typeof(Level)).ToElementIds();

  foreach (ElementId levelId in levelIds)

  {

    collector = new FilteredElementCollector(doc);

    ElementLevelFilter filter = new ElementLevelFilter(levelId);

    ICollection<ElementId> founds = collector.WherePasses(filter).ToElementIds();

    Trace.WriteLine(String.Format("  {0} Elements are associated to Level {1}.", founds.Count, levelId.IntegerValue));

  }

}

 

//============代码片段3-43:元素过滤器============

/// <summary>

/// 使用ElementParameterFilter过滤元素

/// </summary>

void TestElementParameterFilter(Document doc)

{

  // 找到所有id大于99的元素

  BuiltInParameter testParam = BuiltInParameter.ID_PARAM;

  // 提供者

  ParameterValueProvider pvp = new ParameterValueProvider(new ElementId((int)testParam));

  // 评估者

  FilterNumericRuleEvaluator fnrv = new FilterNumericGreater();

  // 规则值   

  ElementId ruleValId = new ElementId(99); // Id 大于 99

  // 创建规则过滤器及对应的元素参数过滤器

  FilterRule fRule = new FilterElementIdRule(pvp, fnrv, ruleValId);

  ElementParameterFilter filter = new ElementParameterFilter(fRule);

  FilteredElementCollector collector = new FilteredElementCollector(doc);

  ICollection<Element> founds = collector.WherePasses(filter).ToElements();

  foreach (Element elem in founds)

  {

    Trace.WriteLine(String.Format("  Element id: {0}", elem.Id.IntegerValue));

  }

}

 

//============代码片段3-44:元素过滤器============

/// <summary>

/// 使用FamilyInstanceFilter过滤元素

/// </summary>

void TestFamilyInstanceFilter(Document doc)

{

  // 找到名字"W10X49"的族类型

  FilteredElementCollector collector = new FilteredElementCollector(Document);

  collector = collector.OfClass(typeof(FamilySymbol));

  var query = from element in collector

      where element.Name == "W10X49"

      select element; // Linq 查询

  List<Autodesk.Revit.DB.Element> famSyms = query.ToList<Autodesk.Revit.DB.Element>();

  ElementId symbolId = famSyms[0].Id;

    

  // 创建过滤器并找到该族类型对应的所有族实例

  collector = new FilteredElementCollector(doc);

  FamilyInstanceFilter filter = new FamilyInstanceFilter(doc, symbolId);

  ICollection<Element> founds = collector.WherePasses(filter).ToElements();

  foreach (FamilyInstance inst in founds)

  {

    Trace.WriteLine(String.Format("  FamilyInstance {0}, FamilySybmol Id {1}, Name: {2}",inst.Id.IntegerValue, inst.Symbol.Id.IntegerValue, inst.Symbol.Name));

  }

}

 

//============代码片段3-45:元素过滤器============

      ///  /// <summary>

/// 使用CurveElementFilter 过滤元素

/// </summary>

void TestCurveElementFilter(Document doc)

{

    // 找到所有线元素类型对应的线型元素

    Array stTypes = Enum.GetValues(typeof(CurveElementType));

    foreach (CurveElementType tstType in stTypes)

    {

        if (tstType == CurveElementType.Invalid) continue;

        FilteredElementCollector collector = new FilteredElementCollector(Document);

        CurveElementFilter filter = new CurveElementFilter(tstType);

        int foundNum = collector.WherePasses(filter).ToElementIds().Count;

        Trace.WriteLine(String.Format(" {0}: elements amount {1}", tstType.GetType().Name, foundNum));

    }

}

 

//============代码片段3-46:元素过滤器============

/// <summary>

/// 使用LogicalOrFilter过滤元素

/// </summary>

void TestLogicalOrFilter(Document doc)

{

  // 情形 1: 合并两个过滤器 ->

    // 找到所有属于墙类别或者属于标高类别的元素

  ElementCategoryFilter filterWall = new ElementCategoryFilter(BuiltInCategory.OST_Walls);

  ElementCategoryFilter filterLevel = new ElementCategoryFilter(BuiltInCategory.OST_Levels);

  LogicalOrFilter orFilter = new LogicalOrFilter(filterWall, filterLevel);

  FilteredElementCollector collector = new FilteredElementCollector(doc);

  ICollection<Element> founds = collector.WherePasses(orFilter).ToElements();

  foreach(Element elem in founds)

  {

    Trace.WriteLine(String.Format("  Element Id {0}, type {1}", elem.Id.IntegerValue, elem.GetType()));

  }

    

  // 情形 2: 合并两个过滤器集合 -> 找到所有属于传入类型的元素

  Type[] elemTypes = { typeof(Wall), typeof(Level), typeof(Floor), typeof(Rebar), typeof(MEPSystem)};

  List<ElementFilter> filterSet = new List<ElementFilter>();

  foreach (Type elemType in elemTypes)

  {

    ElementClassFilter filter = new ElementClassFilter(elemType);

    filterSet.Add(filter);

  }

  orFilter = new LogicalOrFilter(filterSet);

  collector = new FilteredElementCollector(doc);

  founds = collector.WherePasses(orFilter).ToElements();

  foreach (Element elem in founds)

  {

    Trace.WriteLine(String.Format("  Element Id {0}, type {1}", elem.Id.IntegerValue, elem.GetType().Name));

  }

}

 

//============代码片段3-47:元素过滤器============

/// <summary>

/// 使用LogicalAndFilter过滤器

/// </summary>

void TestLogicalAndFilter(Document doc)

{

  // 情形 1: 合并两个过滤器 -> 找到所有符合特定设计选项的墙

  ElementClassFilter wallFilter = new ElementClassFilter(typeof(Wall));

  FilteredElementCollector collector = new FilteredElementCollector(doc);

  ICollection<ElementId> designOptIds = collector.OfClass(typeof(DesignOption)).ToElementIds();

  foreach(ElementId curId in designOptIds)

  {

    ElementDesignOptionFilter designFilter = new ElementDesignOptionFilter(curId);

    LogicalAndFilter andFilter = new LogicalAndFilter(wallFilter, designFilter);

    collector = new FilteredElementCollector(doc);

    int wallCount = collector.WherePasses(andFilter).ToElementIds().Count;

    Trace.WriteLine(String.Format("  {0} Walls belong to DesignOption {1}.", wallCount, curId.IntegerValue));

  }

    

  // 情形 2: 找到所有符合特定设计选项并且其StructuralWallUsage 属于承重的墙

  foreach (ElementId curId in designOptIds)

  {

    // 构造逻辑与过滤器

    List<ElementFilter> filters = new List<ElementFilter>();

    filters.Add(wallFilter);

    filters.Add(new ElementDesignOptionFilter(curId));

    filters.Add(new StructuralWallUsageFilter(StructuralWallUsage.Bearing));

    LogicalAndFilter andFilter = new LogicalAndFilter(filters);

        

    // 应用该过滤器并遍历获取到的元素

    collector = new FilteredElementCollector(doc);

    int wallCount = collector.WherePasses(andFilter).ToElementIds().Count;

    Trace.WriteLine(String.Format("  {0} Bearing Walls belong to DesignOption {1}.", wallCount, curId.IntegerValue));

  }

}

 

//============代码片段3-48:元素过滤器============

  FilteredElementCollector collector = new FilteredElementCollector(document);

  // 找到所有符合某种特定设计选项的墙

  optionICollection<ElementId> walls =    collector.OfClass(typeof(Wall)).ContainedInDesignOption(myDesignOptionId).ToElementIds();

 

四、总结

1、收集器、元素过滤器的层次。

2、内建的元素过滤器。

3、常用的快速过滤器、慢速过滤器、逻辑过滤器的应用案例代码操练。

猜你喜欢

转载自blog.csdn.net/yunyouxy/article/details/82917838