这是根据
http://image.szpt.edu.cn/UploadFiles/%E6%95%B0%E6%8D%AE%E9%9B%86%E4%B8%8E%E6%95%B0%E6%8D%AE%E5%B1%9E%E6%80%A7.swf
上面的例子改编的,代码全部改为用C# 实现。
例子1:生成多边形数据集
说明:
立方体有8个顶点,需要有8个顶点坐标。
立方体有6个面,需要六组点来表示。
点标量属性数据是与点一 一对应的。所以其个数必须与点的个数相同。在程序中循环8次调用方法InsertValue()插入标量数据。该方法有两个参数,第一个参数是对应点的ID,第二个参数是标量值。
public partial class Form1 : Form { // private vtkRenderer _renderer = null; //private vtkRenderWindow _renwin = null; public Form1() { InitializeComponent(); } private void renderWindowControl1_Load(object sender, EventArgs e) { vtkPolyData cube = new vtkPolyData(); vtkPoints points = new vtkPoints(); vtkCellArray polys = new vtkCellArray(); vtkFloatArray scalars = new vtkFloatArray(); int i; float[][] x = new float[8][] { new float[]{0,0,0},//第0个点的坐标 new float[]{1,0,0},//第1个点的坐标 new float[]{1,1,0},//第2个点的坐标 new float[]{0,1,0},//3 new float[]{0,0,1},//4 new float[]{1,0,1},//5 new float[]{1,1,1},//6 new float[]{0,1,1} //7 }; for (i = 0; i < 8; i++) points.InsertPoint(i,x[i][0],x[i][1],x[i][2]);//加载点,创建数据结构的几何 List<int[]> temp = new List<int[]>(); int[] temparray0 = new int[4] { 0, 1, 2, 3 };//第0,1,2,3个点连接在一起,成为一个单元 int[] temparray1 = new int[4] { 4, 5, 6, 7 };//第4,5,6,7个点连接在一起,成为一个单元 int[] temparray2 = new int[4] { 0, 1, 5, 4 }; int[] temparray3 = new int[4] { 1, 2, 6, 5 }; int[] temparray4 = new int[4] { 2, 3, 7, 6 }; int[] temparray5 = new int[4] { 3, 0, 4, 7 }; temp.Add(temparray0); temp.Add(temparray1); temp.Add(temparray2); temp.Add(temparray3); temp.Add(temparray4); temp.Add(temparray5); //因为在activiz中没有vtkIdType这个类,所以用了其他的方法代替C++代码中的实现。 for(int j=0;j<temp.Count;j++) { IntPtr pP = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(int))*4); Marshal.Copy(temp[j],0,pP,4); polys.InsertNextCell(4,pP);//加载单元,定义数据集的拓扑 Marshal.FreeHGlobal(pP); } for (i = 0; i < 8; i++) scalars.InsertTuple1(i,i);//为每一个点设置点属性。 cube.SetPoints(points); cube.SetPolys(polys); cube.GetPointData().SetScalars(scalars); vtkPolyDataMapper cubemapper = new vtkPainterPolyDataMapper(); cubemapper.SetInput(cube); cubemapper.SetScalarRange(0,7); vtkActor cubeactor = new vtkActor(); cubeactor.SetMapper(cubemapper); // Create components of the rendering subsystem // vtkRenderWindow _renwin = renderWindowControl1.RenderWindow; vtkRenderer ren1 = _renwin.GetRenderers().GetFirstRenderer(); // Add the actors to the renderer, set the window size // ren1.AddViewProp(cubeactor); _renwin.SetSize(250, 250); _renwin.Render(); ren1.ResetCamera(); } }
例子2:结构化点数据集的创建
说明:
结构化点数据集根据其表示的数据的维数分别由线单元(1D)、像素单元(2D)或体素单元(3D)组成。而且这些单元的大小、形状都是一样的。所以数据集中的点是非常规则地排列在一起,并且排列的方向是与全局x-y-z坐标轴平行的。
正是由于结构上的规则,定义一个结构化点数据集时,不需要定义所有的点和所有的单元,只需要知道一个起始点的坐标以及沿三个坐标轴方向上的相邻点的距离(该距离也就是单元的边的长度),就可以算出所有点的坐标。这两个参数通过SetOrigin() 和SetSpacing()进行设置。对于单元,由于已知单元的类型只属于上面提到的三种中的一种,并且只有相邻的点才能构成单元,所以知道知道每个坐标轴方向上有多少个点(nx,ny,nz)就可以确定所有的单元了。该参数称为尺寸,用方法SetDimensions()进行设置。
也是由于结构上的规则,数据集中的点和单元可以用一个i-j-k自然坐标系来指定。数据集中共有nx*ny*nz个点,共有(nx-1)(ny-1)(nz-1)个单元。一个特定的点和单元可以用三个索引i-j-k指定。类似的,一条线可以用三个索引中的两个指定,一个面可以用一个索引指定。
代码:
public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void renderWindowControl1_Load(object sender, EventArgs e) { int i, j, k, kOffset, jOffset, offset; float s, sp, x, y, z; //创建结构化点数据集,(创建点和单元) vtkStructuredPoints vol = new vtkStructuredPoints(); vol.SetDimensions(26,26,26);//x,y,z三个坐标轴方向上各有26个点 vol.SetOrigin(-0.5,-0.5,-0.5);//设置数据集在坐标空间内的起点 sp = (float)(1.0 / 25.0); vol.SetSpacing(sp,sp,sp);//设置坐标轴上每个点的间距 //创建标量数据(作为结构化点数据集的属性数据) vtkFloatArray scalars = new vtkFloatArray(); scalars.SetNumberOfTuples(26*26*26);//设置标量个数,因为是点属性所以和点的个数相同 for (k = 0; k < 26; k++) { z = (float)(-0.5 + k * sp); kOffset = k * 26 * 26; for(j=0;j<26;j++) { y=(float)(-0.5+j*sp); jOffset = j * 26; for (i = 0; i < 26; i++) { x=(float)(-0.5+i*sp); s =(float)( x * x + y * y + z * z - (0.4 * 0.4)); //计算标量值,该方程为球体方程,位于球体上的点标量值为0 offset = i + jOffset + kOffset;//计算id scalars.InsertTuple1(offset,s);//插入标量值 } } } vol.GetPointData().SetScalars(scalars); //将标量值与点关联 //抽取标量值为0的点所形成的面 vtkContourFilter contour = new vtkContourFilter(); contour.SetInput(vol); contour.SetValue(0,0); vtkPolyDataMapper volmapper = new vtkPainterPolyDataMapper(); volmapper.SetInput(contour.GetOutput()); vtkActor actor = new vtkActor(); actor.GetProperty().SetRepresentationToWireframe(); // actor.GetProperty().SetRepresentationToSurface(); // actor.GetProperty().SetRepresentationToPoints(); actor.GetProperty().SetColor(0,0,0); actor.SetMapper(volmapper); vtkRenderWindow _renwin=renderWindowControl1.RenderWindow; vtkRenderer _render = _renwin.GetRenderers().GetFirstRenderer(); _render.AddActor(actor); _renwin.Render(); _render.ResetCamera(); } }
效果图:
结构化点数据集在拓扑和几何上都是规则的,其几何和拓扑都是隐式定义的,所以结构化点数据集很容易构造。创建该数据集的步骤可以总结为如下散步(假设 vtkStructurePoints的实例名为vol):
1、使用操作vol.SetDimensions()定义数据集的拓扑。
2、使用操作vol.SetOrigin()和vol.SetSpacing()定义数据集的集几何。
3、创建点属性数据并与数据集关联。