简易CAD程序:使用OCC的自带的功能,搭建程序框架

Qt多文档实现参看Qt多文档程序的一种实现

概要

本文利用Occ搭建一个简易CAD程序框架,包括新建并显示一个box并、操作杆交互操纵box。其中视图中可以显示3d坐标系以及View Cube。本文主要讲实现,理论请参看OCC的官方文档即可。
在这里插入图片描述

文档类CADDocument

  1. 在文档类中,关于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;
    };
    
  2. 文档类构造函数中做了些工作,此处是为了演示,一般来说,构造函数不要做太多逻辑,职责单一需要遵守。构造函数中主要新建了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

  1. 头文件声明
    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;
    };
    
    
  2. 初始化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();
    
    }
    
  3. 通用的一些设置,参看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);
    	}
    }
    
    
  4. OcctWindow
    直接从occ关于qt例子程序复制过来即可,这个类很重要,是occ在qt窗口中显示图形的关键。

源码

https://gitee.com/shanql/OccLearn/tree/v1.0.0/src

运行演示

在这里插入图片描述

  • 13
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值