废话不说,直接上代码:
#include "vtkAutoInit.h"
#include "vtkPolyData.h"
#include "vtkProbeFilter.h"
#include "vtkParametricFunctionSource.h"
#include "vtkParametricSpline.h"
#include "vtkDICOMImageReader.h"
#include "vtkPoints.h"
#include "vtkCellArray.h"
#include "vtkWindowLevelLookupTable.h"
#include "vtkActor.h"
#include "vtkCamera.h"
#include "vtkNamedColors.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkImageData.h"
#include "vtkDataSetMapper.h"
VTK_MODULE_INIT(vtkRenderingFreeType)
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);
// 由曲线生成曲面
vtkPolyData* SweepLine(vtkParametricFunctionSource* line, double direction[3], double distance, int cols)
{
int rows = line->GetOutput()->GetNumberOfPoints(); //待生成的surface的行数为曲线上点的个数
double spacing = distance / rows; //列方向上的spacing
vtkPolyData* surface = vtkPolyData::New();
//生成点
cols += 1;
int numberOfPoints = rows * cols; //surface内点的个数
int numberOfPolys = (rows - 1) * (cols - 1);
vtkPoints* points = vtkPoints::New();
points->Allocate(numberOfPoints);
vtkCellArray* polys = vtkCellArray::New();
polys->Allocate(numberOfPolys);
//生成每行每列的点坐标,
double x[] = { 0.0, 0.0, 0.0 };
int cnt = 0;
for (int row = 0; row < rows; row++)
{
for (int col = 0; col < cols; col++)
{
double p[3] = { 0.0,0.0,0.0 };
line->GetOutput()->GetPoint(row, p);
x[0] = p[0] + direction[0] * col * spacing;
x[1] = p[1] + direction[1] * col * spacing;
x[2] = p[2] + direction[2] * col * spacing;
points->InsertPoint(cnt, x);
cnt++;
}
}
//生成四边形
vtkIdType pts[4] = { 0,0,0,0 };
for (int row = 0; row < rows - 1; row++)
{
for (int col = 0; col < cols - 1; col++)
{
pts[0] = col + row * cols;
pts[1] = pts[0] + 1;
pts[2] = pts[0] + cols + 1;
pts[3] = pts[0] + cols;
// polys->InsertNextCell(4, pts); //每临近的四个点构成一个单元
polys->InsertNextCell(4, pts);
}
}
surface->SetPoints(points);
surface->SetPolys(polys);
return surface;
}
int main(int argc, char* argv[])
{
char szInputFile[] = { "D:/imgdata/2013-06-04_dcm" };
vtkDICOMImageReader* reader = vtkDICOMImageReader::New();
reader->SetDataByteOrderToLittleEndian();
reader->SetDirectoryName(szInputFile);
reader->Update();
int resolution = 100;
int extent[2] = { 255, 255 };
double thickness = 1.0;
double spacing[2] = { 1.0, 1.0 };
//自定义折线顶点坐标
vtkPoints* points = vtkPoints::New();
//(a,b,c,d)其中a表示序号,(b,c,d)表示点的坐标
points->InsertPoint(0, 1.0, 0.0, 0.0);
points->InsertPoint(1, 200, 100, 0.0);
points->InsertPoint(2, 100, 200, 0.0);
points->InsertPoint(3, 200, 300, 0.0);
//将点插值逆合成一条曲线
vtkParametricSpline* spline = vtkParametricSpline::New();
spline->SetPoints(points);
vtkParametricFunctionSource* splineFilter = vtkParametricFunctionSource::New();
splineFilter->SetParametricFunction(spline);
splineFilter->Update();
//有曲线生成曲面
double direction[] = { 0.0, 0.0, 1.0 };
int distance = 160;
vtkPolyData* surface = SweepLine(splineFilter, direction, distance, resolution);
vtkProbeFilter* sampleVolume = vtkProbeFilter::New();
//这里只能填1,和0,否则曲面要么是一块,要么什么也没有;
sampleVolume->SetInputConnection(1, reader->GetOutputPort());
sampleVolume->SetInputData(0, surface);
//根据数据源的数据范围设置映射表的窗宽窗位
vtkWindowLevelLookupTable* wlLut = vtkWindowLevelLookupTable::New();
double range = reader->GetOutput()->GetScalarRange()[1] - reader->GetOutput()->GetScalarRange()[0];
double level = (reader->GetOutput()->GetScalarRange()[1] - reader->GetOutput()->GetScalarRange()[0]) / 2;
wlLut->SetWindow(range);
wlLut->SetLevel(level);
//创建映射器和角色
vtkDataSetMapper* mapper = vtkDataSetMapper::New();
mapper->SetInputConnection(sampleVolume->GetOutputPort());
mapper->SetLookupTable(wlLut);
mapper->SetScalarRange(0, 255);
vtkActor* actor = vtkActor::New();
actor->SetMapper(mapper);
//创建渲染器,渲染窗口和交互
vtkRenderer* ren = vtkRenderer::New();
vtkRenderWindow* renWin = vtkRenderWindow::New();
renWin->AddRenderer(ren);
renWin->SetWindowName("CurvedReformation");
vtkRenderWindowInteractor* iren = vtkRenderWindowInteractor::New();
iren->SetRenderWindow(renWin);
//将角色添加到场景
ren->AddActor(actor);
vtkNamedColors* colors = vtkNamedColors::New();
// ren->SetBackground(colors->GetColor3d("DarkSlateGray"));
ren->SetBackground(0.4, 0.4, 0.4);
//设置相机以查看图像
ren->GetActiveCamera()->SetViewUp(0, 0, 1);
ren->GetActiveCamera()->SetPosition(0, 0, 0);
ren->GetActiveCamera()->SetFocalPoint(1, 0, 0);
ren->ResetCamera();
//渲染和交互
renWin->Render();
iren->Start();
return 0;
}
效果: