You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将修改后的Geom_BSplineSurface转换为TopoDS_Face/TopoDS_Shape?

解决OpenCASCADE中重新参数化BSpline曲面后生成TopoDS_Face变形问题

我读取了一个STEP模型,将其中一个TopoDS_Face转换为Geom_BSplineSurface并进行重新参数化后,尝试将其转回TopoDS_Face时出现问题:圆形曲面变成了方形。以下是我的代码:

TopoDS_Face faceo = TopoDS::Face(face_shape);
BRepBuilderAPI_NurbsConvert nurbs_convert;
nurbs_convert = BRepBuilderAPI_NurbsConvert(faceo);
nurbs_convert.Perform(faceo);
TopoDS_Shape face_shape = nurbs_convert.Shape();
Handle(Geom_Surface) h_geomface = BRep_Tool::Surface(TopoDS::Face(face_shape));
Handle(Geom_BSplineSurface)h_bsurface = GeomConvert::SurfaceToBSplineSurface(h_geomface);

//Reparametrize u dir
Standard_Integer nbuk = h_bsurface->NbUKnots();
TColStd_Array1OfReal uk(1, nbuk);
BSplCLib::Reparametrize(0, 1, uk);
h_bsurface->SetUKnots(uk);

//Reparametrize v dir
Standard_Integer nbvk = h_bsurface->NbVKnots();
TColStd_Array1OfReal vk(1, nbvk);
BSplCLib::Reparametrize(0, 1, vk);
h_bsurface->SetVKnots(vk);

//convert Geom_BSplineSurface to TopoDS_Face
TopoDS_Face res = BRepBuilderAPI_MakeFace(h_bsurface, Precision::Approximation());

原始图形为圆形,运行后生成的Face变为方形。


问题原因

  1. 丢失修剪边界:原始圆形Face本质是大BSpline曲面被修剪轮廓(Wire)切割而成,直接用修改后的曲面生成新Face时,默认使用曲面的完整参数域,因此显示为方形。
  2. 重新参数化不完整:仅修改节点数组而未保留节点重数,可能破坏曲面连续性,导致不必要的变形。

解决方案

方案1:复用原始拓扑结构(推荐)

使用BRepBuilderAPI_ModifyFace替换原始Face的曲面,自动保留修剪边界、方向等拓扑信息,这是最简单可靠的方法:

TopoDS_Face faceo = TopoDS::Face(face_shape);
BRepBuilderAPI_NurbsConvert nurbs_convert(faceo);
nurbs_convert.Perform(faceo);
TopoDS_Face nurbsFace = TopoDS::Face(nurbs_convert.Shape());
Handle(Geom_Surface) h_geomface = BRep_Tool::Surface(nurbsFace);
Handle(Geom_BSplineSurface) h_bsurface = Handle(Geom_BSplineSurface)::DownCast(h_geomface);

// 重新参数化U方向:保留节点重数
Standard_Integer nbuk = h_bsurface->NbUKnots();
TColStd_Array1OfReal uk(1, nbuk);
TColStd_Array1OfInteger umults(1, nbuk);
h_bsurface->GetUKnots(uk);
h_bsurface->GetUMultiplicities(umults);
BSplCLib::Reparametrize(0, 1, uk, umults);
h_bsurface->SetUKnots(uk);
h_bsurface->SetUMultiplicities(umults);

// 重新参数化V方向:保留节点重数
Standard_Integer nbvk = h_bsurface->NbVKnots();
TColStd_Array1OfReal vk(1, nbvk);
TColStd_Array1OfInteger vmults(1, nbvk);
h_bsurface->GetVKnots(vk);
h_bsurface->GetVMultiplicities(vmults);
BSplCLib::Reparametrize(0, 1, vk, vmults);
h_bsurface->SetVKnots(vk);
h_bsurface->SetVMultiplicities(vmults);

// 替换原始Face的曲面,保留修剪边界
BRepBuilderAPI_ModifyFace modifyFace(faceo, h_bsurface, Precision::Approximation());
modifyFace.Perform();
TopoDS_Face res = TopoDS::Face(modifyFace.Shape());

方案2:手动适配修剪边界

如果需要手动处理修剪边界,步骤如下:

  1. 提取原始Face的外部修剪Wire:
TopoDS_Wire outerWire = BRepTools::OuterWire(faceo);
  1. 对Wire中的每条Edge,重新计算其在新参数域曲面上的曲线:
    • 提取Edge的Geom_CurveOnSurface,获取原始参数范围
    • 将原始参数线性映射到新的0-1参数域
    • 用新曲线重新构建Edge和Wire
  2. 用修改后的曲面和新Wire生成带修剪的Face:
TopoDS_Face res = BRepBuilderAPI_MakeFace(h_bsurface, outerWire, Precision::Approximation());

注意事项

  • 重新参数化时必须保留节点重数,否则会改变曲面的连续性(如C2变C1),导致曲面变形。
  • 若原始Face有内部孔洞(内部Wire),需要同时处理内部修剪边界。

内容的提问来源于stack exchange,提问作者Rennngw

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 22:02:58