【问题标题】:vtk value at x,y,z pointx,y,z 点的 vtk 值
【发布时间】:2016-02-13 10:34:57
【问题描述】:

我有一个vtk 文件,它映射了 3 个维度的温度。我想确定给定 x、y、z 点的温度。我将使用以下代码来加载vtk 文件(Reading .vtk file):

int main(int argc, char *argv[]) 
{
  // simply set filename here (oh static joy)
  std::string inputFilename = "setYourPathToVtkFileHere";

  // Get all data from the file
  vtkSmartPointer<vtkGenericDataObjectReader> reader =
        vtkSmartPointer<vtkGenericDataObjectReader>::New();
  reader->SetFileName(inputFilename.c_str());
  reader->Update();

  // All of the standard data types can be checked and obtained like this:
  if (reader->IsFilePolyData()) 
  {
    std::cout << "output is a polydata" << std::endl;
    vtkPolyData* output = reader->GetPolyDataOutput();
    std::cout << "output has " << output->GetNumberOfPoints() << "     points." << std::endl;
  }

  return EXIT_SUCCESS;
}

但是,在搜索 vtk 库中的大量方法列表时,我找不到合适的函数来在特定位置提取值。有什么建议吗?

【问题讨论】:

    标签: c++ vtk


    【解决方案1】:

    在给定位置检索标量值的正确方法取决于两个问题:

    1. 您的数据是如何布局的?
    2. 您要从哪个位置检索属性

    关于数据布局主要有两种布局:

    • 结构化:数据位于统一的网格中
    • 非结构化:点样本是任意的

    关于位置,您可以有两种情况:

    • 在样本位置查询:您要求在数据集中直接作为样本的点
    • 在任意位置查询:您要求的点位于您域中的某个位置,但不一定与您的数据样本一致。

    独立于数据布局,要在样本位置(即原始数据集的样本)检索数据,您可以使用 vtkPointLocator 类。使用类如下(未经测试):

    // Build locator object
    vtkSmartPointer<vtkPointLocator> locator = vtkPointLocator::New();
    locator->SetDataSet(polyData);
    locator->BuildLocator();
    // Define query position
    double pt[3] = {0.1, 0.2, 0.3};
    // Get the ID of the point that is closest to the query position
    vtkIdType id = locator->FindClosestPoint(pt);
    // Retrieve the first attribute value from this point
    double value = polyData->GetPointData()->GetScalars()->GetTuple(id, 0);
    

    这将为您提供最接近数据样本的点值。 请注意,这不会为您提供数据集中点的显式位置,因为它已隐式编码在变量 id 中。要检索最近点的实际位置,可以这样写:

    double *dataPt = polyData->GetPoint(id);
    

    如果您想在域的任意位置检索数据,您将需要某种插值方式。 在这里,数据布局很重要。

    • 对于结构化数据,您可以先将数据转换为 vtkImage,然后对其执行查询。如果您想使用线性或三次方案检索插值属性,您可以在过滤器链中添加一个 vtkImageInterpolator,然后使用 GetScalarComponentAsDouble 方法检索一个点。
    • 对于非结构化数据,您应首先确定插值方案。 vtk 有各种过滤器来从数据样本中重建连续数据。选项包括 Delaunay 三角剖分/四面体化 (vtkDelaunay2D, vtkDelaunay3D) 以及 Shepard 方法 (vtkShepardMethod)。任何一种方法都会给你一个新的数据集,可以查询任意点。如果您想在不实际重建完整数据集的情况下检索(一批)点的标量属性,您还可以查看 vtkProbeFilter。

    【讨论】:

    • 如果有多个标量可用,是否必须先使用 setActiveScalar("temp")?
    【解决方案2】:

    您需要先从阅读器中提取 polyData。然后,通过vtkPolyData::getPoints 将积分存储到vtksmartPointer&lt;vtkPoints&gt; 中。 最后,创建一个自定义结构的 std::vector 并在迭代 vtkPoints 时存储它们。

    这里有一些代码来说明:

    #include <vtkDataArray.h>
    #include <vtkDataSet.h>
    #include <vtkGenericDataObjectReader.h>
    #include <vtkPointLocator.h>
    #include <vtkPointData.h>
    #include <vtkPolyData.h>
    #include <vtkSmartPointer.h>
    #include <vtkStructuredGrid.h>
    #include <string>
    
    
    struct Pnt {
        double x_, y_, z_;
        Pnt(double x, double y, double z) : x_(x), y_(y), z_(z) {}
    };
    
        int main ( int argc, char *argv[] )
    {
      // Ensure a filename was specified
      if(argc != 2)
        {
        std::cerr << "Usage: " << argv[0] << " InputFilename" << endl;
        return EXIT_FAILURE;
        }
    
      // simply set filename here (oh static joy)
      std::string inputFilename = "setYourPathToVtkFileHere";
    
      // Get all data from the file
      vtkSmartPointer<vtkGenericDataObjectReader> reader = vtkSmartPointer<vtkGenericDataObjectReader>::New();
      reader->SetFileName(inputFilename.c_str());
      reader->Update();
    
      vtkSmartPointer<vtkPolyData> polydata = reader->GetPolyDataOutput();
      vtkSmartPointer<vtkPoints> vtk_points = polydata->GetPoints();
    
      std::vector<Pnt> my_points;
      for (int i = 0; i < vtk_points->GetNumberOfPoints(); i++){
          const auto pnt = vtk_points->GetPoint(i);
          my_points.emplace_back(pnt[0], pnt[1], pnt[2]);
      }
    
      return EXIT_SUCCESS;
    }
    

    这是 QnD 的回答中提到的带有 vtkPointLocator 的版本:

    int main(int argc, char *argv[])
    {
        // Ensure a filename was specified
        if (argc != 2)
        {
            std::cerr << "Usage: " << argv[0] << " InputFilename" << endl;
            return EXIT_FAILURE;
        }
    
        // simply set filename here (oh static joy)
        std::string inputFilename = "setYourPathToVtkFileHere";
    
        // Get all data from the file
        vtkSmartPointer<vtkGenericDataObjectReader> reader = vtkSmartPointer<vtkGenericDataObjectReader>::New();
        reader->SetFileName(inputFilename.c_str());
        reader->Update();
    
        vtkSmartPointer<vtkPolyData> polydata = reader->GetPolyDataOutput();
    
        //Building locator
        vtkSmartPointer<vtkPointLocator> locator = vtkPointLocator::New();
        locator->SetDataSet(polydata);
        locator->BuildLocator();
    
        //Finding point
        const double pt[3] = { 0.1, 0.2, 0.3 };
        vtkIdType id = locator->FindClosestPoint(pt);
        double pnt_found[3];
        polydata->GetPointData()->GetScalars()->GetTuple(id, pnt_found);
    
        return EXIT_SUCCESS;
    }
    

    还有 CMakeLists.txt

    cmake_minimum_required(VERSION 2.8)
    
    PROJECT(GenericDataObjectReader)
    
    find_package(VTK REQUIRED)
    include(${VTK_USE_FILE})
    
    add_executable(GenericDataObjectReader MACOSX_BUNDLE GenericDataObjectReader)
    
    if(VTK_LIBRARIES)
      target_link_libraries(GenericDataObjectReader ${VTK_LIBRARIES})
    else()
      target_link_libraries(GenericDataObjectReader vtkHybrid vtkWidgets)
    endif()
    

    如果我需要采取任何具体行动来正确记入其他答案,请告诉我。我是新手,还不知道所有细节。

    【讨论】:

    • cmake CMakeLists.txt
    • 感谢 dutiona。如果以下后续问题是盲目的,我深表歉意,但是我是 VTK 库的完全新手。我已经尝试了以下代码和 make 方法(以及许多变体),但仍然出现编译错误。我假设我没有在 CMakeLists.txt 文件中包含正确的标题或添加正确的库。
    • 您好,我会争取一些时间在明天的工作中完整地编写一个工作示例。家里没有编译过vtk,需要很多时间。
    猜你喜欢
    • 2013-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-12
    • 1970-01-01
    • 2012-01-07
    相关资源
    最近更新 更多