背景
上一篇绘制点云的博文中,使用的vtkCameraOrientationWidget来绘制的坐标轴,最近又学习到两种新的坐标轴绘制形式。
vtkOrientationMarkerWidget + vtkAxesActor
单独使用vtkAxesActor能够绘制出坐标轴,但是会随着鼠标操作旋转和平移时,在三维窗口中移动。搭配vtkOrientationMarkerWidget 的话能够在三维窗口的widget中,再放置一个小的widget,专门放置vtkAxesActor,可以达到停留在窗口左下角,只随着鼠标旋转的目的。
在头文件中定义vtkOrientationMarkerWidget 的对象
vtkSmartPointer<vtkOrientationMarkerWidget> markerOrientationWidget;
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);//创建polyMappervtkSmartPointer<vtkPolyDataMapper> g_vtkpointsMapper = vtkSmartPointer<vtkPolyDataMapper>::New();g_vtkpointsMapper->SetInputConnection(g_elevationFilter->GetOutputPort());//创建ActorvtkSmartPointer<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来设定我们当前的视角,提升观感
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);//创建polyMappervtkSmartPointer<vtkPolyDataMapper> g_vtkpointsMapper = vtkSmartPointer<vtkPolyDataMapper>::New();g_vtkpointsMapper->SetInputConnection(g_elevationFilter->GetOutputPort());//创建ActorvtkSmartPointer<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中即可
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);//创建polyMappervtkSmartPointer<vtkPolyDataMapper> g_vtkpointsMapper = vtkSmartPointer<vtkPolyDataMapper>::New();g_vtkpointsMapper->SetInputConnection(g_elevationFilter->GetOutputPort());//创建ActorvtkSmartPointer<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);//vtkCubeAxesvtkSmartPointer<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;
}
带灰度纹理点云的三维显示