最近在用过滤器功能,先按照教程做了筛选墙,再自己做了筛选常规模型的功能,发现有点不一样,问题在于筛选这些Elements的时候没弄清元素是怎么分类的,研究了下Element下”继承关系“的问题,给找到的相关资料做了些笔记分享如下: 感谢:叶雄进老师link、黑夜de骑士link
首先要理解Revit中“Category、Family、 FamilySymbol、 FamilyInstance”四者之间的关系与区别。
图源b站up主:黑夜de骑士-面向工程人员的Revit二次开发06_Revit二次开发之过滤器的使用(01:20/58:17)
Revit中直观的关系: 还有个族实例,当然把族类型拖到界面里就变成了族实例了。
当前选中元素的族类型/族实例可以在lookup左上角查看; 特殊的族类型/族实例,如墙,就对应WallType/Wall,选取界面里的一面墙(这里就是选了一个族实例)用lookup查看可以发现:
族类别Category中BuiltInCategory.XXX可以在lookup-Category里查看。 在代码里的体现:
collector.OfCategory(BuiltInCategory.OST_Planting).OfClass(typeof(FamilyInstance));图源b站up主:黑夜de骑士-面向工程人员的Revit二次开发06_Revit二次开发之过滤器的使用(11:00/58:17) 过滤-快速过滤方法: OfCategory是从大到小找,先找目标Category(如BuiltInCategory.OST_Doors); OfClass是从小到大找,先找族实例(找FamilyInstance、找Wall); 所以尽量先OfCategory再OfClass(but其实结果都一样,顺序也是可以调换的)。
过滤-通用方法: 将在代码案例里展示。
结合上文给了一些例子,大部分是typeof(Instance),墙是特殊的typeof(wall)。
//筛选窗 FilteredElementCollector collector = new FilteredElementCollector(doc); collector.OfCategory(BuiltInCategory.OST_Windows).OfClass(typeof(FamilyInstance)); //筛选常规模型 FilteredElementCollector collector = new FilteredElementCollector(doc); collector.OfCategory(BuiltInCategory.OST_GenericModel).OfClass(typeof(FamilyInstance)); //筛选墙 FilteredElementCollector collector = new FilteredElementCollector(doc); collector.OfCategory(BuiltInCategory.OST_Walls).OfClass(typeof(Wall));有时需要筛选族(Family)的时候,只能上OfClass,不能上OfCategory。黑夜de骑士链接:link
下面是叶雄进老师教程里过滤窗&门并收集个数的完整代码 内联代码片。 这里收集窗时先OfClass再OfCategory了,但效果一模一样的。 收集门时,用的通用方法,相当于把一句话扩写成了三句,详情看注释。
using Autodesk.Revit.Attributes; using Autodesk.Revit.DB; using Autodesk.Revit.UI; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Forms; namespace Project { [Autodesk.Revit.Attributes.Transaction(TransactionMode.Manual)] [Autodesk.Revit.Attributes.Regeneration(RegenerationOption.Manual)] public class GetAllWindows : IExternalCommand { public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elementSet) { UIApplication uiApp = commandData.Application; Autodesk.Revit.ApplicationServices.Application app = uiApp.Application; Document doc = uiApp.ActiveUIDocument.Document; //获得所有窗户 FilteredElementCollector collector = new FilteredElementCollector(doc); collector.OfClass(typeof(FamilyInstance)).OfCategory(BuiltInCategory.OST_Windows); //将结果放在lists变量里,再输出有多少个对象 IList<Element> lists = collector.ToElements(); String strMsg = string.Format("There are {0} windows in current model", lists.Count); MessageBox.Show(strMsg); //获得所有门(另一种筛选方式) FilteredElementCollector collector2 = new FilteredElementCollector(doc); ElementClassFilter ClassFilter = new ElementClassFilter(typeof(FamilyInstance)); ElementCategoryFilter CatFilter = new ElementCategoryFilter(BuiltInCategory.OST_Doors); //把上两个定义的过滤器当做参数传到逻辑与过滤器里 LogicalAndFilter logicalFilter = new LogicalAndFilter(ClassFilter, CatFilter); //让collector2通过自定义的LogicalFilter过滤器 collector2.WherePasses(logicalFilter); //以上两句也可以简写,省略那个逻辑与过滤器 //collector.WherePasses(ClassFilter).WherePasses(CatFilter); IList<Element> lists2 = collector2.ToElements(); String strMsg2 = string.Format("There are {0} doors in current model", lists2.Count); MessageBox.Show(strMsg2); return Result.Succeeded; } } }这两幅也是来自叶雄进老师link教程里的图,年代久远了,和上面整理的分类略有不同,先存个档。