手动仿射变换

news2024/11/26 12:27:10

开发环境:

  1. Windows 11 家庭中文版
  2. Microsoft Visual Studio Community 2019
  3. VTK-9.3.0.rc0
  4. vtk-example
  5. 参考代码
  6. 目的:学习与总结

demo解决问题:通过仿射控件vtkAffineWidget对目标actor进行手动的拖拽的仿射变换

关键类:vtkAffineWidget

仿射变换概念参考链接
在这里插入图片描述

关键代码说明及效果展示:

  1. 获取仿射控件的transtorm,并设置到需要同等仿射变换的actor中
  this->AffineRep->GetTransform(this->Transform);
  this->Actor->SetUserTransform(this->Transform);
  1. SetUserTransform详细说明:(需要重点理解user的含义)
  /**
   * In addition to the instance variables such as position and orientation, you can add an additional transformation for your own use.  
   * This transformation is concatenated with the actor's internal transformation, which you implicitly create through the use of SetPosition(), SetOrigin() and SetOrientation().
   * If the internal transformation is identity (i.e. if you don't set the Position, Origin, or Orientation) then the actors final transformation will be the UserTransform, concatenated with the UserMatrix if the UserMatrix is present.
   */

/**
   * 除了位置和方向等实例变量外,您还可以添加额外的变换供自己使用。 
   * 此转换与 actor 的内部转换连接,通过使用 SetPosition()、SetOrigin() 和 SetOrientation() 隐式创建。

   * 如果内部转换是 identity(即,如果您没有设置 Position、Origin 或 Orientation),则 actor 的最终转换将是 UserTransform,如果存在 UserMatrix,则与 UserMatrix 串联。
   */

在这里插入图片描述
3. affineWidget添加观察者对象

  affineWidget->AddObserver(vtkCommand::InteractionEvent, affineCallback);
  affineWidget->AddObserver(vtkCommand::EndInteractionEvent, affineCallback);

  //这里可以考虑使用renderWindowInteractor进行回调,但是回调中需要判断操作对象是否为放射控件,比较繁琐
  //renderWindowInteractor->AddObserver(vtkCommand::InteractionEvent,affineCallback);
  //renderWindowInteractor->AddObserver(vtkCommand::EndInteractionEvent,affineCallback);
  1. 成员函数:SetRepresentationToWireframe()
    在这里插入图片描述

  2. GrandientBackgroundOn(开启渐变色)、SetBackground(底部颜色设置)、SetBackground2(顶部颜色设置)
    在这里插入图片描述
    在这里插入图片描述


#include <vtkActor.h>
#include <vtkAffineRepresentation2D.h>
#include <vtkAffineWidget.h>
#include <vtkAppendPolyData.h>
#include <vtkCallbackCommand.h>
#include <vtkCommand.h>
#include <vtkInteractorStyleSwitch.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkPlaneSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkSphereSource.h>
#include <vtkTransform.h>

namespace {
class vtkAffineCallback : public vtkCallbackCommand
{
public:
  static vtkAffineCallback* New()
  {
    return new vtkAffineCallback;
  }
  virtual void Execute(vtkObject* caller, unsigned long, void*);
  vtkAffineCallback() : Actor(0), AffineRep(0)
  {
    this->Transform = vtkTransform::New();
  }
  ~vtkAffineCallback()
  {
    this->Transform->Delete();
  }
  vtkActor* Actor;
  vtkAffineRepresentation2D* AffineRep;
  vtkTransform* Transform;
};
} // namespace

