vtk第六章 基本的图形操作

  • 利用vtkMassProperties计算三角网格模型面积、体积、最大单元面积和最小单元面积
#include <vtkAutoInit.h> 
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);

#include <vtkSmartPointer.h>
#include <vtkPointData.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkScalarBarActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkPolyData.h>
#include <vtkCubeSource.h>
#include <vtkProperty.h>
#include <vtkTriangleFilter.h>
#include <vtkMassProperties.h>

int main(int argc, char* argv[])
{
	//创建一个立方体网格数据
	vtkSmartPointer<vtkCubeSource> cubeSource =
		vtkSmartPointer<vtkCubeSource>::New();
	cubeSource->Update();

	//将数据进行三角化,转化为三角形构成的网格
	vtkSmartPointer<vtkTriangleFilter> triFilter =
		vtkSmartPointer<vtkTriangleFilter>::New();
	triFilter->SetInputData(cubeSource->GetOutput());
	triFilter->Update();

	//vtkMassProperties用于计算三角化网格的质量属性 输入数据为三角化之后的数据
	vtkSmartPointer<vtkMassProperties> massProp =
		vtkSmartPointer<vtkMassProperties>::New();
	massProp->SetInputData(triFilter->GetOutput());
	//计算体积
	float vol = massProp->GetVolume();
	//计算表面积
	float area = massProp->GetSurfaceArea();
	//最大单元面积
	float maxArea = massProp->GetMaxCellArea();
	//最小单元面积
	float minArea = massProp->GetMinCellArea();

	std::cout << "Volume      :" << vol << std::endl;
	std::cout << "Surface Area:" << area << std::endl;
	std::cout << "Max Area    :" << maxArea << std::endl;
	std::cout << "Min Area    :" << minArea << std::endl;

	vtkSmartPointer<vtkPolyDataMapper> mapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	//mapper->SetInput(cubeSource->GetOutput());
	mapper->SetInputData(triFilter->GetOutput());

	vtkSmartPointer<vtkActor> actor =
		vtkSmartPointer<vtkActor>::New();
	actor->SetMapper(mapper);
	actor->GetProperty()->SetColor(0, 1, 0);
	//设置边缘的颜色 就是立方体的边
	actor->GetProperty()->SetEdgeColor(1, 0, 0);
	actor->GetProperty()->SetEdgeVisibility(1);

	vtkSmartPointer<vtkRenderer> renderer =
		vtkSmartPointer<vtkRenderer>::New();
	renderer->AddActor(actor);
	renderer->SetBackground(1.0, 1.0, 1.0);

	vtkSmartPointer<vtkRenderWindow> renderWindow =
		vtkSmartPointer<vtkRenderWindow>::New();
	renderWindow->AddRenderer(renderer);
	renderWindow->SetSize(640, 480);
	renderWindow->Render();
	renderWindow->SetWindowName("PolyDataMassProperty");

	vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	renderWindowInteractor->SetRenderWindow(renderWindow);

	renderWindow->Render();
	renderWindowInteractor->Start();

	return EXIT_SUCCESS;
}

测地距离:两个点沿着模型表面两者之间最短距离,使用vtkDijkstraGraphGeodesicPath类实现测地距离的计算
包围盒:vtkOutlineFilter提供一个方法来生成包围盒,输入是一个vtkPolyData模型数据,输出为vtkPolyData数据,只需要将其作为vtkPolyDataMapper的输入,建立可视化管线即可显示

#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);

#include <vtkSphereSource.h>
#include <vtkProperty.h>
#include <vtkPolyData.h>
#include <vtkSmartPointer.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkOutlineFilter.h>
#include <vtkDijkstraGraphGeodesicPath.h>

int main()
{
	//定义一个球面模型,计算球面上两点的索引号
	vtkSmartPointer<vtkSphereSource> sphereSource =
		vtkSmartPointer<vtkSphereSource>::New();
	sphereSource->Update();

	//vtkOutlineFilter的输入是一个vtkPolyData类型数据 需要转换一下
	vtkPolyData* sphere = sphereSource->GetOutput();

	vtkSmartPointer<vtkOutlineFilter> outline =
		vtkSmartPointer<vtkOutlineFilter>::New();
	outline->SetInputData(sphere);
	outline->Update();	//!!!一定要更新数据,包围盒要不显示不出来

	vtkSmartPointer<vtkDijkstraGraphGeodesicPath> dijkstra =
		vtkSmartPointer<vtkDijkstraGraphGeodesicPath>::New();
	dijkstra->SetInputData(sphereSource->GetOutput());
	//设置开始点
	dijkstra->SetStartVertex(0);
	//结束点
	dijkstra->SetEndVertex(10);
	dijkstra->Update();

	//建立可视化管线可以显示
	vtkSmartPointer<vtkPolyDataMapper> pathMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	pathMapper->SetInputData(dijkstra->GetOutput());

	vtkSmartPointer<vtkActor> pathActor =
		vtkSmartPointer<vtkActor>::New();
	pathActor->SetMapper(pathMapper);
	pathActor->GetProperty()->SetColor(1, 0, 0);
	pathActor->GetProperty()->SetLineWidth(4);

	vtkSmartPointer<vtkPolyDataMapper> mapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	mapper->SetInputData(sphereSource->GetOutput());

	vtkSmartPointer<vtkActor> actor =
		vtkSmartPointer<vtkActor>::New();
	actor->SetMapper(mapper);

	vtkSmartPointer<vtkPolyDataMapper> spheremapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	spheremapper->SetInputData(outline->GetOutput());

	vtkSmartPointer<vtkActor> sphereactor =
		vtkSmartPointer<vtkActor>::New();
	sphereactor->SetMapper(spheremapper);
	sphereactor->GetProperty()->SetColor(1, 0, 0);
	sphereactor->GetProperty()->SetLineWidth(4);

	vtkSmartPointer<vtkRenderer> renderer =
		vtkSmartPointer<vtkRenderer>::New();
	renderer->AddActor(actor);
	renderer->AddActor(pathActor);
	renderer->AddActor(sphereactor);
	renderer->SetBackground(1.0, 1.0, 1.0);

	vtkSmartPointer<vtkRenderWindow> renderWindow =
		vtkSmartPointer<vtkRenderWindow>::New();
	renderWindow->AddRenderer(renderer);
	renderWindow->SetSize(640, 480);
	renderWindow->Render();
	renderWindow->SetWindowName("PolyDataGeodesic");

	vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	renderWindowInteractor->SetRenderWindow(renderWindow);

	renderWindow->Render();
	renderWindowInteractor->Start();

	return EXIT_SUCCESS;
}

1.法向量计算和符号化Glyphing

  • 三维平面的法向量:垂直于该平面的三维向量
  • 曲面在某点P处的法向量:垂直与该点切平面的向量
  • 格模型单元法向量:组成每个单元的任意两条边的叉乘向量并归一化
  • 点的法向量:所有使用该点的单元法向量的平均值来表示

使用vtkPolyDataBNormals对单元为三角形或者多边形类型的vtkPolyData数据进行计算,由于法向量分为点法向量和单元法向量类型,可以通过函数SetComputeCellNormals()和SetcomputePointNormals()来设置需要计算的法向量类型,默认情况计算点法向量,关闭单元法向量

通过以下函数获取

#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);

#include <vtkSmartPointer.h>
#include <vtkActor.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkXMLPolyDataReader.h>
#include <vtkPolyDataReader.h>
#include <vtkPLYReader.h>
#include <vtkFloatArray.h>
#include <vtkPointData.h>
#include <vtkPolyDataNormals.h>
#include <vtkGlyph3D.h>
#include <vtkArrowSource.h>
#include <vtkSphereSource.h>
#include <vtkMaskPoints.h>
#include <vtkProperty.h>

