简单的操作方法
上面描述的方法不一直是控制相机的最方便的方法。如果相机“看到”了你要看的点(i.e,焦点被设好了),你可以使用Azimuth()和Elevation()方法对于焦点移动相机。
这些方法在一个中心为焦点的球形坐标系统中沿着经度方向(azimuth)和纬度方向(elevation)移动给定的角度来移动相机。这些方法依赖保持不变的view-up向量,而且没有修改view-up向量。注意在北极点和南极点有异常—view-up向量平行于视平面法线。为了避免这点,通过使用OrthogonalizeViewUp(),你可以强迫view-up向量垂直于view向量。可是,这改变了相机坐标系统,因此如果你使一个自然水平的或者view-up向量(例如地形)围绕一个对象飞来飞去,相机操作不再与数据自然相关。 控制视方向
相机的一个通用的功能是生成来自一个特定方向的场景。你可以通过调用SetFocalPoint(),SetPosition(),和通过调用绘制器上与相机相关的ResetCamera()而跟随的ComputeViewPlaneNormal()作到这一点。
初始方向(view向量或者视平面法线)由焦点和相机的位置计算,相机的位置与ComputeViewPlaneNormal()一起定义了初始view向量。随意地,你可以确定一个初始view-up向量而且使它与view向量正交。ResetCamera()方法接着沿着view向量的方向移动相机因此绘制器的actors对相机都是可见的。 透视画法和正交视场 在目前展示的例子中,我们已经假设相机是透视相机;即,一个视角控制了绘制过程中actors到视平面的投射。透视投射,在产生更多自然观察图象时,引入了在某些应用中不期望得到的失真。正交(或平行)投射是另外一种投射方法。在透视投射中,视光线是平行的,而且对象的绘制没有距离效果。
为了设定相机使用正交投射,使用vtkCamera::ParallelProjectionOn()方法。在平行投射模式中,相机视角对于控制缩放不再有效。替代地,使用SetParallelScale()方法来控制actors的放大倍率。
保存/重新储存相机状态
应用的另外一个通用的需求是保存和重新储存相机状态(i.e..,复原一个view)的能力。为了保存相机状态,你需要保存(最小限度地)剪切范围,焦点和位置,和view-up向量。你也会要计算视平面法线(53页的“安装相机”的例子)接着,为了恢复相机状态,简单地用保存下来的信息例示一个相机而且把它赋给合适的绘制器(i.e,SetActiveCamera())。 在某些情况下你可能需要存储额外的信息。例如,如果相机视角(或者平行比例)被设定,你会需要保存这些。或者,如果你在使用相机来进行立体观察,就需要EyeAngle和Stereo。
4.5控制光源
光源比相机容易控制。最通用的方法是SetFocalPoint(),SetPosition(),和SetColor()。光源的位置和焦点控制了光源点的方向。光源的颜色表达为一个RGB向量。同样,通过SwitchOn()和SwitchOff()方法可以打开或者关闭光源,而且光源的亮度可以用SetIntensity()方法来设定。
默认地,vtkLight的实例是方向光源。即,位置和焦点定义了平行于光线传播的一个向量,而且光源被认为是在无穷大点处。这意味着如果位置和焦点等价地转换,那么在一个物体上的光线不改变。
光源与如下的绘制器相联系。
这里我们已经创建了一个红色前灯:定位于相机(caml’s)而且指向相机焦点的一个光源。这是一个有用的诀窍,而且被交互的绘制器用来定位相机移动时的光源(看48页的“使用VTK Interactors”) 位置光源
通过使用PositionOn()方法创建位置是可能的。这个方法结合SetConeAngle()方法使用来控制点的传播。180度的一个cone角意味着没有哪个点光源效果会被应用(i.e..,截短的光源cone);只有位置的效果。 4.6控制3D 道具
VTK中的将要被在绘制窗口中画出的对象通常被称为“道具”(道具是出现在舞台上的东西)有一些不同类型的道具包括vtkProp3D和vtkActor。vtkProp3D是存在于3D空间中的那些道具类型的一个抽象超类(vtkProp3D有支持平移、旋转、缩放,和3D空间中几何投射的一个4*4变换矩阵。)类vtkActor是vtkProp3D的一个类型,它的几何由分析元素例如多边形和线来定义。我们会研究vtkActor和vtkProp3D的其他类型。 确定vtkProp3D的位置
我们已经看了如何使用相机来围绕一个对象移动;可以选择地,我们也可以稳定地掌握相机和转换道具。可以使用以下的方法来定义一个vtkProp3D的位置(和它的子类) ? SetPosition(x,y,z)——在world坐标中确定了vtkProp3D的位置。
? AddPosition(deltaX,deltaY,deltaZ)——沿着每个x,y,z轴变换确定数量的道具。 ? RotateX(theta),RotateY(theta),RotateZ(theta)——分别围绕x,y,z轴旋转theta角
度。
? SetOrientation(x,y,z)——通过围绕z轴旋转设定道具的方位,接着是y轴,然后是z
轴。
? AddOrientation(x,y,z)——添加到道具的当前方位。
? RotateWXYZ(theta,x,y,z)——把道具围绕定义的x-y-z向量旋转theta角度。 ? Scale(sx,sy,sz)——在x,y,z轴坐标方向上缩放道具。
? SetOrigin(x,y,z)——确定道具的原点。旋转和缩放围绕原点发生。
这些方法用复杂的方式组合起来以控制结果变换矩阵。要记住的最重要的事情是上面的操作应用于一个特定的顺序,而且应用的顺序影响了结果actor位置。在VTK中应用这些变换的顺序如下:
到原点和来自原点的变化分别是原点值的正负变换。Net变换由vtkProp3D的位置值给定。这些变换最令人困惑的部分是旋转。例如,执行一个由y旋转跟随的x旋转与相反顺序的操作结果不同(看图4-4)。为了得到更多关于actor变换的信息,参考Visualization Toolkit的74页。
在本节中我们描述了一系列的vtkProp3D——在VTK中最通用的类是vtkActor。接下来(看70页的“控制vtkActor2D”)我们会研究2D道具(i.e..,vtkActor2D),它将被用来进行注释和其它的2D操作。
Actors
Actor是最通用的vtkProp3D类型。像其他具体的vtkProp3D子类那样,vtkActor用来把例如表面属性(e.g,ambient,散播,镜射颜色),表达(e.g,表面或者线框),纹理图片,和/或一个几何定义(一个绘图者)的绘制属性分组。
定义几何。一个actor的几何用 SetMapper()方法来确定:
在这种情况下mapper是vtkPolyDataMapper的类型,它使用分析元素例如点,线,多边形,和三角形条来绘制几何。mapper终止了可视化流水线,而且作为可视化子系统和图象子系统之间的桥梁。
Actor属性。Actor指vtkProperty的一个实例,它反过来控制actor的外观。可能最通用的属性是actor颜色。其他重要的属性特征是它的表示(点,线框,或者表面),它的消隐方法(flat或者Gouraud消隐),actor的不透明度(相对透明度),和ambient(氛围),散播,镜射颜色及相关的系数。以下脚本展示了如何设定这些实例变量中的一些。
注意我们如何通过GetProperty()方法废弃actor的属性。我们也可以创建一个属性而且把它赋给actor:
后一种方法的优点是我们通过赋予同样的属性控制了一些actors的属性。
Actor颜色。颜色可能是应用于actor的最重要的属性。最简单的程序是使用SetColor()方法设定actor的RGB值。每个值的范围是从0到1。
你也可以分别设定ambient,散播,镜射颜色。
在这个例子中我们已经把ambient颜色设为黑色灰度,散播颜色设为蓝色阴暗,镜射颜色为白色。(注意。SetColor()方法把ambient,散播,镜射颜色设为特定的颜色。)
重要:如果没有对actor的mapper可用的标量数据,actor的属性中设好的颜色才发挥作用。默认地,mapper的输入标量数据对actor着色,而且actor的颜色被忽略了。为了忽略标量数据,使用以下的Tcl脚本ScalarVisibilityOff()。
Actor透明度。很多时候调整一个actor的透明度是有用的。例如,如果你希望展示由一个病人皮肤包围的内部组织,调整皮肤的透明度允许用户看到与皮肤相关的组织。使用以下的vtkProperty()方法:
(请注意使用绑定过程在绘制库中实施透明度。过程需要以正确的顺序绘制多边形。实践中,这很难得到,特别是如果你有多重透明的actor。对于有序的多边形,你应该把透明的actor添加到actor的绘制器列表的末端。(i.e,,最后添加它们)。同样,你可以使用滤波器vtkDepthSortPolyData对沿着观察向量的多边形进行排序。请看
VTK/Examples/VisualizationAlgorithms/Tcl/DepthSort.tcl得到使用这个滤波器的一个例子。 混杂的特征。Actors有其它的一些重要特征。你可以使用VisibilityOn()和0VisibilityOff()方法来控制一个actor是否是可见的。如果你不想在一个采集操作过程中采集一个actor,就使用PickableOff()方法(看65页的“采集”得到更多的信息)Actors也有一个当它们被采集时就被调用的一个采集事件。你也可以使用GetBounds()方法得到轴线排列的actor bounding 盒子。 细节层次Actors
图象系统的一个主要问题是交互使用时变地太慢。为了解决这个问题,VTK使用细节层次Actors以低精度的分辩率为代价得到可以接受的绘制效果。
在47页的“绘制器源对象”中我们看到如何使用一个vtkLODActor。基本地,最简单的使用vtkLODActor的方法是用vtkLODActor的实例来代替vtkActor的实例。此外,你可以控制细节层次的显示。vtkLODActor的默认行为是创建两个额外的,来自原始投射器的低分辩率模型。第一个是一个从定义了投射器输入的点采样的点云。你可以如下控制云中点的数目。(默认地是150个点)
最低分辩率模型是actor的一个bounding 盒子。使用AddLODMapper()方法可以添加额外的细节层次。它们可以不必按照复杂度的顺序来添加。
为了控制绘制过程中由actor选择的细节层次,你可以在绘制窗口中设定期望的帧频:
它每分钟转化为五个帧。vtkLODActor会自动地选择合适的细节层次来得到要求的速度。(注意:例如vtkRenderWindowInteractor的交互器配件自动地控制期望的更新。当释放一个鼠标按钮时它们通常把帧频设地很低,当按下一个鼠标按钮时增加帧频。当相机运动时得到低分辩率/高帧频的模型,当相机停止时得到高分辩率低帧频的模型。如果你要控制更多的细节层次,看64页的“vtkLODProp3D”。vtkLODProp3D允许你指定每个层次。) 集合
Actors通常分级地组装以便一个actor的动作影响其它actors的位置。例如,一个机械臂可能包括一个上臂,前臂,腕和末端效应器,所有的这些通过关节连接。当上臂绕肩关节旋转时,我们期望剩余的部分随之旋转。这个行为通过使用集合来实施,它是vtkActor的一种类型(子集)。以下的脚本展示了它是如何做的(来自VTK/ Examples/Rendering/Tcl/assembly.tcl)