VTK9.2.0+QT5.14.0绘制三维显示背景

背景

上一篇绘制点云的博文中,使用的vtkCameraOrientationWidget来绘制的坐标轴,最近又学习到两种新的坐标轴绘制形式。

vtkOrientationMarkerWidget + vtkAxesActor

单独使用vtkAxesActor能够绘制出坐标轴,但是会随着鼠标操作旋转和平移时,在三维窗口中移动。搭配vtkOrientationMarkerWidget 的话能够在三维窗口的widget中,再放置一个小的widget,专门放置vtkAxesActor,可以达到停留在窗口左下角,只随着鼠标旋转的目的。

在头文件中定义vtkOrientationMarkerWidget 的对象

cpp 复制代码
	vtkSmartPointer<vtkOrientationMarkerWidget> markerOrientationWidget;
cpp 复制代码
void QVtkDemo2::testVtk3D()
{
	//创建着色器对象
	vtkSmartPointer<vtkRenderer> g_vtkRenderer = vtkSmartPointer<vtkRenderer>::New();
	//设置背景颜色
	g_vtkRenderer->SetBackground(.1, .2, .4);
	//创建point对象
	vtkSmartPointer<vtkPoints> g_vtkPoints = vtkSmartPointer<vtkPoints>::New();
	g_vtkPoints->SetNumberOfPoints(200);
	//创建cell对象
	vtkSmartPointer<vtkCellArray> g_vtkVertices = vtkSmartPointer<vtkCellArray>::New();
	vtkIdType id[1];
	//随机生成200个点
	float minz = VTK_FLOAT_MAX, maxz = VTK_FLOAT_MIN;
	for (int i = 0; i < 200; i++)
	{
		float x = rand() % 10;
		float y = rand() % 10;
		float z = rand() % 10;
		//提前申请了points的数量,使用set比insert速度更快
		g_vtkPoints->SetPoint(i, x, y, z);
		id[0] = i;
		g_vtkVertices->InsertNextCell(1, id);
		if (z > maxz)
		{
			maxz = z;
		}
		if (z < minz)
		{
			minz = z;
		}
	}
	//创建poly对象
	vtkSmartPointer<vtkPolyData> g_vtkpolyData = vtkSmartPointer<vtkPolyData>::New();
	g_vtkpolyData->SetPoints(g_vtkPoints);
	g_vtkpolyData->SetVerts(g_vtkVertices);

	vtkSmartPointer<vtkVertexGlyphFilter> g_glyphFilter = vtkSmartPointer<vtkVertexGlyphFilter>::New();
	g_glyphFilter->SetInputData(g_vtkpolyData);
	g_glyphFilter->Update();

	vtkSmartPointer<vtkElevationFilter> g_elevationFilter = vtkSmartPointer<vtkElevationFilter>::New();
	g_elevationFilter->SetInputConnection(g_glyphFilter->GetOutputPort());
	g_elevationFilter->SetLowPoint(0, 0, minz);
	g_elevationFilter->SetHighPoint(0, 0, maxz);

	//创建polyMapper
	vtkSmartPointer<vtkPolyDataMapper> g_vtkpointsMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
	g_vtkpointsMapper->SetInputConnection(g_elevationFilter->GetOutputPort());

	//创建Actor
	vtkSmartPointer<vtkActor> g_vtkpointsActor = vtkSmartPointer<vtkActor>::New();
	g_vtkpointsActor->SetMapper(g_vtkpointsMapper);
	g_vtkpointsActor->GetProperty()->SetPointSize(3);//设置点的大小
	g_vtkRenderer->AddActor(g_vtkpointsActor);

	vtkNew<vtkLookupTable> lut = vtkNew<vtkLookupTable>::vtkNew();
	lut->SetNumberOfTableValues(7);
	lut->SetHueRange(0.0, 0.67);
	lut->SetTableRange(minz, maxz);
	lut->Build();

	vtkNew<vtkScalarBarActor> colorBar = vtkNew<vtkScalarBarActor>::vtkNew();
	colorBar->SetLookupTable(lut);
	colorBar->SetNumberOfLabels(7);
	colorBar->SetBarRatio(0.10);
	colorBar->SetUnconstrainedFontSize(0.05);
	colorBar->SetMaximumHeightInPixels(100);
	colorBar->SetDisplayPosition(500, 80);
	g_vtkRenderer->AddActor2D(colorBar);

	//根据点云的包围盒,寻找最佳的显示视点位置
	g_vtkRenderer->ResetCamera();
	//ui中的绘制窗口添加定义的着色器
	ui.openGLWidget->renderWindow()->AddRenderer(g_vtkRenderer);
	//开始三维渲染
	ui.openGLWidget->renderWindow()->Render();

	//绘制坐标轴
	vtkSmartPointer<vtkAxesActor> axes_actor = vtkSmartPointer<vtkAxesActor>::New();
	axes_actor->SetPosition(0, 0, 0);
	axes_actor->SetTotalLength(50, 50, 50);
	//axes_actor->SetScale(5.0);
	//axes_actor->SetShaftType(0);
	//axes_actor->SetCylinderRadius(0.1);
	//axes_actor->SetConeRadius(0.3);
	//axes_actor->SetAxisLabels(1);
	//axes_actor->SetTipType(0); //坐标轴顶部为圆锥体
	axes_actor->GetXAxisShaftProperty()->SetColor(1, 0, 1);
	axes_actor->GetXAxisTipProperty()->SetColor(1, 0, 1);

	axes_actor->GetZAxisShaftProperty()->SetColor(1, 1, 0);
	axes_actor->GetZAxisTipProperty()->SetColor(1, 1, 0);

	markerOrientationWidget = vtkSmartPointer<vtkOrientationMarkerWidget>::New();
	markerOrientationWidget->SetOrientationMarker(axes_actor);
	markerOrientationWidget->SetInteractor(ui.openGLWidget->interactor());
	markerOrientationWidget->SetCurrentRenderer(g_vtkRenderer);
	markerOrientationWidget->SetDefaultRenderer(g_vtkRenderer);
	markerOrientationWidget->SetViewport(0.0, 0.0, 0.2, 0.2);
	markerOrientationWidget->SetEnabled(1);
	markerOrientationWidget->SetZoom(1.2);
	markerOrientationWidget->SetInteractive(false);

	return;
}