//测试文件:../data/fran_cut.vtk
int main(int argc, char* argv[])
{

	vtkSmartPointer<vtkPolyDataReader> reader =
		vtkSmartPointer<vtkPolyDataReader>::New();
	reader->SetFileName("D:\\lqyWord\\VTK图形图像开发进阶随书代码\\Examples\\Chap06\\data\\fran_cut.vtk");
	reader->Update();

	vtkSmartPointer<vtkPolyDataNormals> normFilter =
		vtkSmartPointer<vtkPolyDataNormals>::New();
	normFilter->SetInputData(reader->GetOutput());
	/****这里计算点法向量和单元法向量
	**调用update()函数之后可生成一个vtkPolyData数据,
	**生成的法向量数据存储在内部的vtkPointData和vtkCellData中*/
	normFilter->SetComputePointNormals(1);
	normFilter->SetComputeCellNormals(1);
	/*会根据拓扑结构自动调整法向量的方向,
	**确保法向量在给定表面元素中的指向正确。
	**将参数设置为 1,则表示开启自动调整法向量方向*/
	normFilter->SetAutoOrientNormals(1);
	//关闭对锐边缘的处理 检测到锐边缘,会将其分裂,模型数据会发生变化
	normFilter->SetSplitting(0);
	normFilter->Update();

	//保留输入数据中的点数据以及其属性
	vtkSmartPointer<vtkMaskPoints> mask =
		vtkSmartPointer<vtkMaskPoints>::New();
	mask->SetInputData(normFilter->GetOutput());
	//随机采样了300个点做显示
	mask->SetMaximumNumberOfPoints(300);
	mask->RandomModeOn();
	mask->Update();		//!!!数据计算之后必须要进行更新,否则数据没有添加进来

	//这样的效果输入数据的每一个点处会显示一个Gly图形
	vtkSmartPointer<vtkArrowSource> arrow =
		vtkSmartPointer<vtkArrowSource>::New();
	arrow->Update();

	vtkSmartPointer<vtkGlyph3D> glyph =
		vtkSmartPointer<vtkGlyph3D>::New();
	glyph->SetInputData(mask->GetOutput());
	glyph->SetSourceData(arrow->GetOutput());	//显示效果会显示一个图形
	//指定要使用法向量数据来控制Glyph图形的方向
	glyph->SetVectorModeToUseNormal();
	//控制Glyph图形大小
	glyph->SetScaleFactor(0.01);
	glyph->Update();

	vtkSmartPointer<vtkPolyDataMapper> originMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	originMapper->SetInputData(reader->GetOutput());

	vtkSmartPointer<vtkActor> originActor =
		vtkSmartPointer<vtkActor>::New();
	originActor->SetMapper(originMapper);

	vtkSmartPointer<vtkPolyDataMapper> normedMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	normedMapper->SetInputData(normFilter->GetOutput());

	vtkSmartPointer<vtkActor> normedActor =
		vtkSmartPointer<vtkActor>::New();
	normedActor->SetMapper(normedMapper);

	vtkSmartPointer<vtkPolyDataMapper> glyphMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	glyphMapper->SetInputData(glyph->GetOutput());

	vtkSmartPointer<vtkActor> glyphActor =
		vtkSmartPointer<vtkActor>::New();
	glyphActor->SetMapper(glyphMapper);
	glyphActor->GetProperty()->SetColor(1., 0., 0.);

	double originalViewport[4] = { 0.0, 0.0, 0.33, 1.0 };
	double normViewport[4] = { 0.33, 0.0, 0.66, 1.0 };
	double glphViewport[4] = { 0.66, 0.0, 1.0, 1.0 };

	vtkSmartPointer<vtkRenderer> originalRenderer =
		vtkSmartPointer<vtkRenderer>::New();
	originalRenderer->SetViewport(originalViewport);
	originalRenderer->AddActor(originActor);
	originalRenderer->ResetCamera();
	originalRenderer->SetBackground(1.0, 1.0, 1.0);

	vtkSmartPointer<vtkRenderer> normedRenderer =
		vtkSmartPointer<vtkRenderer>::New();
	normedRenderer->SetViewport(normViewport);
	normedRenderer->AddActor(normedActor);
	normedRenderer->ResetCamera();
	normedRenderer->SetBackground(1.0, 1.0, 1.0);

	vtkSmartPointer<vtkRenderer> glyphRenderer =
		vtkSmartPointer<vtkRenderer>::New();
	glyphRenderer->SetViewport(glphViewport);
	glyphRenderer->AddActor(glyphActor);
	glyphRenderer->AddActor(normedActor);
	glyphRenderer->ResetCamera();
	glyphRenderer->SetBackground(1.0, 1.0, 1.0);

	vtkSmartPointer<vtkRenderWindow> renderWindow =
		vtkSmartPointer<vtkRenderWindow>::New();
	renderWindow->AddRenderer(originalRenderer);
	renderWindow->AddRenderer(normedRenderer);
	renderWindow->AddRenderer(glyphRenderer);
	renderWindow->SetSize(640, 320);
	renderWindow->Render();
	renderWindow->SetWindowName("PolyDataNormal");

	vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	renderWindowInteractor->SetRenderWindow(renderWindow);
	renderWindowInteractor->Initialize();
	renderWindowInteractor->Start();

	return EXIT_SUCCESS;
}

实验效果:
在这里插入图片描述

2.曲率计算

取最大曲率和最小曲率的两条法截线为主法截线k1,k2,高斯曲率=主曲率的乘积(k1叉乘k2),平均曲率=主曲率的平均值(k1+k2)/2

vtk中vtkCurvatures类接受一个vtkPolyData数据,将计算得到的曲率数据作为网格模型的点的属性数据存入返回的vtkPolyData中
使用vtkScalarBarActor类头文件,将一个颜色映射表转换为一个Actor对象,将颜色表以图形的形式显示
头文件要加上VTK_MODULE_INIT(vtkRenderingFreeType),要不会报错

#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingFreeType)

#include <vtkSmartPointer.h>
#include <vtkCurvatures.h>
#include <vtkPolyDataReader.h>
#include <vtkLookupTable.h>
#include <vtkColorTransferFunction.h>
#include <vtkColorSeries.h>
#include <vtkPointData.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkScalarBarActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>

#include <iostream>
using namespace std;

//测试文件:../data/fran_cut.vtk
int main(int argc, char* argv[])
{
	//读入一个vtkPolyData数据 作为vtkCurvatures的输入
	vtkSmartPointer<vtkPolyDataReader> reader =
		vtkSmartPointer<vtkPolyDataReader>::New();
	reader->SetFileName("D:\\lqyWord\\VTK图形图像开发进阶随书代码\\Examples\\Chap06\\data\\fran_cut.vtk");
	reader->Update();

	vtkSmartPointer<vtkCurvatures> curvaturesFilter =
		vtkSmartPointer<vtkCurvatures>::New();
	curvaturesFilter->SetInputConnection(reader->GetOutputPort());
	//最小曲率
	//curvaturesFilter->SetCurvatureTypeToMinimum();
	//SetCurvatureTypeToMaximum计算最大曲率
	curvaturesFilter->SetCurvatureTypeToMaximum();
	//高斯曲率
	//curvaturesFilter->SetCurvatureTypeToGaussian();
	// //平均曲率
	//curvaturesFilter->SetCurvatureTypeToMean();
	curvaturesFilter->Update();

	//将curvaturesFilter的数据存储到scalarRange数组中
	double scalarRange[2];
	//获取曲率的最大值和最小值
	curvaturesFilter->GetOutput()->GetScalarRange(scalarRange);

	vtkSmartPointer<vtkLookupTable> lut =
		vtkSmartPointer<vtkLookupTable>::New();
	//颜色的色调范围,从红色到黄绿色的过度
	lut->SetHueRange(0.0, 0.6);
	//透明度范围  设置为1 表示不透明
	lut->SetAlphaRange(1.0, 1.0);
	//颜色的饱和度范围  1最大值
	lut->SetValueRange(1.0, 1.0);
	lut->SetSaturationRange(1.0, 1.0);
	//颜色表的条目数 256
	lut->SetNumberOfTableValues(256);
	//将数据设置为颜色表的范围
	lut->SetRange(scalarRange);
	lut->Build();

	//将数据用颜色表显示出来
	vtkSmartPointer<vtkPolyDataMapper> mapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	mapper->SetInputData(curvaturesFilter->GetOutput());
	//颜色表设置
	mapper->SetLookupTable(lut);
	//标量范围设置为scalarRange
	mapper->SetScalarRange(scalarRange);

	vtkSmartPointer<vtkActor> actor =
		vtkSmartPointer<vtkActor>::New();
	actor->SetMapper(mapper);

	//显示一个颜色表 vtkScalarBarActor将一个颜色映射表转化为一个Actor对象,将颜色表以图形的形式显示
	vtkSmartPointer<vtkScalarBarActor> scalarBar =
		vtkSmartPointer<vtkScalarBarActor>::New();
	//设置颜色表
	scalarBar->SetLookupTable(mapper->GetLookupTable());
	//标量条的标题设置为数据集中数据数组的名称
	scalarBar->SetTitle(
		curvaturesFilter->GetOutput()->GetPointData()->GetScalars()->GetName());
	//设置标量条的标签数量
	scalarBar->SetNumberOfLabels(5);

	vtkSmartPointer<vtkRenderer> renderer =
		vtkSmartPointer<vtkRenderer>::New();
	renderer->AddActor(actor);
	renderer->AddActor2D(scalarBar);
	renderer->SetBackground(1.0, 1.0, 1.0);

	vtkSmartPointer<vtkRenderWindow> renderWindow =
		vtkSmartPointer<vtkRenderWindow>::New();
	renderWindow->AddRenderer(renderer);
	renderWindow->SetSize(640, 480);
	renderWindow->Render();
	renderWindow->SetWindowName("PolyDataCurvature");

	vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	renderWindowInteractor->SetRenderWindow(renderWindow);

	renderWindow->Render();
	renderWindowInteractor->Start();

	return EXIT_SUCCESS;
}

3.网格平滑

拉普拉斯平滑:每个点用其邻域点的中心来代替,通过不断地迭代,凯源得到较为光滑的网格

#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingFreeType)

#include <vtkSmartPointer.h>
#include <vtkPolyDataReader.h>
#include <vtkPolyData.h>
#include <vtkSmoothPolyDataFilter.h>
#include <vtkWindowedSincPolyDataFilter.h>
#include <vtkSphereSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>

