C# VTK 移动旋转交互功能实现

 更新时间:2024年06月25日 09:45:01   作者:Mr.For  
对vtk场景中一个或多个选中物体进行移动旋转,今天通过本文给大家分享C# VTK 移动旋转交互功能实现,感兴趣的朋友跟随小编一起看看吧

对vtk 场景中一个或多个选中物体进行移动旋转。

交互移动旋转坐标系

首先我们创建旋转的交互坐标系,三个移动Actor,三个旋转Actor,还需要4个定位坐标的小球Actor。

 public class CoordinateActor 中添加Actor
// 当前选中的Actor
  public vtkActor selActor;
  // 定位中心小球
  public vtkActor cenActor;
  // 旋转Actor
  public vtkActor rotX;
  public vtkActor rotY;
  public vtkActor rotZ;
  // 移动Actor
  public vtkActor moveX;
  public vtkActor moveY;
  public vtkActor moveZ;
  // 末端定位小球
  public vtkActor moveXEnd;
  public vtkActor moveYEnd;
  public vtkActor moveZEnd;

创建X轴移动Actor 

  public vtkActor LineActor(Point3d p1, Point3d p2, double[] color)
  {
      vtkLineSource lineSource = new vtkLineSource();
      lineSource.SetPoint1(p1.X, p1.Y, p1.Z);
      lineSource.SetPoint2(p2.X, p2.Y, p2.Z);
      lineSource.Update();
      vtkPolyDataMapper mapper = new vtkPolyDataMapper();
      mapper.SetInputData(lineSource.GetOutput());
      mapper.Update();
      vtkActor actor = new vtkActor();
      actor.SetMapper(mapper);
      actor.GetProperty().SetColor(color[0], color[1], color[2]);
      actor.GetProperty().SetLineWidth(10);
      return actor;
  }

这里的p1,p2 是根据模型的中心点和大小决定的。

假设创建了一个Box 长宽高 200, 模型中心在(0,0,0)。

以X移动Actor为例,这样vtkLineSource p1 = (0,0,0)   p2(200,0,0) 。

同时创建 cenActor , moveXEnd 两个定位小球。

现在我们已经创建了一个X轴方向的移动交互Actor ------- moveX。

X轴移动交互

有了moveX 现在为其添加移动交互的事件,参与移动的鼠标事件有四种。

MouseMove(LeftDown==false):

 当鼠标只是在场景中自由移动,未点击时,移动到moveX时应该触发待选状态,既是改变moveX 颜色。在MouseMove中需要随时判断是否鼠标选中Actor 且是 moveX。是就改变颜色,不是就还原颜色(需要设置为默认颜色)。

MouseDown

改变 bool LeftDown = true 

MouseUp

改变 bool LeftDown = false

firstPos == null 

lastPos = null

MouseMove(LeftDown==true):

此时真正开始旋转

1.计算移动距离方向

需要 两个Point2d 记录firstPos 和 lastPos 两个鼠标平面点,用于鼠标的移动距离和方向。

Point2d moveNorm = lastPos - firstPos; 

还记得我们之前的定位小球吗,将cenActor 和 moveXEnd  中心点 转换为屏幕坐标。

得到 center2d ,moveXEnd2d  

Point2d xLineNorm = moveXEnd2d - center2d

计算 moveNorm 投影到 xLineNorm  的 长度,既是移动的长度和方向(我们只在X 的正负方向移动)。

 // 计算点积
 public static double DotProduct2D(Point2d vectorA, Point2d vectorB)
 {
     return vectorA.X * vectorB.X + vectorA.Y * vectorB.Y;
 }
 // 计算向量的模(长度)
 public static double Magnitude2D(Point2d vector)
 {
     return Math.Sqrt(vector.X * vector.X + vector.Y * vector.Y);
 }
 // 计算向量 A 投影到向量 B 上的长度
 public static double ProjectionLength(Point2d vectorA, Point2d vectorB)
 {
     double dotProduct = DotProduct2D(vectorA, vectorB);
     double magnitudeB = Magnitude2D(vectorB);
     if (magnitudeB == 0)
         return 0;
     return dotProduct / magnitudeB;
 }

2.实现移动

vtk 通过vtkTransform实现移动旋转

   public void MoveAllAcotr(double moveValue, Orien orien)
   {
       vtkTransform transform = new vtkTransform();
       if(orien == Orien.X)
       {
           transform.Translate(moveValue,0,0);
       }
       else if (orien == Orien.Y)
       {
           transform.Translate(0, moveValue, 0);
       }
       else if (orien == Orien.Z)
       {
           transform.Translate(0, 0, moveValue);
       }
       transform.Update();
       // 移动 模型
       TransformActor(model, transform);
       TransformActor(cenActor, transform);
       TransformActor(moveXEnd, transform);
       TransformActor(moveYEnd, transform);
       TransformActor(moveZEnd, transform);
       TransformActor(moveX, transform);
       TransformActor(moveY, transform);
       TransformActor(moveZ, transform);
       TransformActor(rotX, transform);
       TransformActor(rotY, transform);
       TransformActor(rotZ, transform);
   }
        public void TransformActor(vtkActor actor,  vtkTransform transform)
        {
            vtkTransformFilter filter = new vtkTransformFilter();
            filter.SetTransform(transform);
            filter.SetInputData(actor.GetMapper().GetInput());
            filter.Update();
            actor.GetMapper().GetInput().DeepCopy(filter.GetOutput());
        }