int main(int, char*[])
{
  vtkNew<vtkNamedColors> colors;

  // Create two spheres: a larger one and a smaller one on top of the larger one
  // to show a reference point while rotating
  vtkNew<vtkSphereSource> sphereSource;//大球
  sphereSource->Update();
  std::cout << "sphereSource radius: " <<  sphereSource->GetRadius() << std::endl;//0.5
  std::cout << "sphereSource center: " 
            << sphereSource->GetCenter()[0] << " "
            << sphereSource->GetCenter()[1] << " "
            << sphereSource->GetCenter()[2] << " "
            << std::endl; // 0 0 0

  vtkNew<vtkSphereSource> sphereSource2;//小球(中心刚好位于大球正上方边缘处)
  sphereSource2->SetRadius(0.075);
  sphereSource2->SetCenter(0, 0.5, 0);
  sphereSource2->Update();

  // Append the two spheres into one vtkPolyData
  vtkNew<vtkAppendPolyData> append;
  append->AddInputConnection(sphereSource->GetOutputPort());
  append->AddInputConnection(sphereSource2->GetOutputPort());

  // Create a plane centered over the larger sphere with 4x4 sub sections
  vtkNew<vtkPlaneSource> planeSource;
  planeSource->SetXResolution(4);
  planeSource->SetYResolution(4);
  planeSource->SetOrigin(-1, -1, 0);    //左下角
  planeSource->SetPoint1(1, -1, 0);     //右下角
  planeSource->SetPoint2(-1, 1, 0);     //左上角

  // Create a mapper and actor for the plane: show it as a wireframe
  vtkNew<vtkPolyDataMapper> planeMapper;
  planeMapper->SetInputConnection(planeSource->GetOutputPort());
  vtkNew<vtkActor> planeActor;
  planeActor->SetMapper(planeMapper);
  planeActor->GetProperty()->SetRepresentationToWireframe();//设置表现形式为线形边框;否则为面板
  planeActor->GetProperty()->SetColor(colors->GetColor3d("Red").GetData());//设置线形边框为欸红色

  // Create a mapper and actor for the spheres
  vtkNew<vtkPolyDataMapper> mapper;
  mapper->SetInputConnection(append->GetOutputPort());
  vtkNew<vtkActor> actor;
  actor->SetMapper(mapper);
  actor->GetProperty()->SetRepresentationToWireframe(); //只有线构成的球体

  // Create a renderer and render window
  vtkNew<vtkRenderer> renderer;
  vtkNew<vtkRenderWindow> renderWindow;
  renderWindow->AddRenderer(renderer);
  renderWindow->SetWindowName("AffineWidget");

  renderer->AddActor(actor);
  renderer->AddActor(planeActor);
  renderer->GradientBackgroundOn();                                         // 开启渐变色背景设置
  renderer->SetBackground(colors->GetColor3d("LightSkyBlue").GetData());    // 设置页面底部颜色值
  renderer->SetBackground2(colors->GetColor3d("MidnightBlue").GetData());   // 设置页面顶部颜色值

  // Create an interactor
  vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
  renderWindowInteractor->SetRenderWindow(renderWindow);
  dynamic_cast<vtkInteractorStyleSwitch*>(
      renderWindowInteractor->GetInteractorStyle())
      ->SetCurrentStyleToTrackballCamera();//设置交互对象是相机,形式是trackball

  // Create an affine widget to manipulate the actor
  // the widget currently only has a 2D representation and therefore applies
  // transforms in the X-Y plane only
  vtkNew<vtkAffineWidget> affineWidget;
  affineWidget->SetInteractor(renderWindowInteractor);
  affineWidget->CreateDefaultRepresentation();
  dynamic_cast<vtkAffineRepresentation2D*>(affineWidget->GetRepresentation())
      ->PlaceWidget(actor->GetBounds());//设置放射操作控件的位置在actor的外接矩形正中间

  //定义仿射控件交互事件对应的回调对象,并添加到观察者列表中,交互时进行通知
  vtkNew<vtkAffineCallback> affineCallback;
  affineCallback->Actor = actor;
  affineCallback->AffineRep = dynamic_cast<vtkAffineRepresentation2D*>(
      affineWidget->GetRepresentation());

  affineWidget->AddObserver(vtkCommand::InteractionEvent, affineCallback);
  affineWidget->AddObserver(vtkCommand::EndInteractionEvent, affineCallback);

  //这里可以考虑使用renderWindowInteractor进行回调,但是回调中需要判断操作对象是否为放射控件,比较繁琐
  //renderWindowInteractor->AddObserver(vtkCommand::InteractionEvent,affineCallback);
  //renderWindowInteractor->AddObserver(vtkCommand::EndInteractionEvent,affineCallback);

  renderWindow->Render();
  renderWindowInteractor->Initialize();
  renderWindow->Render();
  affineWidget->On();

  // begin mouse interaction
  renderWindowInteractor->Start();

  return EXIT_SUCCESS;
}

namespace {
void vtkAffineCallback::Execute(vtkObject*, unsigned long vtkNotUsed(event),
                                void*)
{
  this->AffineRep->GetTransform(this->Transform);
  this->Actor->SetUserTransform(this->Transform);
}
} // namespace

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1160965.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PostGIS轨迹分析——简化轨迹