//测试文件:../data/fran_cut.vtk
int main(int argc, char* argv[])
{

	vtkSmartPointer<vtkPolyDataReader> reader =
		vtkSmartPointer<vtkPolyDataReader>::New();
	reader->SetFileName("D:\\lqyWord\\VTK图形图像开发进阶随书代码\\Examples\\Chap06\\data\\fran_cut.vtk");
	reader->Update();

	vtkSmartPointer<vtkSmoothPolyDataFilter> smoothFilter =
		vtkSmartPointer<vtkSmoothPolyDataFilter>::New();
	smoothFilter->SetInputConnection(reader->GetOutputPort());
	//控制平滑次数  平滑的同时会损失一些细节信息
	smoothFilter->SetNumberOfIterations(200);
	smoothFilter->Update();

	vtkSmartPointer<vtkPolyDataMapper> inputMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	inputMapper->SetInputConnection(reader->GetOutputPort());
	vtkSmartPointer<vtkActor> inputActor =
		vtkSmartPointer<vtkActor>::New();
	inputActor->SetMapper(inputMapper);

	vtkSmartPointer<vtkPolyDataMapper> smoothedMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	smoothedMapper->SetInputConnection(smoothFilter->GetOutputPort());

	vtkSmartPointer<vtkActor> smoothedActor =
		vtkSmartPointer<vtkActor>::New();
	smoothedActor->SetMapper(smoothedMapper);

	double leftViewport[4] = { 0.0, 0.0, 0.5, 1.0 };
	double rightViewport[4] = { 0.5, 0.0, 1.0, 1.0 };

	vtkSmartPointer<vtkRenderer> leftRenderer =
		vtkSmartPointer<vtkRenderer>::New();

	leftRenderer->SetViewport(leftViewport);
	leftRenderer->AddActor(inputActor);
	leftRenderer->SetBackground(0.8, 0.8, 0.8);
	leftRenderer->ResetCamera();

	vtkSmartPointer<vtkRenderer> rightRenderer =
		vtkSmartPointer<vtkRenderer>::New();
	rightRenderer->SetViewport(rightViewport);
	rightRenderer->AddActor(smoothedActor);
	rightRenderer->SetBackground(0.8, 0.8, 0.8);
	rightRenderer->SetActiveCamera(leftRenderer->GetActiveCamera());
	rightRenderer->ResetCamera();

	vtkSmartPointer<vtkRenderWindow> renderWindow =
		vtkSmartPointer<vtkRenderWindow>::New();
	renderWindow->AddRenderer(leftRenderer);
	renderWindow->AddRenderer(rightRenderer);
	renderWindow->SetSize(640, 320);
	renderWindow->Render();
	renderWindow->SetWindowName("PolyDataLapLasianSmooth");

	vtkSmartPointer<vtkRenderWindowInteractor> interactor =
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	interactor->SetRenderWindow(renderWindow);

	renderWindow->Render();
	interactor->Start();

	return EXIT_SUCCESS;
}

4. 封闭性检测

边界边:如果一条边只被一个多边形包含,那么这条边就是边界边,是否存在边界边是检测一个网络模型是否封闭的重要特征

vtkFeatureEdges类的BoundaryEdgesOn()函数提取边界边
类vtkFillHolesFilter填补空洞:首先检测出网格中所有的边界边,然后找出这些边界边中的每一个闭合回路,最后将这个闭合回路进行三角化以实现填补的目的
vtkFillHolesFilter中的SetHloeSize()控制需要修补的漏洞的面积最大值,大于该值的漏洞不需要填补处理


#include "vtkAutoInit.h" 
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);

#include <vtkSmartPointer.h>
#include <vtkSelectionNode.h>
#include <vtkInformation.h>
#include <vtkUnstructuredGrid.h>
#include <vtkPolyData.h>
#include <vtkPolyDataNormals.h>
#include <vtkPointData.h>
#include <vtkXMLPolyDataReader.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkSelection.h>
#include <vtkSelectionNode.h>
#include <vtkSphereSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkCamera.h>
#include <vtkProperty.h>
#include <vtkIdTypeArray.h>
#include <vtkExtractSelection.h>
#include <vtkDataSetSurfaceFilter.h>
#include <vtkFeatureEdges.h>
#include <vtkFillHolesFilter.h>


//提取出原球体数据集中指定单元的表面数据集
/*设置选择节点-->选择器-->从原始数据中提取选择器中的数据-->得到表面数据
*/
void GenerateData(vtkSmartPointer<vtkPolyData> input)
{
	//定义一个球面网格
	vtkSmartPointer<vtkSphereSource> sphereSource =
		vtkSmartPointer<vtkSphereSource>::New();
	sphereSource->Update();

	vtkSmartPointer<vtkIdTypeArray> ids =
		vtkSmartPointer<vtkIdTypeArray>::New();
	ids->SetNumberOfComponents(1);
	ids->InsertNextValue(2);
	ids->InsertNextValue(10);

	//指定数据集中要选择那些单元或点的数据
	vtkSmartPointer<vtkSelectionNode> selectionNode =
		vtkSmartPointer<vtkSelectionNode>::New();
	//选择的是单元
	selectionNode->SetFieldType(vtkSelectionNode::CELL);
	//表示通过指定的标识符选择
	selectionNode->SetContentType(vtkSelectionNode::INDICES);
	//设置选择单元的标识符
	selectionNode->SetSelectionList(ids);
	//表示选择非指定单元
	selectionNode->GetProperties()->Set(vtkSelectionNode::INVERSE(), 1);

	//选择器
	vtkSmartPointer<vtkSelection> selection =
		vtkSmartPointer<vtkSelection>::New();
	selection->AddNode(selectionNode);

	vtkSmartPointer<vtkExtractSelection> extractSelection =
		vtkSmartPointer<vtkExtractSelection>::New();
	extractSelection->SetInputData(0, sphereSource->GetOutput());
	extractSelection->SetInputData(1, selection);
	extractSelection->Update();

	//vtkDataSetSurfaceFilter提取数据仍然保持原始数据的结构
	vtkSmartPointer<vtkDataSetSurfaceFilter> surfaceFilter =
		vtkSmartPointer<vtkDataSetSurfaceFilter>::New();
	surfaceFilter->SetInputConnection(extractSelection->GetOutputPort());
	surfaceFilter->Update();

	input->ShallowCopy(surfaceFilter->GetOutput());
}

int main(int argc, char* argv[])
{
	vtkSmartPointer<vtkPolyData> input =
		vtkSmartPointer<vtkPolyData>::New();
	GenerateData(input);

	vtkSmartPointer<vtkFeatureEdges> featureEdges =
		vtkSmartPointer<vtkFeatureEdges>::New();
	featureEdges->SetInputData(input);
	//设置提取边界边
	featureEdges->BoundaryEdgesOn();
	//特征边
	featureEdges->FeatureEdgesOff();
	//流形边
	featureEdges->ManifoldEdgesOff();
	//非流形边
	featureEdges->NonManifoldEdgesOff();
	featureEdges->Update();

	//输出一个包含边信息的vtkPolyData数据,通过判断边界边的数目来确定网格是否封闭
	int numberOfOpenEdges = featureEdges->GetOutput()->GetNumberOfCells();
	if (numberOfOpenEdges)
	{
		std::cout << "该网格模型不是封闭的..." << std::endl;
	}
	else
	{
		std::cout << "该网格模型是封闭的..." << std::endl;
		return EXIT_SUCCESS;
	}

	//填补空洞
	vtkSmartPointer<vtkFillHolesFilter> fillHolesFilter =
		vtkSmartPointer<vtkFillHolesFilter>::New();
	fillHolesFilter->SetInputData(input);
	fillHolesFilter->Update();

	//漏洞填充,模型的所有单元的点顺序不一致,使用ConsistencyOn进行调整
	vtkSmartPointer<vtkPolyDataNormals> normals =
		vtkSmartPointer<vtkPolyDataNormals>::New();
	normals->SetInputConnection(fillHolesFilter->GetOutputPort());
	normals->ConsistencyOn();
	normals->SplittingOff();
	normals->Update();
	
	double leftViewport[4] = { 0.0, 0.0, 0.5, 1.0 };
	double rightViewport[4] = { 0.5, 0.0, 1.0, 1.0 };

	vtkSmartPointer<vtkPolyDataMapper> originalMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	originalMapper->SetInputData(input);

	//设置一个属性  漫射颜色
	vtkSmartPointer<vtkProperty> backfaceProp =
		vtkSmartPointer<vtkProperty>::New();
	backfaceProp->SetDiffuseColor(1.0, 1.0, 0.34);

	vtkSmartPointer<vtkActor> originalActor =
		vtkSmartPointer<vtkActor>::New();
	originalActor->SetMapper(originalMapper);
	//设置背面属性 
	originalActor->SetBackfaceProperty(backfaceProp);
	//设置正面的视觉表现
	originalActor->GetProperty()->SetDiffuseColor(1.0, 0.3882, 0.2784);

	//边界边的显示设置
	vtkSmartPointer<vtkPolyDataMapper> edgeMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	edgeMapper->SetInputData(featureEdges->GetOutput());
	vtkSmartPointer<vtkActor> edgeActor =
		vtkSmartPointer<vtkActor>::New();
	edgeActor->SetMapper(edgeMapper);
	edgeActor->GetProperty()->SetEdgeColor(0., 0., 1.0);
	edgeActor->GetProperty()->SetEdgeVisibility(1);
	edgeActor->GetProperty()->SetLineWidth(5);

	vtkSmartPointer<vtkPolyDataMapper> filledMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	filledMapper->SetInputData(normals->GetOutput());

	//填补之后的图形显示
	vtkSmartPointer<vtkActor> filledActor =
		vtkSmartPointer<vtkActor>::New();
	filledActor->SetMapper(filledMapper);
	//filledActor->GetProperty()->SetDiffuseColor(1.0, 0.3882, 0.2784);
	filledActor->GetProperty()->SetDiffuseColor(1.0, 1.0, 0);

	vtkSmartPointer<vtkRenderer> leftRenderer =
		vtkSmartPointer<vtkRenderer>::New();
	leftRenderer->SetViewport(leftViewport);
	leftRenderer->AddActor(originalActor);
	leftRenderer->AddActor(edgeActor);
	leftRenderer->SetBackground(1.0, 1.0, 1.0);

	vtkSmartPointer<vtkRenderer> rightRenderer =
		vtkSmartPointer<vtkRenderer>::New();
	rightRenderer->SetViewport(rightViewport);
	rightRenderer->AddActor(filledActor);
	rightRenderer->SetBackground(1.0, 1.0, 1.0);

	vtkSmartPointer<vtkRenderWindow> renderWindow =
		vtkSmartPointer<vtkRenderWindow>::New();
	renderWindow->AddRenderer(leftRenderer);
	renderWindow->AddRenderer(rightRenderer);
	renderWindow->SetSize(640, 320);
	renderWindow->Render();
	renderWindow->SetWindowName("PolyDataClosed");

	vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	renderWindowInteractor->SetRenderWindow(renderWindow);

	//设置左视图相机的位置、焦点、视线方向和视角
	leftRenderer->GetActiveCamera()->SetPosition(0, -1, 0);
	leftRenderer->GetActiveCamera()->SetFocalPoint(0, 0, 0);
	leftRenderer->GetActiveCamera()->SetViewUp(0, 0, 1);
	leftRenderer->GetActiveCamera()->Azimuth(30);
	leftRenderer->GetActiveCamera()->Elevation(30);
	leftRenderer->ResetCamera();
	//右侧渲染器的相机设置为左侧渲染器的相机
	rightRenderer->SetActiveCamera(leftRenderer->GetActiveCamera());

	renderWindow->Render();
	renderWindowInteractor->Start();

	return EXIT_SUCCESS;
}

