前言
Revit 有一套完整的几何造型能力,每一个体量都是一个GenericForm
,这些体量可以通过拉伸、扫掠等创建。这个例子介绍如何将他们合并成一个体量。
内容
合并体量的关键接口:
// Autodesk.Revit.DB.Document
public GeomCombination CombineElements(CombinableElementArray members);
可以合并的实体,相关类的集成体系:
如何通过UI创建各种类型的实体,可以参考 Revit 官方文档:创建实心形状
case 1:手动选中了一些元素
核心逻辑:
- 遍历所有选中元素
- 确保元素是
GenericForm
,且是实体solid - 确保都是
CombinableElement
(GenericForm
集成自CombinableElement
,这步有点多余) - 合并符合条件的元素:
doc.Document.CombineElements(solids)
核心代码:
// 遍历所有选中元素
foreach (Autodesk.Revit.DB.ElementId elementId in doc.Selection.GetElementIds())
{Autodesk.Revit.DB.Element element = doc.Document.GetElement(elementId);// 确保元素是`GenericForm`,且是实体solidGenericForm gf = element as GenericForm;if (null != gf && !gf.IsSolid)continue;// 确保都是 `CombinableElement` (`GenericForm`集成自`CombinableElement`,这步有点多余)CombinableElement ce = element as CombinableElement;if (null != ce)solids.Append(ce);
}
// 合并符合条件的元素
doc.Document.CombineElements(solids);
case 2:没有选中,则处理整个文档
核心逻辑:
- 过滤出所有的
GenericForm
和GeomCombination
- 遍历过滤元素
- 确保元素是
GenericForm
,且是实体solid - 确保都是
CombinableElement
(GenericForm
集成自CombinableElement
,这步有点多余) - 对有重叠的元素进行几何合并:
JoinOverlapping
,判断是否重叠的逻辑在IsOverlapped
核心代码:
// 过滤出所有的`GenericForm`和`GeomCombination`
LogicalOrFilter filter = new LogicalOrFilter(new ElementClassFilter(typeof(GenericForm)), new ElementClassFilter(typeof(GeomCombination)));
// 遍历过滤元素
FilteredElementIterator itor = (new FilteredElementCollector(document)).WherePasses(filter).GetElementIterator();
itor.Reset();
while (itor.MoveNext()){// 确保元素是`GenericForm`,且是实体solidGenericForm gf = itor.Current as GenericForm;if (null != gf && !gf.IsSolid)continue;// 确保都是 `CombinableElement` (`GenericForm`集成自`CombinableElement`,这步有点多余)CombinableElement ce = itor.Current as CombinableElement;if (null == ce)continue;m_elements.Add(ce);
}
// 对有重叠的元素进行几何合并
GeomCombination geomCombination = JoinOverlapping(m_elements, document);
JoinOverlapping 的核心逻辑在于判断是否重叠的逻辑, IsOverlapped
:
- 获取元素几何,GeometryElement get_Geometry(Options options)
- 获取GeometryObject所有Face
类型是 Solid,通过接口 solid.Faces
类型是 GeometryElement, 通过 GetEnumerator 接口递归调用 - 获取所有的线 GetAllCurves
首先获取所有的 Face,通过 face.EdgeLoops 获取线的几何信息 - 判断线和面是否相交
部分核心代码:
// 获取元素几何
Options geOptions = Command.s_appCreation.NewGeometryOptions();
elementA.get_Geometry(geOptions);// 获取所有的 Face,需要递归调用
private static void GetAllFaces(GeometryElement geoElement, List<Face> faces){IEnumerator<GeometryObject> Objects = geoElement.GetEnumerator();while (Objects.MoveNext()){GeometryObject geObject = Objects.Current;GetAllFaces(geObject, faces);}
}
private static void GetAllFaces(Solid solid, List<Face> faces){foreach (Face face in solid.Faces){faces.Add(face);}
}
private static void GetAllFaces(GeometryObject geometry, List<Face> faces){if (geometry is GeometryElement){GetAllFaces(geometry as GeometryElement, faces);return;
}if (geometry is Solid){GetAllFaces(geometry as Solid, faces);return;}
}// 获取所有的 curve,类似,省略
其它
这个 sample 代码质量有些混乱,需自行整理分析。