Open CASCADE学习|QT5.12.10实现可视化

文章详细描述了如何在Qt应用程序中利用OCC库进行几何建模,创建一个三维瓶子模型,包括定义支持点、构建几何体、定义拓扑结构,以及添加颈部、应用倒角和创建空心体。最后展示了如何在程序中显示坐标轴和视方体以辅助用户理解和操作模型。
摘要由CSDN通过智能技术生成

目录

 

1、代码编写

OCC.h:

QtWidgetsApplication1.h:

QtWidgetsApplication1.cpp:

main.cpp:

2、项目配置

3、代码调试

4、运行结果

5、显示坐标轴、视方体

修改QtWidgetsApplication1.cpp:


 

1、代码编写

 

b2a41c812166fe4bf5b3be0abefed28f.png

以默认条件创建一个QT项目,添加以下源文件与头文件:

OCC.h:

#include <BRep_Tool.hxx>
#include <BRepAlgoAPI_Fuse.hxx>
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepBuilderAPI_Transform.hxx>
#include <BRepFilletAPI_MakeFillet.hxx>
#include <BRepLib.hxx>
#include <BRepOffsetAPI_MakeThickSolid.hxx>
#include <BRepOffsetAPI_ThruSections.hxx>
#include <BRepPrimAPI_MakeCylinder.hxx>
#include <BRepPrimAPI_MakePrism.hxx>
#include <GC_MakeArcOfCircle.hxx>
#include <GC_MakeSegment.hxx>
#include <GCE2d_MakeSegment.hxx>
#include <gp.hxx>
#include <gp_Ax1.hxx>
#include <gp_Ax2.hxx>
#include <gp_Ax2d.hxx>
#include <gp_Dir.hxx>
#include <gp_Dir2d.hxx>
#include <gp_Pnt.hxx>
#include <gp_Pnt2d.hxx>
#include <gp_Trsf.hxx>
#include <gp_Vec.hxx>
#include <Geom_CylindricalSurface.hxx>
#include <Geom_Plane.hxx>
#include <Geom_Surface.hxx>
#include <Geom_TrimmedCurve.hxx>
#include <Geom2d_Ellipse.hxx>
#include <Geom2d_TrimmedCurve.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Wire.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Compound.hxx>
#include <TopTools_ListOfShape.hxx>
​
​
//QT
using namespace std;
class OCC
{
public:
    TopoDS_Shape MakeBottle(const Standard_Real myWidth, const Standard_Real myHeight, const Standard_Real myThickness)
{
        // Profile : Define Support Points
        gp_Pnt aPnt1(-myWidth / 2., 0, 0);
        gp_Pnt aPnt2(-myWidth / 2., -myThickness / 4., 0);
        gp_Pnt aPnt3(0, -myThickness / 2., 0);
        gp_Pnt aPnt4(myWidth / 2., -myThickness / 4., 0);
        gp_Pnt aPnt5(myWidth / 2., 0, 0);
​
        // Profile : Define the Geometry
        Handle(Geom_TrimmedCurve) anArcOfCircle = GC_MakeArcOfCircle(aPnt2, aPnt3, aPnt4);
        Handle(Geom_TrimmedCurve) aSegment1 = GC_MakeSegment(aPnt1, aPnt2);
        Handle(Geom_TrimmedCurve) aSegment2 = GC_MakeSegment(aPnt4, aPnt5);
​
        // Profile : Define the Topology
        TopoDS_Edge anEdge1 = BRepBuilderAPI_MakeEdge(aSegment1);
        TopoDS_Edge anEdge2 = BRepBuilderAPI_MakeEdge(anArcOfCircle);
        TopoDS_Edge anEdge3 = BRepBuilderAPI_MakeEdge(aSegment2);
        TopoDS_Wire aWire = BRepBuilderAPI_MakeWire(anEdge1, anEdge2, anEdge3);
​
        // Complete Profile
        gp_Ax1 xAxis = gp::OX();
        gp_Trsf aTrsf;
​
        aTrsf.SetMirror(xAxis);
        BRepBuilderAPI_Transform aBRepTrsf(aWire, aTrsf);
        TopoDS_Shape aMirroredShape = aBRepTrsf.Shape();
        TopoDS_Wire aMirroredWire = TopoDS::Wire(aMirroredShape);
        BRepBuilderAPI_MakeWire mkWire;
        mkWire.Add(aWire);
        mkWire.Add(aMirroredWire);
        TopoDS_Wire myWireProfile = mkWire.Wire();
        // Body : Prism the Profile
        TopoDS_Face myFaceProfile = BRepBuilderAPI_MakeFace(myWireProfile);
        gp_Vec aPrismVec(0, 0, myHeight);
        TopoDS_Shape myBody = BRepPrimAPI_MakePrism(myFaceProfile, aPrismVec);
        // Body : Apply Fillets
        BRepFilletAPI_MakeFillet mkFillet(myBody);
        TopExp_Explorer anEdgeExplorer(myBody, TopAbs_EDGE);
        while (anEdgeExplorer.More()) {
            TopoDS_Edge anEdge = TopoDS::Edge(anEdgeExplorer.Current());
            //Add edge to fillet algorithm
            mkFillet.Add(myThickness / 12., anEdge);
            anEdgeExplorer.Next();
        }
        myBody = mkFillet.Shape();
        // Body : Add the Neck  
        gp_Pnt neckLocation(0, 0, myHeight);
        gp_Dir neckAxis = gp::DZ();
        gp_Ax2 neckAx2(neckLocation, neckAxis);
        Standard_Real myNeckRadius = myThickness / 4.;
        Standard_Real myNeckHeight = myHeight / 10.;
        BRepPrimAPI_MakeCylinder MKCylinder(neckAx2, myNeckRadius, myNeckHeight);
        TopoDS_Shape myNeck = MKCylinder.Shape();
        myBody = BRepAlgoAPI_Fuse(myBody, myNeck);
        // Body : Create a Hollowed Solid
        TopoDS_Face   faceToRemove;
        Standard_Real zMax = -1;
​
        for (TopExp_Explorer aFaceExplorer(myBody, TopAbs_FACE); aFaceExplorer.More(); aFaceExplorer.Next()) {
            TopoDS_Face aFace = TopoDS::Face(aFaceExplorer.Current());
            // Check if <aFace> is the top face of the bottle抯 neck 
            Handle(Geom_Surface) aSurface = BRep_Tool::Surface(aFace);
            if (aSurface->DynamicType() == STANDARD_TYPE(Geom_Plane)) {
                Handle(Geom_Plane) aPlane = Handle(Geom_Plane)::DownCast(aSurface);
                gp_Pnt aPnt = aPlane->Location();
                Standard_Real aZ = aPnt.Z();
                if (aZ > zMax) {
                    zMax = aZ;
                    faceToRemove = aFace;
                }
            }
        }
        TopTools_ListOfShape facesToRemove;
        facesToRemove.Append(faceToRemove);
        BRepOffsetAPI_MakeThickSolid aSolidMaker;
        aSolidMaker.MakeThickSolidByJoin(myBody, facesToRemove, -myThickness / 50, 1.e-3);
        myBody = aSolidMaker.Shape();
        // Threading : Create Surfaces
        Handle(Geom_CylindricalSurface) aCyl1 = new Geom_CylindricalSurface(neckAx2, myNeckRadius * 0.99);
        Handle(Geom_CylindricalSurface) aCyl2 = new Geom_CylindricalSurface(neckAx2, myNeckRadius * 1.05);
        // Threading : Define 2D Curves
        gp_Pnt2d aPnt(2. * M_PI, myNeckHeight / 2.);
        gp_Dir2d aDir(2. * M_PI, myNeckHeight / 4.);
        gp_Ax2d anAx2d(aPnt, aDir);
        Standard_Real aMajor = 2. * M_PI;
        Standard_Real aMinor = myNeckHeight / 10;
        Handle(Geom2d_Ellipse) anEllipse1 = new Geom2d_Ellipse(anAx2d, aMajor, aMinor);
        Handle(Geom2d_Ellipse) anEllipse2 = new Geom2d_Ellipse(anAx2d, aMajor, aMinor / 4);
        Handle(Geom2d_TrimmedCurve) anArc1 = new Geom2d_TrimmedCurve(anEllipse1, 0, M_PI);
        Handle(Geom2d_TrimmedCurve) anArc2 = new Geom2d_TrimmedCurve(anEllipse2, 0, M_PI);
        gp_Pnt2d anEllipsePnt1 = anEllipse1->Value(0);
        gp_Pnt2d anEllipsePnt2 = anEllipse1->Value(M_PI);
​
        Handle(Geom2d_TrimmedCurve) aSegment = GCE2d_MakeSegment(anEllipsePnt1, anEllipsePnt2);
        // Threading : Build Edges and Wires
        TopoDS_Edge anEdge1OnSurf1 = BRepBuilderAPI_MakeEdge(anArc1, aCyl1);
        TopoDS_Edge anEdge2OnSurf1 = BRepBuilderAPI_MakeEdge(aSegment, aCyl1);
        TopoDS_Edge anEdge1OnSurf2 = BRepBuilderAPI_MakeEdge(anArc2, aCyl2);
        TopoDS_Edge anEdge2OnSurf2 = BRepBuilderAPI_MakeEdge(aSegment, aCyl2);
        TopoDS_Wire threadingWire1 = BRepBuilderAPI_MakeWire(anEdge1OnSurf1, anEdge2OnSurf1);
        TopoDS_Wire threadingWire2 = BRepBuilderAPI_MakeWire(anEdge1OnSurf2, anEdge2OnSurf2);
        BRepLib::BuildCurves3d(threadingWire1);
        BRepLib::BuildCurves3d(threadingWire2);
        // Create Threading 
        BRepOffsetAPI_ThruSections aTool(Standard_True);
        aTool.AddWire(threadingWire1);
        aTool.AddWire(threadingWire2);
        aTool.CheckCompatibility(Standard_False);
        TopoDS_Shape myThreading = aTool.Shape();
        // Building the Resulting Compound 
        TopoDS_Compound aRes;
        BRep_Builder aBuilder;
        aBuilder.MakeCompound(aRes);
        aBuilder.Add(aRes, myBody);
        aBuilder.Add(aRes, myThreading);
        return aRes;
    }
};
​