5. 连通区域分析

vtkAppendPolyData类可以实现vtkPolyData数据的合并,可以方便地构造含有多个连通区域的数据,接受两个或者多个vtkPolyData数据输入,合并结果包含输入数据的所有几何和拓扑数据

#include "vtkAutoInit.h" 
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);

#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkConeSource.h>
#include <vtkPolyDataConnectivityFilter.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkProperty.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkAppendPolyData.h>

int main(int, char* [])
{
	//定义一个球面数据
	vtkSmartPointer<vtkSphereSource> sphereSource =
		vtkSmartPointer<vtkSphereSource>::New();
	sphereSource->SetRadius(10);
	//设置球面的经线和纬线的数量 ,可以控制球体的光滑程度
	sphereSource->SetThetaResolution(10);
	sphereSource->SetPhiResolution(10);
	sphereSource->Update();

	//定义一个锥形数据
	vtkSmartPointer<vtkConeSource> coneSource =
		vtkSmartPointer<vtkConeSource>::New();
	coneSource->SetRadius(5);
	coneSource->SetHeight(10);
	coneSource->SetCenter(25, 0, 0);
	coneSource->Update();

	//将两个多边形数据合成一个多边形数据
	//输入俩个数据  生成一个包含两个对象的vtkPolyData数据  每一个输入模型为一个连通区域
	vtkSmartPointer<vtkAppendPolyData> appendFilter =
		vtkSmartPointer<vtkAppendPolyData>::New();
	appendFilter->AddInputData(sphereSource->GetOutput());
	appendFilter->AddInputData(coneSource->GetOutput());
	appendFilter->Update();

	/*从appendFilter中提取最多点的连通区域*/
	vtkSmartPointer<vtkPolyDataConnectivityFilter> connectivityFilter =
		vtkSmartPointer<vtkPolyDataConnectivityFilter>::New();
	connectivityFilter->SetInputData(appendFilter->GetOutput());
	//SetExtractionModeToCellSeededRegions用于提取具有最多点的连通区域
	//在本例中是球面数据
	connectivityFilter->SetExtractionModeToCellSeededRegions();
	connectivityFilter->AddSeed(100);
	connectivityFilter->Update();

	vtkSmartPointer<vtkPolyDataMapper> originalMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	originalMapper->SetInputConnection(appendFilter->GetOutputPort());
	originalMapper->Update();

	vtkSmartPointer<vtkActor> originalActor =
		vtkSmartPointer<vtkActor>::New();
	originalActor->SetMapper(originalMapper);

	vtkSmartPointer<vtkPolyDataMapper> extractedMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	extractedMapper->SetInputConnection(connectivityFilter->GetOutputPort());
	extractedMapper->Update();

	vtkSmartPointer<vtkActor> extractedActor =
		vtkSmartPointer<vtkActor>::New();
	extractedActor->SetMapper(extractedMapper);

	double leftViewport[4] = { 0.0, 0.0, 0.5, 1.0 };
	double rightViewport[4] = { 0.5, 0.0, 1.0, 1.0 };

	vtkSmartPointer<vtkRenderer> leftRenderer =
		vtkSmartPointer<vtkRenderer>::New();
	leftRenderer->SetViewport(leftViewport);
	leftRenderer->AddActor(originalActor);
	leftRenderer->SetBackground(0.8, 0.8, 0.8);

	vtkSmartPointer<vtkRenderer> rightRenderer =
		vtkSmartPointer<vtkRenderer>::New();
	rightRenderer->SetViewport(rightViewport);
	rightRenderer->AddActor(extractedActor);
	rightRenderer->SetBackground(1.0, 1.0, 1.0);

	vtkSmartPointer<vtkRenderWindow> renderWindow =
		vtkSmartPointer<vtkRenderWindow>::New();
	renderWindow->AddRenderer(leftRenderer);
	renderWindow->AddRenderer(rightRenderer);
	renderWindow->SetSize(640, 320);
	renderWindow->Render();
	renderWindow->SetWindowName("PolyDataConnectedCompExtract");

	leftRenderer->ResetCamera();
	rightRenderer->SetActiveCamera(leftRenderer->GetActiveCamera());

	vtkSmartPointer<vtkRenderWindowInteractor> interactor =
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	interactor->SetRenderWindow(renderWindow);
	interactor->Initialize();
	interactor->Start();

	return EXIT_SUCCESS;
}

6 多分辨率处理

6.1 模型抽取

模型抽取:减少模型数据中的点数据和单元数据,便于模型的后续处理和交换渲染(类似图像数据的降采样)
网格细化:利用一定的细化规则,在给定的初始网格中插入新的点,从而不断细化新的网格单元,在极限细化情况下,该网格能够收敛于一个光滑曲面

vtkDecimatePro是最常用的网格提取类,利用边塌陷的方法删除点和单元,处理速度比较快,可以方便控制网格提取的幅度,得到不同级别的模型数据
需要满足四个条件:
1.vtkDecimatePro需要支持模型拓扑的改变,将PreserveTopology变量的值设置为FALSE
2.支持网格分类,即Splitting变量的值设置为TRUE
3.支持修改模型的边界,即将变量BoundaryVertexDeletion的值设置为TRUE
4.设置最大误差变量MaximumError的值为VTK_DOUBLE_MAX

网格抽取类接收的是vtkPolyData的三角网格数据,如果vtkPolyData数据为多边形网格数据,需要先通过vtkTriangleFilter将多边形网格数据转化为三角网格数据

#include "vtkAutoInit.h" 
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);

#include <vtkPolyData.h>
#include <vtkSphereSource.h>
#include <vtkDecimatePro.h>
#include <vtkQuadricDecimation.h>
#include <vtkQuadricClustering.h>
#include <vtkSmartPointer.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkPolydataReader.h>
#include <vtkCamera.h>

//测试文件:../data/fran_cut.vtk
int main(int argc, char* argv[])
{
	vtkSmartPointer<vtkPolyDataReader> reader =
		vtkSmartPointer<vtkPolyDataReader>::New();
	reader->SetFileName("D:\\lqyWord\\VTK图形图像开发进阶随书代码\\Examples\\Chap06\\data\\fran_cut.vtk");
	reader->Update();
	vtkSmartPointer<vtkPolyData> original = reader->GetOutput();

	std::cout << "抽取前:" << std::endl << "------------" << std::endl;
	std::cout << "模型点数为: " << original->GetNumberOfPoints() << std::endl;
	std::cout << "模型面数为: " << original->GetNumberOfPolys() << std::endl;

	//vtkDecimatePro接收一个单元为三角网络的vtkPolyData数据
	vtkSmartPointer<vtkDecimatePro> decimate =
		vtkSmartPointer<vtkDecimatePro>::New();
	decimate->SetInputData(original);
	//设置面片移除的比例(0-1),说明有8%的三角面片要被移除
	decimate->SetTargetReduction(.80);
	decimate->Update();

	vtkSmartPointer<vtkPolyData> decimated = decimate->GetOutput();
	std::cout << "抽取后" << std::endl << "------------" << std::endl;
	std::cout << "模型点数为:" << decimated->GetNumberOfPoints() << std::endl;
	std::cout << "模型面数为:" << decimated->GetNumberOfPolys() << std::endl;

	vtkSmartPointer<vtkPolyDataMapper> origianlMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	origianlMapper->SetInputData(original);

	vtkSmartPointer<vtkActor> origianlActor =
		vtkSmartPointer<vtkActor>::New();
	origianlActor->SetMapper(origianlMapper);

	vtkSmartPointer<vtkPolyDataMapper> decimatedMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	decimatedMapper->SetInputData(decimated);

	vtkSmartPointer<vtkActor> decimatedActor =
		vtkSmartPointer<vtkActor>::New();
	decimatedActor->SetMapper(decimatedMapper);

	double leftViewport[4] = { 0.0, 0.0, 0.5, 1.0 };
	double rightViewport[4] = { 0.5, 0.0, 1.0, 1.0 };

	vtkSmartPointer<vtkRenderer> leftRenderer =
		vtkSmartPointer<vtkRenderer>::New();
	leftRenderer->SetViewport(leftViewport);
	leftRenderer->AddActor(origianlActor);
	leftRenderer->SetBackground(1.0, 1.0, 1.0);

	vtkSmartPointer<vtkRenderer> rightRenderer =
		vtkSmartPointer<vtkRenderer>::New();
	rightRenderer->SetViewport(rightViewport);
	rightRenderer->AddActor(decimatedActor);
	rightRenderer->SetBackground(1.0, 1.0, 1.0);

	leftRenderer->GetActiveCamera()->SetPosition(0, -1, 0);
	leftRenderer->GetActiveCamera()->SetFocalPoint(0, 0, 0);
	leftRenderer->GetActiveCamera()->SetViewUp(0, 0, 1);
	leftRenderer->GetActiveCamera()->Azimuth(30);
	leftRenderer->GetActiveCamera()->Elevation(30);
	leftRenderer->ResetCamera();
	rightRenderer->SetActiveCamera(leftRenderer->GetActiveCamera());

	vtkSmartPointer<vtkRenderWindow> renderWindow =
		vtkSmartPointer<vtkRenderWindow>::New();
	renderWindow->AddRenderer(leftRenderer);
	renderWindow->AddRenderer(rightRenderer);
	renderWindow->SetSize(640, 320);
	renderWindow->Render();
	renderWindow->SetWindowName("PolyDataDecimation");

	vtkSmartPointer<vtkRenderWindowInteractor> interactor =
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	interactor->SetRenderWindow(renderWindow);

	renderWindow->Render();
	interactor->Start();

	return EXIT_SUCCESS;
}

