1

我正在制作一个更简单的查看器来阅读和可视化网格。

VTK 对我来说是新的,我首先试图找出为查看器设置网格数据的最佳/最有效的方法。我看到有很多使用 C++ 的 VTK 示例,但其中很多是转换为 vtk 格式或渲染原语。

我对转换为 vtk 格式不感兴趣,我只是将我的网格数据设置为vtk 非结构化网格vtk 多边形数据集并渲染它。

我做了一个小测试。下面的代码正确呈现,但这是设置数据集的最有效方法吗?如果我设置N_SQUARES为 1 000 000,它可以工作,但三角形循环似乎很慢。

    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);
4

1 回答 1

2

由于多种原因,您的示例中的代码可能会很慢

  • 您正在j-loop 中构建和销毁 2 个 vtkTriangle 实例。这是昂贵的,并且可能是缓慢的最大原因。
  • 由于您构建了 polydata,因此最好完全避免使用 vtkTriangle。相反,做类似的事情

    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);
    }
    
  • 您不会提前告诉 VTK 数组(点坐标或连通性)有多大。这意味着 VTK 必须在增加数组大小时重新分配和复制数组。尝试nodes->GetData()->Allocate(4 * N_SQUARES);在第一个循环之前添加(over i)。同样,您可以告诉 vtkCellArray 提前分配适量的内存(有点棘手;它是一个整数数组,格式如下:nptsPerPoly0 ptId0Poly0 ptId1Poly0 ... ptIdNPoly0 nPtsPerPoly1 ...)。对于三角形,您可以调用triangles->Allocate((1 + 3) * 2 * N_SQUARES);. 对于前面示例中的四边形,它将是triangles->Allocate((1 + 4) * N_SQUARES);.

  • 您的示例不重复使用由多个正方形共享的点。这使得两者都nodes消耗triangles了比必要更多的内存。
  • 对于中等大小的网格(适合单台计算机的内存),您可以使用线程来准备nodestriangles数组。对于大型网格,VTK 可在多台计算机上工作,其中每台计算机仅保存部分网格(分布式内存并行性)。
  • 如果您已经在内存中拥有网格,VTK 的最新版本允许您编写特殊的类,将网格暴露给 VTK,而不需要任何副本,但这超出了这个问题的范围。但是,它将给定网格消耗的内存量减半,因此它可能很重要,具体取决于网格和计算机的内存。
  • 根据您制作的大小N_SQUARES,您可能会导致计算机使用交换文件或分区。在这种情况下,您应该减小网格的大小或使用分布式内存并行性。
于 2017-07-01T01:12:51.320 回答