QtWidgetsApplication1.h:

#pragma once
#include <QtWidgets/QMainWindow>
#include <Standard_Handle.hxx>
#include <V3d_Viewer.hxx>
#include <OpenGl_GraphicDriver.hxx>
#include <WNT_Window.hxx>
#include <V3d_View.hxx>
#include <AIS_InteractiveContext.hxx>
#include <BRepPrimAPI_MakeBox.hxx>
#include <TopoDs_Shape.hxx>
#include <AIS_Shape.hxx>
#include <qevent.h>
#include "OCC.h"
#include "ui_QtWidgetsApplication1.h"
​
class QtWidgetsApplication1 : public QMainWindow
{
    Q_OBJECT
​
public:
    QtWidgetsApplication1(QWidget* parent = nullptr);
    ~QtWidgetsApplication1();
protected:
    //重写绘图事件
    void paintEvent(QPaintEvent* event) override;
    //返回窗口绘图引擎
    QPaintEngine* paintEngine() const;
​
    enum Action3d
    {
        Action3d_Nothing,
        Action3d_Panning,//平移
        Action3d_Zooming,//缩放
        Action3d_Rotation//旋转
    };
​
    void mousePressEvent(QMouseEvent* event) override;
    void mouseReleaseEvent(QMouseEvent* event) override;
    void mouseMoveEvent(QMouseEvent* event) override;
    void wheelEvent(QWheelEvent* event) override;
​
​
private:
    //Ui::QtWidgetsApplication1Class  ui;
    //定义查看器viewer 3D查看器
    Handle(V3d_Viewer) viewer;
    //视图
    Handle(V3d_View) view;
    //交互式上下文,管理一个或者多个viewer
    Handle(AIS_InteractiveContext) context;
    //window NT窗口
    Handle(WNT_Window) window;
​
​
    Standard_Integer m_x;//记录鼠标平移坐标X
    Standard_Integer m_y;//记录鼠标平移坐标y
    Action3d m_mode;//平移、缩放、旋转
​
    OCC occ;
​
};
​