6.2网格细化

  • 模型细化只对三角网络数据有效,在处理多边形数据时,需要通过vtkTriangleFilter将多边形数据转化为三角网格数据
  • 实现网格细化的类有vtkLinearSubdivisionFilter、vtkLoopSubdivisionFilter、vtkButterflySubdivisionFilter,这三类都继承自vtkInterpolatingSubdivisionFilter。
  • vtkInterpolatingSubdivisionFilter内部提供了SetNumberOfSubdivisions()函数来设置细化的次数,其中每次细化后模型的三角面片的个数将是细化前的4倍,所以,在对网络模型进行n次细分后,该模型的面片个数是原始模型面片数目的4n倍
#include "vtkAutoInit.h" 
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);

#include <vtkSmartPointer.h>
#include <vtkCellData.h>
#include <vtkCellArray.h>
#include <vtkDoubleArray.h>
#include <vtkPoints.h>
#include <vtkTriangle.h>
#include <vtkPolyData.h>
#include <vtkPointData.h>
#include <vtkSphereSource.h>
#include <vtkTriangleFilter.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkButterflySubdivisionFilter.h>
#include <vtkLoopSubdivisionFilter.h>
#include <vtkLinearSubdivisionFilter.h>
#include <string>

int main(int argc, char* argv[])
{
	vtkSmartPointer<vtkPolyData> originalMesh;

	vtkSmartPointer<vtkSphereSource> sphereSource =
		vtkSmartPointer<vtkSphereSource>::New();
	sphereSource->Update();
	originalMesh = sphereSource->GetOutput();

	double numberOfViewports = 3;
	int numberOfSubdivisions = 2;

	vtkSmartPointer<vtkRenderWindow> renderWindow =
		vtkSmartPointer<vtkRenderWindow>::New();
	renderWindow->SetSize(200 * numberOfViewports, 200);
	renderWindow->SetWindowName("Multiple ViewPorts");

	vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	renderWindowInteractor->SetRenderWindow(renderWindow);

	for (unsigned i = 0; i < numberOfViewports; i++)
	{
		//定义一个基类指针 这样就可以将任意一个子类的指针赋值给该变量
		vtkSmartPointer<vtkPolyDataAlgorithm> subdivisionFilter;
		switch (i)
		{
		case 0:
			subdivisionFilter = vtkSmartPointer<vtkLinearSubdivisionFilter>::New();
			dynamic_cast<vtkLinearSubdivisionFilter*> (subdivisionFilter.GetPointer())->SetNumberOfSubdivisions(numberOfSubdivisions);
			break;
		case 1:
			subdivisionFilter = vtkSmartPointer<vtkLoopSubdivisionFilter>::New();
			dynamic_cast<vtkLoopSubdivisionFilter*> (subdivisionFilter.GetPointer())->SetNumberOfSubdivisions(numberOfSubdivisions);
			break;
		case 2:
			subdivisionFilter = vtkSmartPointer<vtkButterflySubdivisionFilter>::New();
			dynamic_cast<vtkButterflySubdivisionFilter*> (subdivisionFilter.GetPointer())->SetNumberOfSubdivisions(numberOfSubdivisions);
			break;
		default:
			break;
		}

		//设置好细化次数之后  传入原始数据
		subdivisionFilter->SetInputData(originalMesh);
		subdivisionFilter->Update();

		vtkSmartPointer<vtkRenderer> renderer =
			vtkSmartPointer<vtkRenderer>::New();

		renderWindow->AddRenderer(renderer);
		renderer->SetViewport(static_cast<double>(i) / numberOfViewports, 0, static_cast<double>(i + 1) / numberOfViewports, 1);
		renderer->SetBackground(1.0, 1.0, 1.0);

		vtkSmartPointer<vtkPolyDataMapper> mapper =
			vtkSmartPointer<vtkPolyDataMapper>::New();
		mapper->SetInputConnection(subdivisionFilter->GetOutputPort());
		vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
		actor->SetMapper(mapper);
		renderer->AddActor(actor);
		renderer->ResetCamera();
	}

	renderWindow->SetSize(640, 320);
	renderWindow->Render();
	renderWindow->SetWindowName("PolyDataSubdivision");

	renderWindow->Render();
	renderWindowInteractor->Start();

	return EXIT_SUCCESS;
}

在这里插入图片描述

7.表面重建

7.1三角剖分
Delaunay三角剖分:在所有的三角剖分中,所生成的三角形的最小角的角度最大(无论从哪个区域开始构建,最终生成的三角网格都是唯一的)
vtkDelaunay2D实现二维的三角剖分,输入为vtkPolyData点数据

#include "vtkAutoInit.h" 
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);

#include <vtkSmartPointer.h>
#include <vtkProperty.h>
#include <vtkPoints.h>
#include <vtkPolyData.h>
#include <vtkPointData.h>
#include <vtkDelaunay2D.h>
#include <vtkMath.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkVertexGlyphFilter.h>
#include <vtkPolyDataReader.h>

int main(int, char* [])
{
	unsigned int gridSize = 10;
	vtkSmartPointer<vtkPoints> points =
		vtkSmartPointer<vtkPoints>::New();
	for (unsigned int x = 0; x < gridSize; x++)
	{
		for (unsigned int y = 0; y < gridSize; y++)
		{
			points->InsertNextPoint(x, y, vtkMath::Random(0.0, 3.0));
		}
	}
	//定义一个点集
	vtkSmartPointer<vtkPolyData> polydata =
		vtkSmartPointer<vtkPolyData>::New();
	polydata->SetPoints(points);

	vtkSmartPointer<vtkDelaunay2D> delaunay =
		vtkSmartPointer<vtkDelaunay2D>::New();
	delaunay->SetInputData(polydata);
	delaunay->Update();

	//在点数据上生成图元数据 就是将点数据显示出来
	vtkSmartPointer<vtkVertexGlyphFilter> glyphFilter =
		vtkSmartPointer<vtkVertexGlyphFilter>::New();
	glyphFilter->SetInputData(polydata);
	glyphFilter->Update();

	vtkSmartPointer<vtkPolyDataMapper> pointsMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	pointsMapper->SetInputData(glyphFilter->GetOutput());

	vtkSmartPointer<vtkActor> pointsActor =
		vtkSmartPointer<vtkActor>::New();
	pointsActor->SetMapper(pointsMapper);
	pointsActor->GetProperty()->SetPointSize(3);
	pointsActor->GetProperty()->SetColor(1, 0, 0);

	vtkSmartPointer<vtkPolyDataMapper> triangulatedMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	triangulatedMapper->SetInputData(delaunay->GetOutput());

	vtkSmartPointer<vtkActor> triangulatedActor =
		vtkSmartPointer<vtkActor>::New();
	triangulatedActor->SetMapper(triangulatedMapper);

	vtkSmartPointer<vtkRenderer> renderer =
		vtkSmartPointer<vtkRenderer>::New();
	//renderer->AddActor(pointsActor);
	renderer->AddActor(triangulatedActor);
	renderer->SetBackground(1.0, 1.0, 1.0);

	vtkSmartPointer<vtkRenderWindow> renderWindow =
		vtkSmartPointer<vtkRenderWindow>::New();
	renderWindow->AddRenderer(renderer);

	vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	renderWindowInteractor->SetRenderWindow(renderWindow);

	renderWindow->SetSize(640, 320);
	renderWindow->Render();
	renderWindow->SetWindowName("PolyDataDelaunay2D");
	renderWindow->Render();

	renderWindowInteractor->Start();

	return EXIT_SUCCESS;
}

vtkDelaunay2D还支持加入边界限制。用户可以设置另一个vtkPolyData数据,其内部的线段、闭合或者非闭合的线段集合将作为边界条件控制三角剖分的过程,其中组成这些边界的点的索引必须与原始点集数据一致

#include "vtkAutoInit.h" 
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);

#include <vtkSmartPointer.h>
#include <vtkProperty.h>
#include <vtkPolygon.h>
#include <vtkCellArray.h>
#include <vtkPoints.h>
#include <vtkPolyData.h>
#include <vtkPointData.h>
#include <vtkDelaunay2D.h>
#include <vtkMath.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkVertexGlyphFilter.h>

