第05章-可视化技术(3)
【译者:这个系列教程是以Kitware公司出版的《VTK User’s Guide -11th edition》一书作的中文翻译(出版时间2010年,ISBN: 978-1-930934-23-8),因为时间关系,我们不能保证每周都能更新本书内容,但尽量做到一周更新一篇到两篇内容。敬请期待^_^。欢迎转载。另请转载时注明本文出处。谢谢合作!
同一时候,因为译者水平有限,出错之处在所难免,欢迎指出订正!
】
5.2 多边形数据可视化
多边形数据(vtkPolyData)是一种重要的可视化数据类型。
由于它是图像硬件或者渲染引擎的几何接口。其它的数据必须转换为多边形数据才干被渲染。除了vtkImageData外。VtkImageData使用的时特别图像或者体绘制技术。能够參考104页“以多边形数据类型为输出提取单元”来了解如何转换数据类型。
多边形数据主要由点和点集,直线和直线组合。三角形,四边形。多边形和三角形带组合而成。
大部分接收vtkPolyData的Filter都会处理这些数据组合。
当然也有一些Filter如vtkDecimatePro和vtkTubeFilter会仅仅处理部分数据类型(三角网格和直线)。
手动创建vtkPolyData数据
多边形数据能够通过多种方式构造。通常须要创建一个vtkPoints来存储点集,然后创建4个vtkCellArrays来分别表示点,线。多边形和三角带连接。以下样例取自VTK/Examples/DataManipulation/Tcl/CreateStrip.tcl。它创建了一个具有一个三角形带的vtkPolyData数据。
vtkPoints points points InsertPoint 0 0.0 0.0 0.0 points InsertPoint 1 0.0 1.0 0.0 points InsertPoint 2 1.0 0.0 0.0 points InsertPoint 3 1.0 1.0 0.0 points InsertPoint 4 2.0 0.0 0.0 points InsertPoint 5 2.0 1.0 0.0 points InsertPoint 6 3.0 0.0 0.0 points InsertPoint 7 3.0 1.0 0.0 vtkCellArray strips strips InsertNextCell 8;#number of points strips InsertCellPoint 0 strips InsertCellPoint 1 strips InsertCellPoint 2 strips InsertCellPoint 3 strips InsertCellPoint 4 strips InsertCellPoint 5 strips InsertCellPoint 6 strips InsertCellPoint 7 vtkPolyData profile profile SetPoints points profile SetStrips strips vtkPolyDataMapper map map SetInput profile vtkActor strip strip SetMapper map [strip GetProperty] SetColor 0.3800 0.7000 0.1600
这里有另外一个C++样例来演示如何创建一个立方体(VTK/Examples/DataManipulation/Cxx/Cube.cxx)。
这次我们创建6个四边形和每一个顶点相应的标量值。
int i; staticfloat x[8][3]={{0,0,0}, {1,0,0}, {1,1,0}, {0,1,0}, {0,0,1}, {1,0,1},{1,1,1}, {0,1,1}}; staticvtkIdType pts[6][4]={{0,1,2,3}, {4,5,6,7}, {0,1,5,4}, {1,2,6,5}, {2,3,7,6},{3,0,4,7}}; vtkPolyData *cube = vtkPolyData::New(); vtkPoints *points = vtkPoints::New(); vtkCellArray *polys = vtkCellArray::New(); vtkFloatArray *scalars = vtkFloatArray::New(); // Load the point, cell, and data attributes. for (i=0;i<8; i++) points->InsertPoint(i,x[i]); for (i=0; i<6;i++) polys->InsertNextCell(4,pts[i]); for (i=0;i<8; i++) scalars->InsertTuple1(i,i); // We now assign the pieces to the vtkPolyData. cube->SetPoints(points); points->Delete(); cube->SetPolys(polys); polys->Delete(); cube->GetPointData()->SetScalars(scalars); scalars->Delete();
vtkPolyData能够由点,线。多边形和三角形带的随意组合构建。同一时候。vtkPolyData支持一系列扩展的操作来对数据结构进行编辑和改动。參考345页“多边形数据”。
计算表面法向量
当你渲染多边形网格时,你可能会发现渲染图像中清晰的显示了网格面片(图5-10)。採用Gouraud着色技术能够提高渲染结果(见53页“Actor属性”)。然而Gouraud着色技术依赖于网格每一个顶点的法向量。因此须要利用vtkPolyDataNoramals filter来计算网格顶点法向量。
217页“Extrusion”、94页“Glyphing”和102页“用其它标量着色等值面”都是用了该类计算法向量。
图5-10 使用和不使用表面法向量的网格面片对照
该Filter有两个重要的參数。splitting和FeatureAngle。假设splitting开启,那么特征边被分裂(假设一条边随意一端的顶点法向与该边所成夹角大于或者等于特征角FeatureAngle的话,那么该边定义为特征边)。也就是沿着该条边复制顶点,网格在特征边的随意一边被切割。
这样尽管产生了新的顶点。可是可以清晰的渲染尖锐角处。另外一个重要的參数是FlipNormals。
调用函数FlipNormalsOn()将使法向量反向(同一时候多边形连接表也会反向)。
抽取(Decimation)
多边形数据,特别是三角形网格是非经常常使用的图形数据格式。比方vtkContourFilter产生的结果就是三角形网格。可是这些三角形网格往往会比較大,因此在一些交互应用中难以高速的处理。
抽取技术常被用来解决问题。抽取也被称作多边形消减,网格简化或者多分辨率建模。其在保持近似原始网格条件下对三角网格中的三角形数量进行消减。
VTK支持三种消减方法,vtkDecimatePro,vtkQuadricClustering和vtkQuadricDecimation。尽管每一种都有各自的优缺点,但在应用上基本都一致。
- vtkDecimatePro相对来说速度比較快,并且在消减过程中能够改动拓扑结构。它採用边塌陷方法来去除顶点和三角形。它的误差度量是基于到平面或者边的距离。该方法的一个长处是能够完毕随意程度的消减。由于该算法一開始就将网格分裂为小的碎片来完毕消减目的(假设同意拓扑改动的话)。
- vtkQuadricDecimation採用的Siggraph97论文“SurfaceSimplification Using Quadric Error Metrics”中提出的二次误差度量。它採用边塌陷方法来剔除顶点和三角面片。二次误差度量通常被觉得是比較好的误差度量。
- vtkQuadricClustering是最快的方法。
它的思想基于Siggraph2000中的论文“Out-of-Core Simplification of Large Polygonal Models”。它能够高速的消减大网格模型。并且支持网格片段消减(利用StartAppend(), Append()和EndAppend()方法)。这样能够避免读取整个模型到内存中。
对于大网格模型,该方法有较好的效果;可是当网格变小时,三角化过程效果不是非常好(须要结合其它的算法会有较理想的效果)。
以下是关于类vtkDecimatePro的一个应用实例。
代码取自VTK/Examples/VisualizationAlgorithms/Tcl/deciFram.tcl(如图5-11)。
vtkDecimatePro deci deci SetInputConnection [fran GetOutputPort] deci SetTargetReduction 0.9 deci PreserveTopologyOn vtkPolyDataNormals normals normals SetInputConnection [deci GetOutputPort] normals FlipNormalsOn vtkPolyDataMapper franMapper franMapper SetInputConnection [normals GetOutputPort] vtkActor franActor franActor SetMapper franMapper eval [franActor GetProperty] SetColor 1.0 0.49 0.25
图5-11 三角网格面片经90%抽取后的效果对照(左为原始图。右为抽取后的图)
vtkDecimatePro有两个重要的參数:TargetReduction和PreserveTopology。
TargetReduction是用户的消减量(比如0.9意味着我们希望降低网格中90%的面片。
)依据你是否同意改动拓扑结构(PreserveTopologyOn/Off())来得到对应的消减结果。
最后注意的是消减filter的输入为三角形数据。假设你的是多边形数据。那么须要利用vtkTriangleFilter 来进行转换。
网格平滑(SmoothMesh)
多边形网格往往因为噪声或者过于粗糙,从而影响渲染的结果。比如,低分辨率数据的等值面会有走样的效果。数据平滑是处理这样的问题的方法之中的一个。平滑是通过改变顶点位置来降低曲面噪声数据的的过程。
VTK中提供了两种平滑对象:vtkSmoothPolyDataFilter和vtkWindowSincPolyDataFilter。
两者中。vtkWindowSincPolyDataFilter处理效果最好,并且处理速度也较快。
以下样例(代码来自VTK/Examples/VisualizationAlgorithms/Tcl/smoothFran.tcl)演示了如何利用该平滑filter。该例与上节样例内容同样,仅仅是多了一个平滑filter处理。图5-12显示了简化模型的平滑效果。
vtkDecimatePro deci deci SetInputConnection [fran GetOutputPort] deci SetTargetReduction 0.9 deci PreserveTopologyOn vtkSmoothPolyDataFilter smoother smoother SetInputConnection [deci GetOutputPort] smoother SetNumberOfIterations 50 vtkPolyDataNormals normals normals SetInputConnection [smoother GetOutputPort] normals FlipNormalsOn vtkPolyDataMapper franMapper franMapper SetInputConnection [normals GetOutputPort] vtkActor franActor franActorSetMapper franMapper eval [franActor GetProperty] SetColor 1.0 0.49 0.25
图5-12 多边形网格平滑(右图为平滑后的效果)
两种平滑Filter的用法类似。他们提供了一些函数来控制特征边或者边界处的平滑效果。可查阅在线文档或者*.h头文件了解相关信息。
数据裁剪(ClipData)
裁剪类似于分割(98页“分割”)利用一个隐函数来定义裁剪面。裁剪将多边形模型分解为片段,如图5-13所看到的。裁剪在裁剪面的随意一边将多边形几何体分解为单独的部分。如分割一样,裁剪能够设置一个裁剪值来定义隐式裁剪函数的值。
下例中利用一个平面来裁剪一个牛的三维多边形模型。分割值用来定义分割平面沿着法向量移动距离的大小,这样便能够在不同的位置对模型进行裁剪。代码取自(VTK/Examples/VisualizationAlgorithms/Tcl/ClipCow.tcl)。
vtkBYUReader cow cow SetGeometryFileName "$VTK_DATA_ROOT/Data/Viewpoint/cow.g" vtkPolyDataNormals cowNormals cowNormals SetInputConnection [cow GetOutputPort] vtkPlane plane plane SetOrigin 0.25 0 0 plane SetNormal -1 -1 0 vtkClipPolyData clipper clipper SetInputConnection [cowNormals GetOutputPort] clipper SetClipFunction plane clipper GenerateClipScalarsOn clipper GenerateClippedOutputOn clipper SetValue 0.5 vtkPolyDataMapper clipMapper clipMapper SetInputConnection [clipper GetOutputPort] clipMapper ScalarVisibilityOff vtkProperty backProp evalbackProp SetDiffuseColor $tomato vtkActor clipActor clipActorSetMapper clipMapper eval [clipActor GetProperty] SetColor $peacock clipActor SetBackfaceProperty backProp vtkPolyDataMapper restMapper restMapper SetInputConnection [clipper GetClippedOutputPort] restMapper ScalarVisibilityOff vtkActor restActor restActor SetMapper restMapper [restActor GetProperty] SetRepresentationToWireframe
图5-13 模型裁剪
GenerateClippedOutputOn()函数计算裁剪过程中被裁剪掉得数据。在该例中这部分数据採用线框方式显示。假设通过SetValue()函数改变了裁剪值,那么裁剪面将移动至初始裁剪面前或者后而且平行与初始裁剪面的位置。(相同改变vtkPlane的定义也可实现相同的效果。)
计算纹理坐标
经常使用的计算纹理坐标的Filter是vtkTextureMapToPlane,vtkTextureMapToCylinder和vtkTextureMapToSphere。
他们分别基于平面,圆柱和球面坐标系计算纹理坐标。另外,vtkTransformTextureCoordinates通过平移和缩放纹理坐标在曲面上定义纹理映射。
下例中演示了利用vtkTextureMapToCylinder来为一个由vtkDelaunay3D计算产生的不规则网格数据计算纹理坐标(參考218页“Delaunay Triangulation”)。
完整代码能够參考VTK/Examples/VisualizationAlgorithms/Tcl/GenerateTextureCoords.tcl。
vtkPointSource sphere sphere SetNumberOfPoints 25 vtkDelaunay3D del del SetInputConnection [sphere GetOutputPort] del SetTolerance 0.01 vtkTextureMapToCylinder tmapper tmapper SetInputConnection [del GetOutputPort] tmapper PreventSeamOn vtkTransformTextureCoords xform xform SetInputConnection [tmapper GetOutputPort] xform SetScale 4 4 1 vtkDataSetMapper mapper mapper SetInputConnection [xform GetOutputPort] vtkBMPReader bmpReader bmpReaderSetFileName "$VTK_DATA_ROOT/Data/masonry.bmp" vtkTexture atext atext SetInputConnection [bmpReader GetOutputPort] atext InterpolateOn vtkActor triangulation triangulation SetMapper mapper triangulation SetTexture atext
该例中首先对一个单位球上的随机点进行三角剖分,并为三角网格计算纹理坐标。接着在纹理坐标i-j方向上对纹理坐标进行缩放以便使纹理可以反复。最后读入纹理图像并指定到Actor上。
(注意,vtkDataSetMapper能够接收随意数据类型的输入。其内部vtkGeometryfilter对象将数据转换为多边形数据然后再传入到渲染引擎中。
參考104页“以多边形数据为输出提取单元”)
假设须要深入学习纹理坐标,能够执行VTK/Examples/VisualizationAlgorithms/Tcl/TransformTexturecoords.tcl实例(如图5-14所看到的)。该例GUI能够选择多边形模型,纹理图像。纹理计算方法和纹理变换方法。
图5-14 变换以及应用不同的纹理