需求 对轨迹线进行简化,并将原始轨迹上的两个特征点拉取到简化后的轨迹上 简化线 红色线是简化后的轨迹线,蓝色线是原始轨迹,有两个特征点 知识点: st_makeline函数将点连成线st_simplify简化线函数,其中第二个参数为坐标系的单位,0.002度大概代表0.002x1.11x10^5≈22…

使用 ElementUI 组件构建 Window 桌面应用探索与实践(WinForm)

零、实现原理与应用案例设计 1、原理 基础实例 Demo 可以参照以下这篇博文&#xff0c; 基于.Net CEF 实现 Vue 等前端技术栈构建 Windows 窗体应用-CSDN博客文章浏览阅读291次。基于 .Net CEF 库&#xff0c;能够使用 Vue 等前端技术栈构建 Windows 窗体应用https://blog.c…

通过xshell传输文件到服务器

一、user is not in the sudoers file. This incident will be reported. 参考链接&#xff1a; [已解决]user is not in the sudoers file. This incident will be reported.(简单不容易出错的方式)-CSDN博客 简单解释下就是&#xff1a; 0、你的root需要设置好密码 sudo …

java 申请堆外内存吗? java如何使用堆外内存?

java 申请堆外内存吗&#xff1f; java如何使用堆外内存&#xff1f; Java堆外内存管理 JVM可以使用的内存分外2种&#xff1a;堆内存和堆外内存&#xff1a; 堆内存完全由JVM负责分配和释放&#xff0c;如果程序没有缺陷代码导致内存泄露&#xff0c;那么就不会遇到java.lan…

【DriveGPT学习笔记】自动驾驶汽车Autonomous Vehicle Planning

原文地址&#xff1a;DriveGPT - Lei Maos Log Book 自动驾驶汽车的核心软件组件是感知、规划和控制。规划是指在给定场景或一系列场景的情况下为自动驾驶汽车制定行动计划的过程&#xff0c;以实现安全和理想的自动驾驶。 用于规划的场景是从感知软件组件获得的。计划的行动将…

Node学习笔记之跨域

1.跨域是什么&#xff1f; 跨域&#xff0c;是指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的&#xff0c;是浏览器对JavaScript实施的安全限制。 同源策略限制了一下行为&#xff1a; Cookie无法读取DOM 和 JS 对象无法获取Ajax请求发送不出去 同源是指&#…

如何通过 NAT 模式连接VMware虚拟机以及存在和不存在ens33文件的解决方案

文章目录 前言1 VMware配置1.1 打开vmvare虚拟网络编辑器1.2 取消使用本地DHCP1.3 NAT设置 2 虚拟机的配置2.1 存在ens332.2.1 修改ifcfg-ens33文件2.2.1.1 为什么设置BOOTPROTOstatic&#xff1f;2.2.1.2 如何选择使用static还是dhcp&#xff1f; 2.2.2 关闭防火墙 2.2 不存在…

王道p18 3.对长度为n的顺序表L,编写一个时间复杂度为 O(n)、空间复杂度为 O(1)的算法,该算法删除线性表中所有值为x的数据元素。(c语言代码实现)

视频讲解在这里&#xff08;谢谢各位大佬&#xff09; &#x1f447; p18 第三题数据结构课后算法题_哔哩哔哩_bilibili 本题代码如下 void deletex(struct sqlist* s, int x) {int k 0;int i 0;for (i 0; i < s->length; i){if (s->a[i] ! x)//只要不等于x&…

rcore 笔记 批处理系统 邓氏鱼

批处理系统 批处理系统 (Batch System) &#xff0c;它可用来管理无需或仅需少量用户交互即可运行的程序&#xff0c;在资源允许的情况下它可以自动安排程序的执行&#xff0c;这被称为“批处理作业”。 特权机制 实现特权级机制的根本原因是应用程序运行的安全性不可充分信…

Linux-----nginx的简介,nginx搭载负载均衡以及nginx部署前后端分离项目

目录 nginx的简介 是什么 nginx的特点以及功能 Nginx负载均衡 下载 安装 负载均衡 nginx的简介 是什么 Nginx是一个高性能的开源Web服务器和反向代理服务器。它的设计目标是为了解决C10k问题&#xff0c;即在同一时间内支持上万个并发连接。 Nginx采用事件驱动的异…