int main(int, char* [])
{
	vtkSmartPointer<vtkPoints> points =
		vtkSmartPointer<vtkPoints>::New();

	unsigned int gridSize = 10;
	for (unsigned int x = 0; x < gridSize; x++)
	{
		for (unsigned int y = 0; y < gridSize; y++)
		{
			points->InsertNextPoint(x, y, vtkMath::Random(0.0, 3.0));
		}
	}

	vtkSmartPointer<vtkPolyData> polydata =
		vtkSmartPointer<vtkPolyData>::New();
	polydata->SetPoints(points);

	vtkSmartPointer<vtkPolygon> poly =
		vtkSmartPointer<vtkPolygon>::New();
	poly->GetPointIds()->InsertNextId(22);
	poly->GetPointIds()->InsertNextId(23);
	poly->GetPointIds()->InsertNextId(24);
	poly->GetPointIds()->InsertNextId(25);
	poly->GetPointIds()->InsertNextId(35);
	poly->GetPointIds()->InsertNextId(45);
	poly->GetPointIds()->InsertNextId(44);
	poly->GetPointIds()->InsertNextId(43);
	poly->GetPointIds()->InsertNextId(42);
	poly->GetPointIds()->InsertNextId(32);

	/*poly->GetPointIds()->InsertNextId(32);
	poly->GetPointIds()->InsertNextId(42);
	poly->GetPointIds()->InsertNextId(43);
	poly->GetPointIds()->InsertNextId(44);
	poly->GetPointIds()->InsertNextId(45);
	poly->GetPointIds()->InsertNextId(35);
	poly->GetPointIds()->InsertNextId(25);
	poly->GetPointIds()->InsertNextId(24);
	poly->GetPointIds()->InsertNextId(23);
	poly->GetPointIds()->InsertNextId(22);*/

	vtkSmartPointer<vtkCellArray> cell =
		vtkSmartPointer<vtkCellArray>::New();
	cell->InsertNextCell(poly);

	//加入一个多边形边界来限制三角剖分
	vtkSmartPointer<vtkPolyData> boundary =
		vtkSmartPointer<vtkPolyData>::New();
	boundary->SetPoints(points);
	boundary->SetPolys(cell);

	vtkSmartPointer<vtkDelaunay2D> delaunay =
		vtkSmartPointer<vtkDelaunay2D>::New();
	delaunay->SetInputData(polydata);
	//设置边界数据
	delaunay->SetSourceData(boundary);
	delaunay->Update();

	vtkSmartPointer<vtkVertexGlyphFilter> glyphFilter =
		vtkSmartPointer<vtkVertexGlyphFilter>::New();
	glyphFilter->SetInputData(polydata);
	glyphFilter->Update();

	vtkSmartPointer<vtkPolyDataMapper> pointsMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	pointsMapper->SetInputData(glyphFilter->GetOutput());

	vtkSmartPointer<vtkActor> pointsActor =
		vtkSmartPointer<vtkActor>::New();
	pointsActor->SetMapper(pointsMapper);
	pointsActor->GetProperty()->SetPointSize(3);
	pointsActor->GetProperty()->SetColor(1, 0, 0);

	vtkSmartPointer<vtkPolyDataMapper> triangulatedMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	triangulatedMapper->SetInputData(delaunay->GetOutput());

	vtkSmartPointer<vtkActor> triangulatedActor =
		vtkSmartPointer<vtkActor>::New();
	triangulatedActor->SetMapper(triangulatedMapper);

	vtkSmartPointer<vtkRenderer> renderer =
		vtkSmartPointer<vtkRenderer>::New();
	renderer->AddActor(pointsActor);
	renderer->AddActor(triangulatedActor);
	renderer->SetBackground(1.0, 1.0, 1.0);

	vtkSmartPointer<vtkRenderWindow> renderWindow =
		vtkSmartPointer<vtkRenderWindow>::New();
	renderWindow->AddRenderer(renderer);

	vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	renderWindowInteractor->SetRenderWindow(renderWindow);

	renderWindow->SetSize(640, 480);
	renderWindow->Render();
	renderWindow->SetWindowName("PolyDataConstrainedDelaunay2D");
	renderWindow->Render();
	renderWindowInteractor->Start();

	return EXIT_SUCCESS;
}

7.2 等值面提取
vtkImageMarchingCubes主要处理三维图像处理
vtkMarchingCubes主要针对规则体数据生成等值面
vtkMarchingSquares针对二维规格网格数据生成等值线
在这里插入图片描述

#include "vtkAutoInit.h" 
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);

#include <vtkSmartPointer.h>
#include <vtkMarchingCubes.h>
#include <vtkContourFilter.h>
#include <vtkVoxelModeller.h>
#include <vtkSphereSource.h>
#include <vtkImageData.h>
#include <vtkMetaImageReader.h>
#include <vtkInteractorStyleImage.h>
#include <vtkActor.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkImageActor.h>
#include <vtkProperty.h>

//测试:../data/HeadMRVolume.mhd 200
int main(int argc, char* argv[])
{
	vtkSmartPointer<vtkMetaImageReader> reader =
		vtkSmartPointer<vtkMetaImageReader>::New();
	reader->SetFileName("D:\\lqyWord\\VTK图形图像开发进阶随书代码\\Examples\\Chap06\\data\\brain.mhd");
	reader->Update();

	double isoValue = 200;

	/*vtkSmartPointer<vtkMarchingCubes> surface =
		vtkSmartPointer<vtkMarchingCubes>::New();
	surface->SetInputData(reader->GetOutput());
	surface->ComputeNormalsOn();
	//设置等值面的值 第一个参数是等值面的序号
	//因此可以设置多个等值面数值来提取多个等值面
	surface->SetValue(0, isoValue);*/
	//surface->GenerateValues(5, 150,200);

	vtkSmartPointer<vtkContourFilter> surface =
	vtkSmartPointer<vtkContourFilter>::New();
	surface->SetInputData(reader->GetOutput());
	//计算等值面的法向量
	surface->ComputeNormalsOn();
	surface->SetValue(1, isoValue);

	vtkSmartPointer<vtkPolyDataMapper> surfMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	surfMapper->SetInputConnection(surface->GetOutputPort());
	surfMapper->ScalarVisibilityOn();

	vtkSmartPointer<vtkActor> surfActor =
		vtkSmartPointer<vtkActor>::New();
	surfActor->SetMapper(surfMapper);
	surfActor->GetProperty()->SetColor(1.0, 0.0, 0.0);

	vtkSmartPointer<vtkRenderer> renderer =
		vtkSmartPointer<vtkRenderer>::New();
	renderer->AddActor(surfActor);
	renderer->SetBackground(1.0, 1.0, 1.0);

	vtkSmartPointer<vtkRenderWindow> renderWindow =
		vtkSmartPointer<vtkRenderWindow>::New();
	renderWindow->AddRenderer(renderer);
	renderWindow->SetSize(640, 480);
	renderWindow->Render();
	renderWindow->SetWindowName("PolyDataMarchingCubes");
	renderWindow->Render();

	vtkSmartPointer<vtkRenderWindowInteractor> interactor =
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	interactor->SetRenderWindow(renderWindow);

	renderWindow->Render();
	interactor->Start();

	return EXIT_SUCCESS;
}

7.3 点云重建

Delaunay三角剖分算法可以实现网格曲面重建,但是主要运用在二维剖分,在三维空间网格生成中遇到问题,不仅基于最大最小角判断的对角线交换准则不在成立,而且基于外接圆判断的Delaunay三角化也不能保证网格质量
vtkSurfaceReconstructionFilter实现一种隐式曲面重建的方法

#include "vtkAutoInit.h" 
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);

#include <vtkSmartPointer.h>
#include <vtkSurfaceReconstructionFilter.h>
#include <vtkProgrammableSource.h>
#include <vtkContourFilter.h>
#include <vtkReverseSense.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkPolyData.h>
#include <vtkCamera.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkCamera.h>
#include <vtkPolydataReader.h>
#include <vtkVertexGlyphFilter.h>
#include <vtkLookupTable.h>

