OpenCASCADE(OCC)在MFC中实现模型的旋转、平移、缩放的实现

上一篇文章中的视频展示了模型的旋转、平移和缩放的运行结果图。下面是具体的实现:

首先在*****View.h中定义一下成员变量:

protected:
	//三维场景转换模式
	enum CurrentAction3d
	{
		CurAction3d_Nothing,
		CurAction3d_DynamicPanning, //平移
		CurAction3d_DynamicZooming, //缩放
		CurAction3d_DynamicRotation //旋转
	};
	Standard_Integer m_x_max;    //记录鼠标平移坐标X
	Standard_Integer m_y_max;    //记录鼠标平移坐标Y
	float m_scale;    //记录滚轮缩放比例 
	CurrentAction3d m_current_mode; //三维场景转换模式(平移\缩放\旋转)
	bool leftMouseBtn = false; //记录鼠标左键状态
	bool midMouseBtn = false;  //记录鼠标中键状态
	CPoint mouseDownPT;    //控制旋转角度
	CPoint m_Pt;

接着在*****View的类向导中添加鼠标消息响应:

添加完成之后,会出现六个成员函数:

public:
	
	afx_msg void OnMouseMove(UINT nFlags, CPoint point);
	afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);
	afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
	afx_msg void OnMButtonDown(UINT nFlags, CPoint point);
	afx_msg void OnMButtonUp(UINT nFlags, CPoint point);

至此,成员变量和成员函数添加完毕。

接下来进行变量初始化和函数的实现:

在*****View.h的构造函数COCCmfcMDIView::COCCmfcMDIView() noexcept 进行变量的初始化

COCCmfcMDIView::COCCmfcMDIView() noexcept
{
	// TODO: 在此处添加构造代码
	mouseDownPT.x = 0;
	mouseDownPT.y = 0;

	m_Pt.x = 0;
	m_Pt.y = 0;
	m_scale = 1.0;
}

下面进行鼠标响应事件的实现:

1. afx_msg void OnLButtonDown(UINT nFlags, CPoint point);的实现

void COCCmfcMDIView::OnLButtonDown(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	m_current_mode = CurAction3d_DynamicRotation;
	mouseDownPT = point;
	myView->StartRotation(point.x, point.y);
	leftMouseBtn = true;
	CView::OnLButtonDown(nFlags, point);
}

2. afx_msg void OnLButtonUp(UINT nFlags, CPoint point);的实现

void COCCmfcMDIView::OnLButtonUp(UINT nFlags, CPoint point)
{
    // TODO: 在此添加消息处理程序代码和/或调用默认值
    m_current_mode = CurAction3d_Nothing;
    if (leftMouseBtn==true)
    {
        leftMouseBtn = false;
    }
    CView::OnLButtonUp(nFlags, point);
}

3. afx_msg void OnMButtonDown(UINT nFlags, CPoint point);的实现

//鼠标中键按下事件初始操作
void COCCmfcMDIView::OnMButtonDown(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	m_current_mode = CurAction3d_DynamicPanning;
	mouseDownPT = point;
	m_x_max = point.x; //记录平移时起始X位置
	m_y_max = point.y; //记录平移时起始Y位置
	midMouseBtn = true;
	CView::OnMButtonDown(nFlags, point);
}

4. afx_msg void OnMButtonUp(UINT nFlags, CPoint point);的实现

void COCCmfcMDIView::OnMButtonUp(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	m_current_mode = CurAction3d_Nothing;
	if (midMouseBtn==true)
	{
		midMouseBtn == false;
	}
	CView::OnMButtonUp(nFlags, point);
}

5. afx_msg void OnMouseMove(UINT nFlags, CPoint point);的实现

void COCCmfcMDIView::OnMouseMove(UINT nFlags, CPoint point)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值

	CView::OnMouseMove(nFlags, point);
	
	switch (m_current_mode)
	{

	case COCCmfcMDIView::CurAction3d_DynamicPanning:
		//执行平移
		myView->Pan(point.x - m_x_max, m_y_max-point.y);
		m_x_max = point.x;
		m_y_max = point.y;
		break;
	
	case COCCmfcMDIView::CurAction3d_DynamicRotation:
		//执行旋转
		myView->Rotation(point.x, point.y);
		break;
	}
	
}

6. afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);的实现

