VTK 绘制等值线
VTK 绘制等值线
使用vtk来绘制等值线,需要使用到vtkContourFilter,它所处理的数据需要是规则网格数据,如规则的正方形网格等。
通过使用vtkContourFilter::SetValue(i,value)方法,i表示第几条等值线,从0开始计算,value表示等值线的值。多边形的每个点都有一个属性值,两个相邻的属性值之间要先通过插值,再把这些属性值作为该函数的输入。如:
SetValue(0,5);
画一条等值为5的等值线。两个相邻的点的属性值为3和6,则先插值为(3,4,5,6),所以该先应该经过这条边的2/3处。
也可以使用vtkContourFilter::GenerateValues(count, start, end);来生成一些列的等值线,其中count参数指定等值线的条数,而start指定第一条等值线的值,end指定最后一条等值线的值,中间等值线的值则通过计算得到。
vtkContourFilter::SetValue(…)、GenerateValues(…)、GetNumberOfContours(…)
解释:
SetValue和GenerateValues均为设置等值线值的函数;这两个函数的不同之处在于SetValue设置一条等值线值,而GenerateValues对应n条等值线的值,同时数量n包括两个边界值,其余n-2条等值线的值自动按照线性关系产生。
SetValue和GenerateValues函数根据先后调用关系产生覆盖,即后调用的函数产生的等值线可能覆盖掉先调用函数产生的等值线,这与等值线的条数(GetNumberOfContours)相关。
例如:首先调用GenerateValues(3, 100, 300)产生3条等值线,分别为100、200、300;然后调用SetValue(0, 125),则最终效果为共有3条等值线,分别为125、200、300;如果改为调用SetValue(3, 400),则最终效果为共有4条等值线,分别为100、200、300、400。
SetValue一般用于覆盖某一条已经存在的等值线,或者增加一条等值线;GenerateValues一般重新设置等值线的条数。
示例代码:
#include "vtkAutoInit.h"VTK_MODULE_INIT( vtkRenderingOpenGL2 );VTK_MODULE_INIT( vtkInteractionStyle );#include "vtkSmartPointer.h"#include "vtkContourFilter.h"#include "vtkInteractorStyleUser.h"#include "vtkProperty.h"#include "vtkOutlineFilter.h"#include "vtkCommand.h"#include "vtkSliderWidget.h"#include "vtkSliderRepresentation.h"#include "vtkSliderRepresentation3D.h"#include "vtkImageData.h"#include "vtkCellArray.h"#include "vtkFloatArray.h"#include "vtkPointData.h"#include "vtkPolyDataMapper.h"#include "vtkActor.h"#include "vtkRenderer.h"#include "vtkRenderWindow.h"#include "vtkRenderWindowInteractor.h"#include "vtkXMLImageDataWriter.h"#include "vtkNamedColors.h"namespace{
void CreateData( vtkImageData* data );class vtkSliderCallback : public vtkCommand{public: static vtkSliderCallback* New() { return new vtkSliderCallback; } virtual void Execute( vtkObject *caller, unsigned long eventId, void *callData ) { vtkSliderWidget* sliderWidget = reinterpret_cast(caller); double value = static_cast(sliderWidget->GetRepresentation())->GetValue(); this->ContourFilter->GenerateValues( 5, 10.0, value ); //5: 5contour line //10.0 * value: start value //value: end value } vtkSliderCallback() : ContourFilter( NULL ){} vtkContourFilter* ContourFilter;};
}
int main()
{
vtkSmartPointer
vtkSmartPointer imgData = vtkSmartPointer::New();CreateData( imgData );//Create an iso surfacevtkSmartPointer contourFilter = vtkSmartPointer::New();contourFilter->SetInputData( imgData );contourFilter->GenerateValues( 5, 10, 10 );//Map the contours to graphical primitivesvtkSmartPointer contourMapper = vtkSmartPointer::New();contourMapper->SetInputConnection( contourFilter->GetOutputPort() );//Create an actor for the contoursvtkSmartPointer contourActor = vtkSmartPointer::New();contourActor->SetMapper( contourMapper );contourActor->GetProperty()->SetLineWidth( 5 );//Create the outlinevtkSmartPointer outlineFilter = vtkSmartPointer::New();outlineFilter->SetInputData( imgData );vtkSmartPointer outlineMapper = vtkSmartPointer::New();outlineMapper->SetInputConnection( outlineFilter->GetOutputPort() );vtkSmartPointer outlineActor = vtkSmartPointer::New();outlineActor->SetMapper( outlineMapper );outlineActor->GetProperty()->SetColor( colors->GetColor3d( "Gray" ).GetData() );outlineActor->GetProperty()->SetLineWidth( 3 );//VisualizevtkSmartPointer renderer = vtkSmartPointer::New();vtkSmartPointer renderWindow = vtkSmartPointer::New();renderWindow->AddRenderer( renderer );vtkSmartPointer interactor = vtkSmartPointer::New();interactor->SetRenderWindow( renderWindow );renderer->AddActor( contourActor );renderer->AddActor( outlineActor );renderer->SetBackground( colors->GetColor3d( "Burlywood" ).GetData() );vtkSmartPointer sliderRep = vtkSmartPointer::New();sliderRep->SetMinimumValue( 0.0 );sliderRep->SetMaximumValue( 30.0 );sliderRep->SetValue( 10.0 );sliderRep->SetTitleText( "Contour value" );sliderRep->SetPoint1InWorldCoordinates( -20, -40, 0 );sliderRep->SetPoint2InWorldCoordinates( 0, -40, 0 );sliderRep->SetSliderWidth( 0.2 );sliderRep->SetLabelHeight( 0.1 );vtkSmartPointer sliderWidget = vtkSmartPointer::New();sliderWidget->SetInteractor( interactor );sliderWidget->SetRepresentation( sliderRep );sliderWidget->SetAnimationModeToAnimate();sliderWidget->EnabledOn();vtkSmartPointer callback = vtkSmartPointer::New();callback->ContourFilter = contourFilter;sliderWidget->AddObserver( vtkCommand::InteractionEvent, callback );vtkSmartPointer interactStyle = vtkSmartPointer::New();interactor->SetInteractorStyle( interactStyle );renderWindow->SetSize( 500, 500 );renderWindow->Render();interactor->Start();return EXIT_SUCCESS;
}namespace{ void CreateData( vtkImageData* pData ) { pData->SetExtent( -25, 25, -25, 25, 0, 0 ); pData->AllocateScalars( VTK_DOUBLE, 1 ); int* extent = pData->GetExtent();
for( int y = extent[ 2 ]; y <= extent[ 3 ]; y++ ) { for( int x = extent[ 0 ]; x <= extent[ 1 ]; x++ ) { double* pixel = static_cast(pData->GetScalarPointer( x, y, 0 )); pixel[ 0 ] = sqrt( pow( x, 2.0 ) + pow( y, 2.0 ) ); } } vtkSmartPointer writer = vtkSmartPointer::New(); writer->SetFileName( "data.vti" ); writer->SetInputData( pData ); writer->Write(); writer->Update();}
}
结果如下图所示: