本文最后更新于 186 天前,其中的信息可能已经有所发展或是发生改变。
1. 使用vtk提供的格式转换方法
以XML格式为例:
vtk库中支持多种格式的读写转换,比如利用XML格式,可以将vtkPolyData格式序列化为string类型,直接使用vtk库中的 vtkXMLPolyDataWriter
方法进行序列化 ,以及 vtkXMLPolyDataReader
方法解序列化。
示例:
// 读vtkPolyData,序列化为string类型
std::string write(vtkSmartPointer<vtkPolyData> polyData)
{
vtkSmartPointer<vtkXMLPolyDataWriter> polyDataWriter =
vtkSmartPointer<vtkXMLPolyDataWriter>::New();
polyDataWriter->SetInputData(polyData);
polyDataWriter->WriteToOutputStringOn();
polyDataWriter->Write();
return polyDataWriter->GetOutputString();
}
// 读string类型,解序列化为vtkPolyData类型
vtkSmartPointer<vtkPolyData> read(std::string str)
{
vtkSmartPointer<vtkXMLPolyDataReader> polyDataReader =
vtkSmartPointer<vtkXMLPolyDataReader>::New();
polyDataReader->ReadFromInputStringOn();
polyDataReader->SetInputString(str);
polyDataReader->Update();
return polyDataReader->GetOutput();
}
当然还有其他的类似方法,比如JSON格式的vtkJSONDataSetWriter
/ vtkJSONDataSetReader
等等,另外要注意的是,即便是vtk内部分装的方式,其本质上也还是循环读取数据,比较暴力,如果vtkPolyData数据量比较大,其序列化还是要占用比较多的时间。
2. 使用原生的内存拷贝方法
与其使用暴力的、占用时间长的封装的序列化方法,不如直接对内部数据考虑,采用原生的序列化方法,避免遍历数据,利用内存拷贝的方式,提高序列化速度。
示例:
序列化,通过内存的方式,将vtkPolyData的数据进行拆分再序列化:
void serialize(vtkPolyData* polyData, std::string& pointsStr, std::string& colorsStr){
vtkPoints* points = polyData->GetPoints();
vtkUnsignedCharArray* colors = polyData->GetPointData()->GetScalars();
// 内存拷贝,序列化点数据
int pointsNum = points->GetNumberOfPoints();
pointsStr.resize(pointsNum * 3 * sizeof(double));
double* pointsPtr = static_cast<double*>(points->GetVoidPointer(0));
memcpy(pointsStr.data(), pointsPtr, pointsStr.size());
// 内存拷贝,序列化颜色数据(如果存在)
if(colors){
colorsStr.resize(pointsNum * 3 * sizeof(unsigned char));
unsigned char* colorsPtr = static_cast<unsigned char*>(colors->GetVoidPointer(0));
memcpy(colorsStr.data(), colorsPtr, colorsStr.size());
}
}
解序列化,通过内存的方式,直接将数据还原回vtkPolyData:
void deserialize(const std::string& pointsStr, const std::string& colorsStr, vtkSmartPointer<vtkPolyData> polyData){
// 获取点的数目,注意三维点坐标是三个一组的
int pointsNum = pointsStr.size() / (3 * sizeof(double));
// 内存拷贝直接读点坐标
vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
points->SetDataTypeToDouble();
points->SetNumberOfPoints(pointsNum);
double* pointsPtr = static_cast<double*>(points->GetVoidPointer(0));
memcpy(pointsPtr, pointsStr.data(), pointsStr.size());
// 内存拷贝直接读对应颜色
vtkSmartPointer<vtkUnsignedCharArray> colors = vtkSmartPointer<vtkUnsignedCharArray>::New();
colors->SetNumberOfComponents(3);
colors->SetNumberOfTuples(pointsNum);
unsigned char* colorsPtr = static_cast<unsigned char*>(colors->GetVoidPointer(0));
memcpy(colorsPtr, colorsStr.data(), colorsStr.size());
// 全部赋值给vtkPolyData,得到最终的vtkPolyData
polyData->SetPoints(points);
polyData->GetPointData()->SetScalars(colors);
}