其原理是将源对象数据设置成纯黑色,背景设置成纯白色,然后离屏渲染出一副黑白图像,在这幅图像上提取标量值为255的等值线,最终生成源对象当前视图的轮廓对象
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
vtkSmartPointer data3d;
//创建程序源对象——球体
vtkSmartPointer source = vtkSmartPointer::New();
//设置球体的中心坐标
source->SetCenter(0.0, 0.0, 5.0);
//设置球体的半径
source->SetRadius(2.0);
//设置球体纬度方向上的点数
source->SetPhiResolution(20.);
//设置球体经度方向上的点数
source->SetThetaResolution(20.);
//手动触发流水线,执行生成源对象操作
source->Update();
//从程序源对象中获取多边形数据集polyData
data3d = source->GetOutput();
double bounds_data[6], center_data[3];
//获取源对象的边界[Xmin,Xmax,Ymin,Ymax,Zmin,Zmax]
data3d->GetBounds(bounds_data);
//获取源对象的中心点[Xmin,Xmax,Ymin,Ymax,Zmin,Zmax]
data3d->GetCenter(center_data);
//将几何对象设置到映射器中
vtkSmartPointer mapper_data = vtkSmartPointer::New();
mapper_data->SetInputData(data3d);
vtkSmartPointer actor_data = vtkSmartPointer::New();
actor_data->SetMapper(mapper_data);
//将待渲染的演员对象设置成黑色
actor_data->GetProperty()->SetColor(0,0,0);
vtkSmartPointer tmp_rend = vtkSmartPointer::New();
//将渲染背景渲染成白色
tmp_rend->SetBackground(1,1,1);
tmp_rend->AddActor(actor_data);
tmp_rend->ResetCamera();
//开启平行光投影
tmp_rend->GetActiveCamera()->SetParallelProjection(1);
vtkSmartPointer tmp_rW = vtkSmartPointer::New();
//设置成离屏渲染
tmp_rW->SetOffScreenRendering( 1 );
tmp_rW->AddRenderer(tmp_rend);
tmp_rW->Render();
vtkSmartPointer windowToImageFilter = vtkSmartPointer::New();
//获取离屏渲染的窗口图像
windowToImageFilter->SetInput(tmp_rW);
#if VTK_MAJOR_VERSION >= 8 || VTK_MAJOR_VERSION == 8 && VTK_MINOR_VERSION >= 90
windowToImageFilter->SetScale(2); // image quality
#else
//设置当前渲染窗口的方法倍数
windowToImageFilter->SetMagnification(2); //image quality
#endif
//手动触发流水线
windowToImageFilter->Update();
// 提取图像黑白交界的轮廓
vtkSmartPointer ContFilter = vtkSmartPointer::New();
ContFilter->SetInputConnection(windowToImageFilter->GetOutputPort());
//提取标量值为255的轮廓线,0表示第1条轮廓
ContFilter->SetValue(0,255);
ContFilter->Update();
//获取轮廓数据集——POLYDATA
vtkSmartPointer contour = ContFilter->GetOutput();
double bounds_contour[6], center_contour[3];
double trans_x=0., trans_y=0., trans_z=0., ratio_x=0., ratio_y=0.;
contour->GetBounds(bounds_contour);
//源对象XY方向的边界与轮廓对象XY方向边界的比值
ratio_x = (bounds_data[1]-bounds_data[0])/(bounds_contour[1]-bounds_contour[0]);
ratio_y = (bounds_data[3]-bounds_data[2])/(bounds_contour[3]-bounds_contour[2]);
//调整边界对象的比例以适应源对象的边界
vtkSmartPointertransform1 = vtkSmartPointer::New();
transform1->Scale( ratio_x, ratio_y, 1.);
vtkSmartPointer tfilter1 = vtkSmartPointer::New();
tfilter1->SetInputData(contour);
tfilter1->SetTransform(transform1);
tfilter1->Update();
contour = tfilter1->GetOutput();
//平移轮廓对象以对齐程序源对象的中心
contour->GetCenter(center_contour);
trans_x = center_data[0]-center_contour[0];
trans_y = center_data[1]-center_contour[1];
trans_z = center_data[2]-center_contour[2];
vtkSmartPointer transform2 = vtkSmartPointer::New();
transform2->Translate( trans_x, trans_y, trans_z);
vtkSmartPointer tfilter2 = vtkSmartPointer::New();
tfilter2->SetInputData(contour);
tfilter2->SetTransform(transform2);
tfilter2->Update();
contour = tfilter2->GetOutput();
// 分两个viewport分别渲染程序源对象和轮廓对象
// 重新设置程序源对象的颜色
actor_data->GetProperty()->SetColor(0.9,0.9,0.8);
// Create a mapper and actor of the silhouette
vtkSmartPointer mapper_contour = vtkSmartPointer::New();
mapper_contour->SetInputData(contour);
vtkSmartPointer actor_contour = vtkSmartPointer::New();
actor_contour->SetMapper(mapper_contour);
actor_contour->GetProperty()->SetLineWidth(2.);
// 2 renderers and a render window
vtkSmartPointer renderer1 = vtkSmartPointer::New();
renderer1->AddActor(actor_data);
vtkSmartPointer renderer2 = vtkSmartPointer::New();
renderer2->AddActor(actor_contour);
vtkSmartPointer renderwindow = vtkSmartPointer::New();
renderwindow->SetSize(400,400);
renderwindow->AddRenderer(renderer1);
renderer1->SetViewport(0., 0., 0.5, 1.);
renderwindow->AddRenderer(renderer2);
renderer2->SetViewport(0.5, 0., 1., 1.);
vtkSmartPointer style = vtkSmartPointer::New();
vtkSmartPointer iren = vtkSmartPointer::New();
iren->SetRenderWindow( renderwindow);
iren->SetInteractorStyle(style);
renderwindow->Render();
iren->Start();
return EXIT_SUCCESS;
}
其大致流程如下
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
vtkSmartPointer colors = vtkSmartPointer::New();
//读取STL文件以创建读源对象
const char* inputFilename = "C:\\Users\\qiang.shen\\Desktop\\IronData\\XZW.stl";
vtkSmartPointer reader = vtkSmartPointer::New();
reader->SetFileName(inputFilename);
//手动触发流水线,否则reader里面没有值
reader->Update();
//获取读源对象的轮廓[Xmin,Xmax, Ymin, Ymax, Zmin, Zmax]
double bounds[6];
reader->GetOutput()->GetBounds(bounds);
std::cout << "Bounds: "
<< bounds[0] << ", " << bounds[1] << " "
<< bounds[2] << ", " << bounds[3] << " "
<< bounds[4] << ", " << bounds[5] << std::endl;
//创建一个平面程序源对象
vtkSmartPointer plane = vtkSmartPointer::New();
//平面对象是由点和法向量定义的,这里设置平面经过的源对象的中心点坐标
plane->SetOrigin((bounds[1] + bounds[0]) / 2.0,
(bounds[3] + bounds[2]) / 2.0,
(bounds[5] + bounds[4]) / 2.0);
//设置平面对象的法向量;
plane->SetNormal(0,0,1);
//创建一个double型的标量数组
vtkSmartPointer scalars = vtkSmartPointer::New();
//获取源对象的点数
int numberOfPoints = reader->GetOutput()->GetNumberOfPoints();
//分配numberOfPoints属性数据的空间
scalars->SetNumberOfTuples(numberOfPoints);
//获取源对象的点集
vtkSmartPointer pts = reader->GetOutput()->GetPoints();
std::vector aa;
for (int i = 0; i < numberOfPoints; ++i)
{
double point[3];
//获取点的坐标
pts->GetPoint(i, point);
//EvaluateFunction 评估点的平面方程(本质是求点point与平面中心点连接的向量在平面法向量上的投影)
double evaValue = plane->EvaluateFunction(point);
aa.push_back(evaValue);
scalars->SetTuple1(i, evaValue);
}
reader->GetOutput()->GetPointData()->SetScalars(scalars);
auto range = reader->GetOutput()->GetPointData()->GetScalars()->GetRange();
// Create cutter
vtkSmartPointer cutter = vtkSmartPointer::New();
cutter->SetInputConnection(reader->GetOutputPort());
cutter->ComputeScalarsOff();
cutter->ComputeNormalsOff();
int numberOfCuts = 10;
//生成给定的标量值
cutter->GenerateValues(numberOfCuts, 0.99 * range[0], 0.99 * range[1]);//设置需要抽取的标量值
vtkSmartPointer cutterMapper = vtkSmartPointer::New();
cutterMapper->SetInputConnection( cutter->GetOutputPort());
//避免点的属性值被当做颜色来处理了
cutterMapper->ScalarVisibilityOff();
// Create cut actor
vtkSmartPointer cutterActor = vtkSmartPointer::New();
cutterActor->GetProperty()->SetColor(colors->GetColor3d("Banana").GetData());
cutterActor->GetProperty()->SetLineWidth(2);
cutterActor->SetMapper(cutterMapper);
// Create model actor
vtkSmartPointer modelMapper = vtkSmartPointer::New();
modelMapper->SetInputConnection( reader->GetOutputPort());
modelMapper->ScalarVisibilityOff();
vtkSmartPointer modelActor = vtkSmartPointer::New();
modelActor->GetProperty()->SetColor(colors->GetColor3d("Flesh").GetData());
modelActor->SetMapper(modelMapper);
// Create renderers and add actors of plane and model
vtkSmartPointer renderer = vtkSmartPointer::New();
renderer->AddActor(cutterActor);
renderer->AddActor(modelActor);
// Add renderer to renderwindow and render
vtkSmartPointer renderWindow = vtkSmartPointer::New();
renderWindow->AddRenderer(renderer);
renderWindow->SetSize(600, 600);
vtkSmartPointer interactor = vtkSmartPointer::New();
interactor->SetRenderWindow(renderWindow);
renderer->SetBackground(colors->GetColor3d("Burlywood").GetData());
renderer->GetActiveCamera()->SetPosition(0, -1, 0);
renderer->GetActiveCamera()->SetFocalPoint(0, 0, 0);
renderer->GetActiveCamera()->SetViewUp(0, 0, 1);
renderer->GetActiveCamera()->Azimuth(30);
renderer->GetActiveCamera()->Elevation(30);
renderer->ResetCamera();
renderWindow->Render();
interactor->Start();
return EXIT_SUCCESS;
}