Building Coder(Revit 二次开发) - 提高针对族的元素过滤器的性能
来源:互联网 发布:sai for mac 打不开 编辑:程序博客网 时间:2024/05/17 03:43
原文链接:Family Usage Filtered Element Collector Performance
问题
针对 Revit 数据的访问绝大多数情况下都是基于从 FilteredElementCollector 中返回的 Revit 元素,可见提高元素过滤的性能是保证 Revit 二次开发性能的基石。
Jeremy
我在博文 XML family usage report(http://thebuildingcoder.typepad.com/blog/2010/12/xml-family-usage-report.html) 中介绍了如果使用元素过滤器获取一个文档中所有被加载的族,并为每一个被加载的族创建一个元素过滤器来获取其族实例。不过你的问题中只关心指定类别的族,特别是那些被创建了族实例的族。所以我上面这篇博文里的代码就显得效率不高了。
问题
我想获取当前文档中所有被创建了族实例的族。但是我的代码在加载了几百个族的文档中效率太低。
Jeremy
首先你可以将 Collector 转换成 Collection 的代码删除。Collector 本身就是可以被遍历的,Collector 到 Collection 的转换需要重新申请内存并转换数据类型,这通常需要不少时间。
更重要的是,你不应该首先获取所有的族,然后使用循环的方式为每个族再次创建一个过滤器来找到可能的族实例。如果一个族只是被加载但是没有族实例的话,这部分工作就是多余的了。
所以我建议采用如下步骤:
1. 确认所有你感兴趣的类别
2. 为所有这些类别创建一个族实例过滤器
3. 遍历这些族实例,确认它们属于哪个族或者族类型(FamilySymbol)
我这篇博文里列举了很多关于元素过滤的例子:filtered element collector samples
答复
我的场景里无法预先知道所有感兴趣的类别。不过按照你的建议修改的下面这段代码效率提高了很多(从3到5分钟缩短到了10秒钟)。
Jeremy
下面这段利用泛型的C#代码更加简洁一些:
问题
针对 Revit 数据的访问绝大多数情况下都是基于从 FilteredElementCollector 中返回的 Revit 元素,可见提高元素过滤的性能是保证 Revit 二次开发性能的基石。
Jeremy
我在博文 XML family usage report(http://thebuildingcoder.typepad.com/blog/2010/12/xml-family-usage-report.html) 中介绍了如果使用元素过滤器获取一个文档中所有被加载的族,并为每一个被加载的族创建一个元素过滤器来获取其族实例。不过你的问题中只关心指定类别的族,特别是那些被创建了族实例的族。所以我上面这篇博文里的代码就显得效率不高了。
问题
我想获取当前文档中所有被创建了族实例的族。但是我的代码在加载了几百个族的文档中效率太低。
Sub GetFamilyType(ByVal mydoc As Document) Dim collector As New Autodesk.Revit.DB.FilteredElementCollector(mydoc) Dim collection As ICollection(Of Autodesk.Revit.DB.Element) = collector.OfClass(GetType(DB.Family)).ToElements() ' 获取所有属于指定类别的族 Dim families As List(Of Family) Dim category As DB.Category = Nothing Dim familyTypeCategoryList As New Dictionary(Of String, List(Of Family)) '族和族实例 Dim categoryList As New Dictionary(Of String, Category) '类别及其族实例 For Each family As DB.Family In collection category = Nothing If family.Symbols.Size > 0 Then Dim symbols As FamilySymbolSetIterator = family.Symbols.ForwardIterator() symbols.Reset() Dim symbol As Autodesk.Revit.DB.FamilySymbol = Nothing While symbols.MoveNext() symbol = TryCast(symbols.Current, Autodesk.Revit.DB.FamilySymbol) '------------------------- '下面这段效率太低 '------------------------- 'Find the symbol of which at least a Family instance exists Dim filter As New DB.FamilyInstanceFilter(mydoc, symbol.Id) collector = New Autodesk.Revit.DB.FilteredElementCollector(mydoc) Dim familyInstances As ICollection(Of DB.Element) = collector.WherePasses(filter).ToElements() If familyInstances.Count > 0 Then '所有族的类型都属于同一个类别,不同的族也可能包含属于同一类别的族类型 category = symbol.Category Exit While End If End While If category IsNot Nothing Then If familyTypeCategoryList.ContainsKey(category.Name) Then familyTypeCategoryList.Item(category.Name).Add(family) Else families = New List(Of DB.Family) families.Add(family) familyTypeCategoryList.Add(category.Name, families) categoryList.Add(category.Name, category) End If End If End If NextEnd Sub
Jeremy
首先你可以将 Collector 转换成 Collection 的代码删除。Collector 本身就是可以被遍历的,Collector 到 Collection 的转换需要重新申请内存并转换数据类型,这通常需要不少时间。
更重要的是,你不应该首先获取所有的族,然后使用循环的方式为每个族再次创建一个过滤器来找到可能的族实例。如果一个族只是被加载但是没有族实例的话,这部分工作就是多余的了。
所以我建议采用如下步骤:
1. 确认所有你感兴趣的类别
2. 为所有这些类别创建一个族实例过滤器
3. 遍历这些族实例,确认它们属于哪个族或者族类型(FamilySymbol)
我这篇博文里列举了很多关于元素过滤的例子:filtered element collector samples
答复
我的场景里无法预先知道所有感兴趣的类别。不过按照你的建议修改的下面这段代码效率提高了很多(从3到5分钟缩短到了10秒钟)。
Public Shared Sub CreateFamilyTreeTest( ByVal myDoc As Document) Dim collector As New FilteredElementCollector(myDoc) collector.WhereElementIsNotElementType() Dim familyInstances = From elem In collector _ Where elem.Category IsNot Nothing _ And TypeOf elem Is FamilyInstance() Dim familySymbols = From elem In collector _ Join sb In familyInstances _ On elem.UniqueId Equals CType(sb.ObjectType, FamilySymbol).Family.UniqueId _ Where TypeOf elem Is Family Select elem familySymbols = familySymbols.Distinct() Dim mapCatToFam As New Dictionary(Of String, List(Of Family)) Dim categoryList As New Dictionary(Of String, Category) Dim families As List(Of Family) Dim category As Category Dim symbol As FamilySymbol For Each family As Family In familySymbols If family.Symbols.Size > 0 Then symbol = family.Symbols(0) category = symbol.Category If mapCatToFam.ContainsKey(category.Name) Then mapCatToFam.Item(category.Name).Add(family) Else families = New List(Of Family) families.Add(family) mapCatToFam.Add(category.Name, families) categoryList.Add(category.Name, category) End If End If NextEnd Sub
Jeremy
下面这段利用泛型的C#代码更加简洁一些:
public static void CreateFamilyTreeTest( Document myDoc ){ IEnumerable<Element> familiesCollector = new FilteredElementCollector( myDoc ) .OfClass( typeof( FamilyInstance ) ) .WhereElementIsNotElementType() .Cast<FamilyInstance>() .GroupBy( fi => fi.Symbol.Family ) .Select( f => f.Key ); var mapCatToFam = new Dictionary<string, List<Element>>(); var categoryList = new Dictionary<string, Category>(); foreach( var f in familiesCollector ) { var catName = f.Category.Name; if( mapCatToFam.ContainsKey( catName ) ) { mapCatToFam[catName].Add( f ); } else { mapCatToFam.Add( catName, new List<Element> { f } ); categoryList.Add( catName, f.Category ); } }}
- Building Coder(Revit 二次开发) - 提高针对族的元素过滤器的性能
- Building Coder(Revit 二次开发) - ToElementIds() 的性能
- Building Coder(Revit 二次开发) - 族元素可见性
- Building Coder(Revit 二次开发) - 设置锁定参数的值
- Building Coder(Revit 二次开发) - NewFamilyInstance() 重载版本的选择
- Building Coder(Revit 二次开发) - 临时事务的使用技巧
- Building Coder(Revit 二次开发) - 元素层级事件(上)
- Building Coder(Revit 二次开发) - 元素层级事件(下)
- Building Coder(Revit 二次开发) - 改变元素类型
- Building Coder(Revit 二次开发) - 改变元素颜色
- Building Coder(Revit 二次开发) - 缺少层(Level)属性的族实例
- Building Coder(Revit 二次开发) - 放置族实例
- Building Coder(Revit 二次开发) - 族符号与族类型
- Building Coder(Revit 二次开发) - 对象关系
- Building Coder(Revit 二次开发) - RevitLoopup 更新
- Building Coder(Revit 二次开发) - 拖放API
- Building Coder(Revit 二次开发) - GetInstanceGeometry() 的开销和无效的引用
- Building Coder(Revit 二次开发) - 无模式窗口和消失的共享参数
- msgserver.c
- msgclient.c
- AsyncTask详解
- 终于培训完了,可以学习了 (滚动信息的小例子)
- SQL SERVER中一些常见性能问题的总结
- Building Coder(Revit 二次开发) - 提高针对族的元素过滤器的性能
- Archlinux中pacman,yaourt的常用用法
- 访问samba服务器错误:"您可能没有权限使用网络资源"
- 反射模拟--List<User>users-----JSON
- a++, a+=1,a=a+1,++a 四者的区别
- 测试驱动开发三部曲——走出TDD丛林
- android--- Linux Proc虚拟文件系统—Android CPU、内存、网络流量获取
- MySQL常用操作指南
- 嵌入式实验——开发环境建立 心得