BOOL COCCmfcMDIView::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
{
	// TODO: 在此添加消息处理程序代码和/或调用默认值
	static float upLimit = 10.0f;
	static float downLimit = 0.04f;
	static float fUp = 1.1f;
	static float fDown = 0.9f;
	m_Pt = pt;
	myView->StartZoomAtPoint(pt.x, pt.y);   //在鼠标光标的点处进行放大
	if (zDelta > 0 && m_scale <= upLimit)
	{
		m_scale *= fUp;
		myView->ZoomAtPoint(0, 0, 10, 0);
	}
	else if (zDelta<0 && m_scale>downLimit)
	{
		m_scale *= fDown;
		myView->ZoomAtPoint(0, 0, -10, 0);

	}
	
	return CView::OnMouseWheel(nFlags, zDelta, pt);
}

至此,完成了的模型的旋转、平移、缩放功能 !!!!!!!!!!!

### OpenCASCADE平移旋转实现方式 #### 平移功能的实现OpenCASCADEMFC 应用程序中,可以通过捕获鼠标的移动事件并更新视图矩阵来实现平移效果。具体来说,在 `View.h` 文件中定义了一个枚举类型 `CurrentAction3d` 来表示当前的操作模式(无操作、平移缩放旋转)。当用户按下鼠标中间按钮时,进入平移模式 (`CurAction3d_DynamicPanning`),并通过记录鼠标位置的变化量调整视图的位置[^4]。 以下是平移的核心逻辑代码示例: ```cpp void CMyView::OnMouseMove(UINT nFlags, CPoint point) { if (m_current_mode == CurAction3d_DynamicPanning && midMouseBtn) { int deltaX = point.x - mouseDownPT.x; int deltaY = point.y - mouseDownPT.y; Handle_V3d_View aView = myAISContext->CurrentViewer()->ActiveView(); gp_Pnt eye, center, vec; aView->ProjectionType() == V3d_PERSPECTIVE ? aView->ProjReferencePlane().Coefficients(eye.X(), eye.Y(), eye.Z()) : aView->Camera()->Direction().XYZ().Coord(center.X(), center.Y(), center.Z()); double aspectRatio = static_cast<double>(aView->Window()->Height()) / aView->Window()->Width(); gp_Trsf trsf; trsf.SetTranslation(gp_Vec(deltaX * 0.1 / aspectRatio, -deltaY * 0.1, 0)); aView->SetTransform(trsf); aView->Redraw(); } } ``` 上述代码通过计算鼠标位移 `(deltaX, deltaY)` 调整视图中心点的位置,并应用变换矩阵重新渲染视图。 --- #### 旋转功能的实现 对于旋转功能,同样依赖于用户的输入行为触发相应的处理函数。当检测到鼠标右键拖动时,切换至动态旋转模式 (`CurAction3d_DynamicRotation`),利用两次点击之间的角度差值构建绕特定轴向的旋转变换矩阵。 下面是旋转的具体实现片段: ```cpp void CMyView::OnLButtonDown(UINT nFlags, CPoint point) { if (!leftMouseBtn) { leftMouseBtn = true; m_current_mode = CurAction3d_DynamicRotation; mouseDownPT = point; } } void CMyView::OnMouseMove(UINT nFlags, CPoint point) { if (m_current_mode == CurAction3d_DynamicRotation && leftMouseBtn) { int deltaX = point.x - mouseDownPT.x; int deltaY = point.y - mouseDownPT.y; Handle_V3d_View aView = myAISContext->CurrentViewer()->ActiveView(); gp_Ax1 axisOfRotation(aView->CenterOfRotation(), gp::OX()); gp_Trsf rotationTransformation; Standard_Real angleInRadians = deltaX * M_PI / 180.0; // 假设每像素对应一度角变化 rotationTransformation.SetRotation(axisOfRotation, angleInRadians); aView->SetTransform(rotationTransformation); aView->Redraw(); } } ``` 此部分实现了基于鼠标水平方向偏移量的角度增量映射关系,从而完成围绕指定轴线的连续旋转动作。 --- ### 总结 综上所述,OpenCASCADE 提供了一套完善的工具链支持开发者轻松集成交互式的三维图形界面组件。无论是简单的几何对象展示还是复杂的装配体浏览需求都可以借助其内置 API 完成高效开发工作流[^2]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值