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
运行演示