基于nodejs+vue啄木鸟便民维修网站设计与实现

目 录 摘 要 I ABSTRACT II 目 录 II 第1章 绪论 1 1.1背景及意义 1 1.2 国内外研究概况 1 1.3 研究的内容 1 第2章 相关技术 3 2.1 nodejs简介 4 2.2 express框架介绍 6 2.4 MySQL数据库 4 第3章 系统分析 5 3.1 需求分析 5 3.2 系统可行性分析 5 3.2.1技术可行性&#xff1a;…

树结构及其算法-二叉树节点的删除

目录 树结构及其算法-二叉树节点的删除 C代码 树结构及其算法-二叉树节点的删除 二叉树节点的删除操作稍为复杂&#xff0c;可分为以下3种情况。 删除的节点为树叶&#xff0c;只要将其相连的父节点指向NULL即可。删除的节点只有一棵子树。删除的节点有两棵子树。要删除节点…

Mysql高级操作和六大约束

一.数据库高级操作 1.1.克隆表 &#xff08;1&#xff09;克隆表&#xff0c;将数据表的数据记录生成到新的表中 方法一&#xff1a; create table test01 like KY08; #通过LIKE方法&#xff0c;复制KY08表结构生成test01 表 insert into test01 select * from KY08; #此方法…

分布式事务(再深入)——分布式事务理论基础 Java分布式事务解决方案

前言 事务(TRANSACTION)是一个不可分割的逻辑单元&#xff0c;包含了一组数据库操作命令&#xff0c;并且把所有的命令作为一个整体向系统提交&#xff0c;要么都执行、要么都不执行。 事务作为系统中必须考虑的问题&#xff0c;无论是在单体项目还是在分布式项目中都需要进行…

HAL服务整编错误处理

HAL服务整编错误处理 1、HIDL HAL服务2、HIDL HAL服务集成1》manifest.xml 配置报错2》hidl服务未启动报错3》有rc启动文件&#xff0c;没有so库报错4》SELinux权限问题5》整编译还是没有集成 或 报错 1、HIDL HAL服务 请参考下面几篇&#xff1a; 简单HIDL HAL的实现 Android系…

Ubuntu18.04LTS上安装ROS melodic

目录 前言创建source.list安装curl通过curl获取PGP公钥更新系统软件包索引安装ROS激活ROS系统空间 前言 本文参考ROS官方wiki&#xff0c;描述在Ubuntu18.04LTS上安装ROS的过程。 创建source.list sudo sh -c echo "deb http://packages.ros.org/ros/ubuntu $(lsb_rele…

「更新」Macos屏幕录像工具:ScreenFlow

mac电脑屏幕截图工具哪个好&#xff1f;ScreenFlow是Mac上的一款优秀的屏幕录像软件&#xff0c;它不仅具有屏幕录制功能&#xff0c;还具有视频编辑功能。以下是对ScreenFlow的一些详细介绍&#xff1a; 首先&#xff0c;ScreenFlow可以捕获摄像机、麦克风和计算机音频&#…

一段奇葩的1024代码

入门教程、案例源码、学习资料、读者群 请访问&#xff1a; python666.cn 大家好&#xff0c;欢迎来到 Crossin的编程教室 &#xff01; 10月24号那天&#xff0c;也就是传说中的1024程序员节&#xff0c;我翻开日历的时候&#xff0c;看到一段代码&#xff1a; 说实话&#xf…

CPU就绪情况及其对虚拟机性能的影响

CPU就绪是虚拟化中的一种性能度量&#xff0c;用于指示物理CPU中的潜在问题&#xff0c;作为对系统效率的度量&#xff0c;它用于跟踪性能和资源利用率&#xff0c;并避免严重错误。为了理解它在管理虚拟机中的重要性&#xff0c;我们将探讨CPU就绪作为一种性能指标的作用。 让…

HarmonyOS(二)—— 初识ArkTS开发语言(中)之ArkTS的由来和演进

前言 在上一篇文章HarmonyOS&#xff08;二&#xff09;—— 初识ArkTS开发语言&#xff08;上&#xff09;之TypeScript入门&#xff0c;我初识了TypeScript相关知识点&#xff0c;也知道ArkTS是华为基于TypeScript发展演化而来。 从最初的基础的逻辑交互能力&#xff0c;到…