Revit API技术问询:如何从Solid Form获取生成它的FamilyInstance
嘿,这个问题我之前也碰到过!当你通过Revit UI的「创建形状→实心形状」生成Solid Form后,直接用GetGeneratingElementIds()确实拿不到原始的FamilyInstance——因为这个API方法更多是针对通过API直接创建的Form对象,而非UI操作生成的衍生形状。下面给你几个可行的解决思路:
1. 解析轮廓引用的原始元素ID
你提到form.get_CurveLoopReferencesOnProfile()返回了ReferenceArray,这里面的Reference对象很可能包含了原始FamilyInstance的ID!因为生成的实心形状的轮廓曲线其实是引用了原始FamilyInstance的几何边界,所以可以遍历这些Reference来提取对应的元素:
var form = ele as Autodesk.Revit.DB.Form; Document doc = form.Document; // 遍历所有轮廓和曲线环 for (int profileIdx = 0; profileIdx < form.ProfileCount; profileIdx++) { int loopCount = form.GetCurveLoopCountOnProfile(profileIdx); for (int loopIdx = 0; loopIdx < loopCount; loopIdx++) { ReferenceArray refs = form.get_CurveLoopReferencesOnProfile(profileIdx, loopIdx); foreach (Reference r in refs) { if (r.ElementId != ElementId.InvalidElementId) { Element elem = doc.GetElement(r.ElementId); if (elem is FamilyInstance originalInstance) { // 找到对应的原始FamilyInstance // 这里可以添加你的处理逻辑,比如记录ID或操作实例 TaskDialog.Show("找到原始实例", $"ID: {originalInstance.Id}, 类型: {originalInstance.Name}"); } } } } }
这个方法应该是最直接的,因为UI生成的形状本质是基于原始实例的几何轮廓创建的,引用关系会保留在轮廓的Reference里。
2. 通过依赖关系追踪原始元素
Revit的DependencyUtils类可以用来追踪元素之间的依赖关系,你可以尝试获取Form的所有依赖源元素,从中筛选FamilyInstance:
var form = ele as Autodesk.Revit.DB.Form; Document doc = form.Document; // 获取Form的所有依赖源元素 ICollection<ElementId> sourceIds = DependencyUtils.GetDependencySources(doc, form.Id, DependencyType.Any); foreach (ElementId id in sourceIds) { Element elem = doc.GetElement(id); if (elem is FamilyInstance originalInstance) { // 找到目标FamilyInstance // 处理逻辑 break; } }
注意:DependencyUtils是Revit 2021及以上版本才有的API,如果你的项目需要兼容旧版本,这个方法可能不适用。
3. 自定义参数存储关联(适合插件触发创建的场景)
如果这个Form是你自己的插件触发创建的,那可以提前记录原始FamilyInstance的ID,并将其存储到Form的自定义共享参数中:
步骤1:提前创建共享参数
先在Revit中创建一个名为OriginalFamilyInstanceId的共享参数,绑定到Form类别。
步骤2:创建Form时存储关联ID
// 假设你已经选中了要转换的FamilyInstance列表 foreach (FamilyInstance fi in selectedFamilyInstances) { // 执行创建实心形状的操作(这里需要根据你的插件逻辑实现Form创建) Form newForm = CreateSolidFormFromInstance(doc, fi); // 给Form设置自定义参数,存储原始实例ID Parameter originalIdParam = newForm.LookupParameter("OriginalFamilyInstanceId"); if (originalIdParam != null && !originalIdParam.IsReadOnly) { originalIdParam.Set(fi.Id); } }
步骤3:后续读取关联ID
var form = ele as Autodesk.Revit.DB.Form; Parameter originalIdParam = form.LookupParameter("OriginalFamilyInstanceId"); if (originalIdParam != null && originalIdParam.StorageType == StorageType.ElementId) { ElementId originalId = originalIdParam.AsElementId(); FamilyInstance originalInstance = form.Document.GetElement(originalId) as FamilyInstance; // 处理逻辑 }
这个方法的优势是关联关系非常明确,不会受Revit内部API变化的影响。
内容的提问来源于stack exchange,提问作者KungPhoo