QtWidgetsApplication1.cpp:

#include "QtWidgetsApplication1.h"
QtWidgetsApplication1::QtWidgetsApplication1(QWidget* parent)
    : QMainWindow(parent)
{
    resize(1000, 1000);
    //提供X server的连接,在window和Mac中不起作用
    Handle(Aspect_DisplayConnection) hAspect_DisplayConnect = new Aspect_DisplayConnection;
    //创建3D接口定义图形驱动
    Handle(OpenGl_GraphicDriver) driver = new OpenGl_GraphicDriver(hAspect_DisplayConnect);
    //该类的方法允许编辑、询问连接该类的其他参数(如视图、光)
    viewer = new V3d_Viewer(driver);
    view = viewer->CreateView();
    WId win_handle = winId();
    //在已有的窗口上创建窗口
    window = new WNT_Window((Aspect_Handle)win_handle);
    view->SetWindow(window);
    if (!window->IsMapped())
    {
        window->Map();//打开窗口
    }
    view->SetBackgroundColor(Quantity_NOC_WHITE);
    view->MustBeResized();
    viewer->SetDefaultLights();
    setAttribute(Qt::WA_PaintOnScreen);
    //交互式上下文
    context = new AIS_InteractiveContext(viewer);
    context->SetDisplayMode(AIS_Shaded, Standard_True);
    TopoDS_Shape boxShape = occ.MakeBottle(50, 70, 30);
    Quantity_Color color = Quantity_Color(0.3, 0.5, 0.3, Quantity_TOC_RGB);
    Handle(AIS_Shape) abox = new AIS_Shape(boxShape);
    context->SetMaterial(abox, Graphic3d_NameOfMaterial_Stone, Standard_False);
    context->SetColor(abox, color, Standard_False);
    context->Display(abox, 1, 1, Standard_True);
    view->FitAll();
}
​
QtWidgetsApplication1::~QtWidgetsApplication1()
{}
void QtWidgetsApplication1::paintEvent(QPaintEvent* event)
{
    view->Redraw();
}
​
QPaintEngine* QtWidgetsApplication1::paintEngine() const
{
    return 0;
}
void QtWidgetsApplication1::mousePressEvent(QMouseEvent* event)
{
    //平移 鼠标右键+shift
    if ((event->buttons() & Qt::RightButton))//&& (QApplication::keyboardModifiers() == Qt::ShiftModifier))
    {
        m_mode = Action3d_Panning;
        m_x = event->pos().x();
        m_y = event->pos().y();
    }
    else if (event->buttons() & Qt::MidButton)//旋转
    {
        m_mode = Action3d_Rotation;
        //开始旋转视图围绕屏幕轴
        view->StartRotation(event->pos().x(), event->pos().y());
    }
}
void QtWidgetsApplication1::mouseReleaseEvent(QMouseEvent* event)
{
    m_mode = Action3d_Nothing;
}
​
void QtWidgetsApplication1::mouseMoveEvent(QMouseEvent* event)
{
    switch (m_mode)
    {
    case QtWidgetsApplication1::Action3d_Panning:
        view->Pan(event->pos().x() - m_x, m_y - event->pos().y());
        m_x = event->pos().x();
        m_y = event->pos().y();
        break;
    case QtWidgetsApplication1::Action3d_Rotation:
        view->Rotation(event->pos().x(), event->pos().y());
        break;
    default:
        break;
    }
}
//缩放
//Zoom方法通过相邻两侧鼠标位置来判断缩小或者放大,以及缩放程度。鼠标滚轮event->angleDelta().y()会返回数值,以此模拟第二次鼠标位置
void QtWidgetsApplication1::wheelEvent(QWheelEvent* event)
{
    //view->Zoom(0, 0, event->angleDelta().y(), 0);//固定点缩放
    //跟随鼠标位置进行缩放
    view->StartZoomAtPoint(event->pos().x(), event->pos().y());
    view->ZoomAtPoint(0, 0, event->angleDelta().y(), 0);
}
​

