在CFD后处理时,经常使用流线图展示流体流动的轨迹和流动方向,以及查看漩涡的位置。vtk中自带生成流线的函数,使用vtkStreamTracer类就可以生成流线图。使用vtkStreamTracer需要两个数据输入,一个表示流线生成的位置,一般使用SetSourceConnection,一个需要矢量数据类使用SetInputConnection;然后设置流线的积分类型,流线的生成方向,流线终止条件等。
以openfoam的经典后台阶算例结果为数据,使用vtk生成流线的过程如下:
#include <vtkOpenFOAMReader.h>
#include <vtkSmartPointer.h>
#include <vtkAppendPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkUnstructuredGrid.h>
#include <vtkProperty.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkMultiBlockDataSet.h>
#include <vtkPointData.h>
#include <vtkDataSetMapper.h>
#include <vtkScalarBarActor.h>
#include <vtkLookupTable.h>
#include <vtkTextProperty.h>
#include <vtkLineSource.h>
#include <vtkStreamTracer.h>
#include <vtkPolyData.h>
#include <vtkArrayCalculator.h>
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2)
VTK_MODULE_INIT(vtkRenderingFreeType)
VTK_MODULE_INIT(vtkInteractionStyle)
int main()
{
vtkSmartPointer<vtkOpenFOAMReader> openFOAMReader = vtkSmartPointer<vtkOpenFOAMReader>::New();
openFOAMReader->SetFileName("D://openfoam//pitzDaily//case.foam");//设置读取文件路径
openFOAMReader->SetCreateCellToPoint(1);
openFOAMReader->SetSkipZeroTime(1);//开启跳过0时刻
openFOAMReader->SetTimeValue(298.0);//设置需要读取的时刻
openFOAMReader->Update();
vtkUnstructuredGrid *block0 = vtkUnstructuredGrid::SafeDownCast(openFOAMReader->GetOutput()->GetBlock(0));
//设置生成流线的位置
vtkSmartPointer<vtkLineSource> line1 = vtkSmartPointer<vtkLineSource>::New();
line1->SetPoint1(-0.019,0.0254,0.0005);
line1->SetPoint2(-0.0206,0,0.0005);
line1->SetResolution(10);
line1->Update();
vtkSmartPointer<vtkStreamTracer> streamline = vtkSmartPointer<vtkStreamTracer>::New();
streamline->SetSourceConnection(line1->GetOutputPort());
streamline->SetInputData(block0);
streamline->SetIntegratorTypeToRungeKutta45();//设置流线的积分类型
streamline->SetMaximumPropagation(5000);//设置流线长度
streamline->SetIntegrationStepUnit(2);//设置流线积分步长单位
streamline->SetInitialIntegrationStep(0.2);//设置流线积分初始步长
streamline->SetMinimumIntegrationStep(0.01);//设置流线积分最小步长
streamline->SetMaximumIntegrationStep(0.5);//设置流线积分最大步长
streamline->SetMaximumNumberOfSteps(2000);//设置流线积分最大步数
streamline->SetIntegrationDirectionToBoth();//设置流线积分方向
streamline->SetTerminalSpeed(1e-12);//设置流线积分终止速度
streamline->SetMaximumError(1e-6);
streamline->Update();
//计算速度的模
vtkSmartPointer<vtkArrayCalculator> calc = vtkSmartPointer<vtkArrayCalculator>::New();
calc->SetInputConnection(streamline->GetOutputPort());
calc->AddVectorArrayName("U");
calc->SetFunction("mag(U)");
calc->SetResultArrayName("u_mag");
calc->Update();
vtkPolyData *streamlinedata = vtkPolyData::SafeDownCast(calc->GetOutput());
streamlinedata->GetPointData()->SetActiveScalars("u_mag");
//计算速度范围
double scalarRange[2];
scalarRange[0] = streamlinedata->GetPointData()->GetScalars()->GetRange()[0];
scalarRange[1] = streamlinedata->GetPointData()->GetScalars()->GetRange()[1];
vtkSmartPointer<vtkScalarBarActor> scalarBar =
vtkSmartPointer<vtkScalarBarActor>::New();
vtkSmartPointer<vtkLookupTable> pColorTable =
vtkSmartPointer<vtkLookupTable>::New();
pColorTable->SetNumberOfTableValues(31);
pColorTable->SetHueRange(0.67, 0);//标量条颜色范围,从蓝到红
pColorTable->SetAlphaRange(1.0, 1.0);
pColorTable->SetValueRange(1, 1);
pColorTable->SetSaturationRange(1, 1);
pColorTable->SetRange(scalarRange);
pColorTable->Build();
scalarBar->SetTitle("U (m/s)");
scalarBar->GetTitleTextProperty()->SetColor(0, 0, 0);
scalarBar->GetTitleTextProperty()->SetFontFamilyToArial();
scalarBar->GetTitleTextProperty()->SetFontSize(20);
scalarBar->GetLabelTextProperty()->SetColor(0, 0, 0);
scalarBar->SetLabelFormat("%5.3f");
scalarBar->GetLabelTextProperty()->SetFontFamilyToArial();
scalarBar->GetLabelTextProperty()->SetFontSize(20);
scalarBar->SetNumberOfLabels(7);
scalarBar->SetUnconstrainedFontSize(1);
scalarBar->SetMaximumWidthInPixels(80);
scalarBar->SetMaximumHeightInPixels(900);
scalarBar->SetLookupTable(pColorTable);
vtkSmartPointer<vtkPolyDataMapper> streamlinemappper = vtkSmartPointer<vtkPolyDataMapper>::New();
streamlinemappper->SetInputData(streamlinedata);
streamlinemappper->SetLookupTable(pColorTable);
streamlinemappper->SetScalarRange(scalarRange);
vtkSmartPointer<vtkActor> streamlineactor = vtkSmartPointer<vtkActor>::New();
streamlineactor->SetMapper(streamlinemappper);
vtkSmartPointer<vtkRenderer> ren = vtkSmartPointer<vtkRenderer>::New();
ren->AddActor(streamlineactor);
ren->AddActor(scalarBar);
ren->SetBackground(1,1,1);//设置背景色为白色
ren->ResetCamera();
vtkSmartPointer<vtkRenderWindow> renWin =
vtkSmartPointer<vtkRenderWindow>::New();
vtkSmartPointer<vtkRenderWindowInteractor> iren =
vtkSmartPointer<vtkRenderWindowInteractor>::New();
iren->SetRenderWindow(renWin);
vtkSmartPointer<vtkInteractorStyleTrackballCamera> TrackballCamera =
vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
iren->SetInteractorStyle(TrackballCamera);
renWin->AddRenderer(ren.GetPointer());
renWin->SetSize(500, 500);
renWin->Render();
iren->Initialize();
iren->Start();
}
最终生成的流线云图如下: