vtk读取CGNS文件
vtk里面有vtkCGNSReader类,用于读取cgns文件。用法很简单:
//设置cgns文件名
reader->SetFileName(gridFilename.c_str());
//
reader->Update();
//读取结果存到vtkMultiBlockDataSet对象中
vtkSmartPointer<vtkMultiBlockDataSet> mb = reader->GetOutput();
这个vtkMultiBlockDataSet是vtkCompositeDataSet的子类。它是一种树形结构。大概的结构我画了一下:
按照上面的结构,要想获得网格部分的数据,需要如下操作:
vtkCompositeDataIterator *iter = multiBlockDataSet->NewIterator();
for(iter->InitTraversal();!iter->IsDoneWithTraversal();iter->GoToNextItem())
{
vtkDataObject* dObj = iter->GetCurrentDataObject();
vtkUnstructuredGrid* ugd = vtkUnstructuredGrid::SafeDownCast(dObj);
ugd->Print(cout);
cout << ugd->GetNumberOfCells()<<endl;
}
通过建立一个vtkCompositeDataSet的迭代器,去遍历其Dataset。
遍历器返回的是vtkDataObject,他是所有vtk数据集的基类,需要将其变为具体类型的指针才能进行后续处理(不知道对不对,好麻烦)。所以,还需要:
vtkUnstructuredGrid* ugd = vtkUnstructuredGrid::SafeDownCast(dObj);
这里,我已经知道子数据集都是非结构网格。如果预先不知道子数据集的类型,可以使用
dObj->GetClassName()
获得其类型,然后加上判断语句,来进行类型转换。
此外,获得DataObject的信息需要用vtkInformation类。
vtkInformation *info = info = multiBlockDataSet->GetMetaData(iter);
string zoneName = info->Get(vtkCompositeDataSet::NAME());
string familyName = info->Get(vtkInformationStringKey::FAMILY());
information类里面的项要用informationxxxKey来获取,xxx代表类型,比如int,double等等。这里cgns文件用的是compositeDataSet的name()预定义宏返回的informationStringKey,和family宏返回的stringKey。
每个对象都可print(cout, vtkIndent()),便于察看详细信息。第一个参数是ostream对象,第二参数是缩进对象,vtkIndent(ind = 0)默认是0缩进。
附录:vtk tutorial里面关于compositeDataSet的说明。
从上图中可以明显看出,我们有 3 个 vtkCompositeDataSet 的具体子类。vtkMultiBlockDataSet 是一个由块组成的数据集。每个块可以是非复合 vtkDataObject 子类(或叶),也可以是 vtkMultiBlockDataSet 本身的实例。这使得构建完整的树成为可能。vtkHierarchicalBoxDataSet用于AMR数据集,其中包括每个精简级别的精简级别和统一网格数据集。vtkMultiPieceDataSet可以被认为是vtkMultiBlockDataSet的特化,其中没有一个块可以是复合数据集。vtkMultiPieceDataSet 用于将数据集的多个部分组合在一起。
vtkCompositeDataSet 是所有复合数据集的抽象基类。它为树数据结构提供了实现。复合数据集的所有子类基本上都是具有某些限制的 vtkDataSet 实例的树。因此,vtkCompositeDataSet 为内部树实现提供了受保护的 API,以便子类访问此内部树,同时将其留给子类以提供公共 API 来填充数据集。此类提供的唯一公共 API 与迭代器相关。
迭代器用于访问复合数据集中的节点。以下示例显示了如何使用迭代器来循环访问非空的非复合数据集节点。
vtkCompositeDataIterator* iter = compositeData->NewIterator();
for (iter->InitTraversal(); !iter->IsDoneWithTraversal(); iter->GoToNextItem())
{
vtkDataObject* dObj = iter->GetCurrentDataObject();
cout << dObj->GetClassName() <<endl;
}