C# VTK 移動(dòng)旋轉(zhuǎn)交互功能實(shí)現(xiàn)
對(duì)vtk 場(chǎng)景中一個(gè)或多個(gè)選中物體進(jìn)行移動(dòng)旋轉(zhuǎn)。
交互移動(dòng)旋轉(zhuǎn)坐標(biāo)系
首先我們創(chuàng)建旋轉(zhuǎn)的交互坐標(biāo)系,三個(gè)移動(dòng)Actor,三個(gè)旋轉(zhuǎn)Actor,還需要4個(gè)定位坐標(biāo)的小球Actor。
public class CoordinateActor 中添加Actor // 當(dāng)前選中的Actor public vtkActor selActor; // 定位中心小球 public vtkActor cenActor; // 旋轉(zhuǎn)Actor public vtkActor rotX; public vtkActor rotY; public vtkActor rotZ; // 移動(dòng)Actor public vtkActor moveX; public vtkActor moveY; public vtkActor moveZ; // 末端定位小球 public vtkActor moveXEnd; public vtkActor moveYEnd; public vtkActor moveZEnd;
創(chuàng)建X軸移動(dòng)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 是根據(jù)模型的中心點(diǎn)和大小決定的。
假設(shè)創(chuàng)建了一個(gè)Box 長(zhǎng)寬高 200, 模型中心在(0,0,0)。
以X移動(dòng)Actor為例,這樣vtkLineSource p1 = (0,0,0) p2(200,0,0) 。
同時(shí)創(chuàng)建 cenActor , moveXEnd 兩個(gè)定位小球。
現(xiàn)在我們已經(jīng)創(chuàng)建了一個(gè)X軸方向的移動(dòng)交互Actor ------- moveX。
X軸移動(dòng)交互
有了moveX 現(xiàn)在為其添加移動(dòng)交互的事件,參與移動(dòng)的鼠標(biāo)事件有四種。
MouseMove(LeftDown==false):
當(dāng)鼠標(biāo)只是在場(chǎng)景中自由移動(dòng),未點(diǎn)擊時(shí),移動(dòng)到moveX時(shí)應(yīng)該觸發(fā)待選狀態(tài),既是改變moveX 顏色。在MouseMove中需要隨時(shí)判斷是否鼠標(biāo)選中Actor 且是 moveX。是就改變顏色,不是就還原顏色(需要設(shè)置為默認(rèn)顏色)。
MouseDown
改變 bool LeftDown = true
MouseUp
改變 bool LeftDown = false
firstPos == null
lastPos = null
MouseMove(LeftDown==true):
此時(shí)真正開始旋轉(zhuǎn)
1.計(jì)算移動(dòng)距離方向
需要 兩個(gè)Point2d 記錄firstPos 和 lastPos 兩個(gè)鼠標(biāo)平面點(diǎn),用于鼠標(biāo)的移動(dòng)距離和方向。
Point2d moveNorm = lastPos - firstPos;
還記得我們之前的定位小球嗎,將cenActor 和 moveXEnd 中心點(diǎn) 轉(zhuǎn)換為屏幕坐標(biāo)。
得到 center2d ,moveXEnd2d
Point2d xLineNorm = moveXEnd2d - center2d
計(jì)算 moveNorm 投影到 xLineNorm 的 長(zhǎng)度,既是移動(dòng)的長(zhǎng)度和方向(我們只在X 的正負(fù)方向移動(dòng))。
// 計(jì)算點(diǎn)積 public static double DotProduct2D(Point2d vectorA, Point2d vectorB) { return vectorA.X * vectorB.X + vectorA.Y * vectorB.Y; } // 計(jì)算向量的模(長(zhǎng)度) public static double Magnitude2D(Point2d vector) { return Math.Sqrt(vector.X * vector.X + vector.Y * vector.Y); } // 計(jì)算向量 A 投影到向量 B 上的長(zhǎng)度 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.實(shí)現(xiàn)移動(dòng)
vtk 通過(guò)vtkTransform實(shí)現(xiàn)移動(dòng)旋轉(zhuǎn)
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(); // 移動(dòng) 模型 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()); }
(記得每一個(gè)交互的Actor 都要進(jìn)行這個(gè)操作一起移動(dòng),包括定位小球)
X 軸旋轉(zhuǎn)交互
使用 vtkRegularPolygonSource 創(chuàng)建空間圓 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; }
其他操作與移動(dòng)相同。
不同的是旋轉(zhuǎn)時(shí)和移動(dòng)相關(guān)Actor不旋轉(zhuǎn)的,為了保持永遠(yuǎn)在X 方向上移動(dòng)。
(如果想在任意方向上移動(dòng)可以計(jì)算移動(dòng)時(shí)的方向向量,此時(shí)全部Actor旋轉(zhuǎn))
旋轉(zhuǎn)代碼
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()); }
這只是個(gè)簡(jiǎn)單的基本方法有不足的地方,其中有很過(guò)細(xì)節(jié)可以根據(jù)需要進(jìn)行修改。
到此這篇關(guān)于C# VTK 移動(dòng)旋轉(zhuǎn)的文章就介紹到這了,更多相關(guān)C# 移動(dòng)旋轉(zhuǎn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- c# WinForm制作圖片編輯工具(圖像拖動(dòng)、縮放、旋轉(zhuǎn)、摳圖)
- C#使用opencv截取旋轉(zhuǎn)矩形區(qū)域圖像的實(shí)現(xiàn)示例
- C# 使用 GDI+ 實(shí)現(xiàn)添加中心旋轉(zhuǎn)(任意角度)的文字
- 利用C#代碼實(shí)現(xiàn)圖片旋轉(zhuǎn)360度
- C#實(shí)現(xiàn)計(jì)算一個(gè)點(diǎn)圍繞另一個(gè)點(diǎn)旋轉(zhuǎn)指定弧度后坐標(biāo)值的方法
- C#中圖片旋轉(zhuǎn)和翻轉(zhuǎn)(RotateFlipType)用法分析
- C#控制圖像旋轉(zhuǎn)和翻轉(zhuǎn)的方法
相關(guān)文章
用C#在本地創(chuàng)建一個(gè)Windows帳戶(DOS命令)
用C#在本地創(chuàng)建一個(gè)Windows帳戶(DOS命令)...2007-03-03C#控制臺(tái)基礎(chǔ) list<>初始化的兩種方法
這篇文章主要介紹了C#控制臺(tái)基礎(chǔ) list<>初始化的兩種方法,需要的朋友可以參考下2016-12-12C# 快速高效率復(fù)制對(duì)象(表達(dá)式樹)
在代碼中經(jīng)常會(huì)遇到需要把對(duì)象復(fù)制一遍,或者把屬性名相同的值復(fù)制一遍。本文將對(duì)其解決方法進(jìn)行詳細(xì)介紹。下面跟著小編一起來(lái)看下吧2017-04-04C#實(shí)現(xiàn)HTTP訪問(wèn)類HttpHelper的示例詳解
在項(xiàng)目開發(fā)過(guò)程中,我們經(jīng)常會(huì)訪問(wèn)第三方接口,如我們需要接入的第三方接口是Web API,這時(shí)候我們就需要使用HttpHelper調(diào)用遠(yuǎn)程接口了。本文為大家介紹了C#實(shí)現(xiàn)HTTP訪問(wèn)類HttpHelper的示例代碼,需要的可以參考一下2022-09-09理解C#中參數(shù)的值和引用以及傳遞結(jié)構(gòu)和類引用的區(qū)別
這篇文章主要介紹了理解C#中參數(shù)的值和引用以及傳遞結(jié)構(gòu)和類引用的區(qū)別,文中舉了兩段代碼例子來(lái)簡(jiǎn)單說(shuō)明,需要的朋友可以參考下2016-01-01C# async/await任務(wù)超時(shí)處理的實(shí)現(xiàn)
本文主要介紹了C# async/await任務(wù)超時(shí)處理的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02