【OCCT+ImGUI系列】007-GP-几何变换gp_trsf

在这里插入图片描述

一、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);
参数说明
参数名类型作用
translationVecgp_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θ+(1cosθ)x2(1cosθ)yx+zsinθ(1cosθ)zxysinθ0(1cosθ)xyzsinθcosθ+(1cosθ)y2(1cosθ)zy+xsinθ0(1cosθ)xz+ysinθ(1cosθ)yzxsinθcosθ+(1cosθ)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);
参数说明
参数名类型作用
rotationAxisgp_Ax1旋转轴定义(位置+方向)
angleStandard_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(1s)px(1s)py(1s)pz1

代码实现
gp_Pnt basePoint(0, 0, 0);  // 缩放基准点
Standard_Real scale = 2.0;   // 放大2倍

gp_Trsf trsf;
trsf.SetScale(basePoint, scale);
参数说明
参数名类型作用
basePointgp_Pnt缩放中心点
scaleStandard_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());
        }
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值