可以为三维空间添加一个网格底面,如图所示

只需要在上述代码中,创建一个新的Actor以及对应的Mapper和PlaneSource,然后向renderer中添加一个额外的Actor,并通过vtkCamera来设定我们当前的视角,提升观感

cpp 复制代码
void QVtkDemo2::testVtk3D()
{
	//创建着色器对象
	vtkSmartPointer<vtkRenderer> g_vtkRenderer = vtkSmartPointer<vtkRenderer>::New();
	//设置背景颜色
	g_vtkRenderer->SetBackground(.1, .2, .4);
	//创建point对象
	vtkSmartPointer<vtkPoints> g_vtkPoints = vtkSmartPointer<vtkPoints>::New();
	g_vtkPoints->SetNumberOfPoints(200);
	//创建cell对象
	vtkSmartPointer<vtkCellArray> g_vtkVertices = vtkSmartPointer<vtkCellArray>::New();
	vtkIdType id[1];
	//随机生成200个点
	float minz = VTK_FLOAT_MAX, maxz = VTK_FLOAT_MIN;
	for (int i = 0; i < 200; i++)
	{
		float x = rand() % 10;
		float y = rand() % 10;
		float z = rand() % 10;
		//提前申请了points的数量,使用set比insert速度更快
		g_vtkPoints->SetPoint(i, x, y, z);
		id[0] = i;
		g_vtkVertices->InsertNextCell(1, id);
		if (z > maxz)
		{
			maxz = z;
		}
		if (z < minz)
		{
			minz = z;
		}
	}
	//创建poly对象
	vtkSmartPointer<vtkPolyData> g_vtkpolyData = vtkSmartPointer<vtkPolyData>::New();
	g_vtkpolyData->SetPoints(g_vtkPoints);
	g_vtkpolyData->SetVerts(g_vtkVertices);

	vtkSmartPointer<vtkVertexGlyphFilter> g_glyphFilter = vtkSmartPointer<vtkVertexGlyphFilter>::New();
	g_glyphFilter->SetInputData(g_vtkpolyData);
	g_glyphFilter->Update();

	vtkSmartPointer<vtkElevationFilter> g_elevationFilter = vtkSmartPointer<vtkElevationFilter>::New();
	g_elevationFilter->SetInputConnection(g_glyphFilter->GetOutputPort());
	g_elevationFilter->SetLowPoint(0, 0, minz);
	g_elevationFilter->SetHighPoint(0, 0, maxz);

	//创建polyMapper
	vtkSmartPointer<vtkPolyDataMapper> g_vtkpointsMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
	g_vtkpointsMapper->SetInputConnection(g_elevationFilter->GetOutputPort());

	//创建Actor
	vtkSmartPointer<vtkActor> g_vtkpointsActor = vtkSmartPointer<vtkActor>::New();
	g_vtkpointsActor->SetMapper(g_vtkpointsMapper);
	g_vtkpointsActor->GetProperty()->SetPointSize(3);//设置点的大小
	g_vtkRenderer->AddActor(g_vtkpointsActor);

	vtkNew<vtkLookupTable> lut = vtkNew<vtkLookupTable>::vtkNew();
	lut->SetNumberOfTableValues(7);
	lut->SetHueRange(0.0, 0.67);
	lut->SetTableRange(minz, maxz);
	lut->Build();

	vtkNew<vtkScalarBarActor> colorBar = vtkNew<vtkScalarBarActor>::vtkNew();
	colorBar->SetLookupTable(lut);
	colorBar->SetNumberOfLabels(7);
	colorBar->SetBarRatio(0.10);
	colorBar->SetUnconstrainedFontSize(0.05);
	colorBar->SetMaximumHeightInPixels(100);
	colorBar->SetDisplayPosition(500, 80);
	g_vtkRenderer->AddActor2D(colorBar);

	//定义一个平面
	vtkSmartPointer<vtkPlaneSource> mReferencePlaneSource;
	vtkSmartPointer<vtkPolyDataMapper> mReferencePlaneMapper;
	vtkSmartPointer<vtkActor>  mReferencePlaneActor;

	//添加平面
	mReferencePlaneSource = vtkSmartPointer<vtkPlaneSource>::New();
	mReferencePlaneMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
	mReferencePlaneActor = vtkSmartPointer<vtkActor>::New();
	mReferencePlaneSource->SetXResolution(20);
	mReferencePlaneSource->SetYResolution(20);
	mReferencePlaneSource->SetOrigin(-10.0, -10.0, -6.0); //根据视野范围来调整
	mReferencePlaneSource->SetPoint1(10.0, -10.0, -6.0);
	mReferencePlaneSource->SetPoint2(-10.0, 10.0, -6.0);
	mReferencePlaneMapper->SetInputConnection(mReferencePlaneSource->GetOutputPort());
	mReferencePlaneActor->SetMapper(mReferencePlaneMapper);
	mReferencePlaneActor->GetProperty()->SetRepresentationToWireframe();
	mReferencePlaneActor->GetProperty()->SetColor(0.5, 1.0, 1.0);
	mReferencePlaneActor->SetVisibility(true);
	g_vtkRenderer->AddActor(mReferencePlaneActor);
	vtkSmartPointer<vtkCamera> _vtk_icamera = vtkSmartPointer<vtkCamera>::New();
	_vtk_icamera->SetPosition(50.0, 50.0, 30.0);
	_vtk_icamera->SetFocalPoint(0.0, 0.0, 0.0);
	_vtk_icamera->SetViewUp(0.0, 0.0, 1.0);
	_vtk_icamera->ComputeViewPlaneNormal();
	if (_vtk_icamera)
	{
		g_vtkRenderer->SetActiveCamera(_vtk_icamera);
		g_vtkRenderer->ResetCamera();
	}

	//根据点云的包围盒,寻找最佳的显示视点位置
	//g_vtkRenderer->ResetCamera();
	//ui中的绘制窗口添加定义的着色器
	ui.openGLWidget->renderWindow()->AddRenderer(g_vtkRenderer);
	//开始三维渲染
	ui.openGLWidget->renderWindow()->Render();

	//绘制坐标轴
	vtkSmartPointer<vtkAxesActor> axes_actor = vtkSmartPointer<vtkAxesActor>::New();
	axes_actor->SetPosition(0, 0, 0);
	axes_actor->SetTotalLength(50, 50, 50);
	//axes_actor->SetScale(5.0);
	//axes_actor->SetShaftType(0);
	//axes_actor->SetCylinderRadius(0.1);
	//axes_actor->SetConeRadius(0.3);
	//axes_actor->SetAxisLabels(1);
	//axes_actor->SetTipType(0); //坐标轴顶部为圆锥体
	axes_actor->GetXAxisShaftProperty()->SetColor(1, 0, 1);
	axes_actor->GetXAxisTipProperty()->SetColor(1, 0, 1);

	axes_actor->GetZAxisShaftProperty()->SetColor(1, 1, 0);
	axes_actor->GetZAxisTipProperty()->SetColor(1, 1, 0);

	markerOrientationWidget = vtkSmartPointer<vtkOrientationMarkerWidget>::New();
	markerOrientationWidget->SetOrientationMarker(axes_actor);
	markerOrientationWidget->SetInteractor(ui.openGLWidget->interactor());
	markerOrientationWidget->SetCurrentRenderer(g_vtkRenderer);
	markerOrientationWidget->SetDefaultRenderer(g_vtkRenderer);
	markerOrientationWidget->SetViewport(0.0, 0.0, 0.2, 0.2);
	markerOrientationWidget->SetEnabled(1);
	markerOrientationWidget->SetZoom(1.2);
	markerOrientationWidget->SetInteractive(false);

	return;
}

