OpenCasCade学习笔记(三):加载显示STEP格式图片,并实现平移、缩放和旋转操作
C3DWidget.h
#pragma once
#include <QtWidgets/QApplication>
#include <QtWidgets/QWidget>
#include "qevent.h"
#include "stable.h"
#define BUTTON_OFF 0
#define BUTTON_ON 1
class C3DWidget : public QWidget
{
Q_OBJECT
public:
C3DWidget(QWidget *parent = Q_NULLPTR);
protected:
//!三维场景转换模式
enum CurrentAction3d
{
CurAction3d_Nothing,
CurAction3d_DynamicPanning, //平移
CurAction3d_DynamicZooming, //缩放
CurAction3d_DynamicRotation //旋转
};
//!覆写绘图事件
void paintEvent(QPaintEvent *);
//!覆写窗口尺寸变化事件
void resizeEvent(QResizeEvent *);
//!返回窗口的绘制引擎
QPaintEngine *paintEngine() const;
//!覆写键盘按键按下事件
//void keyPressEvent(QKeyEvent *event);
//!覆写键盘按键释放事件
//void keyReleaseEvent(QKeyEvent *event);
//!覆写鼠标按键按下事件
void mousePressEvent(QMouseEvent *event);
//!覆写鼠标按键释放事件
void mouseReleaseEvent(QMouseEvent *event);
//!覆写鼠标移动事件
void mouseMoveEvent(QMouseEvent *event);
//!覆写鼠标滚轮事件
void wheelEvent(QWheelEvent *event);
//加载step模型
void loadSTEP();
//显示STEP模型
void displaySTEP();
//把屏幕坐标转换为窗口坐标
gp_Pnt ConvertClickToPoint(Standard_Real theX, Standard_Real theY, Handle(V3d_View) theView);
void DrawLineByMouse(gp_Pnt thePntStart, gp_Pnt thePntEnd);
private:
//!交互式上下文能够管理一个或多个查看器(viewer)中的图形行为和交互式对象的选择
Handle(AIS_InteractiveContext) m_context;
//!定义查看器(viewer)类型对象上的服务
Handle(V3d_Viewer) m_viewer;
//!创建一个视图
Handle(V3d_View) m_view;
//!创建3d接口定义图形驱动程序
Handle(Graphic3d_GraphicDriver) m_graphic_driver;
//存储STEP模型形状
TopoDS_Shape m_Shape;
Handle_AIS_Shape myAISShape;
//线的模型
Handle_AIS_Shape myLine;
Standard_Integer m_x_max; //!记录鼠标平移坐标X
Standard_Integer m_y_max; //!记录鼠标平移坐标Y
CurrentAction3d m_current_mode; //!三维场景转换模式(平移\缩放\旋转)
bool leftMouseBtn = BUTTON_OFF; //记录鼠标左键状态
gp_Pnt m_line_start_point; //记录鼠标画线开始点
//gp_Pnt m_line_end_point; //记录鼠标画线结束点
// bool draw_line = false;
};
C3DWidget.cpp
#include "C3DWidget.h"
#include "ProjLib.hxx"
#include "ELSLib.hxx"
#include "GC_MakeSegment.hxx"
#include "BRepBuilderAPI_MakeEdge.hxx"
#include <gl\GLU.h>
#include <GeomAPI_IntCS.hxx>
#include "qdebug.h"
C3DWidget::C3DWidget(QWidget *parent)
: QWidget(parent)
{
//若交互式上下文为空,则创建对象
if (m_context.IsNull())
{
//此对象提供与X server的连接,在Windows和Mac OS中不起作用
Handle(Aspect_DisplayConnection) m_display_donnection = new Aspect_DisplayConnection();
//创建OpenGl图形驱动
if (m_graphic_driver.IsNull())
{
m_graphic_driver = new OpenGl_GraphicDriver(m_display_donnection);
}
//获取QWidget的窗口系统标识符
WId window_handle = (WId)winId();
//创建Windows NT 窗口
Handle(WNT_Window) wind = new WNT_Window((Aspect_Handle)window_handle);
//创建3D查看器
m_viewer = new V3d_Viewer(m_graphic_driver, Standard_ExtString("viewer3d"));
//创建视图
m_view = m_viewer->CreateView();
m_view->SetWindow(wind);
//打开窗口
if (!wind->IsMapped())
{
wind->Map();
}
m_context = new AIS_InteractiveContext(m_viewer); //创建交互式上下文
//配置查看器的光照
m_viewer->SetDefaultLights();
m_viewer->SetLightOn();
//设置视图的背景颜色为灰色
m_view->SetBackgroundColor(Quantity_NOC_GRAY60);
m_view->MustBeResized();
//显示直角坐标系,可以配置在窗口显示位置、文字颜色、大小、样式
m_view->TriedronDisplay(Aspect_TOTP_LEFT_LOWER, Quantity_NOC_GOLD, 0.08, V3d_ZBUFFER);
//设置显示模式
m_context->SetDisplayMode(AIS_Shaded, Standard_True);
loadSTEP();
displaySTEP();
}
//配置QWidget
setAttribute(Qt::WA_PaintOnScreen);
setAttribute(Qt::WA_NoSystemBackground);
setBackgroundRole(QPalette::NoRole); //无背景
setFocusPolicy(Qt::StrongFocus);
setAttribute(Qt::WA_PaintOnScreen);
setAttribute(Qt::WA_NoSystemBackground);
setMouseTracking(true); //开启鼠标位置追踪
}
void C3DWidget::paintEvent(QPaintEvent *)
{
//if(draw_line == false)
m_view->Redraw();
}
void C3DWidget::resizeEvent(QResizeEvent *)
{
if (!m_view.IsNull())
{
m_view->MustBeResized();
}
}
QPaintEngine *C3DWidget::paintEngine() const
{
return 0;
}
void C3DWidget::loadSTEP()
{
/*将STEP文件转换为OCCT形状:
加载文件,
检查文件一致性,
设置翻译参数,
执行翻译,
获取结果。*/
//load the file
STEPControl_Reader reader;
IFSelect_ReturnStatus stat = reader.ReadFile("sample.STEP");
switch (stat)
{
case IFSelect_RetVoid:
std::cout << "normal execution which created nothing, or no data to process!" << std::endl;
break;
case IFSelect_RetDone:
break;
case IFSelect_RetError:
std::cout << "error in command or input data, no execution!" << std::endl;
break;
case IFSelect_RetFail:
std::cout << "execution was run and has failed!" << std::endl;
break;
case IFSelect_RetStop:
std::cout << "indicates end or stop (such as Raise)!" << std::endl;
break;
default:
break;
}
if (stat != IFSelect_RetDone)
return;
//Selecting STEP entities for translation : The whole file
//加载文件
Standard_Integer NbRoots = reader.NbRootsForTransfer();
Standard_Integer num = reader.TransferRoots();
//Mapping STEP entities to Open CASCADE Technology shapes
m_Shape = reader.OneShape();
}
void C3DWidget::displaySTEP()
{
//display STEP
myAISShape = new AIS_Shape(m_Shape);
myAISShape->SetDisplayMode(AIS_Shaded);
m_context->Display(myAISShape, true);
}
void C3DWidget::mousePressEvent(QMouseEvent *event)
{
if (((event->buttons() & Qt::MidButton) && (QApplication::keyboardModifiers() == Qt::CTRL)))//平移
{
m_current_mode = CurAction3d_DynamicPanning;
m_x_max = event->pos().x(); //记录起始X位置
m_y_max = event->pos().y(); //记录起始Y位置
}
else if (event->buttons() & Qt::MidButton) //旋转
{
m_current_mode = CurAction3d_DynamicRotation;
m_view->StartRotation(event->pos().x(), event->pos().y());
}
if (event->buttons() & Qt::LeftButton)
{
leftMouseBtn = BUTTON_ON;
//m_line_start_point = ConvertClickToPoint(event->pos().x(), event->pos().x(), m_view);
}
}
void C3DWidget::mouseReleaseEvent(QMouseEvent *event)
{
GLdouble res[3];
GLdouble mm[16], pm[16]; GLint vp[4];
GLfloat pix;
m_current_mode = CurAction3d_Nothing;
if (leftMouseBtn == BUTTON_ON)
{
leftMouseBtn = BUTTON_OFF;
//GLdouble x = event->pos().x();
//GLdouble y = event->pos().y();
//GLint viewport[4];
//GLdouble modleview[16];
//GLdouble projection[16];
获取必要的矩阵
//glPushMatrix();
//glLoadIdentity();
//glLoadMatrixd(m_view->Camera()->OrientationMatrix());
//glGetIntegerv(GL_VIEWPORT, viewport);//获取视口
//glGetDoublev(GL_MODELVIEW_MATRIX, modleview);//获取模型视图矩阵
//glGetDoublev(GL_PROJECTION_MATRIX, projection);//获取投影矩阵
//glPopMatrix();
将屏幕坐标转换为窗口坐标
//GLdouble winX = x;
//GLdouble winY = viewport[3] - y;
//GLdouble winZ1 = 0;
//GLdouble winZ2 = 10;
//double x1, y1, z1, x2, y2, z2;
坐标变换
//gluUnProject(winX, winY, winZ1, modleview, projection, viewport, &x1, &y1, &z1);
//gluUnProject(winX, winY, winZ2, modleview, projection, viewport, &x2, &y2, &z2);
//
生成直线
//Handle(Geom_Line) aLine = new Geom_Line(gp_Pnt(x1, y1, z1), gp_Dir(x2 - x1, y2 - y1, z2 - z1));
//GeomAPI_IntCS intCS(aLine, aSurface);
//gp_Pnt aPnt = intCS.Point(1);
//qDebug() << aPnt.X() << aPnt.Y() << aPnt.Z();
//====================方案二=====================
获取模型视图矩阵
//glGetDoublev(GL_MODELVIEW_MATRIX, mm);
获取投影矩阵
//glGetDoublev(GL_PROJECTION_MATRIX, pm);
获取视口
//glGetIntegerv(GL_VIEWPORT, vp);
读取缓冲区的深度分量
//glReadPixels(event->pos().x(), event->pos().y(), 1, 1, GL_DEPTH_COMPONENT, GL_FLOAT, &pix);
//GLfloat depthrange[2] = { 0,0 };
//glGetFloatv(GL_DEPTH_RANGE, depthrange);
//if (pix == depthrange[1])
// qDebug() << "false";
反投影
//gluUnProject(event->pos().x(), event->pos().y(), pix, mm, pm, vp, &res[0], &res[1], &res[2]);
qDebug() << res[0] << res[1] << res[2];
}
}
void C3DWidget::mouseMoveEvent(QMouseEvent *event)
{
switch (m_current_mode)
{
case CurAction3d_DynamicPanning:
//执行平移
m_view->Pan(event->pos().x() - m_x_max, m_y_max - event->pos().y());
m_x_max = event->pos().x();
m_y_max = event->pos().y();
break;
case CurAction3d_DynamicRotation:
//执行旋转
m_view->Rotation(event->pos().x(), event->pos().y());
break;
}
//if (leftMouseBtn == BUTTON_ON)
//{
// gp_Pnt m_line_end_point = ConvertClickToPoint(event->pos().x(), event->pos().x(), m_view);
// DrawLineByMouse(m_line_start_point, m_line_end_point);
//}
}
void C3DWidget::wheelEvent(QWheelEvent *event)
{
m_view->StartZoomAtPoint(event->pos().x(), event->pos().y());
m_view->ZoomAtPoint(0, 0, event->angleDelta().y(), 0); //执行缩放
}
gp_Pnt C3DWidget::ConvertClickToPoint(Standard_Real theX, Standard_Real theY, Handle(V3d_View) theView)
{
Standard_Real XEye, YEye, ZEye, XAt, YAt, ZAt;
theView->Eye(XEye, YEye, ZEye);
theView->At(XAt, YAt, ZAt);
gp_Pnt EyePoint(XEye, YEye, ZEye);
gp_Pnt AtPoint(XAt, YAt, ZAt);
gp_Vec EyeVector(EyePoint, AtPoint);
gp_Dir EyeDir(EyeVector);
gp_Pln PlaneOfTheView = gp_Pln(AtPoint, EyeDir);
Standard_Real X, Y, Z;
theView->Convert(int(theX), int(theY), X, Y, Z);
gp_Pnt ConvertedPoint(X, Y, Z);
gp_Pnt2d ConvertedPointOnPlane = ProjLib::Project(PlaneOfTheView, ConvertedPoint);
gp_Pnt ResultPoint = ElSLib::Value(ConvertedPointOnPlane.X(),ConvertedPointOnPlane.Y(),PlaneOfTheView);
return ResultPoint;
}
void C3DWidget::DrawLineByMouse(gp_Pnt thePntStart, gp_Pnt thePntEnd)
{
//检查传入参数
if (thePntStart.IsEqual(thePntEnd, 1e-3))
return;
//构建拓扑线段
Handle(Geom_TrimmedCurve) aSegment =
GC_MakeSegment(thePntStart, thePntEnd);
TopoDS_Edge aEdge = BRepBuilderAPI_MakeEdge(aSegment);
//将构建的拓扑线段设置至AIS_Shape形状中
myAISShape->SetShape(aEdge);
//移除前面绘画的旧线段, 绘制新线段。
m_context->Remove(myAISShape, true);
m_context->Display(myAISShape, false);
//更新View
m_context->UpdateCurrentViewer();
}
stable.h
#pragma once
#include <AIS_InteractiveContext.hxx>
#include <AIS_InteractiveObject.hxx>
#include <AIS_ListOfInteractive.hxx>
#include <AIS_ListIteratorOfListOfInteractive.hxx>
#include <AIS_Shape.hxx>
#include <AIS_Trihedron.hxx>
#include <Aspect_Background.hxx>
#include <Aspect_TypeOfline.hxx>
#include <Aspect_WidthOfline.hxx>
#include <Aspect_Window.hxx>
#include <Bnd_Box2d.hxx>
#include <BndLib_Add2dCurve.hxx>
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <BRepBuilderAPI.hxx>
#include <BRepAlgo.hxx>
#include <BRepTools.hxx>
#include <BRepPrimAPI_MakeBox.hxx>
#include <BRepPrimAPI_MakeCylinder.hxx>
#include <Standard_DefineHandle.hxx>
#include <DsgPrs_LengthPresentation.hxx>
#include <GCE2d_MakeSegment.hxx>
#include <GCPnts_TangentialDeflection.hxx>
#include <Geom_CartesianPoint.hxx>
#include <Geom_Axis2Placement.hxx>
#include <Geom_CartesianPoint.hxx>
#include <Geom_Line.hxx>
#include <Geom_Surface.hxx>
#include <Geom2d_BezierCurve.hxx>
#include <Geom2d_BSplineCurve.hxx>
#include <Geom2d_Curve.hxx>
#include <Geom2d_TrimmedCurve.hxx>
#include <Geom2dAdaptor_Curve.hxx>
#include <GeomAbs_CurveType.hxx>
#include <GeomAdaptor_Curve.hxx>
#include <GeomTools_Curve2dSet.hxx>
#include <gp_Ax2d.hxx>
#include <gp_Circ2d.hxx>
#include <gp_Dir2d.hxx>
#include <gp_Lin2d.hxx>
#include <gp_Pnt2d.hxx>
#include <gp_Vec.hxx>
#include <gp_Vec2d.hxx>
#include <MMgt_TShared.hxx>
#include <OSD_Environment.hxx>
#include <Precision.hxx>
#include <Prs3d_Drawer.hxx>
#include <Prs3d_IsoAspect.hxx>
#include <Prs3d_LineAspect.hxx>
#include <Prs3d_Text.hxx>
#include <Quantity_Factor.hxx>
#include <Quantity_Length.hxx>
#include <Quantity_NameOfColor.hxx>
#include <Quantity_PhysicalQuantity.hxx>
#include <Quantity_PlaneAngle.hxx>
#include <Quantity_TypeOfColor.hxx>
#include <SelectMgr_EntityOwner.hxx>
#include <SelectMgr_SelectableObject.hxx>
#include <SelectMgr_Selection.hxx>
#include <SelectMgr_SelectionManager.hxx>
#include <Standard_Boolean.hxx>
#include <Standard_CString.hxx>
#include <Standard_ErrorHandler.hxx>
#include <Standard_Integer.hxx>
#include <Standard_IStream.hxx>
#include <Standard_Macro.hxx>
#include <Standard_NotImplemented.hxx>
#include <Standard_OStream.hxx>
#include <Standard_Real.hxx>
#include <StdPrs_Curve.hxx>
#include <StdPrs_Point.hxx>
#include <StdPrs_PoleCurve.hxx>
#include <TCollection_AsciiString.hxx>
#include <TColgp_Array1OfPnt2d.hxx>
#include <TColgp_HArray1OfPnt2d.hxx>
#include <TCollection_AsciiString.hxx>
#include <TColStd_HSequenceOfTransient.hxx>
#include <TColStd_MapIteratorOfMapOfTransient.hxx>
#include <TColStd_MapOfTransient.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Compound.hxx>
#include <TopoDS_ListIteratorOfListOfShape.hxx>
#include <TopoDS_Shape.hxx>
#include <TopoDS_Solid.hxx>
#include <TopoDS_Vertex.hxx>
#include <TopExp.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
#include <TopTools_HSequenceOfShape.hxx>
#include <TopTools_DataMapOfShapeInteger.hxx>
#include <UnitsAPI.hxx>
#include <V3d_View.hxx>
#include <V3d_Viewer.hxx>
#include <WNT_Window.hxx>
#include <OpenGl_GraphicDriver.hxx>
// specific STEP
#include <STEPControl_Controller.hxx>
#include <STEPControl_Reader.hxx>
#include <STEPControl_Writer.hxx>
main.cpp
#include "C3DWidget.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
C3DWidget w;
w.show();
return a.exec();
}