非结构化数据
非结构化点
非结构化点是在空间中离散随意分布的点,没有拓扑结构,几何机构也是完全没有规则的。
非结构化点由顶点和多点的单元组成;非结构化点是一种简单但很重要的数据集类型,在部分可视化工作中会使用它来表示无结构的数据。
非结构化网格
数据集中最为一般的形式是非结构化网格,其拓扑和几何完全没有结构和规则。
在非结构化网格中,任何单元类型可以按任意形式组合,因此,单元的拓扑范围很广泛,从零维度的点、一维度的线,二维的面、三维度体素和多面体。
在VTK中,任意数据集类型都可以用非结构化网络来表达。但是要注意的是,一般情况下式不会用非结构化网格来表达数据的,这是因为这种数据集类型需要占用最多的内存和计算资源来表达数据和进行操作。
非结构化网格用于有限元分析、计算几何和几何建模这类领域。
vtkUnstructuredGridBase类接口
vtkUnstructuredGrid类继承自vtkUnstructuredGridBase类,vtkUnstructuredGrid实例由几何点+拓扑结构组成。
拓扑结构主要使用了vtkUnstructuredGridBase类的InsertNextCell
接口顺序组成;
InsertNextCell
的声明如下:
// 按照类型和几何点ID创建单元;
// int type:单元类型;
// vtkIdType npts:几何点个数;
// const vtkIdType ptIds[]:几何点的ID数组;
// 大多数几何单元只需要隐式定义的几何类型和一组点及其顺序;
// 对于非多面体单元类型,npts是单元格中唯一点的数目;
// 对于多面体单元,需要特殊的输入格式。npts是单元中的面数。ptIds是一系列面的列表,例如(numFace0Pts, id1, id2, id3, numFace1Pts,id1, id2, id3, ...)
vtkIdType InsertNextCell(int type, vtkIdType npts, const vtkIdType ptIds[]) VTK_SIZEHINT(ptIds, npts);
// 定义同上,这里只使用了几何单元类型和几何点集合;
vtkIdType InsertNextCell(int type, vtkIdList *ptIds);
// 用于创建多面体的接口;
// npts是单元中几何点的数量;
// pts是单元点ID的列表;
// nfaces是单元中的面数;
// faces是多个面的信息流[numFace0Pts,id1,id2,id3,numFace1Pts,id1,id2,id3,…];
vtkIdType InsertNextCell(int type, vtkIdType npts, const vtkIdType ptIds[],
vtkIdType nfaces, const vtkIdType faces[]) VTK_SIZEHINT(ptIds, npts) VTK_SIZEHINT(faces, nfaces);
常用的几何类型
enum VTKCellType
中列举了常用的几何类型;
类型 | 含义 |
---|---|
VTK_EMPTY_CELL | 空单元 |
VTK_VERTEX | 顶点,由一个点定义,是零维度基本类型。 |
VTK_POLY_VERTEX | 多顶点,由多个顶点组合而成,是零维度的组合单元。 |
VTK_LINE | 直线,,由两个点定义,方向是从第一个点指向第二个点。 |
VTK_POLY_LINE | 折线,由一个或多个线段组合而成。由n+1个有序的点连接定义的。n表示折线的线段条数,每两个点定义一条线段。 |
VTK_TRIANGLE | 三角形,由三个点按逆时针的方向连接定义,点的连接方向和表面法向量按照右手法则。 |
VTK_TRIANGLE_STRIP | 三角形条带,由一个或多个三角形组合而成。由n+2 个有序的点连接,n 表示三角形条带里三角形的个数,定义三角形条带的点不需要共面。定义每个三角形的顶点顺序为(i,i+1,i+2),0<=i<=n |
VTK_POLYGON | 多边形,是由共面的三个或三个以上的点按逆时针方向的顺序连接定义的。多边形表面法向量的方向通过右手法则确定。 |
VTK_PIXEL | 是由共面的四个点按一定的顺序连接定义的。与VTK_QUAD的区别在拓扑结构上,VTK_PIXEL 要求相邻的两条边必须垂直,而且相对两条边要与坐标轴平行。定义VTK_PIXEL 四个点的顺序与四边形不同,VTK_PIXEL 顶点的计数先沿着X轴方向,然后是Y轴,最后是Z轴方向。 |
VTK_QUAD | 四边形,由共面的四个点按逆时针的方向连接定义的。四边形要求是非自交的凸多边形。利用右手法则可以得到该四边形的表面法向量。 |
VTK_TETRA | 四面体,包含六条边和四个面,是由不共面的四个点两两连接定义的。 |
VTK_VOXEL | 正方体,与六面体的拓扑一样,几何上要求相邻的两个面必须垂直,VOXEL是VTK_HEXAHEDRON 的特殊形式。 |
VTK_HEXAHEDRON | 六面体,包含六个四边形面、12条边和8个顶点,六面体要求是凸多边形。 |
VTK_WEDGE | 楔形,三棱柱,由三个四边形面、两个三角形面、9条边和6个顶点构成。要求面和边不能与其他的相交,且楔形必须是凸多边形。 |
VTK_PYRAMID | 角椎体,金字塔形状。由一个四边形面、四个三角形面、8条边和五个顶点构成。定义四边形的四个点要求共面,且四个点构成的四边形必须是凸四边形,第五个点不在其他四个点定义的平面上。 |
VTK_PENTAGONAL_PRISM | 五棱柱,由五个四边形面、两个五边形面、15条边和10个顶点构成。五棱柱的面和边不能与其他的相交,且五棱柱必须是凸五边形。 |
VTK_HEXAGONAL_PRISM | 六角柱,由六个四边形面、两个六边形面、18条边和12个顶点构成。六角柱的面和边不能与其他的相交,且六角柱必须是凸六边形。 |
创建非结构化网格数据集的一般步骤
1.创建vtkPoints
实例来指定数据集的几何。使用操作ugrid->SetPoints(points)
将点与数据集关联。
2.使用操作ugrid->InsertNextCell
创建数据集的单元,从而定义数据集的拓扑。
3.创建点属性数据并与数据集关联,这一步可有可无,视情况而定。
4.执行操作ugrid->Squeeze()
完成创建过程。该操作会回收未被数据结构消耗的内存。这一步不是必须的,但可以将内存资源返回给计算机系统。
示例
#include "vtkUnstructuredGrid.h"
#include "vtkDataSetMapper.h"
#include "vtkCellType.h"
#include "vtkProperty.h"
int main()
{
int i;
static float x[27][3] = {
{0,0,0}, {1,0,0}, {2,0,0}, {0,1,0}, {1,1,0}, {2,1,0},
{0,0,1}, {1,0,1}, {2,0,1}, {0,1,1}, {1,1,1}, {2,1,1},
{0,1,2}, {1,1,2}, {2,1,2}, {0,1,3}, {1,1,3}, {2,1,3},
{0,1,4}, {1,1,4}, {2,1,4}, {0,1,5}, {1,1,5}, {2,1,5},
{0,1,6}, {1,1,6}, {2,1,6}
};
static int pts[12][8] = {
{0,1,4,3,6,7,10,9},
{1,2,5,4,7,8,11,10},
{6,10,9,12,0,0,0,0},
{8,11,10,14,0,0,0,0},
{15,16,17,14,13,12,0,0},
{18,15,19,16,20,17,0,0},
{22,23,20,19,0,0,0,0},
{21,22,18,0,0,0,0,0},
{22,19,18,0,0,0,0,0},
{23,26,0,0,0,0,0,0},
{21,24,0,0,0,0,0,0},
{25,0,0,0,0,0,0,0}
};
vtkNew<vtkPoints> points;
for (int i = 0; i < 27; i++)points->InsertPoint(i, x[i]);
vtkNew<vtkUnstructuredGrid> ugrid;
ugrid->InsertNextCell(VTK_HEXAHEDRON, 8, pts[0]);
ugrid->InsertNextCell(VTK_HEXAHEDRON, 8, pts[1]);
ugrid->InsertNextCell(VTK_TETRA, 4, pts[2]);
ugrid->InsertNextCell(VTK_TETRA, 4, pts[3]);
ugrid->InsertNextCell(VTK_POLYGON, 6, pts[4]);
ugrid->InsertNextCell(VTK_TRIANGLE_STRIP, 6, pts[5]);
ugrid->InsertNextCell(VTK_QUAD, 4, pts[6]);
ugrid->InsertNextCell(VTK_TRIANGLE, 3, pts[7]);
ugrid->InsertNextCell(VTK_TRIANGLE, 3, pts[8]);
ugrid->InsertNextCell(VTK_LINE, 2, pts[9]);
ugrid->InsertNextCell(VTK_LINE, 2, pts[10]);
ugrid->InsertNextCell(VTK_VERTEX, 1, pts[11]);
ugrid->SetPoints(points);
vtkNew<vtkDataSetMapper> ugridMapper;
ugridMapper->SetInputData(ugrid);
vtkNew<vtkActor> ugridActor;
ugridActor->SetMapper(ugridMapper);
ugridActor->GetProperty()->SetRepresentationToWireframe();
ugridActor->GetProperty()->SetColor(0, 0, 0);
vtkNew<vtkRenderer> renderer;
renderer->AddActor(ugridActor);
renderer->SetBackground(1, 1, 1);
vtkNew<vtkRenderWindow> renWin;
renWin->AddRenderer(renderer);
renWin->SetSize(450, 450);
renWin->Render();
vtkNew<vtkRenderWindowInteractor> iren;
iren->SetRenderWindow(renWin);
iren->Initialize();
iren->Start();
return 0;
}
1.定义了两个数组:数组x中存放了27个点的坐标;数组pts中存放了12个单元所需要的12组点id序列;
2.创建非结构化网格。
3.使用映射器vtkDataSetMapper
;
参考资料
1.《医学图像编程技术》