OpenCascade(OCCT)的倒角功能由 BRepFilletAPI_MakeChamfer 对外提供,底层复用了与圆角(Fillet)完全相同的算法框架 ChFi3d_Builder,仅在几何曲面生成、拐角过渡两个环节存在差异。整体采用「几何求交先行、拓扑重构后置」的流水线设计,所有计算先写入统一的干涉数据库,最终一次性完成 BRep 拓扑切割与缝合。
倒角前:

倒角后:

一、整体架构:四层设计与核心类
1.1 四层架构
| 层级 | 职责 | 核心类 |
|---|---|---|
| API 层 | 对外接口,封装参数设置、结果查询 | BRepFilletAPI_MakeChamfer |
| 算法调度层 | 流程总控、拐角分发、几何求交 | ChFi3d_Builder |
| 数据结构层 | 存储倒角带、脊线、曲面、干涉关系 | ChFiDS_Stripe / ChFiDS_Spine / TopOpeBRepDS_DataStructure |
| 拓扑重建层 | 通用曲面切割、拓扑缝合、实体组装 | ChFiDS_FilDS / TopOpeBRepBuild_Coupler |
1.2 核心数据概念
- 倒角带(Stripe) :一条待倒角棱对应一个
ChFiDS_Stripe,是算法调度的最小单元,包含脊线、支撑面、倒角参数、生成的倒角曲面。 - 脊线(Spine) :待倒角的原始棱边的参数化表达,
ChFiDS_ChamfSpine为倒角专用子类,存储对称/双距离/角度三种倒角模式。 - 支撑面(Support Face):倒角棱相邻的两个原始实体面,倒角平面沿支撑面偏置生成。
- DS 干涉数据库 :
TopOpeBRepDS_DataStructure,是 OCCT 布尔/倒角通用的中间数据结构,存储所有原始形状、新生几何、相交关系、拓扑映射。
二、完整执行流水线
以下流程对应 ChFi3d_Builder::Compute() 的执行顺序,也是倒角算法的核心主干。
阶段1:输入初始化与倒角带构建
1.1 上层 Add() 构建倒角带
调用 BRepFilletAPI_MakeChamfer::Add(dist1, dist2, edge, face) 时,内部完成三件事:
- 校验棱边与支撑面的拓扑邻接关系;
- 解析倒角参数(对称 C 角、双距离不等角、距离+角度);
- 创建
ChFiDS_Stripe,构建ChFiDS_Spine脊线,加入myListStripe总列表。
关键细节:必须显式传入支撑面,算法依靠支撑面区分倒角的「切除侧」;仅传边会导致方向歧义,批量倒角时容易出现向内切穿实体的错误。
1.2 脊线端点状态判定
对每条脊线的两个端点,标记三种状态:
ChFiDS_FreeBoundary:自由边界,该端点没有其他相邻倒角棱;ChFiDS_BreakPoint:交汇顶点,至少还有另一条倒角棱在此顶点汇聚;ChFiDS_OnSame:共面端点,两条倒角棱共享同一侧面。
1.3 构建顶点-倒角带映射
cpp
// 遍历所有 Stripe,将交汇顶点存入 myVDataMap
for (itel.Initialize(myListStripe); itel.More(); itel.Next()) {
if (端点状态 == BreakPoint)
myVDataMap.Add(顶点, Stripe);
else if (端点状态 == FreeBoundary)
ExtentOneCorner(顶点, Stripe);
}
myVDataMap:Key 为顶点,Value 为汇聚在该顶点的所有倒角带列表;- 自由边界端点直接执行单拐角预延伸,不进入映射表;
- 此映射是后续拐角求解的索引基础。
阶段2:预延伸分析(ExtentAnalyse)
2.1 为什么必须预延伸
倒角曲面默认严格贴合原始棱的参数范围,在顶点处多个倒角曲面仅「点对点接触」,没有重叠区域,后续求交无法找到交线,拐角会出现破洞。预延伸的核心目标是:让相邻倒角曲面产生足够重叠,为拐角求交创造几何条件。
2.2 四类拐角的延伸策略
cpp
switch (顶点汇聚的倒角带数量) {
case 1: ExtentOneCorner(); break; // 单棱端头
case 2: ExtentTwoCorner(); break; // 两棱交汇
case 3: ExtentThreeCorner(); break; // 三棱交汇(立方体顶点)
default: 不预延伸; break; // 四棱及以上,动态求解
}
- ExtentOneCorner:固定系数延伸,将脊线参数区间向外扩展 50% 原始长度,适用于孤立端头。
- ExtentTwoCorner / ExtentThreeCorner:自适应延伸,先找到相邻倒角带的公共支撑面,再根据倒角宽度计算最小必要延伸量,避免过度延伸导致自交。
阶段3:逐条生成倒角曲面(PerformSetOfSurf)
cpp
for (每条 Stripe) {
try { PerformSetOfSurf(stripe); }
catch (...) { badstripes.Append(stripe); }
}
done = badstripes.IsEmpty();
3.1 核心几何计算
根据倒角参数模式,生成对应的倒角平面:
- 对称倒角:两侧支撑面偏置距离相等,倒角平面与两面呈 45°;
- 双距离倒角:两侧偏置距离不同,按比例生成斜面;
- 距离+角度倒角:由一侧距离与角度换算出另一侧等效距离,再生成平面。
与圆角的核心分叉点:圆角此处生成圆环面(Torus),倒角生成平面(Plane);上层调度、拐角处理、拓扑重构逻辑完全复用。
3.2 失败容错机制
单条倒角带曲面生成失败时,加入 badstripes 列表,不直接崩溃;全部生成成功才进入下一阶段。
阶段4:顶点拐角求解(PerformFilletOnVertex)
遍历 myVDataMap 中所有交汇顶点,根据汇聚倒角带数量分发到不同求解器,这是倒角算法最复杂的部分。
4.1 拐角分类与求解器
| 拐角类型 | 求解器 | 典型场景 |
|---|---|---|
| 单拐角 | PerformOneCorner |
棱的端头倒角,无相邻倒角 |
| 两拐角 | PerformTwoCorner |
两条相邻棱同时倒角 |
| 三拐角 | PerformThreeCorner |
立方体顶点三条棱倒角 |
| 多棱拐角 | PerformMoreThreeCorner |
四棱及以上交汇的复杂顶点 |
| 奇异拐角 | PerformSingularCorner |
倒角曲面边界退化重合的极端拓扑 |
4.2 单拐角(PerformOneCorner)深度解析
这是最基础、最常用的拐角类型,核心目标是生成倒角端头的封口交线,封闭倒角斜面。
- 定位曲面与边界点:找到靠近顶点的倒角曲面片,提取两侧边界特征点。
- 拓扑分支判定 :
OnSame = true:封闭实体端头,倒角端面贴合实体端面,走精确封口逻辑;OnSame = false:开放边界,调用FindFace搜索承接面,找不到则降级为通用端点求交。
- 封口交线计算 :调用
ChFi3d_ComputeCurves求解倒角平面与端面的交线,同时输出 3D 曲线与两个面上的 2D 参数曲线。 - 缝合边相交处理:若交线与实体缝合边(Sewing Edge)相交,将交线切割为两段,分别登记入 DS。
- 自相交校验:检查当前封口曲线与其他倒角带的参数曲线是否相交,相交则判定「倒角尺寸过大」,抛出异常终止。
阶段5:倒角带间干涉检测
cpp
// 双重循环,两两倒角带求交(i2>i1 避免重复)
ChFi3d_StripeEdgeInter(st, aCheckStripe, DStr, tol2d);
这是 OCC-119 版本加入的关键修复:
- 检测不同倒角带的曲面是否发生穿透干涉;
- 若求交失败或存在非法干涉,标记当前倒角带为失败,终止流水线;
- 解决了早期版本大倒角、多拐角时出现曲面互穿、实体破碎的问题。
阶段6:倒角拓扑数据填充(ChFi3d_FilDS)
cpp
ChFi3d_FilDS(solidindex, st, DStr, myRegul, tolesp, tol2d);
这是从「几何计算」转向「拓扑构建」的枢纽:
- 将生成的倒角平面、边界曲线、顶点,以「形状+干涉关系」的形式写入 DS 数据库;
- 建立倒角面与原始支撑面的邻接关系;
- 记录拓扑分割所需的所有交线、点干涉信息。
注意:此阶段仍不直接修改原始 BRep,所有变更全部缓存到 DS 中。
阶段7:全局 BRep 拓扑重构(核心重组阶段)
这是真正执行「BRep 重新组织」的环节,分为三步。
7.1 容差同步(两次修正)
倒角分割会产生大量新的边与顶点,容差不匹配是拓扑缝合失败的首要原因。代码中做了两轮容差对齐:
- 第一轮:遍历 DS 中所有曲线,同步曲线与关联顶点的容差,顶点容差取相邻边最大值;
- 第二轮:拓扑分割完成后,遍历所有新生边,再次放大两端顶点容差至边容差水平。
7.2 Coupler 执行拓扑切割与缝合
cpp
myCoup->Perform(myDS);
myCoup 是 TopOpeBRepBuild_Coupler 实例,OCCT 通用布尔分割引擎:
- 读取 DS 中所有原始面、交线、干涉关系;
- 用交线切割原始支撑面,切除被倒角去掉的尖角区域;
- 将倒角面与切割后的基体面进行拓扑缝合,建立共享边与共享顶点;
- 维护「原始形状 → 分割后新形状」的映射关系,支持通过
Splits()/Merged()查询。
核心结论:BRep 拓扑的切割、重组、缝合,90% 以上的工作由 Coupler::Perform 完成;此前所有阶段都只是在为它准备输入数据。
7.3 登记参与合并的实体
将所有原始 Solid / Shell 注册给 Coupler,指定合并方向为 TopAbs_IN,让切割器知道哪些实体需要最终缝合为闭合实体。
阶段8:结果组装与后处理
8.1 结果组装
- 成功分支 :创建
TopoDS_Compound,遍历所有原始实体;若实体被分割则加入分割后的新实体,未分割则直接加入原始实体。 - 失败分支 :将中间结果存入
badShape,供调试定位失败位置;IsDone()返回 false。
8.2 后处理
- SetRegul:拓扑规整,消除退化边、重复顶点,修正非流形拓扑;
- BRepLib::SameParameter:统一曲面参数化,保证边在两侧面上的参数曲线一致,避免后续布尔、网格化出现几何不连续。
三、倒角 vs 圆角:架构复用与核心差异
OCCT 用同一套 ChFi3d_Builder 框架同时支持倒角和圆角,仅两处核心分叉:
- 曲面生成:倒角生成平面,圆角生成圆环面/滚动球面;
- 拐角过渡:三拐角处倒角是平面相交形成的折线拐角,圆角是球面/环面顺滑过渡;多拐角求解器逻辑不同。
其余的脊线管理、预延伸、DS 构建、Coupler 拓扑缝合、容差处理完全复用,这也是 OCCT 几何内核「算法分层、能力复用」的典型设计。
四、工程视角:倒角失败常见原因与定位
结合算法流程,可以快速定位绝大多数倒角失败的根源:
- 输入拓扑错误:原始模型存在自由边、非流形顶点、面法向混乱 → 阶段1 构建 Stripe 失败;
- 支撑面选择错误:批量倒角随机取第一个相邻面,导致向内倒角、切穿实体 → 阶段3 曲面生成异常;
- 倒角尺寸过大:倒角距离超过支撑面宽度,或相邻倒角互相穿透 → 阶段5 干涉检测抛出异常;
- 多棱顶点收敛失败:四棱及以上复杂顶点,拐角求交迭代不收敛 → 阶段4 PerformMoreThreeCorner 失败;
- 容差不匹配:原始模型容差混乱,切割后拓扑缝合失败 → 阶段7 Coupler 报错;
- 延伸不足:特殊角度棱的预延伸量不够,拐角处曲面无重叠 → 拐角求交找不到交线,出现破洞。
五、全流程数据流总结
输入:Solid + {Edge, 距离, 支撑面}
↓
构建 ChFiDS_Stripe 列表 + 脊线 Spine
↓
填充 myVDataMap 顶点映射 + 自由边界直接预延伸
↓
ExtentAnalyse:按拐角类型协同延伸脊线参数
↓
PerformSetOfSurf:逐条生成倒角平面
↓
PerformFilletOnVertex:多类拐角求交、生成封口边界
↓
ChFi3d_StripeEdgeInter:倒角带两两干涉检测
↓
ChFi3d_FilDS:倒角几何写入 DS 干涉数据库
↓
容差同步 → Coupler::Perform 执行 BRep 切割与缝合
↓
拓扑规整 + 参数统一 → 组装输出结果 Solid/Compound