Qt多文档实现参看Qt多文档程序的一种实现
概要
本文利用Occ搭建一个简易CAD程序框架,包括新建并显示一个box并、操作杆交互操纵box。其中视图中可以显示3d坐标系以及View Cube。本文主要讲实现,理论请参看OCC的官方文档即可。
文档类CADDocument
-
在文档类中,关于occ的成员有3个,参看头文件声明
#pragma once #include <QObject> #include <list> #include "V3d_Viewer.hxx" #include "AIS_InteractiveContext.hxx" #include "TDocStd_Document.hxx" class CADChildWindow; //相当与MFC的CDocument class CADDocument : public QObject { //其他略 //... public: Handle(V3d_Viewer) getOccViewer() const { return myViewer; } Handle(AIS_InteractiveContext) getAISContext() const { return myAISContext; } private: //其他略 //... Handle(V3d_Viewer) myViewer; Handle(AIS_InteractiveContext) myAISContext; Handle(TDocStd_Document) myDoc; };
-
文档类构造函数中做了些工作,此处是为了演示,一般来说,构造函数不要做太多逻辑,职责单一需要遵守。构造函数中主要新建了V3d_Viewer,并将OpenGL的图形驱动传给它,然后开启了默认的光照,设置了背景色为黑色。接着创建了交互上下文AIS_InteractiveContext,并设置显示模式为着色。然后加入了View Cube,在occ 7.4.0版本开始,occ帮实现了一个View Cube,目前3d程序一般都有这个功能,在occ中,加入这个非常简单,只需要new一个AIS_ViewCube,然后设置下基本属性即可。最后使用BRepPrimAPI_MakeBox创建了一个box,然后加入显示,并且激活模型点、边、面的选择。
CADDocument::CADDocument(QObject *parent) : QObject(parent) { //其他略 //... Handle(Graphic3d_GraphicDriver) aGraphicDriver = ((CADApplication*)qApp)->GetGraphicDriver(); myViewer = new V3d_Viewer(aGraphicDriver); myViewer->SetDefaultLights(); myViewer->SetLightOn(); myViewer->SetDefaultBackgroundColor(Quantity_Color(0.0, 0.0, 0.0, Quantity_TOC_RGB)); // myViewer->SetDefaultVisualization(V3d_TypeOfVisualization::V3d_ZBUFFER);//暂不知干什么的,无法控制真实模式显示,默认还是线框 myAISContext = new AIS_InteractiveContext(myViewer); myAISContext->SetDisplayMode(AIS_Shaded, Standard_True);//设置显示着色模式 //View Cube Handle(AIS_ViewCube) hViewCube = new AIS_ViewCube(); hViewCube->SetDrawAxes(Standard_False); hViewCube->SetTransformPersistence(new Graphic3d_TransformPers( Graphic3d_TMF_TriedronPers, Aspect_TOTP_RIGHT_UPPER, Graphic3d_Vec2i(70, 70))); myAISContext->Display(hViewCube, Standard_True); //此处直接加入一个box显示 //BRepPrimAPI_MakeTorus mkTorus(30, 10); //create box for test BRepPrimAPI_MakeBox mkBox(gp_Pnt(0, 0, 0), 10, 20, 30); TopoDS_Shape aShpae = mkBox.Shape(); Handle(AIS_Shape) hBoxShape = new AIS_Shape(aShpae); myAISContext->Display(hBoxShape, Standard_True); //开启点、边、面的选择 myAISContext->Deactivate(hBoxShape); myAISContext->Activate(hBoxShape, AIS_Shape::SelectionMode(TopAbs_FACE)); myAISContext->Activate(hBoxShape, AIS_Shape::SelectionMode(TopAbs_EDGE)); myAISContext->Activate(hBoxShape, AIS_Shape::SelectionMode(TopAbs_VERTEX)); }
视图类 CADView
-
头文件声明
CADView中定义了occ的视图类V3d_View#pragma once #include <QWidget> #include "V3d_View.hxx" class CADDocument; //相当与MFC中的CView class CADView : public QWidget { Q_OBJECT public: CADView(QWidget *parent = Q_NULLPTR); ~CADView(); CADDocument* getDocument() const; virtual QPaintEngine* paintEngine() const; virtual void paintEvent(QPaintEvent*); virtual void resizeEvent(QResizeEvent*); virtual void mousePressEvent(QMouseEvent*); virtual void mouseReleaseEvent(QMouseEvent*); virtual void mouseMoveEvent(QMouseEvent*); private: Handle(V3d_View) myView; int m_nLastX = 0; int m_nLastY = 0; };
-
初始化occ视图
CADView::CADView( QWidget *parent) : QWidget(parent) { this->setMinimumSize(300, 200); this->setAttribute(Qt::WA_PaintOnScreen); this->setAttribute(Qt::WA_NoSystemBackground); this->setMouseTracking(true); //创建V3dView并设置投影信息 myView = getDocument()->getOccViewer()->CreateView(); myView->SetProj(V3d_TypeOfOrientation::V3d_XnegYnegZpos); // myView->SetVisualization(V3d_TypeOfVisualization::V3d_ZBUFFER);//这句无作用 //myView->SetComputedMode(Standard_True); myView->Camera()->SetProjectionType(Graphic3d_Camera::Projection::Projection_Orthographic); //关联Qt窗口到V3dView Handle(OcctWindow) aOcctWindow = new OcctWindow(this); myView->SetWindow(aOcctWindow); if (!aOcctWindow->IsMapped()) { aOcctWindow->Map(); } //显示坐标系 myView->TriedronDisplay(Aspect_TOTP_LEFT_LOWER, Quantity_NOC_BLUE1, 0.15, V3d_ZBUFFER); myView->ZBufferTriedronSetup(); myView->FitAll(); }
-
通用的一些设置,参看occ自带的例子程序
CADView::paintEngine()、CADView::paintEvent(QPaintEvent *)、CADView::resizeEvent(QResizeEvent *)一般就这么写,重载的几个鼠标相关的函数,主要是为了图形选择、图形操作杆、ViewCube的功能。QPaintEngine* CADView::paintEngine() const { return 0; } void CADView::paintEvent(QPaintEvent *) { myView->Redraw(); } void CADView::resizeEvent(QResizeEvent *) { if (!myView.IsNull()) { myView->MustBeResized(); } } void CADView::mousePressEvent(QMouseEvent* e) { if (e->button() == Qt::RightButton) { if (e->modifiers() & Qt::ControlModifier)//开始旋转:ctrl+鼠标右键 { myView->StartRotation(e->x(), e->y()); m_nLastX = e->x(); m_nLastY = e->y(); } } } void CADView::mouseReleaseEvent(QMouseEvent* e) { if (e->button() == Qt::LeftButton) { auto hAisContext = getDocument()->getAISContext(); if (hAisContext) { //鼠标移动,激活选择功能 hAisContext->MoveTo(e->x(), e->y(), myView, Standard_False); hAisContext->Select(Standard_True); //code for test // SelectMgr_ListOfFilter aFilters = hAisContext->Filters(); // for (auto it = aFilters.begin(); it != aFilters.end(); ++it) // { // auto aFilter = *it; // int b = 10; // } } } } void CADView::mouseMoveEvent(QMouseEvent* e) { // onMouseMove(e->buttons(), e->pos()); Qt::MouseButtons mouseButtons = e->buttons(); Qt::KeyboardModifiers keyFlags = e->modifiers(); if (mouseButtons & Qt::MouseButton::MiddleButton) { if (keyFlags & Qt::ControlModifier)//平移:ctrl+鼠标中键 { myView->Pan(e->x() - m_nLastX, m_nLastY - e->y()); } } else if (mouseButtons & Qt::MouseButton::LeftButton) { if (keyFlags & Qt::ControlModifier)//缩放:ctrl+鼠标左键 { myView->Zoom(m_nLastX, m_nLastY, e->x(), e->y()); } } else if (mouseButtons & Qt::MouseButton::RightButton) { if (keyFlags & Qt::ControlModifier) //旋转:ctrl+鼠标中键 { myView->Rotation(e->x(), e->y()); } } m_nLastX = e->x(); m_nLastY = e->y(); //转达鼠标移动,激活选择功能、ViewCube的响应 auto hAisContext = getDocument()->getAISContext(); if (hAisContext) { hAisContext->MoveTo(e->x(), e->y(), myView, Standard_True); } }
-
OcctWindow
直接从occ关于qt例子程序复制过来即可,这个类很重要,是occ在qt窗口中显示图形的关键。
源码
https://gitee.com/shanql/OccLearn/tree/v1.0.0/src