vtkCubeAxesActor

下图是matlab的三维显示,想要绘制网格状的坐标轴,并标注坐标,VTK提供了vtkCubeAxesActor

vtkCubeAxesActor作为一类Actor, 因此,我们只需要定义好vtkCubeAxesActor的参数,然后添加到Renderer中即可

cpp 复制代码
void QVtkDemo2::testVtk3D()
{
	//创建着色器对象
	vtkSmartPointer<vtkRenderer> g_vtkRenderer = vtkSmartPointer<vtkRenderer>::New();
	//设置背景颜色
	g_vtkRenderer->SetBackground(.1, .2, .4);
	//创建point对象
	vtkSmartPointer<vtkPoints> g_vtkPoints = vtkSmartPointer<vtkPoints>::New();
	g_vtkPoints->SetNumberOfPoints(200);
	//创建cell对象
	vtkSmartPointer<vtkCellArray> g_vtkVertices = vtkSmartPointer<vtkCellArray>::New();
	vtkIdType id[1];
	//随机生成200个点
	float minz = VTK_FLOAT_MAX, maxz = VTK_FLOAT_MIN;
	for (int i = 0; i < 200; i++)
	{
		float x = rand() % 10;
		float y = rand() % 10;
		float z = rand() % 10;
		//提前申请了points的数量,使用set比insert速度更快
		g_vtkPoints->SetPoint(i, x, y, z);
		id[0] = i;
		g_vtkVertices->InsertNextCell(1, id);
		if (z > maxz)
		{
			maxz = z;
		}
		if (z < minz)
		{
			minz = z;
		}
	}
	//创建poly对象
	vtkSmartPointer<vtkPolyData> g_vtkpolyData = vtkSmartPointer<vtkPolyData>::New();
	g_vtkpolyData->SetPoints(g_vtkPoints);
	g_vtkpolyData->SetVerts(g_vtkVertices);

	vtkSmartPointer<vtkVertexGlyphFilter> g_glyphFilter = vtkSmartPointer<vtkVertexGlyphFilter>::New();
	g_glyphFilter->SetInputData(g_vtkpolyData);
	g_glyphFilter->Update();

	vtkSmartPointer<vtkElevationFilter> g_elevationFilter = vtkSmartPointer<vtkElevationFilter>::New();
	g_elevationFilter->SetInputConnection(g_glyphFilter->GetOutputPort());
	g_elevationFilter->SetLowPoint(0, 0, minz);
	g_elevationFilter->SetHighPoint(0, 0, maxz);

	//创建polyMapper
	vtkSmartPointer<vtkPolyDataMapper> g_vtkpointsMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
	g_vtkpointsMapper->SetInputConnection(g_elevationFilter->GetOutputPort());

	//创建Actor
	vtkSmartPointer<vtkActor> g_vtkpointsActor = vtkSmartPointer<vtkActor>::New();
	g_vtkpointsActor->SetMapper(g_vtkpointsMapper);
	g_vtkpointsActor->GetProperty()->SetPointSize(3);//设置点的大小
	g_vtkRenderer->AddActor(g_vtkpointsActor);

	vtkNew<vtkLookupTable> lut = vtkNew<vtkLookupTable>::vtkNew();
	lut->SetNumberOfTableValues(7);
	lut->SetHueRange(0.0, 0.67);
	lut->SetTableRange(minz, maxz);
	lut->Build();

	vtkNew<vtkScalarBarActor> colorBar = vtkNew<vtkScalarBarActor>::vtkNew();
	colorBar->SetLookupTable(lut);
	colorBar->SetNumberOfLabels(7);
	colorBar->SetBarRatio(0.10);
	colorBar->SetUnconstrainedFontSize(0.05);
	colorBar->SetMaximumHeightInPixels(100);
	colorBar->SetDisplayPosition(500, 80);
	g_vtkRenderer->AddActor2D(colorBar);

	//vtkCubeAxes
	vtkSmartPointer<vtkCubeAxesActor> cubeAxes = vtkSmartPointer<vtkCubeAxesActor>::New();
	auto activeCamera = g_vtkRenderer->GetActiveCamera();
	cubeAxes->SetCamera(activeCamera);

	double bounds[6] = { 0.0, 10.0, 0.0, 10.0, 0.0, 10.0 };
	cubeAxes->SetBounds(bounds);

	cubeAxes->SetXTitle("X-Axis");
	cubeAxes->SetYTitle("Y-Axis");
	cubeAxes->SetZTitle("Z-Axis");

	cubeAxes->GetTitleTextProperty(0)->SetColor(1.0, 0.0, 1.0);
	cubeAxes->GetLabelTextProperty(0)->SetColor(1.0, 0.0, 1.0);

	cubeAxes->GetTitleTextProperty(1)->SetColor(0.0, 1.0, 0.0);
	cubeAxes->GetLabelTextProperty(1)->SetColor(0.0, 1.0, 0.0);

	cubeAxes->GetTitleTextProperty(2)->SetColor(1.0, 1.0, 0.0);
	cubeAxes->GetLabelTextProperty(2)->SetColor(1.0, 1.0, 0.0);

	cubeAxes->SetVisibility(1);

	cubeAxes->SetXAxisRange(0, 10.0);
	cubeAxes->SetYAxisRange(0.0, 10.0);
	cubeAxes->SetZAxisRange(0.0, 10.0);

	cubeAxes->DrawXGridlinesOn();
	cubeAxes->DrawYGridlinesOn();
	cubeAxes->DrawZGridlinesOn();
	cubeAxes->SetDrawXInnerGridlines(0);
	cubeAxes->SetDrawYInnerGridlines(0);
	cubeAxes->SetDrawZInnerGridlines(0);

	cubeAxes->XAxisMinorTickVisibilityOff();
	cubeAxes->YAxisMinorTickVisibilityOff();
	cubeAxes->ZAxisMinorTickVisibilityOff();

	cubeAxes->SetScreenSize(30.0);
	cubeAxes->SetLabelOffset(20.0);

	cubeAxes->SetGridLineLocation(2);
	cubeAxes->SetTickLocation(1);
	cubeAxes->SetFlyMode(0);
	g_vtkRenderer->AddActor(cubeAxes);


	vtkSmartPointer<vtkCamera> _vtk_icamera = vtkSmartPointer<vtkCamera>::New();
	_vtk_icamera->SetPosition(50.0, 50.0, 30.0);
	_vtk_icamera->SetFocalPoint(0.0, 0.0, 0.0);
	_vtk_icamera->SetViewUp(0.0, 0.0, 1.0);
	_vtk_icamera->ComputeViewPlaneNormal();
	if (_vtk_icamera)
	{
		g_vtkRenderer->SetActiveCamera(_vtk_icamera);
		g_vtkRenderer->ResetCamera();
	}

	//根据点云的包围盒,寻找最佳的显示视点位置
	//g_vtkRenderer->ResetCamera();
	//ui中的绘制窗口添加定义的着色器
	ui.openGLWidget->renderWindow()->AddRenderer(g_vtkRenderer);
	//开始三维渲染
	ui.openGLWidget->renderWindow()->Render();

	//绘制坐标轴
	vtkSmartPointer<vtkAxesActor> axes_actor = vtkSmartPointer<vtkAxesActor>::New();
	axes_actor->SetPosition(0, 0, 0);
	axes_actor->SetTotalLength(50, 50, 50);
	//axes_actor->SetScale(5.0);
	//axes_actor->SetShaftType(0);
	//axes_actor->SetCylinderRadius(0.1);
	//axes_actor->SetConeRadius(0.3);
	//axes_actor->SetAxisLabels(1);
	//axes_actor->SetTipType(0); //坐标轴顶部为圆锥体
	axes_actor->GetXAxisShaftProperty()->SetColor(1, 0, 1);
	axes_actor->GetXAxisTipProperty()->SetColor(1, 0, 1);

	axes_actor->GetZAxisShaftProperty()->SetColor(1, 1, 0);
	axes_actor->GetZAxisTipProperty()->SetColor(1, 1, 0);

	markerOrientationWidget = vtkSmartPointer<vtkOrientationMarkerWidget>::New();
	markerOrientationWidget->SetOrientationMarker(axes_actor);
	markerOrientationWidget->SetInteractor(ui.openGLWidget->interactor());
	markerOrientationWidget->SetCurrentRenderer(g_vtkRenderer);
	markerOrientationWidget->SetDefaultRenderer(g_vtkRenderer);
	markerOrientationWidget->SetViewport(0.0, 0.0, 0.2, 0.2);
	markerOrientationWidget->SetEnabled(1);
	markerOrientationWidget->SetZoom(1.2);
	markerOrientationWidget->SetInteractive(false);

	
	return;
}

带灰度纹理点云的三维显示

相关推荐
XiaoLeisj2 小时前
【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题
java·开发语言·java-ee
励志成为嵌入式工程师3 小时前
c语言简单编程练习9
c语言·开发语言·算法·vim
捕鲸叉3 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer3 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法
Peter_chq3 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
记录成长java5 小时前
ServletContext,Cookie,HttpSession的使用
java·开发语言·servlet
前端青山5 小时前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
睡觉谁叫~~~5 小时前
一文解秘Rust如何与Java互操作
java·开发语言·后端·rust
音徽编程5 小时前
Rust异步运行时框架tokio保姆级教程
开发语言·网络·rust
观音山保我别报错5 小时前
C语言扫雷小游戏
c语言·开发语言·算法