代码之家  ›  专栏  ›  技术社区  ›  landings

为什么我的vtkContourFilter没有输出?

  •  1
  • landings  · 技术社区  · 7 年前

    我正在用C++编写一个VTK程序来处理有限元分析结果。为了显示等值面,我尝试使用vtkContourFilter,但在这个过滤器之后什么也得不到。

    所以我写了一个简单的版本:一个自定义阅读器生成一个2单元非结构化网格,然后一个vtkContourFilter提取等值面。我的标量数据是点数据。

    我打算得到等值面,但仍然得到零输出。我想知道我错过了什么。

    我的程序:

    #include <vtkSmartPointer.h>
    #include <vtkUnstructuredGrid.h>
    #include <vtkPoints.h>
    #include <vtkPointData.h>
    #include <vtkCellArray.h>
    #include <vtkIdList.h>
    #include <vtkDoubleArray.h>
    #include <vtkPointData.h>
    #include <vtkUnstructuredGridReader.h>
    #include <vtkInformation.h>
    #include <vtkInformationVector.h>
    #include <vtkClipDataSet.h>
    #include <vtkPlane.h>
    #include <vtkContourFilter.h>
    #include <iostream>
    using namespace std;
    
    // This is a fake reader that outputs an unstructured mesh
    class VTKIOLEGACY_EXPORT FakeUnstructuredGridReader : public vtkUnstructuredGridReader {
    public:
        static FakeUnstructuredGridReader* New() { return new FakeUnstructuredGridReader(); }
        vtkTypeMacro(FakeUnstructuredGridReader, vtkUnstructuredGridReader);
        void PrintSelf(ostream& os, vtkIndent indent) VTK_OVERRIDE {}
    
    protected:
        FakeUnstructuredGridReader() { this->SetNumberOfInputPorts(0); }// No input ports
        // This method passes a 2-cell unstructured grid with 1 set of scalar point data
        int RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector* outputVector) VTK_OVERRIDE {
            static const double rawPoints[15] = { 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1 };
            static const vtkIdType rawIndices[8] = { 0, 1, 2, 3, 1, 2, 3, 4};
            static const double rawScalar[5] = { 5, 10, 20, 15, 50 };
            static const char* scalarName = "Stress";
            // Build Points
            auto points = vtkSmartPointer<vtkPoints>::New();
            for (int i = 0; i < 15; i += 3)
                points->InsertNextPoint(rawPoints + i);
            // Build Cells
            auto cells = vtkSmartPointer<vtkCellArray>::New();
            // Build Cell 1
            auto indices1 = vtkSmartPointer<vtkIdList>::New();
            for (int i = 0; i < 4; ++i)
                indices1->InsertNextId(rawIndices[i]);      
            cells->InsertNextCell(indices1);
            // Build Cell 2
            auto indices2 = vtkSmartPointer<vtkIdList>::New();
            for (int i = 0; i < 4; ++i)
                indices2->InsertNextId(rawIndices[i + 4]);
            cells->InsertNextCell(indices2);
            // Scalar Data
            auto dataArray = vtkSmartPointer<vtkDoubleArray>::New();
            dataArray->SetName(scalarName);
            dataArray->SetNumberOfComponents(1);
            for (int i = 0; i < 5; ++i)
                dataArray->InsertNextValue(rawScalar[i]);
            // Point Data
            auto pointData = vtkSmartPointer<vtkPointData>::New();
            pointData->AddArray(dataArray);
            // Pass Data
            vtkInformation* outInfo = outputVector->GetInformationObject(0);
            vtkUnstructuredGrid *output = vtkUnstructuredGrid::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
            output->SetPoints(points);
            output->SetCells(VTK_TETRA, cells);
            output->SetFieldData(pointData);
            return 1;
        }
    };
    
    
    int main() {
        // Reader
        auto fakeReader = vtkSmartPointer<FakeUnstructuredGridReader>::New();
    
        // Isosurface Filter
        auto isoFilter = vtkSmartPointer<vtkContourFilter>::New();
        isoFilter->SetInputConnection(fakeReader->GetOutputPort());
        isoFilter->GenerateValues(8, 0.0, 50.0);
        isoFilter->Update();
    
        cout << fakeReader->GetOutput()->GetNumberOfPoints() << endl;
        cout << fakeReader->GetOutput()->GetNumberOfCells() << endl;
        cout << fakeReader->GetOutput()->GetFieldData()->GetNumberOfArrays() << endl;
        cout << isoFilter->GetOutput()->GetNumberOfPoints() << endl;
        cout << isoFilter->GetOutput()->GetNumberOfCells() << endl;
        cout << isoFilter->GetOutput()->GetFieldData()->GetNumberOfArrays() << endl;
    
        system("pause");
        return 0;
    }
    

    其输出:

    5
    2
    1
    0
    0
    1
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   Guillaume Favelier    7 年前

    在函数中 RequestData() 首先需要将标量值与数据集的点相关联 output->GetPointData()->AddArray(dataArray) 然后使用以下命令激活标量场: output->GetPointData()->SetActiveScalars(scalarName) 因此,vtkContourFilter将能够选择它来计算轮廓。你可以通过做以下两个动作 output->GetPointData()->SetScalars(dataArray) . 注意,使用此解决方案,您不需要分配 pointData 变量不再存在。

    简而言之,你可以改变:

    int RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector* outputVector) VTK_OVERRIDE {
      /* body of the function here */
    
      // old version
      // output->SetFieldData(pointData);
      // new version
      output->GetPointData()->SetScalars(dataArray);
      return 1;
    }
    

    您可能需要相应地修改打印。

    // old version:
    // cout << fakeReader->GetOutput()->GetFieldData()->GetNumberOfArrays() << endl;
    // new version:
    cout << fakeReader->GetOutput()->GetPointData()->GetNumberOfArrays() << endl;
    
    // old version
    // cout << isoFilter->GetOutput()->GetFieldData()->GetNumberOfArrays() << endl;
    // new version
    cout << isoFilter->GetOutput()->GetPointData()->GetNumberOfArrays() << endl;