Revit API 如何将项目中的Face精确复制到新族文档中
Revit带孔曲面精确复制到族文档实现方案
三角化镶嵌方案本质是离散近似,必然产生三角片间的冗余边,要实现无碎边的精确Face复制,直接通过BRepBuilder基于Face原生几何拓扑数据构造精确BRep即可,对RuledFace、NurbsSurface及带孔洞的场景均完全适配。
具体实现流程
- 提取源Face的原生曲面参数
先判断Face的曲面类型,直接调用API原生方法拿到精确曲面数据,禁止做任何采样、近似处理:- 对
RuledFace类型,调用GetRuledSurfaceInfo()获取生成直纹面的两条基准曲线、曲面参数范围,直接通过Surface.CreateRuledSurface()生成原生曲面对象 - 对
NurbsSurface类型,调用GetNurbsSurfaceData()获取控制点、权重、UV方向阶数、节点向量等完整参数,通过Surface.CreateNurbsSurface()生成原生NURBS曲面对象
跨文档复制时,提前计算源文档到目标族文档的坐标转换矩阵,所有点、曲线、曲面都要做对应坐标变换,避免位置偏移。
- 对
- 提取Face的全部边界环(含孔洞)
调用Face的GetEdgesAsCurveLoops()方法获取所有闭合边界环集合:集合首个元素为面的外轮廓环,其余元素均为面内的孔洞剪切环。校验环方向:以面的法向为视角,外轮廓需为逆时针方向,孔洞内环需为顺时针方向,方向不符时调用CurveLoop.Reverse()翻转,否则BRep构造会失败。 - 构造BRep对象
初始化BRepBuilder,构造类型指定为BRepType.OpenShell(单张曲面无需构造闭合实体)。调用AddFace()传入之前提取的原生曲面对象,再依次将所有边界环通过AddFaceBoundary()绑定到对应Face,绑定时标记清楚环的类型:外轮廓isOuter参数设为true,孔洞环isOuter参数设为false。 - 校验写入族文档
构造完成后先调用BRepBuilder.IsValid()做几何合法性校验,校验不通过优先排查环方向、曲面参数范围与边界是否匹配、坐标转换是否正确。校验通过后调用FinishBRep()生成最终BRep实体,通过DirectShape.CreateElement()将BRep写入新建的族文档即可,生成的曲面与源Face几何完全一致,无三角化带来的冗余中间边。
避坑提示:不要对提取到的曲线、曲面做任何离散化、拟合近似操作,所有传入
BRepBuilder的几何对象必须是API直接返回的原生几何类型,否则仍然会出现精度损失、冗余边或者构造失败的问题。
核心实现代码
// 初始化BRep构造器 BRepBuilder brepBuilder = new BRepBuilder(BRepType.OpenShell); Surface targetSurface = null; // 按曲面类型提取原生曲面数据 if (sourceFace is RuledFace ruledFace) { RuledSurfaceInfo ruledInfo = ruledFace.GetRuledSurfaceInfo(); targetSurface = Surface.CreateRuledSurface(ruledInfo.Curve0, ruledInfo.Curve1); } else if (sourceFace is NurbsSurface nurbsFace) { NurbsSurfaceData nurbsData = nurbsFace.GetNurbsSurfaceData(); targetSurface = Surface.CreateNurbsSurface( nurbsData.ControlPoints, nurbsData.Weights, nurbsData.KnotsU, nurbsData.KnotsV, nurbsData.DegreeU, nurbsData.DegreeV ); } // 向BRep添加面 BRepBuilderFaceId brepFaceId = brepBuilder.AddFace( targetSurface, sourceFace.OrientationMatchesSurfaceOrientation ); // 添加所有边界环(外轮廓+孔洞) IList<CurveLoop> faceLoops = sourceFace.GetEdgesAsCurveLoops(); for (int loopIndex = 0; loopIndex < faceLoops.Count; loopIndex++) { CurveLoop currentLoop = faceLoops[loopIndex]; // 此处补充坐标转换逻辑,将currentLoop内所有曲线转换到目标族文档坐标系 bool isOuterLoop = loopIndex == 0; brepBuilder.AddFaceBoundary(brepFaceId, currentLoop, isOuterLoop); } // 校验并写入族文档 if (brepBuilder.IsValid()) { BrepBody resultBrep = brepBuilder.FinishBRep(); DirectShape newDs = DirectShape.CreateElement( familyDoc, new ElementId(BuiltInCategory.OST_GenericModel) ); newDs.AppendShape(new List<GeometryObject> { resultBrep }); }
内容的提问来源于stack exchange,提问作者KungPhoo
相关产品推荐
相关产品推荐

