# OCCTTutorial **Repository Path**: qhz734/occttutorial ## Basic Information - **Project Name**: OCCTTutorial - **Description**: OpenCASCADE7.9(OCCT)/Qt6/VS2022学习笔记,主要参考官方文档demo - **Primary Language**: C++ - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 22 - **Forks**: 15 - **Created**: 2025-04-18 - **Last Updated**: 2025-09-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: OCCT, opencascade ## README # OCCTTutorial > 作者:工地铁头娃(工地IronMan) 时间:20250416 - 背景:濒临下岗的土木打灰老哥 - 说明:本专题将持续更新OpenCASCADE7.9相关的开发学习笔记。高度依赖OpenCASCADE7.9官方文档overview/refman,因为官方文档实际还是较老版本的OCCT,且因各种原因很多demo运行不起来。本专题更新了一些官方教程的demo,部分demo还结合本人三维软件使用经验做了一些拓展。 ![img](imgs/cover.png) ![img](imgs/gundam.png) ## 环境 - 编译器:MSVC143 - 编程语言:C++17 - 构建工具:CMake - IDE:VS2022 - 操作系统:Win11 x64 - UI库:Qt6.6 - 三维建模引擎:OpenCASCADE7.9(OCCT) - 三维显示库(可选):VTK9.4.1 - 本专题仓库: - 详细教程见本人B站链接,感谢大家观看后能够一键三连。 [【笔记1前期准备】opencascade(OCCT)-7.9+Qt6官方demo](https://www.bilibili.com/video/BV1AV59z5ESJ/?share_source=copy_web&vd_source=004e882833487e71b85a925c4d157996) ## 项目依赖 ### OpenCASCADE7.9 #### 编译 > (不使用VTK库的可跳过VTK部分)。官方提供的预编译VTK只有release版,链接此版本VTK的预编译的OCCT若在Debug模式调用GetOutputPort()会报错,需要先编译Debug版的VTK,再编译OCCT - 官网 - 下载预编译好的freetype,freeimage,tcl/tk(在3rd-party压缩包中) ![img](imgs/img1.png) - 下载OCCT7.9源码(VTK见下文) ![img](imgs/img2.png) - 新建文件夹,3rdparty文件夹放入freetype,freeimage,tcl/tk库 ![img](imgs/img3.png) - 打开CMakeGUI,设置源码、BUILD文件夹位置,点击Configure,报错后出现配置选项 ![img](imgs/img4.png) - 设置INSTALL_DIR位置(Deubg模式编译自动生成Deubg版本文件夹,e.g. bind文件夹) - BUILD_CPP_STANDARD设为C++17 - 设置3RDPARTY_DIR`E:/8other/OCCT-7.9.0/3rdparty` - USE_FREEIMAGE打勾,点击Configure(若不使用VTK,下面内容可跳过。若使用,先不Configure) - USE_VTK打勾,点击Configure,报错后出现3RDPARTY_VTK_DIR配置选项,设置`E:/8other/VTK-9.4.1/INSTALL/lib/cmake/vtk-9.4` - 点击Generate ![img](imgs/img5.png) - VS2022打开BUILD文件夹中OCCT.sln,编译OCCT库 ![img](imgs/img6.png) - 约半小时到1小时后,编译完成。编译好的文件在INSTALL文件夹中 ![img](imgs/img7.png) - 双击运行INSTALL/draw.bat,出现以下界面说明编译无误 ![img](imgs/img8.png) - 编译好的库文件在`INSTALL/win64/vc14`中 ![img](imgs/img9.png) #### 编译官方文档(可选) - 将tcl/tk的bin文件夹加入环境变量。下载doxygen/Graphviz(生成类图用),加入环境变量 - 控制台CD到源码的adm文件夹 - 控制台运行 `./gendoc -overview -s=local` `./gendoc -refman -s=local` - overview是用户说明, refman是API说明 ![img](imgs/img10.png) ### VTK9.4.1(可选) #### 编译 > 此内容详情百度,网上相关内容较多 - 建立BUILD INSTALL文件夹 - 打开CMakeGUI,设置源码、BUILD文件夹位置,点击Configure,报错后出现配置选项 - 设置CMAKE_INSTALL_PREFIX - VTK_GROUP_ENABLE_Qt为WANT - 点击Configure - Qt6_DIR为`C:/Qt/6.6.3/msvc2019_64/lib/cmake/Qt6` - VTK_QT_VERSION为6 - 点击Configure - 点击Generate ## 项目配置VS2022/cmake > 自己编译的OCCT可正常使用cmake的find_package() 本配置比较简单,仅供参考,详见CMakeLists.txt文件 - 注意替换项目代码中出现的文件路径 - 项目树 ![img](imgs/img11.png) - 项目概况 - 项目MView主要就是实现基础的显示、交互功能,将OCCT嵌入到QWidget中显示三维内容 - 项目MViewVTK主要是利用OCCT,QT,VTK实现显示模型 - 项目OCCTQtDemo利用MView实现交互显示,根据OCCT官方文档API,实现demo,部分demo进行了拓展 - 根目录CMakePresets.json,设置vs2022 debug模式运行时的环境变量,需将运行动态库通过CMake install(或者手动)复制到dll文件夹中 ```json "environment": { "PATH": "$penv{PATH};E:\\8other\\CppLearn\\OCCTTutorial\\dlls" } ``` ![img](imgs/img12.png) ## 项目MView > 可以先运行显示个可交互的三维模型瞧瞧。。。 参考: overview索引: User Guides/Visualization/3D Presentations/3D view facilities 官方Qt的demo(OCCTOverview)中的两个文件View.h、OcctWindow.h ![img](imgs/img13.png) ### 概况 - 主要就是实现基础的显示、交互功能,将OCCT嵌入到QWidget中显示三维内容 - 编译运行项目MView后,点击test按钮,将显示一个可交互的长方体。 - 选择:可点击选择,框选。支持Shift选择模式 - 旋转视图:Shift+鼠标右键 - 缩放视图:鼠标中键滚动 - 平移视图:鼠标按住中键移动 - 相对官方demo,类OcctWindow用官方的修改就行,类View改动较多,建议自己新建文件重新写 - 因为官方用的是Qt5,用Qt6运行会出现黑色边框/鼠标位置错误等问题。需修正Qt6分辨率缩放问题,参考网上的解决办法: 为类添加`const Standard_Real _devPx`变量(`Standard_Real`为OCCT的`double`类型),构造函数用`parent->devicePixelRatio()`初始化,类成员函数中涉及`_myWidget->rect()`或鼠标位置处,将获取的数值`*_devPx`。e.g. 修改为`_devPx * _myWidget->rect()` - 官方类View继承了AIS_ViewController,AIS_ViewController是OCCT内置的交互类,只实现了单选功能,还涉及OCCT的鼠标映射等。考虑学习成本,本教程交互尽量都用Qt的事件写 ### 类MainWindow - 主要是实现Qt界面。大部分成员函数、变量都和OCCT无关,只是调用类View中的OCCT函数 - 视口管理,基本是固定代码 ```cpp void MainWindow::initOCCTView() { myViewer = Viewer(V3d_XposYnegZpos); myContext = new AIS_InteractiveContext(myViewer); view_occt = new View(myContext , this); view_occt->installEventFilter(this); setCentralWidget(view_occt); } Handle(V3d_Viewer) MainWindow::Viewer(const V3d_TypeOfOrientation theViewProj) { static Handle(OpenGl_GraphicDriver) aGraphicDriver; Handle(Aspect_DisplayConnection) aDisplayConnection; aGraphicDriver = new OpenGl_GraphicDriver(aDisplayConnection); Handle(V3d_Viewer) aViewer = new V3d_Viewer(aGraphicDriver); aViewer->SetDefaultViewProj(theViewProj); aViewer->SetDefaultLights(); aViewer->SetLightOn(); return aViewer; } ``` - 状态栏显示坐标,项目OCCTQtDemo会详细说明此处涉及OCCT接口 ```cpp void MainWindow::updateStatusBar(const std::vector& aNewPos) { double XScreen = aNewPos[0]; double YScreen = aNewPos[1]; double x , y , z; view_occt->getView()->Convert(XScreen , YScreen , x , y , z); // 将窗口坐标转化为三维坐标 gp_Pnt worldPnt = gp_Pnt(x , y , z); double xEye , yEye , zEye , xAt , yAt , zAt; view_occt->getView()->Eye(xEye , yEye , zEye); view_occt->getView()->At(xAt , yAt , zAt); gp_Pnt eyePoint(xEye , yEye , zEye); gp_Pnt atPoint(xAt , yAt , zAt); gp_Dir eyeDir(gp_Vec(eyePoint , atPoint)); //获取相机方向 gp_Pln plnAt = gp_Pln(atPoint , eyeDir); // 获取at平面 // 根据OCCT内置算法计算投影点坐标 Handle(Geom_Plane) geoPlane = new Geom_Plane(plnAt); GeomAPI_ProjectPointOnSurf project(worldPnt , geoPlane); gp_Pnt position = project.NearestPoint(); // 同上 //gp_Pnt2d ConvertedPointOnPlane = ProjLib::Project(plnAt , worldPnt); //gp_Pnt position1 = ElSLib::Value(ConvertedPointOnPlane.X() , ConvertedPointOnPlane.Y() , plnAt); //QString positionInfo1 = QString("Position: %0, %1, %2").arg(position1.X()).arg(position1.Y()).arg(position1.Z()); //QString screenPntInfo = QString("Screen: %0, %1").arg(XScreen).arg(YScreen); //QString worldPntInfo = QString("World: %0, %1, %2").arg(x).arg(y).arg(z); //QString eyePntInfo = QString("Eye: %0, %1, %2").arg(xEye).arg(yEye).arg(zEye); //QString atPntInfo = QString("At: %0, %1, %2").arg(xAt).arg(yAt).arg(zAt); QString positionInfo = QString("WCS: %0, %1, %2").arg(position.X()).arg(position.Y()).arg(position.Z()); //QString info = screenPntInfo + " " + positionInfo; lb_positionInfo->setText(positionInfo); } ``` ### 类OcctWindow - 相对官方demo,类OcctWindow用官方的修改就行 - 主要是修正Qt6分辨率缩放问题 ### 类View - 类`V3d_Viewer` 类`V3d_View`的创建代码比较固定 - 视图控制相关代码也比较固定,在Qt鼠标事件中实现即可 - 类`AIS_ViewCube`是视口导航工具, 类`AIS_RubberBand`是矩形选择框(一个矩形),以AIS开头的类,在后面会详细说明,简单说就是OCCT预制好的可交互(显示/选择等)模型,用户可以直接调用。 - OCCT的选择分两个方面。一方面要在Qt事件中实现类`AIS_InteractiveContext`的检测选择功能,一方面要确保`AIS_InteractiveContext`显示了类`AIS_InteractiveObject`(或者自定义的AIS类) - 类`AIS_InteractiveContext` - 相较与一般AIS类,此类比较特殊。可以理解为管理若干`AIS_InteractiveObject` 的管理器 ```cpp AIS_InteractiveContext::Display(); // 显示可交互AIS模型 AIS_InteractiveContext::Remove(); // 隐藏可交互AIS模型 // 鼠标移动时检测是否有可选模型,若有会添加到OCCT的选择管理器中 // 选择接口目前网上教程基本都是老版本的,注意接口版本与OCCT版本对应 AIS_InteractiveContext::MoveTo(aNewPos.x() , aNewPos.y() , myV3dView , false); AIS_InteractiveContext::SelectDetected(); //单选 AIS_InteractiveContext::SelectRectangle(); // 矩形选择 // 部分选择类型枚举 AIS_SelectionScheme_XOR // 类似ctrl+选择 AIS_SelectionScheme_Add // 类似shift+选择,但实际效果和XOR一样 ``` - 类`AIS_InteractiveObject`(或者自定义的AIS类) - OCCT模型数据在TopoDS_Shape/TopoDS_Vertex/TopoDS_Edge/TopoDS_Face等类中。这里打个比方:TopoDS_Edge类提供三维模型边的尺寸坐标信息,再将该数据放入类`AIS_InteractiveObject`中,类`AIS_InteractiveObject`定义了该边是否可选择、是什么颜色、高亮样式、透明度等等。可以和类`AIS_InteractiveContext`产生互动交互。自定义的类`AIS_InteractiveObject`也可以实现边的中点、端点是否可选,或者设置中点、端点的显示样式等功能。 - 此类后续有专门讲解 - 若要使用原生OCCT的显示交互功能,最好理解类`AIS_InteractiveObject`作用,能够继承该类实现自己的AIS类 ## 项目MViewVTK(可跳过) > 可以先运行显示个可交互的三维模型瞧瞧。。。 参考: overview索引: User Guides/VTK Integration Services (VIS) ![img](imgs/img15.png) ### 概况 - 与MView相比,主要是MVTKWidget类不一样,该类将VTK/OCCT/QT放在一起实现交互显示窗口。具体实现OCCT官方文档比较详细,而且代码数量不多。本专题不过多介绍 - 只关注OCCT原生交互显示的,可跳过VTK部分内容 ## 项目OCCTOverview > OCCT官方Qt示例,因为官方使用的Qt5,本demo修改主要就是Qt5到Qt6升级 本专题只编译运行了该demo,不详细解读该demo。因为此官方demo涉及OCCT接口较多,不太推荐一上来就学习该源码。 后期感兴趣的话,可以自己看看源码,参考下官方的实现。 ![img](imgs/img16.png) ## 项目OCCTQtDemo > 本专题主要demo。 ![img](imgs/img17.jpg) ![img](imgs/img18.png) ![img](imgs/img14.png) ![img](imgs/img19.png) ![img](imgs/img20.png) ### 概况 - 具体可去官方文档overview中找对应章节。涉及OCCT的示例代码基本在MainWindow类中,直接写在对应函数里了。 - 详细教程见本人B站链接,感谢大家观看后能够一键三连。 [【笔记1前期准备】opencascade(OCCT)-7.9+Qt6官方demo](https://www.bilibili.com/video/BV1AV59z5ESJ/?share_source=copy_web&vd_source=004e882833487e71b85a925c4d157996)