

















前 17 章把 OCCT 的“技术栈”一一拆解。本章以一个综合案例把它们串起来:实现一个简化版的“参数化机械零件查看器”,覆盖建模、可视化、数据交换、OCAF、Draw 测试与部署。读者可以把它当作动手项目,逐步扩展为自己的 CAD 应用。
flange-app/
CMakeLists.txt
src/
main.cpp
MainWindow.cpp/.hpp
OcctView.cpp/.hpp
FlangeBuilder.cpp/.hpp
FlangeDocument.cpp/.hpp
tests/
flange.tcl
resources/
依赖:Qt6、OpenCASCADE 7.8+、CMake 3.22+。
struct FlangeParams {
double outerDiameter = 120.0;
double innerDiameter = 40.0;
double thickness = 20.0;
int boltCount = 6;
double boltDiameter = 10.0;
double boltCircle = 80.0;
};
TopoDS_Shape FlangeBuilder::Build(const FlangeParams& p) {
gp_Ax2 ax(gp_Pnt(0,0,0), gp_Dir(0,0,1));
TopoDS_Shape body = BRepPrimAPI_MakeCylinder(ax, p.outerDiameter/2, p.thickness).Shape();
TopoDS_Shape hole = BRepPrimAPI_MakeCylinder(ax, p.innerDiameter/2, p.thickness + 2).Shape();
TopoDS_Shape r1 = BRepAlgoAPI_Cut(body, hole);
BRep_Builder bb; TopoDS_Compound bolts; bb.MakeCompound(bolts);
for (int i = 0; i < p.boltCount; ++i) {
double a = 2 * M_PI * i / p.boltCount;
gp_Ax2 axb(gp_Pnt(p.boltCircle/2 * std::cos(a),
p.boltCircle/2 * std::sin(a), -1),
gp_Dir(0,0,1));
bb.Add(bolts, BRepPrimAPI_MakeCylinder(axb, p.boltDiameter/2, p.thickness + 2).Shape());
}
TopoDS_Shape r2 = BRepAlgoAPI_Cut(r1, bolts);
BRepFilletAPI_MakeFillet f(r2);
for (TopExp_Explorer ex(r2, TopAbs_EDGE); ex.More(); ex.Next()) {
gp_Pnt mid; double u1, u2;
BRepAdaptor_Curve c(TopoDS::Edge(ex.Current()));
mid = c.Value(0.5*(c.FirstParameter()+c.LastParameter()));
if (std::abs(mid.Z() - p.thickness) < 1e-3 || std::abs(mid.Z()) < 1e-3) {
f.Add(1.0, TopoDS::Edge(ex.Current()));
}
}
f.Build();
return f.IsDone() ? f.Shape() : r2;
}
要点:
MakeCylinder);Cut;IsDone() 检查后退回上一步。class FlangeDocument {
public:
void New(); // 创建空文档
void SetParams(const FlangeParams&);
FlangeParams GetParams() const;
void Recompute(); // 重算并写入 NamedShape
void Save(const TCollection_AsciiString& path);
void Open(const TCollection_AsciiString& path);
void Undo(); void Redo();
Handle(TDocStd_Document) Doc() const { return myDoc; }
TDF_Label ResultLabel() const { return myDoc->Main().FindChild(1, true); }
private:
Handle(TDocStd_Document) myDoc;
};
实现要点:
TDataStd_Real 保存每个参数到独立子 label;Recompute 中调用 BRepAlgoAPI 等并 TNaming_Builder::Generated(shape) 写结果;NewCommand / CommitCommand 包裹每次修改;BinXCAF 格式保存,便于以后扩展 XCAF 颜色/层。继承 QWidget:
class OcctView : public QWidget {
public:
OcctView(const Handle(AIS_InteractiveContext)& ctx, QWidget* parent = nullptr);
protected:
QPaintEngine* paintEngine() const override { return nullptr; }
void paintEvent(QPaintEvent*) override { myView->Redraw(); }
void resizeEvent(QResizeEvent*) override { myView->MustBeResized(); }
void mousePressEvent(QMouseEvent*) override;
// ... 鼠标事件
private:
Handle(V3d_View) myView;
Handle(AIS_InteractiveContext) myContext;
};
复用 OCCT 7.5+ 的 AIS_ViewController 来处理鼠标交互(节省大量代码)。
QFormLayout 展示参数控件(QDoubleSpinBox 等);OcctView;参数变化 → FlangeDocument::SetParams → Recompute → AIS Refresh。void MainWindow::exportStep() {
STEPControl_Writer w;
w.Transfer(myDoc->Result(), STEPControl_AsIs);
w.Write("flange.step");
}
void MainWindow::exportGltf() {
BRepMesh_IncrementalMesh(myDoc->Result(), 0.05, false, 0.3, true);
Handle(TDocStd_Document) tmp;
XCAFApp_Application::GetApplication()->NewDocument("BinXCAF", tmp);
auto st = XCAFDoc_DocumentTool::ShapeTool(tmp->Main());
st->AddShape(myDoc->Result(), false);
RWGltf_CafWriter w("flange.glb", true);
TColStd_IndexedDataMapOfStringString info;
info.Add("Generator", "FlangeApp");
w.Perform(tmp, info, Message_ProgressRange());
}
void MainWindow::exportStl() {
BRepMesh_IncrementalMesh(myDoc->Result(), 0.05);
StlAPI_Writer w; w.ASCIIMode() = false;
w.Write(myDoc->Result(), "flange.stl");
}
ctx->Activate(ais, /*FACE=*/4);
// MouseRelease:
ctx->MoveTo(pos.x(), pos.y(), view, true);
ctx->Select(false);
for (ctx->InitSelected(); ctx->MoreSelected(); ctx->NextSelected()) {
TopoDS_Shape s = ctx->SelectedShape();
if (!s.IsNull() && s.ShapeType() == TopAbs_FACE) {
// 显示属性、面积...
GProp_GProps g;
BRepGProp::SurfaceProperties(s, g);
statusBar()->showMessage(QString("Area=%1").arg(g.Mass()));
}
}
tests/flange.tcl:
pload ALL
source flange_lib.tcl
flange f 120 40 20 6 10 80
checkprops f -v 169646
checkprops f -s 38800
checkmaxtol f 1e-3
flange_lib.tcl 通过自定义 plugin 暴露 C++ FlangeBuilder::Build,或直接用 Tcl 拼装算法命令。运行:
DRAWEXE -batch -script flange.tcl
CI 中执行返回码即可作为测试通过/失败标识。
SetRunParallel(true);Location;BRepMesh 缓存:参数变化才 BRepTools::Clean。install;用 cqtdeployer 或自制脚本拷贝 OCCT、Qt、resources/;windeployqt + 手动拷贝 TK*.dll;macdeployqt + install_name_tool;ubuntu:24.04 构建,开放 X 转发或 noVNC 访问;IBuilder;TFunction 把零件和装配的依赖关系自动求解;XCAF 中的元数据映射到企业系统;FlangeParams,再构造模型;Plugin_Map 加载第三方零件库。完成本案例后,建议按以下循环深耕:
tests/ 中找到与你算法相关的 grid,跑一遍熟悉行为;dox/user_guides/ 中找到对应章节,对照源码复习;BOPAlgo_PaveFiller、ChFi3d_Builder、BRepFill_Pipe);OCCT 是开源 CAD 内核中最完整的一个:从最底层的数学到最上层的应用框架,几乎所有 CAD 软件需要的能力它都有。本教程带你走过 18 章,从全景到底层,从底层回到综合实战。真正掌握 OCCT 需要在每个章节涉及的源码、文档、测试中反复实践——而它给你的回报是:你具备了构建任何 CAD 应用所需的几何与拓扑基础设施。
愿你在 OCCT 的世界里既能解决工程问题,也能享受几何之美。
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。