Как сохранить векторное поле с помощью VTK? C++, VTKWriter
Допустим, у меня есть векторное поле u с компонентами ux, uy и uz, определенными в (неструктурированных) позициях в пространстве rx, ry и rz.
Все, что я хочу, это сохранить это векторное поле в формате VTK, то есть с классом "vtkwriter" из libvtk, чтобы включить визуализацию с Paraview.
Я думаю, что получил код для правильного включения позиций, но почему-то не могу понять, как включить данные:
#include <vtkPoints.h>
#include <vtkPolyDataWriter.h>
#include <vtkSmartPointer.h>
void write_file (double* rx, double* ry, double* rz,
double* ux, double* uy, double* uz,
int n, const char* filename)
{
vtkSmartPointer<vtkPoints> points =
vtkSmartPointer<vtkPoints>::New ();
points->SetNumberOfPoints(n);
for (int i = 0; i < n; ++i) {
points->SetPoint(i, rx[i], ry[i], rz[i]);
}
// how to incorporate the vector field u?
vtkSmartPointer<vtkPolyDataWriter> writer =
vtkSmartPointer<vtkPolyDataWriter>::New ();
writer->setFileName (filename);
// how to tell the writer, what to write?
writer->Write ();
}
Первый вопрос: правильный ли общий путь, то есть обработка координат с vtkPoints
?
При поиске в интернете я нахожу много результатов о том, как должен выглядеть окончательный файл. Я мог бы, вероятно, сгенерировать этот формат вручную, но это не совсем то, что я хочу сделать.
С другой стороны, я почему-то не могу понять документацию ВТК. Всякий раз, когда я просматриваю документацию класса, она ссылается на документацию некоторых других классов, а документация этих других классов ссылается на первый.
То же самое относится и к примерам. До сих пор я не нашел ни одного, который объяснял бы, как обращаться с векторными данными, который определен в произвольных позициях, а другие примеры настолько сложны, что я полностью застрял здесь.
Я думаю, решение как-то использует vtkPolyData
, но я не могу понять, как вставить данные. Я думаю, это нужно vtkDoubleArray
, но я пока не нашел, как сделать, если вектор ценится.
Заранее спасибо.
1 ответ
Хорошо, я сделал это после достаточно проб и ошибок. Координаты, в которых определяется векторное поле, должны быть vtkPoints
и интересующие данные должны быть vtkDoubleArray
, Включение в финал vtkPolyData
объект делается через vtkPolyData::GetPointData()->SetVectors(...)
,
Наконец, тип ячейки должен быть установлен как vtkVertex
:
#include <vtkCellArray.h>
#include <vtkDoubleArray.h>
#include <vtkPointData.h>
#include <vtkPoints.h>
#include <vtkPolyData.h>
#include <vtkPolyDataWriter.h>
#include <vtkSmartPointer.h>
#include <vtkVertex.h>
void VTKWriter::write_file(double* rx, double *ry, double *rz,
double* ux, double *uy, double *uz,
int n, const char* filename)
{
vtkSmartPointer<vtkPoints> points =
vtkSmartPointer<vtkPoints>::New();
points->SetNumberOfPoints(n);
vtkSmartPointer<vtkCellArray> vertices =
vtkSmartPointer<vtkCellArray>::New();
vertices->SetNumberOfCells(n);
for (int i = 0; i < n; ++i) {
points->SetPoint(i, rx[i], ry[i], rz[i]);
vtkSmartPointer<vtkVertex> vertex =
vtkSmartPointer<vtkVertex>::New();
vertex->GetPointIds()->SetId(0, i);
vertices->InsertNextCell(vertex);
}
vtkSmartPointer<vtkDoubleArray> u =
vtkSmartPointer<vtkDoubleArray>::New();
u->SetName("u");
u->SetNumberOfComponents(3);
u->SetNumberOfTuples(n);
for (int i = 0; i < n; ++i) {
u->SetTuple3(i, ux[i], uy[i], uz[i]);
}
vtkSmartPointer<vtkPolyData> polydata =
vtkSmartPointer<vtkPolyData>::New();
polydata->SetPoints(points);
polydata->SetVerts(vertices);
polydata->GetPointData()->SetVectors(u);
vtkSmartPointer<vtkPolyDataWriter> writer =
vtkSmartPointer<vtkPolyDataWriter>::New();
writer->SetFileName(filename);
writer->SetInputData(polydata);
writer->Write ();
}
Причина, по которой я сначала этого не понял, заключалась в том, что взаимодействие между точками, ячейками, вершинами, точечными данными и полиданными нелегко понять, когда кто-то новичок в VTK, учебники на самом деле не охватывают это вообще, и документация ВТК по Doxygen также почему-то бесполезна на этом этапе.