main.cpp:

#include "QtWidgetsApplication1.h"
#include <QtWidgets/QApplication>
​
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QtWidgetsApplication1 w;
    w.show();
    return a.exec();
}
​

2、项目配置

添加QT的库文件与头文件

添加OCC的库文件与头文件

3、代码调试

调试过程发现,无论怎么修改OCC的库文件,总是报错找不到xxx.dll文件,我是采用如下方法解决的:将OCC的库文件下的所有dll文件拷贝到该QT项目的Debug目录下,也就是生成exe的目录下。

4、运行结果

 

d6958f3273f235f0bc5b98e2760684fe.png

5、显示坐标轴、视方体

修改QtWidgetsApplication1.cpp:

#include "QtWidgetsApplication1.h"
#include <AIS_ViewCube.hxx>
#include <Geom_Axis2Placement.hxx>
#include <AIS_Trihedron.hxx>
QtWidgetsApplication1::QtWidgetsApplication1(QWidget* parent)
    : QMainWindow(parent)
{
    resize(500, 500);
    //提供X server的连接,在window和Mac中不起作用
    Handle(Aspect_DisplayConnection) hAspect_DisplayConnect = new Aspect_DisplayConnection;
    //创建3D接口定义图形驱动
    Handle(OpenGl_GraphicDriver) driver = new OpenGl_GraphicDriver(hAspect_DisplayConnect);
    //该类的方法允许编辑、询问连接该类的其他参数(如视图、光)
    viewer = new V3d_Viewer(driver);
    view = viewer->CreateView();
    view->TriedronDisplay(Aspect_TOTP_LEFT_LOWER, Quantity_NOC_WHITE, 0.1, V3d_ZBUFFER);//这是显示小坐标系的代码
    WId win_handle = winId();
    //在已有的窗口上创建窗口
    window = new WNT_Window((Aspect_Handle)win_handle);
    view->SetWindow(window);
    if (!window->IsMapped())
    {
        window->Map();//打开窗口
    }
    view->SetBackgroundColor(Quantity_NOC_WHITE);
    view->MustBeResized();
    viewer->SetDefaultLights();
    setAttribute(Qt::WA_PaintOnScreen);
    //交互式上下文
    context = new AIS_InteractiveContext(viewer);
    context->SetDisplayMode(AIS_Shaded, Standard_True);
    
​
    //creat viewbox
    //myView->TriedronErase(); 隐藏坐标系
    Handle(AIS_ViewCube) viewCube = new AIS_ViewCube();
    context->Display(viewCube, Standard_True);
​
​
    //创建工件坐标系
    gp_Pnt origionPnt(0, 0, 0);//原点
    gp_Pnt xAxisPnt(1, 0, 0);
    gp_Vec vectorX(origionPnt, xAxisPnt);          //X轴矢量
    gp_Dir aixX(vectorX / vectorX.Magnitude());// X轴
​
    gp_Vec vectorY = vectorX.Rotated(gp_Ax1(origionPnt, gp_Dir(0, 0, 1)), M_PI_2);  //获取Y轴矢量
    gp_Vec vectorZ = vectorX.Crossed(vectorY); //Z轴矢量
    gp_Dir aixZ = (vectorZ / vectorZ.Magnitude());//Z轴
​
    gp_Ax2 ax2 = gp_Ax2(origionPnt, aixZ, aixX);
    Handle(Geom_Axis2Placement) TrihedronAxis = new Geom_Axis2Placement(ax2);
    Handle(AIS_Trihedron) partTrihedron = new AIS_Trihedron(TrihedronAxis);
​
    partTrihedron->SetTypeOfPresentation(PrsMgr_TypeOfPresentation3d::PrsMgr_TOP_AllView);   //设置显示样式,所有视图有效
    partTrihedron->SetDatumDisplayMode(Prs3d_DatumMode::Prs3d_DM_Shaded);              //设置基准形状样式
    //设置轴向标签
    partTrihedron->SetLabel(Prs3d_DatumParts::Prs3d_DP_Origin, "OC");
    partTrihedron->SetLabel(Prs3d_DatumParts::Prs3d_DP_XAxis, "XC");
    partTrihedron->SetLabel(Prs3d_DatumParts::Prs3d_DP_YAxis, "YC");
    partTrihedron->SetLabel(Prs3d_DatumParts::Prs3d_DP_ZAxis, "ZC");
    //设置轴向颜色
    partTrihedron->SetColor(Quantity_NOC_BLUE);
    partTrihedron->SetXAxisColor(Quantity_NOC_RED);
    partTrihedron->SetYAxisColor(Quantity_NOC_GREEN);
    //设置轴值,默认是100mm,可以修改
    partTrihedron->SetSize(100);
    context->Display(partTrihedron, true);
​
​
    //display model
    TopoDS_Shape boxShape = occ.MakeBottle(50, 70, 30);
    Quantity_Color color = Quantity_Color(0.3, 0.5, 0.3, Quantity_TOC_RGB);
    Handle(AIS_Shape) abox = new AIS_Shape(boxShape);
    context->SetMaterial(abox, Graphic3d_NameOfMaterial_Stone, Standard_False);
    context->SetColor(abox, color, Standard_False);
    context->Display(abox, 1, 1, Standard_True);
    view->FitAll();
}
​
QtWidgetsApplication1::~QtWidgetsApplication1()
{}
void QtWidgetsApplication1::paintEvent(QPaintEvent* event)
{
    view->Redraw();
}
​
QPaintEngine* QtWidgetsApplication1::paintEngine() const
{
    return 0;
}
void QtWidgetsApplication1::mousePressEvent(QMouseEvent* event)
{
    //平移 鼠标右键+shift
    if ((event->buttons() & Qt::RightButton))//&& (QApplication::keyboardModifiers() == Qt::ShiftModifier))
    {
        m_mode = Action3d_Panning;
        m_x = event->pos().x();
        m_y = event->pos().y();
    }
    else if (event->buttons() & Qt::MidButton)//旋转
    {
        m_mode = Action3d_Rotation;
        //开始旋转视图围绕屏幕轴
        view->StartRotation(event->pos().x(), event->pos().y());
    }
}
void QtWidgetsApplication1::mouseReleaseEvent(QMouseEvent* event)
{
    m_mode = Action3d_Nothing;
}
​
void QtWidgetsApplication1::mouseMoveEvent(QMouseEvent* event)
{
    switch (m_mode)
    {
    case QtWidgetsApplication1::Action3d_Panning:
        view->Pan(event->pos().x() - m_x, m_y - event->pos().y());
        m_x = event->pos().x();
        m_y = event->pos().y();
        break;
    case QtWidgetsApplication1::Action3d_Rotation:
        view->Rotation(event->pos().x(), event->pos().y());
        break;
    default:
        break;
    }
}
//缩放
//Zoom方法通过相邻两侧鼠标位置来判断缩小或者放大,以及缩放程度。鼠标滚轮event->angleDelta().y()会返回数值,以此模拟第二次鼠标位置
void QtWidgetsApplication1::wheelEvent(QWheelEvent* event)
{
    //view->Zoom(0, 0, event->angleDelta().y(), 0);//固定点缩放
    //跟随鼠标位置进行缩放
    view->StartZoomAtPoint(event->pos().x(), event->pos().y());
    view->ZoomAtPoint(0, 0, event->angleDelta().y(), 0);
}
​

dcc8da93d5fa9c5f02c73ce5df962056.png

 

参考文献

1、https://zhuanlan.zhihu.com/p/644533395

2、https://blog.csdn.net/T20151470/article/details/135434210

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值