VTK メモ2019年8月27日 | |
はじめにデータ可視化ライブラリ VTK のメモ。 環境
VTK については、ソースからビルドする。apt-get でもよいのだが、Anaconda3 の Qt と一緒に利用しようとすると、うまく動かなかった (Anaconda3 の Qt が使いたかったというより、Qt と Anaconda3 の Python を使おうとすると、Anaconda3 の Qt が使われてしまうため)。 CMake は apt-get でインストールすればよい。 VTK を用いたプログラムのコンパイルVTK を用いたプログラムのコンパイルには、CMake を用いる。プロジェクトディレクトリを作り、CMakeLists.txt を用意する。 cmake_minimum_required(VERSION 2.8) find_package(VTK REQUIRED) include(${VTK_USE_FILE}) file(GLOB CXX_FILES *.cxx) add_executable(cylinder ${CXX_FILES}) target_link_libraries(cylinder ${VTK_LIBRARIES}) コンパイルはビルドディレクトリを作り、その中で行う。 $ mkdir build $ cd build $ cmake .. $ make 円筒の表示cylinder.cxx #include <vtkSmartPointer.h> #include <vtkCylinderSource.h> #include <vtkPolyDataMapper.h> #include <vtkActor.h> #include <vtkProperty.h> #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> #include <vtkCamera.h> using namespace std; int main(int argc, char **argv) { // source auto cylinder = vtkSmartPointer<vtkCylinderSource>::New(); cylinder->SetResolution(20); // mapper auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); mapper->SetInputConnection(cylinder->GetOutputPort()); // actor auto actor = vtkSmartPointer<vtkActor>::New(); actor->SetMapper(mapper); actor->GetProperty()->SetColor(1., .3882, .2784 ); actor->RotateX(30.); actor->RotateY(-45.); // renderer auto ren = vtkSmartPointer<vtkRenderer>::New(); ren->AddActor(actor); ren->SetBackground(0.1, 0.2, 0.4); auto renWin = vtkSmartPointer<vtkRenderWindow>::New(); renWin->AddRenderer(ren); renWin->SetSize(640, 480); // interactor auto inter = vtkSmartPointer<vtkRenderWindowInteractor>::New(); inter->SetRenderWindow(renWin); ren->ResetCamera(); ren->GetActiveCamera()->Zoom(1.5); renWin->Render(); inter->Initialize(); inter->Start(); return 0; } ![]() マウスイベントmouse.cxx #include <vtkSmartPointer.h> #include <vtkCylinderSource.h> #include <vtkPolyDataMapper.h> #include <vtkActor.h> #include <vtkProperty.h> #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> #include <vtkInteractorStyleTrackballCamera.h> #include <vtkCamera.h> using namespace std; class MouseInteractorStyle : public vtkInteractorStyleTrackballCamera { public: void OnLeftButtonDown() noexcept override { cout << "LEFT" << endl; vtkInteractorStyleTrackballCamera::OnLeftButtonDown(); } void OnRightButtonDown() noexcept override { cout << "RIGHT" << endl; vtkInteractorStyleTrackballCamera::OnRightButtonDown(); } }; int main(int argc, char **argv) { // source auto cylinder = vtkSmartPointer<vtkCylinderSource>::New(); cylinder->SetResolution(20); // mapper auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); mapper->SetInputConnection(cylinder->GetOutputPort()); // actor auto actor = vtkSmartPointer<vtkActor>::New(); actor->SetMapper(mapper); actor->GetProperty()->SetColor(1., .3882, .2784 ); actor->RotateX(30.); actor->RotateY(-45.); // renderer auto ren = vtkSmartPointer<vtkRenderer>::New(); ren->AddActor(actor); ren->SetBackground(0.1, 0.2, 0.4); auto renWin = vtkSmartPointer<vtkRenderWindow>::New(); renWin->AddRenderer(ren); renWin->SetSize(640, 480); // interactor auto inter = vtkSmartPointer<vtkRenderWindowInteractor>::New(); inter->SetRenderWindow(renWin); inter->SetInteractorStyle(new MouseInteractorStyle()); ren->ResetCamera(); ren->GetActiveCamera()->Zoom(1.5); renWin->Render(); inter->Initialize(); inter->Start(); return 0; } キー入力key.cxx #include <vtkSmartPointer.h> #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> #include <vtkInteractorStyleTrackballCamera.h> using namespace std; class KeyInteractorStyle : public vtkInteractorStyleTrackballCamera { public: void OnKeyPress() noexcept override { cout << GetInteractor()->GetKeySym() << endl; vtkInteractorStyleTrackballCamera::OnKeyPress(); } }; int main(int argc, char **argv) { // renderer auto ren = vtkSmartPointer<vtkRenderer>::New(); ren->SetBackground(0.1, 0.2, 0.4); auto renWin = vtkSmartPointer<vtkRenderWindow>::New(); renWin->AddRenderer(ren); renWin->SetSize(640, 480); // interactor auto inter = vtkSmartPointer<vtkRenderWindowInteractor>::New(); inter->SetRenderWindow(renWin); inter->SetInteractorStyle(new KeyInteractorStyle()); renWin->Render(); inter->Initialize(); inter->Start(); return 0; } STL の読み書きstl_writer.cxx #include <vtkSmartPointer.h> #include <vtkSphereSource.h> #include <vtkSTLWriter.h> #include <vtkSTLReader.h> #include <vtkPolyDataMapper.h> #include <vtkActor.h> #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> using namespace std; const char *filename = "sphere.stl"; int main(int argc, char **argv) { // source auto sphere = vtkSmartPointer<vtkSphereSource>(); sphere->SetThetaResolution(50); sphere->SetPhiResolution(50); // writer auto writer = vtkSmartPointer<vtkSTLWriter>(); writer->SetFileName(filename); writer->SetInputConnection(sphere->GetOutputPort()); writer->Write(); // reader auto reader = vtkSmartPointer<vtkSTLReader>(); reader->SetFileName(filename); // mapper auto mapper = vtkSmartPointer<vtkPolyDataMapper>(); mapper->SetInputConnection(reader->GetOutputPort()); // actor auto actor = vtkSmartPointer<vtkActor>(); actor->SetMapper(mapper); // renderer auto ren = vtkSmartPointer<vtkRenderer>(); ren->AddActor(actor); ren->SetBackground(0.1, 0.2, 0.4); auto renWin = vtkSmartPointer<vtkRenderWindow>(); renWin->AddRenderer(ren); renWin->SetSize(640, 480); // interactor auto inter = vtkSmartPointer<vtkRenderWindowInteractor>(); inter->SetRenderWindow(renWin); renWin->Render(); inter->Initialize(); inter->Start(); return 0; } ![]() VTK の読み書きVTK ファイル (Unstructure Grid) を読み込む。 scalar.vtk # vtk DataFile Version 2.0 scalar ASCII DATASET UNSTRUCTURED_GRID POINTS 4 float 0 0 0 1 0 0 1 1 0 0 1 0 CELLS 1 5 4 0 1 2 3 CELL_TYPES 1 9 POINT_DATA 4 SCALARS point_scalars float LOOKUP_TABLE default 1 2 3 4 CELL_DATA 1 SCALARS cell_scalars float LOOKUP_TABLE default 5 vtk_reader.cxx #include <iostream> #include <vtkSmartPointer.h> #include <vtkUnstructuredGridReader.h> #include <vtkUnstructuredGrid.h> #include <vtkDataSetMapper.h> #include <vtkActor.h> #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> using namespace std; const char *filename = "scalar.vtk"; int main(int argc, char **argv) { // reader auto reader = vtkSmartPointer<vtkUnstructuredGridReader>(); reader->SetFileName(filename); reader->Update(); auto output = reader->GetOutput(); auto scalarRange = output->GetScalarRange(); cout << scalarRange << endl; // mapper auto mapper = vtkSmartPointer<vtkDataSetMapper>(); mapper->SetInputData(output); mapper->SetScalarRange(scalarRange); // actor auto actor = vtkSmartPointer<vtkActor>(); actor->SetMapper(mapper); // renderer auto ren = vtkSmartPointer<vtkRenderer>(); ren->AddActor(actor); ren->SetBackground(0.1, 0.2, 0.4); auto renWin = vtkSmartPointer<vtkRenderWindow>(); renWin->AddRenderer(ren); renWin->SetSize(640, 480); // interactor auto inter = vtkSmartPointer<vtkRenderWindowInteractor>(); inter->SetRenderWindow(renWin); renWin->Render(); inter->Initialize(); inter->Start(); return 0; } ![]() OpenFOAM のケースの読み込みOpenFOAM の計算結果を読み込む。ここでは cavity ケースを用いる。 of_reader.cxx #include <iostream> #include <string> #include <vtkSmartPointer.h> #include <vtkDoubleArray.h> #include <vtkInteractorStyleTrackballCamera.h> #include <vtkOpenFOAMReader.h> #include <vtkUnstructuredGrid.h> #include <vtkCellData.h> #include <vtkPointData.h> #include <vtkDataArray.h> #include <vtkGeometryFilter.h> #include <vtkMultiBlockDataSet.h> #include <vtkLookupTable.h> #include <vtkCompositePolyDataMapper.h> #include <vtkActor.h> #include <vtkProperty.h> #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> #include <vtkScalarBarActor.h> #include <vtkTextProperty.h> #include <vtkTextActor.h> using namespace std; const string caseName = "cavity"; const string filename = caseName + "/system/controlDict"; const string field = "U"; const string dataType = "cell"; class MouseInteractorStyle : public vtkInteractorStyleTrackballCamera { public: void Dolly() override { MotionFactor *= -1; vtkInteractorStyleTrackballCamera::Dolly(); MotionFactor *= -1; } }; int main(int argc, char **argv) { // reader const auto reader = vtkSmartPointer<vtkOpenFOAMReader>::New(); reader->SetFileName(filename.c_str()); reader->Update(); //const auto n = reader->GetTimeValues()->GetNumberOfValues(); //const auto latestTime = reader->GetTimeValues()->GetValue(n - 1); const auto latestTime = reader->GetTimeValues()->GetRange()[1]; reader->UpdateTimeStep(latestTime); reader->Update(); const auto block = reader->GetOutput(); //cout << block->GetBlock(0)->GetClassName() << endl; const auto grid = vtkUnstructuredGrid::SafeDownCast(block->GetBlock(0)); string arrayName; vtkDataArray *array; if(field == "p"){ vtkDataArray *p; if(dataType == "cell"){ p = grid->GetCellData()->GetArray("p"); }else if(dataType == "point"){ p = grid->GetPointData()->GetArray("p"); } arrayName = "p"; array = p; }else if(field == "U"){ const auto magU = vtkSmartPointer<vtkDoubleArray>::New(); magU->SetName("magU"); magU->SetNumberOfComponents(1); vtkDataArray *U; if(dataType == "cell"){ U = grid->GetCellData()->GetArray("U"); }else if(dataType == "point"){ U = grid->GetPointData()->GetArray("U"); }else{ assert(0); } for(int i = 0; i < U->GetNumberOfTuples(); i++){ const auto Ux = U->GetComponent(i, 0); const auto Uy = U->GetComponent(i, 1); const auto Uz = U->GetComponent(i, 2); magU->InsertNextValue(sqrt(Ux*Ux + Uy*Uy + Uz*Uz)); } if(dataType == "cell"){ grid->GetCellData()->AddArray(magU); }else if(dataType == "point"){ grid->GetPointData()->AddArray(magU); }else{ assert(0); } arrayName = "magU"; array = magU; }else{ assert(0); } // filter const auto geomFilter = vtkSmartPointer<vtkGeometryFilter>::New(); geomFilter->SetInputData(block); // lookup table const auto lut = vtkSmartPointer<vtkLookupTable>::New(); lut->SetHueRange(0.667, 0.); lut->Build(); // mapper const auto mapper = vtkSmartPointer<vtkCompositePolyDataMapper>::New(); mapper->SetInputConnection(geomFilter->GetOutputPort()); if(dataType == "cell"){ mapper->SetScalarModeToUseCellFieldData(); }else if(dataType == "point"){ mapper->SetScalarModeToUsePointFieldData(); } mapper->SelectColorArray(arrayName.c_str()); mapper->SetScalarRange(array->GetRange()); mapper->SetLookupTable(lut); // actor const auto actor = vtkSmartPointer<vtkActor>::New(); actor->SetMapper(mapper); const auto prop = actor->GetProperty(); prop->SetAmbient(0.5); prop->EdgeVisibilityOn(); prop->SetEdgeColor(0, 0, 0); prop->SetLineWidth(2); prop->SetRepresentationToSurface(); // renderer const auto ren = vtkSmartPointer<vtkRenderer>::New(); ren->AddActor(actor); ren->GradientBackgroundOn(); ren->SetBackground(1., 1., 1.); ren->SetBackground2(0.4, 0.55, 0.75); const auto renWin = vtkSmartPointer<vtkRenderWindow>::New(); renWin->AddRenderer(ren); renWin->SetSize(640, 480); // interactor const auto inter = vtkSmartPointer<vtkRenderWindowInteractor>::New(); inter->SetRenderWindow(renWin); inter->SetInteractorStyle(new MouseInteractorStyle()); // sclar bar const auto scalarBar = vtkSmartPointer<vtkScalarBarActor>::New(); scalarBar->SetOrientationToVertical(); scalarBar->SetLookupTable(lut); const auto textProp = vtkSmartPointer<vtkTextProperty>::New(); textProp->SetColor(0., 0., 0.); textProp->SetFontSize(20); textProp->SetFontFamilyToArial(); textProp->ItalicOff(); textProp->BoldOff(); scalarBar->UnconstrainedFontSizeOn(); scalarBar->SetTitleTextProperty(textProp); scalarBar->SetLabelTextProperty(textProp); scalarBar->SetLabelFormat("%5.2f"); scalarBar->SetTitle(arrayName.c_str()); ren->AddActor(scalarBar); // text const auto text = vtkSmartPointer<vtkTextActor>::New(); text->SetInput(caseName.c_str()); text->GetTextProperty()->SetColor(0., 0., 0.); text->GetTextProperty()->SetFontSize(24); text->SetPosition(300, 30); ren->AddActor(text); renWin->Render(); inter->Initialize(); inter->Start(); return 0; } ![]() ここでは、マウスの操作を ParaView に合わせるために dolly の方向を逆にしている。 OpenFOAM のマルチリージョンケースの読み込みOpenFOAM のマルチリージョンケースの計算結果を読み込む。ここでは multiRegionHeater ケースを用いる。 of_reader_multi.cxx #include <iostream> #include <string> #include <limits> #include <vtkSmartPointer.h> #include <vtkDoubleArray.h> #include <vtkInteractorStyleTrackballCamera.h> #include <vtkOpenFOAMReader.h> #include <vtkCompositeDataIterator.h> #include <vtkUnstructuredGrid.h> #include <vtkCellData.h> #include <vtkPointData.h> #include <vtkDataArray.h> #include <vtkGeometryFilter.h> #include <vtkMultiBlockDataSet.h> #include <vtkLookupTable.h> #include <vtkCompositePolyDataMapper.h> #include <vtkActor.h> #include <vtkProperty.h> #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> #include <vtkScalarBarActor.h> #include <vtkTextProperty.h> #include <vtkTextActor.h> using namespace std; const string caseName = "multiRegionHeater"; const string filename = caseName + "/system/controlDict"; const auto enabledBlock = { "rightSolid/internalMesh", "leftSolid/internalMesh", "heater/internalMesh", }; const string field = "T"; const string dataType = "point"; class MouseInteractorStyle : public vtkInteractorStyleTrackballCamera { public: void Dolly() override { MotionFactor *= -1; vtkInteractorStyleTrackballCamera::Dolly(); MotionFactor *= -1; } }; int main(int argc, char **argv) { // reader const auto reader = vtkSmartPointer<vtkOpenFOAMReader>::New(); reader->SetFileName(filename.c_str()); reader->Update(); const auto latestTime = reader->GetTimeValues()->GetRange()[1]; cout << "Latest time: " << latestTime << endl; reader->UpdateTimeStep(latestTime); reader->Update(); const auto n = reader->GetNumberOfPatchArrays(); for(int i = 0; i < n; i++){ cout << reader->GetPatchArrayName(i) << endl; } reader->DisableAllPatchArrays(); for(const auto& b : enabledBlock){ reader->SetPatchArrayStatus(b, 1); } reader->Update(); const auto block = reader->GetOutput(); const auto arrayName = field; auto arrayMin = numeric_limits<double>::max(); auto arrayMax = numeric_limits<double>::min(); const auto itr = block->NewIterator(); itr->InitTraversal(); while(!itr->IsDoneWithTraversal()){ //cout << itr->GetCurrentDataObject()->GetClassName() << endl; const auto grid = vtkUnstructuredGrid::SafeDownCast( itr->GetCurrentDataObject() ); vtkDataArray *T; if(dataType == "cell"){ T = grid->GetCellData()->GetArray(field.c_str()); }else if(dataType == "point"){ T = grid->GetPointData()->GetArray(field.c_str()); }else{ assert(0); } auto range = T->GetRange(); if(range[0] < arrayMin){ arrayMin = range[0]; } if(range[1] > arrayMax){ arrayMax = range[1]; } itr->GoToNextItem(); } // filter const auto geomFilter = vtkSmartPointer<vtkGeometryFilter>::New(); geomFilter->SetInputData(reader->GetOutput()); // lookup table const auto lut = vtkSmartPointer<vtkLookupTable>::New(); lut->SetHueRange(0.667, 0.); lut->Build(); // mapper const auto mapper = vtkSmartPointer<vtkCompositePolyDataMapper>::New(); mapper->SetInputConnection(geomFilter->GetOutputPort()); if(dataType == "cell"){ mapper->SetScalarModeToUseCellFieldData(); }else if(dataType == "point"){ mapper->SetScalarModeToUsePointFieldData(); } mapper->SelectColorArray(arrayName.c_str()); mapper->SetScalarRange(arrayMin, arrayMax); mapper->SetLookupTable(lut); // actor const auto actor = vtkSmartPointer<vtkActor>::New(); actor->SetMapper(mapper); const auto prop = actor->GetProperty(); prop->SetAmbient(0.5); prop->EdgeVisibilityOn(); prop->SetEdgeColor(0., 0., 0.); prop->SetLineWidth(2); prop->SetRepresentationToSurface(); // renderer const auto ren = vtkSmartPointer<vtkRenderer>::New(); ren->AddActor(actor); ren->GradientBackgroundOn(); ren->SetBackground(1., 1., 1.); ren->SetBackground2(0.4, 0.55, 0.75); const auto renWin = vtkSmartPointer<vtkRenderWindow>::New(); renWin->AddRenderer(ren); renWin->SetSize(640, 480); // interactor const auto inter = vtkSmartPointer<vtkRenderWindowInteractor>::New(); inter->SetRenderWindow(renWin); inter->SetInteractorStyle(new MouseInteractorStyle()); // sclar bar const auto scalarBar = vtkSmartPointer<vtkScalarBarActor>::New(); scalarBar->SetOrientationToVertical(); scalarBar->SetLookupTable(lut); const auto textProp = vtkSmartPointer<vtkTextProperty>::New(); textProp->SetColor(0., 0., 0.); textProp->SetFontSize(20); textProp->SetFontFamilyToArial(); textProp->ItalicOff(); textProp->BoldOff(); scalarBar->UnconstrainedFontSizeOn(); scalarBar->SetTitleTextProperty(textProp); scalarBar->SetLabelTextProperty(textProp); scalarBar->SetLabelFormat("%5.2f"); scalarBar->SetTitle(arrayName.c_str()); ren->AddActor(scalarBar); // text const auto text = vtkSmartPointer<vtkTextActor>::New(); text->SetInput(caseName.c_str()); text->GetTextProperty()->SetColor(0., 0., 0.); text->GetTextProperty()->SetFontSize(24); text->SetPosition(200, 30); ren->AddActor(text); renWin->Render(); inter->Initialize(); inter->Start(); return 0; } ![]() ブロックの抽出上の例では、ブロックの選択を reader の SetPatchArrayStatus() で行なったが、これを vtkExtractBlock で行うこともできる。ParaView で、OpenFOAM リーダーの設定でブロックを選択するか、Extract Block フィルタで選択するかというのと同じである。 extract_block.cxx #include <iostream> #include <string> #include <regex> #include <limits> #include <vtkSmartPointer.h> #include <vtkDoubleArray.h> #include <vtkInteractorStyleTrackballCamera.h> #include <vtkOpenFOAMReader.h> #include <vtkExtractBlock.h> #include <vtkCompositeDataIterator.h> #include <vtkUnstructuredGrid.h> #include <vtkCellData.h> #include <vtkPointData.h> #include <vtkDataArray.h> #include <vtkGeometryFilter.h> #include <vtkMultiBlockDataSet.h> #include <vtkLookupTable.h> #include <vtkCompositePolyDataMapper.h> #include <vtkActor.h> #include <vtkProperty.h> #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> #include <vtkScalarBarActor.h> #include <vtkTextProperty.h> #include <vtkTextActor.h> using namespace std; const string caseName = "multiRegionHeater"; const string filename = caseName + "/system/controlDict"; const auto enabledBlock = { "rightSolid/internalMesh", "leftSolid/internalMesh", "heater/internalMesh", }; const string field = "T"; const string dataType = "point"; class MouseInteractorStyle : public vtkInteractorStyleTrackballCamera { public: void Dolly() override { MotionFactor *= -1; vtkInteractorStyleTrackballCamera::Dolly(); MotionFactor *= -1; } }; int main(int argc, char **argv) { // reader const auto reader = vtkSmartPointer<vtkOpenFOAMReader>::New(); reader->SetFileName(filename.c_str()); reader->Update(); const auto latestTime = reader->GetTimeValues()->GetRange()[1]; cout << "Latest time: " << latestTime << endl; reader->UpdateTimeStep(latestTime); reader->Update(); // // create patch to index table // reader->EnableAllPatchArrays(); reader->Update(); map<string, int> blockIndex; auto index = 1; const auto n = reader->GetNumberOfPatchArrays(); for(int i = 0; i < n; i++){ const auto name = reader->GetPatchArrayName(i); cmatch m; regex_match(name, m, regex(".*internalMesh$")); if(!m.empty()){ index++; } blockIndex[name] = index; if(!m.empty()){ index++; } index++; } for(int i = 0; i < n; i++){ const auto name = reader->GetPatchArrayName(i); cout << name << " " << blockIndex[name] << endl; } const auto extractBlock = vtkSmartPointer<vtkExtractBlock>::New(); extractBlock->SetInputData(reader->GetOutput()); for(const auto& b : enabledBlock){ extractBlock->AddIndex(blockIndex[b]); } extractBlock->Update(); const auto block = extractBlock->GetOutput(); const auto arrayName = field; auto arrayMin = numeric_limits<double>::max(); auto arrayMax = numeric_limits<double>::min(); const auto itr = block->NewIterator(); itr->InitTraversal(); while(!itr->IsDoneWithTraversal()){ //cout << itr->GetCurrentDataObject()->GetClassName() << endl; const auto grid = vtkUnstructuredGrid::SafeDownCast( itr->GetCurrentDataObject() ); vtkDataArray *T; if(dataType == "cell"){ T = grid->GetCellData()->GetArray(field.c_str()); }else if(dataType == "point"){ T = grid->GetPointData()->GetArray(field.c_str()); }else{ assert(0); } auto range = T->GetRange(); if(range[0] < arrayMin){ arrayMin = range[0]; } if(range[1] > arrayMax){ arrayMax = range[1]; } itr->GoToNextItem(); } // filter const auto geomFilter = vtkSmartPointer<vtkGeometryFilter>::New(); geomFilter->SetInputConnection(extractBlock->GetOutputPort()); // lookup table const auto lut = vtkSmartPointer<vtkLookupTable>::New(); lut->SetHueRange(0.667, 0.); lut->Build(); // mapper const auto mapper = vtkSmartPointer<vtkCompositePolyDataMapper>::New(); mapper->SetInputConnection(geomFilter->GetOutputPort()); if(dataType == "cell"){ mapper->SetScalarModeToUseCellFieldData(); }else if(dataType == "point"){ mapper->SetScalarModeToUsePointFieldData(); } mapper->SelectColorArray(arrayName.c_str()); mapper->SetScalarRange(arrayMin, arrayMax); mapper->SetLookupTable(lut); // actor const auto actor = vtkSmartPointer<vtkActor>::New(); actor->SetMapper(mapper); const auto prop = actor->GetProperty(); prop->SetAmbient(0.5); prop->EdgeVisibilityOn(); prop->SetEdgeColor(0., 0., 0.); prop->SetLineWidth(2); prop->SetRepresentationToSurface(); // renderer const auto ren = vtkSmartPointer<vtkRenderer>::New(); ren->AddActor(actor); ren->GradientBackgroundOn(); ren->SetBackground(1., 1., 1.); ren->SetBackground2(0.4, 0.55, 0.75); const auto renWin = vtkSmartPointer<vtkRenderWindow>::New(); renWin->AddRenderer(ren); renWin->SetSize(640, 480); // interactor const auto inter = vtkSmartPointer<vtkRenderWindowInteractor>::New(); inter->SetRenderWindow(renWin); inter->SetInteractorStyle(new MouseInteractorStyle()); // sclar bar const auto scalarBar = vtkSmartPointer<vtkScalarBarActor>::New(); scalarBar->SetOrientationToVertical(); scalarBar->SetLookupTable(lut); const auto textProp = vtkSmartPointer<vtkTextProperty>::New(); textProp->SetColor(0., 0., 0.); textProp->SetFontSize(20); textProp->SetFontFamilyToArial(); textProp->ItalicOff(); textProp->BoldOff(); scalarBar->UnconstrainedFontSizeOn(); scalarBar->SetTitleTextProperty(textProp); scalarBar->SetLabelTextProperty(textProp); scalarBar->SetLabelFormat("%5.2f"); scalarBar->SetTitle(arrayName.c_str()); ren->AddActor(scalarBar); // text const auto text = vtkSmartPointer<vtkTextActor>::New(); text->SetInput(caseName.c_str()); text->GetTextProperty()->SetColor(0., 0., 0.); text->GetTextProperty()->SetFontSize(24); text->SetPosition(200, 30); ren->AddActor(text); renWin->Render(); inter->Initialize(); inter->Start(); return 0; } 実行結果は of_reader_multi.py と同じである。 ハイライト表示注目しているブロックをハイライト表示したい。対象のブロックだけ Extract Block で取り出して、色をつければよい。 highlight.cxx #include <iostream> #include <string> #include <regex> #include <limits> #include <vtkSmartPointer.h> #include <vtkIntArray.h> #include <vtkInteractorStyleTrackballCamera.h> #include <vtkOpenFOAMReader.h> #include <vtkExtractBlock.h> #include <vtkCompositeDataIterator.h> #include <vtkUnstructuredGrid.h> #include <vtkCellData.h> #include <vtkGeometryFilter.h> #include <vtkMultiBlockDataSet.h> #include <vtkLookupTable.h> #include <vtkCompositePolyDataMapper.h> #include <vtkActor.h> #include <vtkProperty.h> #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> using namespace std; const string caseName = "multiRegionHeater"; const string filename = caseName + "/system/controlDict"; const vector<string> enabledBlock = { "bottomWater/internalMesh", "topAir/internalMesh", "rightSolid/internalMesh", "leftSolid/internalMesh", "heater/internalMesh", }; const auto highlightBlock = { "topAir/minX", }; class MouseInteractorStyle : public vtkInteractorStyleTrackballCamera { public: void Dolly() override { MotionFactor *= -1; vtkInteractorStyleTrackballCamera::Dolly(); MotionFactor *= -1; } }; int main(int argc, char **argv) { // reader const auto reader = vtkSmartPointer<vtkOpenFOAMReader>::New(); reader->SetFileName(filename.c_str()); reader->Update(); // // create patch to index table // reader->EnableAllPatchArrays(); reader->Update(); map<string, int> blockIndex; auto index = 1; const auto n = reader->GetNumberOfPatchArrays(); for(int i = 0; i < n; i++){ auto name = reader->GetPatchArrayName(i); cmatch m; regex_match(name, m, regex(".*internalMesh$")); if(!m.empty()){ index++; } blockIndex[name] = index; if(!m.empty()){ index++; } index++; } for(int i = 0; i < n; i++){ auto name = reader->GetPatchArrayName(i); cout << name << " " << blockIndex[name] << endl; } const auto extractBlock = vtkSmartPointer<vtkExtractBlock>::New(); extractBlock->SetInputData(reader->GetOutput()); for(const auto& b : enabledBlock){ extractBlock->AddIndex(blockIndex[b]); } extractBlock->Update(); const auto extractBlock2 = vtkSmartPointer<vtkExtractBlock>::New(); extractBlock2->SetInputData(reader->GetOutput()); for(const auto& b : highlightBlock){ extractBlock2->AddIndex(blockIndex[b]); } extractBlock2->Update(); // // block index // const auto block = extractBlock->GetOutput(); const string arrayName = "index"; auto arrayMin = numeric_limits<int>::max(); auto arrayMax = numeric_limits<int>::min(); for(const auto& item : blockIndex){ if(item.second < arrayMin){ arrayMin = item.second; }else if(item.second > arrayMax){ arrayMax = item.second; } } const auto itr = block->NewIterator(); itr->InitTraversal(); auto i = 0; while(!itr->IsDoneWithTraversal()){ //cout << itr->GetCurrentDataObject()->GetClassName() << endl; const auto grid = vtkUnstructuredGrid::SafeDownCast( itr->GetCurrentDataObject() ); const auto index = vtkSmartPointer<vtkIntArray>::New(); index->SetName(arrayName.c_str()); index->SetNumberOfComponents(1); for(int j = 0; j < grid->GetNumberOfCells(); j++){ index->InsertNextValue(blockIndex[enabledBlock[i]]); } grid->GetCellData()->AddArray(index); itr->GoToNextItem(); i++; } // filter const auto geomFilter = vtkSmartPointer<vtkGeometryFilter>::New(); geomFilter->SetInputConnection(extractBlock->GetOutputPort()); const auto geomFilter2 = vtkSmartPointer<vtkGeometryFilter>::New(); geomFilter2->SetInputConnection(extractBlock2->GetOutputPort()); // lookup table const auto lut = vtkSmartPointer<vtkLookupTable>::New(); lut->SetHueRange(0.667, 0.); lut->Build(); // mapper const auto mapper = vtkSmartPointer<vtkCompositePolyDataMapper>::New(); mapper->SetInputConnection(geomFilter->GetOutputPort()); mapper->SetScalarModeToUseCellFieldData(); mapper->SelectColorArray(arrayName.c_str()); mapper->SetScalarRange(arrayMin, arrayMax); mapper->SetLookupTable(lut); const auto mapper2 = vtkSmartPointer<vtkCompositePolyDataMapper>::New(); mapper2->SetInputConnection(geomFilter2->GetOutputPort()); mapper2->SetScalarModeToUseCellFieldData(); // actor const auto actor = vtkSmartPointer<vtkActor>::New(); actor->SetMapper(mapper); const auto prop = actor->GetProperty(); prop->SetAmbient(0.5); prop->EdgeVisibilityOn(); prop->SetEdgeColor(0., 0., 0.); prop->SetLineWidth(2); prop->SetRepresentationToSurface(); const auto actor2 = vtkSmartPointer<vtkActor>::New(); actor2->SetMapper(mapper2); const auto prop2 = actor2->GetProperty(); prop2->SetColor(1., 0., 1.); prop2->SetOpacity(0.8); // renderer const auto ren = vtkSmartPointer<vtkRenderer>::New(); ren->AddActor(actor); ren->AddActor(actor2); ren->GradientBackgroundOn(); ren->SetBackground(1., 1., 1.); ren->SetBackground2(0.4, 0.55, 0.75); const auto renWin = vtkSmartPointer<vtkRenderWindow>::New(); renWin->AddRenderer(ren); renWin->SetSize(640, 480); // interactor const auto inter = vtkSmartPointer<vtkRenderWindowInteractor>::New(); inter->SetRenderWindow(renWin); inter->SetInteractorStyle(new MouseInteractorStyle()); renWin->Render(); inter->Initialize(); inter->Start(); return 0; } ![]() 特徴線特徴線は vtkFeatureEdges で描画できる。OpenFOAM のマルチリージョンケースで特徴線を描画してみる。 feature_edge.cxx #include <iostream> #include <string> #include <vtkSmartPointer.h> #include <vtkInteractorStyleTrackballCamera.h> #include <vtkOpenFOAMReader.h> #include <vtkGeometryFilter.h> #include <vtkFeatureEdges.h> #include <vtkMultiBlockDataSet.h> #include <vtkCompositePolyDataMapper.h> #include <vtkActor.h> #include <vtkProperty.h> #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> using namespace std; const string caseName = "multiRegionHeater"; const string filename = caseName + "/system/controlDict"; const auto enabledBlock ={ "bottomWater/internalMesh", "topAir/internalMesh", "rightSolid/internalMesh", "leftSolid/internalMesh", "heater/internalMesh", }; class MouseInteractorStyle : public vtkInteractorStyleTrackballCamera { public: void Dolly() override { MotionFactor *= -1; vtkInteractorStyleTrackballCamera::Dolly(); MotionFactor *= -1; } }; int main(int argc, char **argv) { // reader const auto reader = vtkSmartPointer<vtkOpenFOAMReader>::New(); reader->SetFileName(filename.c_str()); reader->Update(); reader->DisableAllPatchArrays(); for(const auto& b : enabledBlock){ reader->SetPatchArrayStatus(b, 1); } reader->Update(); // filter const auto geomFilter = vtkSmartPointer<vtkGeometryFilter>::New(); geomFilter->SetInputData(reader->GetOutput()); const auto featureEdge = vtkSmartPointer<vtkFeatureEdges>::New(); featureEdge->SetInputConnection(geomFilter->GetOutputPort()); // mapper const auto mapper = vtkSmartPointer<vtkCompositePolyDataMapper>::New(); mapper->SetInputConnection(featureEdge->GetOutputPort()); mapper->SetScalarModeToUseCellFieldData(); // actor const auto actor = vtkSmartPointer<vtkActor>::New(); actor->SetMapper(mapper); const auto prop = actor->GetProperty(); prop->SetColor(0., 0., 0.); prop->SetLineWidth(2); prop->SetRepresentationToSurface(); // renderer const auto ren = vtkSmartPointer<vtkRenderer>::New(); ren->AddActor(actor); ren->GradientBackgroundOn(); ren->SetBackground(1., 1., 1.); ren->SetBackground2(0.4, 0.55, 0.75); const auto renWin = vtkSmartPointer<vtkRenderWindow>::New(); renWin->AddRenderer(ren); renWin->SetSize(640, 480); // interactor const auto inter = vtkSmartPointer<vtkRenderWindowInteractor>::New(); inter->SetRenderWindow(renWin); inter->SetInteractorStyle(new MouseInteractorStyle()); renWin->Render(); inter->Initialize(); inter->Start(); return 0; } ![]() | |
PENGUINITIS |