(记得每一个交互的Actor 都要进行这个操作一起移动,包括定位小球)

X 轴旋转交互

使用 vtkRegularPolygonSource 创建空间圆 rotX, norm 为 (1,0,0)

 public vtkActor CircleActor(Point3d center, Point3d norm, double radius, double[] color)
 {
     vtkRegularPolygonSource polygonSource = new vtkRegularPolygonSource();
     polygonSource.SetCenter(center.X, center.Y, center.Z);
     polygonSource.SetNormal(norm.X, norm.Y, norm.Z);
     polygonSource.SetRadius(radius);
     polygonSource.SetNumberOfSides(30);
     polygonSource.SetGeneratePolyline(1);
     polygonSource.SetGeneratePolygon(0);
     polygonSource.Update();
     vtkPolyDataMapper mapper = new vtkPolyDataMapper();
     mapper.SetInputData(polygonSource.GetOutput());
     mapper.Update();
     vtkActor actor = new vtkActor();
     actor.SetMapper(mapper);
     actor.GetProperty().SetColor(color[0], color[1], color[2]);
     actor.GetProperty().SetLineWidth(10);
     return actor;
 }

其他操作与移动相同。

不同的是旋转时和移动相关Actor不旋转的,为了保持永远在X 方向上移动。

(如果想在任意方向上移动可以计算移动时的方向向量,此时全部Actor旋转)

旋转代码

 public void RotateAllAcotr(double rotAngel, Point3d norm, Orien orien)
 {
     Point3d center = new Point3d(cenActor.GetCenter());
     vtkTransform transform = new vtkTransform();
     transform.Translate(-center.X, -center.Y, -center.Z);
     if (orien == Orien.X)
     {
         transform.RotateWXYZ(rotAngel, norm.X, norm.Y, norm.Z);
     }
     else if (orien == Orien.Y)
     {
         transform.RotateWXYZ(rotAngel, norm.X, norm.Y, norm.Z);
     }
     else if (orien == Orien.Z)
     {
         transform.RotateWXYZ(rotAngel, norm.X, norm.Y, norm.Z);
     }
     transform.Translate(center.X, center.Y, center.Z);
     transform.Update();
     TransformActor(model, transform);
     TransformActor(cenActor, transform);
     TransformActor(rotX, transform);
     TransformActor(rotY, transform);
     TransformActor(rotZ, transform);
 }
        public void TransformActor(vtkActor actor,  vtkTransform transform)
        {
            vtkTransformFilter filter = new vtkTransformFilter();
            filter.SetTransform(transform);
            filter.SetInputData(actor.GetMapper().GetInput());
            filter.Update();
            actor.GetMapper().GetInput().DeepCopy(filter.GetOutput());
        }

这只是个简单的基本方法有不足的地方,其中有很过细节可以根据需要进行修改。

到此这篇关于C# VTK 移动旋转的文章就介绍到这了,更多相关C# 移动旋转内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • WPF实现倒计时转场动画效果

    WPF实现倒计时转场动画效果

    这篇文章主要介绍了如何利用WPF实现倒计时转场动画效果,文中的示例代码讲解详细,对我们学习或工作有一定帮助,需要的可以参考一下
    2022-08-08
  • c#通过反射实现对象自动映射的实现

    c#通过反射实现对象自动映射的实现

    本文主要介绍了c#通过反射完成对象自动映射的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-02-02
  • C#接口interface用法实例

    C#接口interface用法实例

    这篇文章主要介绍了C#接口interface用法,实例分析了C#接口的基本使用方法,需要的朋友可以参考下
    2015-06-06
  • C#使用Jquery zTree实现树状结构显示 异步数据加载

    C#使用Jquery zTree实现树状结构显示 异步数据加载

    这篇文章主要为大家详细介绍了C#使用Jquery zTree实现树状结构显示和异步数据加载,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-12-12
  • c#常用表格控件dataGridView的分页显示

    c#常用表格控件dataGridView的分页显示

    最近项目需要自己写了一个用来给DataGridView分页用的控件,下面这篇文章主要给大家介绍了关于c#常用表格控件dataGridView的分页显示,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-10-10
  • C# 中SharpMap的简单使用实例详解

    C# 中SharpMap的简单使用实例详解

    SharpMap是一个基于.net 2.0使用C#开发的Map渲染类库,可以渲染各类GIS数据(目前支持ESRI Shape和PostGIS格式),可应用于桌面和Web程序,具体内容详情大家参考下本文吧
    2017-08-08
  • C#实现轻松从HTML中提取纯文本

    C#实现轻松从HTML中提取纯文本

    这篇文章主要为大家详细介绍了C#如何实现轻松从HTML中提取纯文本,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-11-11
  • C#利用ScriptControl动态执行JS和VBS脚本

    C#利用ScriptControl动态执行JS和VBS脚本

    C#中利用ScriptControl动态执行JS和VBS脚本的实现方法,需要的朋友可以参考下
    2013-04-04
  • c#中虚函数的相关使用方法

    c#中虚函数的相关使用方法

    若一个实例方法声明前带有virtual关键字,那么这个方法就是虚方法。
    2013-02-02
  • C# OpenCV实现形状匹配的方法详解

    C# OpenCV实现形状匹配的方法详解

    这篇文章主要为大家详细介绍了如何利用C#+OpenCV实现形状匹配的效果,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2022-09-09

最新评论