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