一、gp_Trsf 简介
gp_Trsf
是 OpenCASCADE (OCC) 中实现三维几何变换的核心类,支持平移、旋转、缩放等基础变换操作,并能通过矩阵组合实现复合变换。其特点是:
- 数学精确性:基于线性代数矩阵运算
- 操作灵活性:支持局部/全局坐标系变换
- 高效可视化:可与
AIS_Shape
无缝集成
广泛应用于 CAD 建模、机器人运动学、动画路径计算等领域。以下示例展示如何通过交互界面控制立方体变换:
二、核心变换操作解析
1. 平移变换 (Translation)
数学原理
将物体沿指定向量移动,变换矩阵形式为:
T
=
[
1
0
0
t
x
0
1
0
t
y
0
0
1
t
z
0
0
0
1
]
T = \begin{bmatrix} 1 & 0 & 0 & t_x \\ 0 & 1 & 0 & t_y \\ 0 & 0 & 1 & t_z \\ 0 & 0 & 0 & 1 \end{bmatrix}
T=
100001000010txtytz1
代码实现
// 设置平移向量
gp_Vec translationVec(10.0, 20.0, 5.0);
// 创建变换对象
gp_Trsf trsf;
trsf.SetTranslation(translationVec);
// 应用变换到几何体
BRepBuilderAPI_Transform transformer(shape, trsf);
参数说明
参数名 | 类型 | 作用 |
---|---|---|
translationVec | gp_Vec | 定义 XYZ 方向位移量 |
2. 旋转变换 (Rotation)
数学原理
绕指定轴旋转 θ 角度,变换矩阵为:
R
=
[
cos
θ
+
(
1
−
cos
θ
)
x
2
(
1
−
cos
θ
)
x
y
−
z
sin
θ
(
1
−
cos
θ
)
x
z
+
y
sin
θ
0
(
1
−
cos
θ
)
y
x
+
z
sin
θ
cos
θ
+
(
1
−
cos
θ
)
y
2
(
1
−
cos
θ
)
y
z
−
x
sin
θ
0
(
1
−
cos
θ
)
z
x
−
y
sin
θ
(
1
−
cos
θ
)
z
y
+
x
sin
θ
cos
θ
+
(
1
−
cos
θ
)
z
2
0
0
0
0
1
]
R = \begin{bmatrix} \cosθ + (1-\cosθ)x^2 & (1-\cosθ)xy - z\sinθ & (1-\cosθ)xz + y\sinθ & 0 \\ (1-\cosθ)yx + z\sinθ & \cosθ + (1-\cosθ)y^2 & (1-\cosθ)yz - x\sinθ & 0 \\ (1-\cosθ)zx - y\sinθ & (1-\cosθ)zy + x\sinθ & \cosθ + (1-\cosθ)z^2 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}
R=
cosθ+(1−cosθ)x2(1−cosθ)yx+zsinθ(1−cosθ)zx−ysinθ0(1−cosθ)xy−zsinθcosθ+(1−cosθ)y2(1−cosθ)zy+xsinθ0(1−cosθ)xz+ysinθ(1−cosθ)yz−xsinθcosθ+(1−cosθ)z200001
代码实现
// 定义旋转轴(过原点,方向为Z轴)
gp_Ax1 rotationAxis(gp_Pnt(0,0,0), gp_Dir(0,0,1));
// 设置旋转角度(45度转弧度)
Standard_Real angle = 45.0 * M_PI / 180.0;
gp_Trsf trsf;
trsf.SetRotation(rotationAxis, angle);
参数说明
参数名 | 类型 | 作用 |
---|---|---|
rotationAxis | gp_Ax1 | 旋转轴定义(位置+方向) |
angle | Standard_Real | 旋转角度(弧度制) |
3. 缩放变换 (Scaling)
数学原理
以基准点为中心进行等比缩放:
S
=
[
s
0
0
(
1
−
s
)
p
x
0
s
0
(
1
−
s
)
p
y
0
0
s
(
1
−
s
)
p
z
0
0
0
1
]
S = \begin{bmatrix} s & 0 & 0 & (1-s)p_x \\ 0 & s & 0 & (1-s)p_y \\ 0 & 0 & s & (1-s)p_z \\ 0 & 0 & 0 & 1 \end{bmatrix}
S=
s0000s0000s0(1−s)px(1−s)py(1−s)pz1
代码实现
gp_Pnt basePoint(0, 0, 0); // 缩放基准点
Standard_Real scale = 2.0; // 放大2倍
gp_Trsf trsf;
trsf.SetScale(basePoint, scale);
参数说明
参数名 | 类型 | 作用 |
---|---|---|
basePoint | gp_Pnt | 缩放中心点 |
scale | Standard_Real | 缩放系数(>0) |
三、完整实现流程
步骤1:创建原始几何体
生成基础立方体并设置可视化属性:
// 创建立方体(边长50mm)
TopoDS_Shape box = BRepPrimAPI_MakeBox(50.0, 50.0, 50.0).Shape();
// 创建可视化对象
Handle(AIS_Shape) originalShape = new AIS_Shape(box);
originalShape->SetColor(Quantity_NOC_SKYBLUE);
context->Display(originalShape, Standard_True);
步骤2:构建交互界面
使用 ImGui 实现参数控制面板:
// 平移参数控件
ImGui::SliderFloat3("Translation", translation.data(), -50.f, 50.f);
// 旋转参数控件
ImGui::SliderFloat3("Rotation Axis", rotationAxis.data(), -1.f, 1.f);
ImGui::SliderFloat("Rotation Angle", &rotationAngle, 0.f, 360.f);
// 缩放参数控件
ImGui::SliderFloat("Scale Factor", &scaleFactor, 0.1f, 5.f);
步骤3:应用变换
根据用户选择执行变换操作:
平移
trsf.SetTranslation(gp_Vec(translation[0], translation[1], translation[2]));
旋转
trsf.SetRotation(axis, rotationAngle * M_PI / 180.0);
缩放
trsf.SetScale(gp_Pnt(0,0,0), scaleFactor);
四、参数影响分析
1. 平移向量方向性
- 正向平移:
(10, 0, 0)
沿X轴正方向移动 - 复合位移:
(5, 10, 3)
产生空间对角线运动 - 零向量:保持物体原位
2. 旋转轴方向敏感性
旋转轴方向 | 可视化效果 |
---|---|
(0,0,1) | 绕Z轴旋转(类似车轮转动) |
(1,1,0) | 产生倾斜旋转效果 |
非单位向量 | 自动归一化处理 |
3. 缩放系数特性
缩放系数 | 效果 | 限制条件 |
---|---|---|
>1.0 | 放大物体 | 必须为正数 |
=1.0 | 保持原尺寸 | |
<1.0 | 缩小物体 | |
=0.0 | 触发 Standard_ConstructionError 异常 | 需异常捕获处理 |
五、代码
#pragma once
#include "pch.h"
#include <gp_Trsf.hxx>
#include <gp_Ax1.hxx>
#include <gp_Ax2.hxx>
#include <gp_Pln.hxx>
#include <BRepPrimAPI_MakeBox.hxx>
#include <BRepBuilderAPI_Transform.hxx>
#include <AIS_Shape.hxx>
#include "BaseScene.h"
#include "VisSceneComponents.h"
#include "TutorialWindow.h"
class MDTrsf007 : public BaseScene, public VisSceneComponents, public TutorialWindow {
public:
MDTrsf007() { openTutorialWindow(); }
void displayScene(const Handle(V3d_View)& view, const Handle(AIS_InteractiveContext)& context) override {
if (context.IsNull()) return;
if (!bIsSceneInit) {
sceneInit(view, context);
bIsSceneInit = true;
}
renderTutorialWindow(context);
}
void sceneInit(const Handle(V3d_View)& view, const Handle(AIS_InteractiveContext)& context) override {
// 创建初始立方体
CreateOriginalBox(context);
}
void customInitTutorialWindow(const Handle(AIS_InteractiveContext)& context) override {}
void renderTutorialContent(const Handle(AIS_InteractiveContext)& context) override {
// 变换参数控制
ImGui::SliderFloat3("Translation", translation.data(), -50.f, 50.f);
ImGui::SliderFloat3("Rotation Axis", rotationAxis.data(), -1.f, 1.f);
ImGui::SliderFloat("Rotation Angle", &rotationAngle, 0.f, 360.f);
ImGui::SliderFloat("Scale Factor", &scaleFactor, 0.1f, 5.f);
// 变换操作按钮
if (ImGui::CollapsingHeader("Transformation Operations", ImGuiTreeNodeFlags_DefaultOpen)) {
if (ImGui::Button("Apply Translation")) ApplyTransform(context, OperationType::Translation);
if (ImGui::Button("Apply Rotation")) ApplyTransform(context, OperationType::Rotation);
if (ImGui::Button("Apply Scale")) ApplyTransform(context, OperationType::Scale);
if (ImGui::Button("Reset to Original")) ResetShape(context);
}
}
private:
enum class OperationType { Translation, Rotation, Mirror, Scale };
// 变换参数
std::array<float, 3> translation{ 0.f, 0.f, 0.f };
std::array<float, 3> rotationAxis{ 0.f, 0.f, 1.f };
float rotationAngle = 45.f;
float scaleFactor = 1.5f;
// 几何对象
Handle(AIS_Shape) originalShape; // 原始立方体
Handle(AIS_Shape) transformedShape; // 变换后的物体
std::vector<Handle(AIS_Shape)> auxShapes; // 辅助线
// 创建原始立方体
void CreateOriginalBox(const Handle(AIS_InteractiveContext)& context) {
TopoDS_Shape box = BRepPrimAPI_MakeBox(50.0, 50.0, 50.0).Shape();
originalShape = new AIS_Shape(box);
originalShape->SetColor(Quantity_NOC_SKYBLUE);
context->Display(originalShape, Standard_True);
}
// 清除变换后的物体
void ClearTransformed(const Handle(AIS_InteractiveContext)& context) {
if (!transformedShape.IsNull()) {
context->Remove(transformedShape, Standard_False);
transformedShape.Nullify();
}
for (auto& shape : auxShapes) context->Remove(shape, Standard_False);
auxShapes.clear();
context->UpdateCurrentViewer();
}
// 重置到原始状态
void ResetShape(const Handle(AIS_InteractiveContext)& context) {
ClearTransformed(context);
originalShape->SetTransparency(0.0);
context->UpdateCurrentViewer();
}
void ApplyTransform(const Handle(AIS_InteractiveContext)& context, OperationType op) {
ClearTransformed(context);
try {
gp_Trsf trsf;
switch (op) {
case OperationType::Translation: {
trsf.SetTranslation(gp_Vec(translation[0], translation[1], translation[2]));
break;
}
case OperationType::Rotation: {
gp_Ax1 axis(gp_Pnt(0, 0, 0),
gp_Dir(rotationAxis[0], rotationAxis[1], rotationAxis[2]));
trsf.SetRotation(axis, rotationAngle * M_PI / 180.0);
break;
}
case OperationType::Scale: {
trsf.SetScale(gp_Pnt(0, 0, 0), scaleFactor);
break;
}
}
BRepBuilderAPI_Transform transformer(originalShape->Shape(), trsf);
transformedShape = new AIS_Shape(transformer.Shape());
transformedShape->SetColor(Quantity_NOC_ORANGE);
transformedShape->SetTransparency(0.5);
context->Display(transformedShape, Standard_True);
}
catch (Standard_Failure const& e) {
ImGui::TextColored(ImVec4(1, 0, 0, 1), "Transform Error: %s", e.GetMessageString());
}
}
};