//测试文件:../data/fran_cut.vtk
int main(int argc, char* argv[])
{
	vtkSmartPointer<vtkPolyDataReader> reader =
		vtkSmartPointer<vtkPolyDataReader>::New();
	reader->SetFileName("through_cloud_filtered.vtk");
	reader->Update();

	vtkSmartPointer<vtkPolyData> points =
		vtkSmartPointer<vtkPolyData>::New();
	points->SetPoints(reader->GetOutput()->GetPoints());
	

	vtkSmartPointer<vtkSurfaceReconstructionFilter> surf =
		vtkSmartPointer<vtkSurfaceReconstructionFilter>::New();
	surf->SetInputData(points);
	//SetNeighborhoodSize用于设置邻域点的个数,而这些邻域点用于估计每个点的局部切平面
	//个数设置越大,计算时间越长,当点分布不均匀时,可以增加该值
	surf->SetNeighborhoodSize(35);
	//SetSampleSpacing()用于设置划分网格的网格间距,间距越小,网格越密集
	surf->SetSampleSpacing(1.5);
	surf->Update();

	vtkSmartPointer<vtkContourFilter> contour =
		vtkSmartPointer<vtkContourFilter>::New();
	contour->SetInputConnection(surf->GetOutputPort());
	contour->SetValue(0, 0.0);
	contour->Update();

	double leftViewport[4] = { 0.0, 0.0, 0.5, 1.0 };
	double rightViewport[4] = { 0.5, 0.0, 1.0, 1.0 };

	vtkSmartPointer<vtkVertexGlyphFilter> vertexGlyphFilter =
		vtkSmartPointer<vtkVertexGlyphFilter>::New();
	vertexGlyphFilter->AddInputData(points);
	vertexGlyphFilter->Update();

	vtkSmartPointer<vtkPolyDataMapper> vertexMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	vertexMapper->SetInputData(vertexGlyphFilter->GetOutput());
	vertexMapper->ScalarVisibilityOff();

	vtkSmartPointer<vtkActor> vertexActor =
		vtkSmartPointer<vtkActor>::New();
	vertexActor->SetMapper(vertexMapper);
	vertexActor->GetProperty()->SetColor(0.625, 0.625, 0.625);
	vertexActor->GetProperty()->SetPointSize(4);

	vtkSmartPointer<vtkRenderer> vertexRenderer =
		vtkSmartPointer<vtkRenderer>::New();
	vertexRenderer->AddActor(vertexActor);
	vertexRenderer->SetViewport(leftViewport);
	vertexRenderer->SetBackground(1.0, 1.0, 1.0);

	vtkSmartPointer<vtkPolyDataMapper> surfMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	surfMapper->SetInputData(contour->GetOutput());
	surfMapper->ScalarVisibilityOff();

	vtkSmartPointer<vtkActor> surfActor =
		vtkSmartPointer<vtkActor>::New();
	surfActor->SetMapper(surfMapper);
	surfActor->GetProperty()->SetColor(0.625, 0.625, 0.625);

	vtkSmartPointer<vtkRenderer> surfRenderer =
		vtkSmartPointer<vtkRenderer>::New();
	surfRenderer->AddActor(surfActor);
	surfRenderer->SetViewport(rightViewport);
	surfRenderer->SetBackground(1.0, 1.0, 1.0);


	//surfRenderer->SetActiveCamera(vertexRenderer->GetActiveCamera());

	vtkSmartPointer<vtkRenderWindow> renWin =
		vtkSmartPointer<vtkRenderWindow>::New();
	renWin->AddRenderer(surfRenderer);
	renWin->AddRenderer(vertexRenderer);
	renWin->SetSize(640, 320);
	renWin->Render();
	renWin->SetWindowName("PolyDataSurfaceReconstruction");

	vtkSmartPointer<vtkRenderWindowInteractor> iren =
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	iren->SetRenderWindow(renWin);

	renWin->Render();
	iren->Start();

	return EXIT_SUCCESS;
}

在这里插入图片描述

8.点云配准

点云配准:对测量点云数据进行局部配准和整合得到完整的模型数据,对一组源点云数据应用一个空间变换,使得变换后的数据与目标点云能够一一映射,使得两组数据之间的平均距离误差最小
在这里插入图片描述

#include "vtkAutoInit.h" 
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingFreeType);


#include <vtkPoints.h>
#include <vtkSmartPointer.h>
#include <vtkLandmarkTransform.h>
#include <vtkMatrix4x4.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkProperty.h>
#include <vtkTransformPolyDataFilter.h>
#include <vtkVertexGlyphFilter.h>
#include <vtkAxesActor.h>

int main(int, char* [])
{
	//定义源标记点集
	vtkSmartPointer<vtkPoints> sourcePoints =
		vtkSmartPointer<vtkPoints>::New();
	double sourcePoint1[3] = { 0.5, 0.0, 0.0 };
	sourcePoints->InsertNextPoint(sourcePoint1);
	double sourcePoint2[3] = { 0.0, 0.5, 0.0 };
	sourcePoints->InsertNextPoint(sourcePoint2);
	double sourcePoint3[3] = { 0.0, 0.0, 0.5 };
	sourcePoints->InsertNextPoint(sourcePoint3);

	//定义目标标记点集
	vtkSmartPointer<vtkPoints> targetPoints =
		vtkSmartPointer<vtkPoints>::New();
	double targetPoint1[3] = { 0.0, 0.0, 0.55 };
	targetPoints->InsertNextPoint(targetPoint1);
	double targetPoint2[3] = { 0.0, 0.55, 0.0 };
	targetPoints->InsertNextPoint(targetPoint2);
	double targetPoint3[3] = { -0.55, 0.0, 0.0 };
	targetPoints->InsertNextPoint(targetPoint3);

	
	vtkSmartPointer<vtkLandmarkTransform> landmarkTransform =
		vtkSmartPointer<vtkLandmarkTransform>::New();
	landmarkTransform->SetSourceLandmarks(sourcePoints);
	landmarkTransform->SetTargetLandmarks(targetPoints);
	//设置匹配变换的类型为刚体变换,旋转和平移
	landmarkTransform->SetModeToRigidBody();
	//SetModeToSimilarity()相似变换,旋转平移和放缩变换
	//SetModeToAffine()放射变换
	landmarkTransform->Update();

	vtkSmartPointer<vtkPolyData> source =
		vtkSmartPointer<vtkPolyData>::New();
	source->SetPoints(sourcePoints);

	vtkSmartPointer<vtkPolyData> target =
		vtkSmartPointer<vtkPolyData>::New();
	target->SetPoints(targetPoints);

	vtkSmartPointer<vtkVertexGlyphFilter> sourceGlyphFilter =
		vtkSmartPointer<vtkVertexGlyphFilter>::New();
	sourceGlyphFilter->SetInputData(source);
	sourceGlyphFilter->Update();

	vtkSmartPointer<vtkVertexGlyphFilter> targetGlyphFilter =
		vtkSmartPointer<vtkVertexGlyphFilter>::New();
	targetGlyphFilter->SetInputData(target);
	targetGlyphFilter->Update();

	//vtkTransformPolyDataFilter对源标记点进行变换来显示配准后的点集
	vtkSmartPointer<vtkTransformPolyDataFilter> transformFilter =
		vtkSmartPointer<vtkTransformPolyDataFilter>::New();
	transformFilter->SetInputData(sourceGlyphFilter->GetOutput());
	//设置变换的结果
	transformFilter->SetTransform(landmarkTransform);
	transformFilter->Update();

	vtkSmartPointer<vtkPolyDataMapper> sourceMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	sourceMapper->SetInputConnection(sourceGlyphFilter->GetOutputPort());

	vtkSmartPointer<vtkActor> sourceActor =
		vtkSmartPointer<vtkActor>::New();
	sourceActor->SetMapper(sourceMapper);
	sourceActor->GetProperty()->SetColor(1, 1, 0);
	sourceActor->GetProperty()->SetPointSize(5);

	vtkSmartPointer<vtkPolyDataMapper> targetMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	targetMapper->SetInputConnection(targetGlyphFilter->GetOutputPort());

	vtkSmartPointer<vtkActor> targetActor =
		vtkSmartPointer<vtkActor>::New();
	targetActor->SetMapper(targetMapper);
	targetActor->GetProperty()->SetColor(1, 0, 0);
	targetActor->GetProperty()->SetPointSize(5);

	vtkSmartPointer<vtkPolyDataMapper> solutionMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	solutionMapper->SetInputConnection(transformFilter->GetOutputPort());

	vtkSmartPointer<vtkActor> solutionActor =
		vtkSmartPointer<vtkActor>::New();
	solutionActor->SetMapper(solutionMapper);
	solutionActor->GetProperty()->SetColor(0, 0, 1);
	solutionActor->GetProperty()->SetPointSize(5);

	vtkSmartPointer<vtkRenderer> renderer =
		vtkSmartPointer<vtkRenderer>::New();

	vtkSmartPointer<vtkRenderWindow> renderWindow =
		vtkSmartPointer<vtkRenderWindow>::New();
	renderWindow->AddRenderer(renderer);
	renderer->AddActor(sourceActor);
	renderer->AddActor(targetActor);
	renderer->AddActor(solutionActor);

	//设置坐标系
	vtkSmartPointer<vtkAxesActor> axes =
		vtkSmartPointer<vtkAxesActor>::New();
	axes->SetScale(30);
	renderer->AddActor(axes);
	renderer->SetBackground(.3, .6, .3);

	vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	renderWindowInteractor->SetRenderWindow(renderWindow);

	renderWindow->SetSize(640, 480);
	renderWindow->Render();
	renderWindow->SetWindowName("PolyDataLandmarkReg");
	renderWindow->Render();
	renderWindowInteractor->Start();

	return EXIT_SUCCESS;
}

ICP算法是一个迭代的过程,每次迭代 中对于源数据点P找到目标点集Q中的最近点,然后基于最小二乘原理求解当前的变换T。通过不断迭代直至收敛,就完成点集的配准

和上边配准区别:vtkIterativeClosestPointTransform类中设置源点集和目标点集的函数是SetSource()、SetTarget()其中输入的数据类型为vtkDataSet,上边配准中vtkLandmarkTransform的输入数据类型为vtkPoints

#include "vtkAutoInit.h" 
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingFreeType);


#include <vtkPoints.h>
#include <vtkSmartPointer.h>
#include <vtkLandmarkTransform.h>
#include <vtkMatrix4x4.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkProperty.h>
#include <vtkTransformPolyDataFilter.h>
#include <vtkVertexGlyphFilter.h>
#include <vtkIterativeClosestPointTransform.h>
#include <vtkPolyDataReader.h>
#include <vtkTransform.h>

