Reputation: 1047
I'm making a simpler viewer to read and visualize a mesh.
VTK is new to me and I'm first trying to figure out the best/most efficient way to set up the mesh data for the viewer. I see there are many examples of VTK with c++, but a lot of them are to convert to vtk format or rendering primitives.
I'm not interested in converting to vtk format, I just what to set up my mesh data to a vtk unstructured grid or vtk poly data set and render it.
I've done a little test. The code bellow correctly renders, but is this the most efficient way to set up the dataset? If I set N_SQUARES
to 1 000 000, it works, but the triangle loop seems very slow.
vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
//TEST MESH
int N_SQUARES = 100;
//This creates node coordinates for N_SQUARES amount of squares. (Nodal data would be read from a file later on)
vtkSmartPointer<vtkPoints> nodes = vtkSmartPointer<vtkPoints>::New();
for (int i = 0; i < N_SQUARES; i++){
nodes->InsertNextPoint(0.0, 0.0, 0.0 + 0.2f*float(i));
nodes->InsertNextPoint(1.0, 0.0, 0.0 + 0.2f*float(i));
nodes->InsertNextPoint(1.0, 1.0, 0.0 + 0.2f*float(i));
nodes->InsertNextPoint(0.0, 1.0, 0.2 + 0.2f*float(i));
}
//Here two triangles are created for each square. (these indices would later on be read from FEM element data)
vtkSmartPointer<vtkCellArray> triangles = vtkSmartPointer<vtkCellArray>::New();
for (int j = 0; j < N_SQUARES; j++){
vtkSmartPointer<vtkTriangle> triangle1 = vtkSmartPointer<vtkTriangle>::New();
triangle1->GetPointIds()->SetId(0, 0 + j);
triangle1->GetPointIds()->SetId(1, 1 + j);
triangle1->GetPointIds()->SetId(2, 2 + j);
vtkSmartPointer<vtkTriangle> triangle2 = vtkSmartPointer<vtkTriangle>::New();
triangle2->GetPointIds()->SetId(0, 2 + j);
triangle2->GetPointIds()->SetId(1, 3 + j);
triangle2->GetPointIds()->SetId(2, 0 + j);
triangles->InsertNextCell(triangle1);
triangles->InsertNextCell(triangle2);
}
vtkSmartPointer<vtkPolyData> meshData = vtkSmartPointer<vtkPolyData>::New();
meshData->SetPoints(nodes);
meshData->SetPolys(triangles);
vtkSmartPointer<vtkPolyDataMapper> meshMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
meshMapper->SetInputData(meshData);
vtkSmartPointer<vtkActor> meshActor = vtkSmartPointer<vtkActor>::New();
meshActor->SetMapper(meshMapper);
renderer->AddActor(meshActor);
ui.qvtkWidget->GetRenderWindow()->AddRenderer(renderer);
Upvotes: 1
Views: 2249
Reputation: 545
The code in your example could be slow for any of several reasons
j
-loop. This is expensive and probably the largest cause of slowness.Since you build polydata, it would be best to avoid using vtkTriangle at all. Instead, do something like
for (int j = 0; j < N_SQUARES; ++j)
{
vtkIdType triangle1[3] = {j, j+1, j+2};
vtkIdType triangle2[3] = {j+2, j+3, j};
triangles->InsertNextCell(3, triangle1);
triangles->InsertNextCell(3, triangle2);
// ... or better yet, create a single quad:
vtkIdType quad[4] = {j, j+1, j+2, j+3};
triangles->InsertNextCell(4, quad);
}
You don't tell VTK how big the arrays (point coordinates or connectivity) are going to be ahead of time. This means VTK must reallocate and copy the arrays as you increase their size. Try adding nodes->GetData()->Allocate(4 * N_SQUARES);
before your first loop (over i
). Similarly, you can tell the vtkCellArray to allocate the right amount of memory ahead of time (a little tricky; it is an array of integers formatted like so: nptsPerPoly0 ptId0Poly0 ptId1Poly0 ... ptIdNPoly0 nPtsPerPoly1 ...). For triangles, you would call triangles->Allocate((1 + 3) * 2 * N_SQUARES);
. For quads as in the previous example, it would be triangles->Allocate((1 + 4) * N_SQUARES);
.
nodes
and triangles
consume much more memory than necessary.nodes
and triangles
arrays. For large meshes, VTK is built to work across multiple computers where each one holds only part of the mesh (distributed-memory parallelism).N_SQUARES
, you could be causing your computer to use a swap file or partition. In that case you should reduce the size of your mesh or use distributed-memory parallelism.Upvotes: 3