背景
上一篇绘制点云的博文中,使用的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;
}
带灰度纹理点云的三维显示