//测试文件:../data/fran_cut.vtk
int main(int argc, char* argv[])
{
	vtkSmartPointer<vtkPolyDataReader> reader =
		vtkSmartPointer<vtkPolyDataReader>::New();
	reader->SetFileName("D:\\lqyWord\\VTK图形图像开发进阶随书代码\\Examples\\Chap06\\data\\fran_cut.vtk");
	reader->Update();
	vtkSmartPointer<vtkPolyData> original = reader->GetOutput();

	//对原始数据做了一个平移和旋转 这里只是设置变换矩阵
	vtkSmartPointer<vtkTransform> translation =
		vtkSmartPointer<vtkTransform>::New();
	//x轴方向平移量0.2
	translation->Translate(0.2, 0.0, 0.0);
	//旋转绕X轴旋转30°
	translation->RotateX(30);

	//进行旋转平移变换
	vtkSmartPointer<vtkTransformPolyDataFilter> transformFilter1 =
		vtkSmartPointer<vtkTransformPolyDataFilter>::New();
	//设置原始数据
	transformFilter1->SetInputData(reader->GetOutput());
	//设置变换矩阵
	transformFilter1->SetTransform(translation);
	transformFilter1->Update();

	vtkSmartPointer<vtkPolyData> source =
		vtkSmartPointer<vtkPolyData>::New();
	source->SetPoints(original->GetPoints());

	vtkSmartPointer<vtkPolyData> target =
		vtkSmartPointer<vtkPolyData>::New();
	target->SetPoints(transformFilter1->GetOutput()->GetPoints());

	//vtkVertexGlyphFilter根据输入数据集的几何信息生成相应的点数据集
	//将原始数据转化为点数据集,可以实现一些基于点的渲染技术,如点渲染、使用点大小表示某些属性
	vtkSmartPointer<vtkVertexGlyphFilter> sourceGlyphFilter =
		vtkSmartPointer<vtkVertexGlyphFilter>::New();
	sourceGlyphFilter->SetInputData(source);
	sourceGlyphFilter->Update();

	vtkSmartPointer<vtkVertexGlyphFilter> targetGlyphFilter =
		vtkSmartPointer<vtkVertexGlyphFilter>::New();
	targetGlyphFilter->SetInputData(target);
	targetGlyphFilter->Update();

	//设置点云配准的原点云和目标点云 相当于是计算变换矩阵
	vtkSmartPointer<vtkIterativeClosestPointTransform> icpTransform =
		vtkSmartPointer<vtkIterativeClosestPointTransform>::New();
	icpTransform->SetSource(sourceGlyphFilter->GetOutput());
	icpTransform->SetTarget(targetGlyphFilter->GetOutput());
	//刚体变换
	icpTransform->GetLandmarkTransform()->SetModeToRigidBody();
	//设置迭代次数
	icpTransform->SetMaximumNumberOfIterations(20);
	//设置配准之前先计算两个点集重心,并平移源点集使得两者重心重合
	icpTransform->StartByMatchingCentroidsOn();
	icpTransform->Modified();
	icpTransform->Update();

	//对源点集进行空间变换
	vtkSmartPointer<vtkTransformPolyDataFilter> transformFilter2 =
		vtkSmartPointer<vtkTransformPolyDataFilter>::New();
	transformFilter2->SetInputData(sourceGlyphFilter->GetOutput());
	transformFilter2->SetTransform(icpTransform);
	transformFilter2->Update();

	vtkSmartPointer<vtkPolyDataMapper> sourceMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	sourceMapper->SetInputConnection(sourceGlyphFilter->GetOutputPort());

	vtkSmartPointer<vtkActor> sourceActor =
		vtkSmartPointer<vtkActor>::New();
	sourceActor->SetMapper(sourceMapper);
	sourceActor->GetProperty()->SetColor(0, 1, 0);
	sourceActor->GetProperty()->SetPointSize(3);

	vtkSmartPointer<vtkPolyDataMapper> targetMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	targetMapper->SetInputConnection(targetGlyphFilter->GetOutputPort());

	vtkSmartPointer<vtkActor> targetActor =
		vtkSmartPointer<vtkActor>::New();
	targetActor->SetMapper(targetMapper);
	targetActor->GetProperty()->SetColor(1, 0, 0);
	targetActor->GetProperty()->SetPointSize(3);

	vtkSmartPointer<vtkPolyDataMapper> solutionMapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	solutionMapper->SetInputConnection(transformFilter2->GetOutputPort());

	vtkSmartPointer<vtkActor> solutionActor =
		vtkSmartPointer<vtkActor>::New();
	solutionActor->SetMapper(solutionMapper);
	solutionActor->GetProperty()->SetColor(0, 0, 1);
	solutionActor->GetProperty()->SetPointSize(3);

	vtkSmartPointer<vtkRenderer> renderer =
		vtkSmartPointer<vtkRenderer>::New();
	renderer->SetBackground(1.0, 1.0, 1.0);

	vtkSmartPointer<vtkRenderWindow> renderWindow =
		vtkSmartPointer<vtkRenderWindow>::New();
	renderWindow->AddRenderer(renderer);
	renderer->AddActor(sourceActor);
	renderer->AddActor(targetActor);
	renderer->AddActor(solutionActor);

	vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	renderWindowInteractor->SetRenderWindow(renderWindow);

	renderWindow->SetSize(640, 480);
	renderWindow->Render();
	renderWindow->SetWindowName("PolyDataICP");
	renderWindow->Render();
	renderWindow->Render();
	renderWindowInteractor->Start();

	return EXIT_SUCCESS;
}

绿色源点集,红色目标点集,蓝色为配准后的点集
在这里插入图片描述

9.纹理映射

#include "vtkAutoInit.h" 
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingFreeType);

#include <vtkSmartPointer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkActor.h>
#include <vtkPolyDataMapper.h>
#include <vtkTransformTextureCoords.h>
#include <vtkTexture.h>
#include <vtkTextureMapToSphere.h>
#include <vtkTextureMapToCylinder.h>
#include <vtkBMPReader.h>
#include <vtkTexturedSphereSource.h>
#include <vtkXMLPolyDataReader.h>

//测试:../data/masonry.bmp ../data/cow.vtp
int main(int argc, char* argv[])
{
	vtkSmartPointer<vtkBMPReader> texReader =
		vtkSmartPointer<vtkBMPReader>::New();
	texReader->SetFileName("D:\\lqyWord\\VTK图形图像开发进阶随书代码\\Examples\\Chap06\\data\\masonry.bmp");

	//加载纹理图像
	vtkSmartPointer<vtkTexture> texture =
		vtkSmartPointer<vtkTexture>::New();
	texture->SetInputConnection(texReader->GetOutputPort());

	vtkSmartPointer<vtkXMLPolyDataReader> modelReader =
		vtkSmartPointer<vtkXMLPolyDataReader>::New();
	modelReader->SetFileName("D:\\lqyWord\\VTK图形图像开发进阶随书代码\\Examples\\Chap06\\data\\cow.vtp");

	//通过球面建立映射关系  将二维的纹理映射到三维的圆柱体表面
	vtkSmartPointer<vtkTextureMapToCylinder> texturemap =
		vtkSmartPointer<vtkTextureMapToCylinder>::New();
	texturemap->SetInputConnection(modelReader->GetOutputPort());

	vtkSmartPointer<vtkPolyDataMapper> mapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	mapper->SetInputConnection(texturemap->GetOutputPort());

	//渲染的收加上纹理
	vtkSmartPointer<vtkActor> actor =
		vtkSmartPointer<vtkActor>::New();
	actor->SetMapper(mapper);
	actor->SetTexture(texture);

	vtkSmartPointer<vtkRenderer> renderer =
		vtkSmartPointer<vtkRenderer>::New();
	renderer->AddActor(actor);
	renderer->SetBackground(1.0, 1.0, 1.0);

	vtkSmartPointer<vtkRenderWindow> renderWindow =
		vtkSmartPointer<vtkRenderWindow>::New();
	renderWindow->AddRenderer(renderer);

	vtkSmartPointer<vtkRenderWindowInteractor> renWinInteractor =
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	renWinInteractor->SetRenderWindow(renderWindow);

	renderWindow->SetSize(640, 480);
	renderWindow->Render();
	renderWindow->SetWindowName("TextureMap");
	renderWindow->Render();
	renderWindow->Render();
	renWinInteractor->Start();

	return EXIT_SUCCESS;
}
  • 20
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
VTK图形图像开发进阶》是一本有关VTK(Visualization Toolkit)图形图像开发的高级学习指南。VTK是一个强大的开源软件包,用于可视化和图形图像处理,被广泛应用于科学计算、医学领域和计算机图形学等领域。 该书主要向有一定VTK基础的开发人员,并帮助他们更深入地理解和应用VTK库。该书内容丰富,覆盖了VTK的各个方,包括基本概念、数据结构、可视化算法、二维和三维图像建模、交互式操作和图像处理等。 首先,书中介绍了VTK基本概念和架构,帮助读者建立对VTK的整体认识。接着,书中详细介绍了VTK的数据结构,包括点、线、、单元和网格等,以及如何使用VTK来操作和处理这些数据。 然后,书中深入探讨了VTK的可视化算法,包括几何变换、体绘制、表重建、等值提取等。这些算法的原理和实现细节都得到了详细的解释,帮助读者更好地掌握和应用这些算法。 此外,书中还介绍了VTK在二维和三维图像建模方的应用,包括纹理映射、体绘制、体数据可视化等。这些内容对于从事计算机图形学和医学图像处理的开发人员尤为重要。 最后,书中还介绍了VTK的交互式操作和图像处理的相关内容。这些包括用户交互、图像处理、表重建、体数据可视化等,帮助开发人员更好地应用VTK进行实际的图像处理和可视化。 总而言之,《VTK图形图像开发进阶》是一本全深入介绍VTK图形图像开发的书籍。通过学习该书,读者可以更好地理解VTK的原理和应用,并能够利用VTK进行更高级的图形图像开发工作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值