* vtkExecutive is the superclass for all pipeline executives in VTK.
* A VTK executive is responsible for controlling one instance of
* vtkAlgorithm. A pipeline consists of one or more executives that
* control data flow. Every reader, source, writer, or data
* processing algorithm in the pipeline is implemented in an instance
* of vtkAlgorithm.
vtkExective 是所有管道处理的父类,一个vtkExective对象处理一个vtkAlgorithm实例,但一个管道可以有多个vtkexective对象来处理数据流,读写器,数据对象显示源都要继承vtkAlgorithm类。
以vtkPolydatareader类为例。
vtkPolyDataReader is a source object that reads ASCII or binary
* polygonal data files in vtk format (see text for format details).
* The output of this reader is a single vtkPolyData data object.
* The superclass of this class, vtkDataReader, provides many methods for
* controlling the reading of the data file, see vtkDataReader for more
* information.
* @warning
* Binary files written on one system may not be readable on other systems.
* @sa
* vtkPolyData vtkDataReader
官方解释如上,此类就是来读取.vtk文件来生成vtkpolydata数据(包含里点、线、面及相互的拓扑关系,随后详细展开)。从源文件分析此类。.vtk文件格式解析之前的一篇可以查看。
static vtkPolyDataReader *New(); 实例化对象
vtkTypeMacro(vtkPolyDataReader,vtkDataReader);父子继承类型宏,用来追踪父子关系,能看出来vtkpolydatareader继承vtkDataReader类。他的父类不再展开说了。
void PrintSelf(ostream& os, vtkIndent indent) override;打印这是vtkbaseobject祖师类的方法了。
vtkPolyData *GetOutput(int idx); 得到第idx端口的数据,可以有多端口,根据实际类型情况分析,vtkPolydatareader是单输出口,idx为0.
void SetOutput(vtkPolyData *output);
这是最核心的读取方法类,不同的格式读取主要重写这个方法。
int ReadMeshSimple(const std::string& fname,
vtkDataObject* output) override;
详细分析此方法,便于书写.off等官方未重写的文件读取方法。
# vtk DataFile Version 3.0
vtk output
ASCII
DATASET POLYDATA
POINTS 989 float
-0.300020 -0.500000 0.000000
节选文件的一部分。
int vtkPolyDataReader::ReadMeshSimple(
const std::string& fname, vtkDataObject* doOutput)
{
vtkIdType numPts=0;
char line[256];
vtkIdType npts, size = 0, ncells, i;
vtkPolyData *output = vtkPolyData::SafeDownCast(doOutput);
int *tempArray;
vtkIdType *idArray;
vtkDebugMacro(<<"Reading vtk polygonal data...");
//vtkdebug输出正在读取vtkpolydata数据。
if ( !(this->OpenVTKFile(fname.c_str())) || !this->ReadHeader(fname.c_str()))
{
return 1;
}
//打不开vtk文件
// Read polygonal data specific stuff
//文件读取完毕
if (!this->ReadString(line))
{
vtkErrorMacro(<<"Data file ends prematurely!");
this->CloseVTKFile ();
return 1;
}
if ( !strncmp(this->LowerCase(line),"dataset",(unsigned long)7) )
{
//判断是否是dataset数据格式。
// Make sure we're reading right type of geometry
//读完文件
if (!this->ReadString(line))
{
vtkErrorMacro(<<"Data file ends prematurely!");
this->CloseVTKFile ();
return 1;
}
//确定是polydata文件格式。
if ( strncmp(this->LowerCase(line),"polydata",8) )
{
vtkErrorMacro(<< "Cannot read dataset type: " << line);
this->CloseVTKFile ();
return 1;
}
//
// Might find points, vertices, lines, polygons, or triangle strips
//文件读取正确
while (true)
{
if (!this->ReadString(line))
{
break;
}
//读取完毕,下面的判读不知道是兼容哪个版本的,3.0vtk中polydata格式中没有发现field字段。或者在一些兼容格式中有field字段类型。
if (! strncmp(this->LowerCase(line), "field", 5))
{
vtkFieldData* fd = this->ReadFieldData();//需要说明下vtkfielddata类,继承vtkObject,主要用来对field这种类型的文件流读取处理。读取的是字符串数组。后面介绍vtkdatareader类。
output->SetFieldData(fd);
fd->Delete(); // ?
}
//开始正常的vtk文件读取。先从points开始。
else if ( ! strncmp(line, "points",6) )
{
if (!this->Read(&numPts))
{
vtkErrorMacro(<<"Cannot read number of points!");
this->CloseVTKFile ();
return 1;
}
//读取点坐标
// this->IS->getline(line,256); istream IS
// this->IS->read((char *)ptr,sizeof(unsigned char)*(numTuples*numComp+7)/8);
this->ReadPointCoordinates(output, numPts);
}
//顶点坐标
else if ( ! strncmp(line,"vertices",8) )
{
vtkCellArray *verts = vtkCellArray::New();
if (!(this->Read(&ncells) && this->Read(&size)))
{
vtkErrorMacro(<<"Cannot read vertices!");
this->CloseVTKFile ();
return 1;
}
tempArray = new int[size];
idArray = verts->WritePointer(ncells, size);
this->ReadCells(size, tempArray);
// this->ReadCells(size, verts->WritePointer(ncells,size));
for (i = 0; i < size; i++)
{
idArray[i] = tempArray[i];
}
output->SetVerts(verts);
verts->Delete();
delete [] tempArray;
vtkDebugMacro(<<"Read " << ncells << " vertices");
}
else if ( ! strncmp(line,"lines",5) )
{
vtkCellArray *lines = vtkCellArray::New();
if (!(this->Read(&ncells) && this->Read(&size)))
{
vtkErrorMacro(<<"Cannot read lines!");
this->CloseVTKFile ();
return 1;
}
tempArray = new int[size];
idArray = lines->WritePointer(ncells, size);
this->ReadCells(size, tempArray);
// this->ReadCells(size, lines->WritePointer(ncells,size));
for (i = 0; i < size; i++)
{
idArray[i] = tempArray[i];
}
output->SetLines(lines);
lines->Delete();
delete [] tempArray;
vtkDebugMacro(<<"Read " << ncells << " lines");
}
//读取三角面片
else if ( ! strncmp(line,"polygons",8) )
{
vtkCellArray *polys = vtkCellArray::New();
if (!(this->Read(&ncells) && this->Read(&size)))
{
vtkErrorMacro(<<"Cannot read polygons!");
this->CloseVTKFile ();
return 1;
}
tempArray = new int[size];
idArray = polys->WritePointer(ncells, size);
this->ReadCells(size, tempArray);
// this->ReadCells(size, polys->WritePointer(ncells,size));
for (i = 0; i < size; i++)
{
idArray[i] = tempArray[i];
}
output->SetPolys(polys);
polys->Delete();
delete [] tempArray;
vtkDebugMacro(<<"Read " << ncells << " polygons");
}
else if ( ! strncmp(line,"triangle_strips",15) )
{
vtkCellArray *tris = vtkCellArray::New();
if (!(this->Read(&ncells) && this->Read(&size)))
{
vtkErrorMacro(<<"Cannot read triangle strips!");
this->CloseVTKFile ();
return 1;
}
tempArray = new int[size];
idArray = tris->WritePointer(ncells, size);
this->ReadCells(size, tempArray);
// this->ReadCells(size, tris->WritePointer(ncells,size));
for (i = 0; i < size; i++)
{
idArray[i] = tempArray[i];
}
output->SetStrips(tris);
tris->Delete();
delete [] tempArray;
vtkDebugMacro(<<"Read " << ncells << " triangle strips");
}
//读取cell_data scalar值
else if ( ! strncmp(line, "cell_data", 9) )
{
if (!this->Read(&ncells))
{
vtkErrorMacro(<<"Cannot read cell data!");
this->CloseVTKFile ();
return 1;
}
if ( ncells != output->GetNumberOfCells() )
{
vtkErrorMacro(<<"Number of cells don't match number data values!");
return 1;
}
this->ReadCellData(output, ncells);
break; //out of this loop
}
else if ( ! strncmp(line, "point_data", 10) )
{
if (!this->Read(&npts))
{
vtkErrorMacro(<<"Cannot read point data!");
this->CloseVTKFile ();
return 1;
}
if ( npts != numPts )
{
vtkErrorMacro(<<"Number of points don't match number data values!");
return 1;
}
this->ReadPointData(output, npts);
break; //out of this loop
}
else
{
vtkErrorMacro(<< "Unrecognized keyword: " << line);
this->CloseVTKFile ();
return 1;
}
}
if ( ! output->GetPoints() ) vtkWarningMacro(<<"No points read!");
if ( !(output->GetVerts() || output->GetLines() ||
output->GetPolys() || output->GetStrips()) )
vtkWarningMacro(<<"No topology read!");
}
else if ( !strncmp(line, "cell_data", 9) )
{
vtkWarningMacro(<<"No geometry defined in data file!");
if (!this->Read(&ncells))
{
vtkErrorMacro(<<"Cannot read cell data!");
this->CloseVTKFile ();
return 1;
}
this->ReadCellData(output, ncells);
}
else if ( !strncmp(line, "point_data", 10) )
{
vtkWarningMacro(<<"No geometry defined in data file!");
if (!this->Read(&numPts))
{
vtkErrorMacro(<<"Cannot read point data!");
this->CloseVTKFile ();
return 1;
}
this->ReadPointData(output, numPts);
}
else
{
vtkErrorMacro(<< "Unrecognized keyword: " << line);
}
this->CloseVTKFile ();
return 1;
}
//读取fielddata
vtkFieldData *vtkDataReader::ReadFieldData(FieldType fieldType)
{
int i, numArrays=0, skipField=0;
vtkFieldData *f;
char name[256], type[256];
vtkIdType numComp, numTuples;
vtkAbstractArray *data;
if ( !(this->ReadString(name) && this->Read(&numArrays)) )
{
const char* fname = this->CurrentFileName.c_str();
vtkErrorMacro(<<"Cannot read field header!" << " for file: "
<< (fname?fname:"(Null FileName)"));
return nullptr;
}
// See whether field data name (if specified)
if ( (this->FieldDataName && strcmp(name,this->FieldDataName)) )
{
skipField = 1;
}
f = vtkFieldData::New();
f->AllocateArrays(numArrays);
// Read the number of arrays specified
for (i=0; i<numArrays; i++)
{
char buffer[1024];
this->ReadString(buffer);
if ( strcmp(buffer, "NULL_ARRAY") == 0 )
{
continue;
}
this->DecodeString(name, buffer);
this->Read(&numComp);
this->Read(&numTuples);
this->ReadString(type);
data = this->ReadArray(type, numTuples, numComp);
if ( data != nullptr )
{
if ( ! skipField || this->ReadAllFields )
{
data->SetName(name);
this->ConvertGhostLevelsToGhostType(fieldType, data);
f->AddArray(data);
}
data->Delete();
}
else
{
f->Delete();
return nullptr;
}
}
if ( skipField && ! this->ReadAllFields )
{
f->Delete();
return nullptr;
}
else
{
return f;
}
}
// Read point coordinates. Return 0 if error. 读取坐标方法解析
int vtkDataReader::ReadPointCoordinates(vtkPointSet *ps, vtkIdType numPts)
{
char line[256];
vtkDataArray *data;
if (!this->ReadString(line))
{
const char* fname = this->CurrentFileName.c_str();
vtkErrorMacro(<<"Cannot read points type!" << " for file: " << (fname?fname:"(Null FileName)"));
return 0;
}
//一行是三个xyz坐标值
data = vtkArrayDownCast<vtkDataArray>(
this->ReadArray(line, numPts, 3));
if ( data != nullptr )
{
vtkPoints *points=vtkPoints::New();
points->SetData(data);
data->Delete();
ps->SetPoints(points);//点集合
points->Delete();
}
else
{
return 0;
}
vtkDebugMacro(<<"Read " << ps->GetNumberOfPoints() << " points");
float progress = this->GetProgress();
this->UpdateProgress(progress + 0.5*(1.0 - progress));
//该类继承算法类,updateProgress后面的参数要求在(0,1)之间,属于激活事件将调用此算法的所有数据进行通知更新。在vtkAlgorithm类中有详细介绍,可参考。
return 1;
}
总结下,vtk文件存的可以认为是字符串,在数据读取时都认为是字符串的提取就可以了。