Building Coder(Revit 二次开发) - 过滤非本地(Non-Native)类

Building Coder 链接:http://thebuildingcoder.typepad.com/blog/2010/08/filtering-for-a-nonnative-class.html

Revit 二次开发论坛链接:http://revit.5d6d.com/viewthread.php?tid=1304&extra=

元素过滤(filtered element collector)一直是我们讨论的重点。我最近两篇相关的博文是“参数过滤”及其更正和“共享参数过滤”。其中“参数过滤”一文中还包含了一个
元素过滤相关例程的列表。今天我想讨论的是一个虽然 Revit API 文档有清楚的解释,但是依然被屡次问及的问题。(译者注:大师不淡定了,罕见哦)

问题:
请问如何使用 API 访问标注符号(AnnotationSymbol)?我想在族文档中获取所有标注符号的集合。刚开始我尝试了如下代码:

ElementClassFilter filter1 = new ElementClassFilter( typeof( AnnotationSymbol ) ); 
但是 Revit 抛出了一个异常:输入类型在 API 中存在,但是不属于 Revit 本地对象模型。请使用 Autodesk.Revit.DB.FamilyInstance,并对过滤结果进行后处理来获取需要的元素。

我在博文“族的导入”中找到如下一段代码,但是它在 Revit 2011 中无法工作。
List annotations = new List();
doc.get_Elements( typeof( AnnotationSymbol ), annotations );
回答:
Revit 的异常信息其实已经回答了问题。AnnotationSymbol 类虽然是有效的 API 类,但是它没有对应的 Revit 内部类。所以 Revit 内部过滤机制无法对它进行检索。
但是 AnnotationSymbol 的基类 FamilyInstance 有对应的 Revit 内部类,所以你可以使用它进行检索。博文“族的导入”中的使用的 Document.get_Elements() 方法
在 Revit 2011 中已经不再使用了,原因是相对元素过滤,这种方法的效率太低。

这里有另外一个出现在 Revit MEP 中的类似例子:
/// <summary>
/// Retrieve all spaces in given document.
/// </summary>
public static List<Space> GetSpaces( Document doc )
{
  FilteredElementCollector collector
    = new FilteredElementCollector( doc );
 
  // trying to collect all spaces directly causes
  // the following error:
  //
  // Input type is of an element type that exists
  // in the API, but not in Revit's native object
  // model. Try using Autodesk.Revit.DB.Enclosure
  // instead, and then postprocessing the results
  // to find the elements of interest.
  //
  //collector.OfClass( typeof( Space ) );
 
  collector.OfClass( typeof( Enclosure ) );
 
  return (from e in collector.ToElements() where e is Space select e as Space).ToList<Space>();
}
基于相同的原因,如果使用 Space 类设置过滤器,过滤操作会抛出相同的异常。所以我们应该先使用 Space 类的基类 Enclosure 来进行过滤,然后再对结果进行后处理。
同样的,在希望获取文档中的 Room 集合时也应该采用相同处理。不过针对 Room 对象,Revit API 提供了一个专属的过滤器 RoomFilter 来简化代码。
  FilteredElementCollector rooms = new FilteredElementCollector( doc );
 
  RoomFilter filter = new RoomFilter();
  rooms.WherePasses( filter );
其实 Revit API 文档在介绍 ElementClassFilter 类时对此已经有详细的说明了:
过滤器执行的是快速过滤,它只会处理处理低级别的 ElementRecord 类。该类只提供有限的元素属性读取接口。被快速过滤忽略的元素不会在内存中被展开。所以快速过滤
只会收集那些类型和输入类型完全匹配、或者是输入类型的派生类型的元素。

下面是非 Revit 本地类的类列表:
    Subclasses of Autodesk.Revit.DB.Material
    Subclasses of Autodesk.Revit.DB.CurveElement
    Subclasses of Autodesk.Revit.DB.ConnectorElement
    Subclasses of Autodesk.Revit.DB.HostedSweep
    Autodesk.Revit.DB.Architecture.Room
    Autodesk.Revit.DB.Mechanical.Space
    Autodesk.Revit.DB.Area
    Autodesk.Revit.DB.Architecture.RoomTag
    Autodesk.Revit.DB.Mechanical.SpaceTag
    Autodesk.Revit.DB.AreaTag
    Autodesk.Revit.DB.CombinableElement
    Autodesk.Revit.DB.Mullion
    Autodesk.Revit.DB.Panel
    Autodesk.Revit.DB.AnnotationSymbol
    Autodesk.Revit.DB.Structure.AreaReinforcementType
    Autodesk.Revit.DB.Structure.PathReinforcementType
    Autodesk.Revit.DB.AnnotationSymbolType
    Autodesk.Revit.DB.Architecture.RoomTagType
    Autodesk.Revit.DB.Mechanical.SpaceTagType
    Autodesk.Revit.DB.AreaTagType
    Autodesk.Revit.DB.Structure.TrussType

你可能感兴趣的:(Building Coder(Revit 二次开发) - 过滤非本地(Non-Native)类)