VTK 二维 外部轮廓线绘制

本文介绍了一种从三维模型中提取轮廓线的方法,并通过VTK库实现了具体流程。该方法首先将三维模型转换为图像,然后提取图像中的轮廓线,并通过变换使其与原始三维模型对齐。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

有时我们需求,三维的轮廓线

 

 可以用来做什么,自己想一下;

#include <vtkActor.h>
#include <vtkCamera.h>
#include <vtkContourFilter.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkTransform.h>
#include <vtkTransformPolyDataFilter.h>
#include <vtkVersion.h>
#include <vtkWindowToImageFilter.h>
#include <vtkXMLPolyDataReader.h>
#include <vtkSTLReader.h>
int main(int argc, char* argv[])
{
	vtkNew<vtkNamedColors> colors;

	vtkNew<vtkPolyData> data3d;

	//if (argc > 1)
	//{
	//	vtkNew<vtkXMLPolyDataReader> reader;
	//	reader->SetFileName(argv[1]);
	//	reader->Update();

	//	data3d = reader->GetOutput();
	//}
	//else
	//{
	//	vtkNew<vtkSphereSource> source;
	//	source->SetCenter(0.0, 0.0, 5.0);
	//	source->SetRadius(2.0);
	//	source->SetPhiResolution(20.);
	//	source->SetThetaResolution(20.);
	//	source->Update();

	//	data3d = source->GetOutput();
	//}

	std::string inputFilename = "E:/leftlumen.stl";

	vtkSmartPointer<vtkSTLReader> reader = vtkSmartPointer<vtkSTLReader>::New();
	reader->SetFileName(inputFilename.c_str());
	reader->Update();
 


	data3d->DeepCopy( reader->GetOutput());
	vtkSmartPointer<vtkTransform> pTransform = vtkSmartPointer<vtkTransform>::New();
	pTransform->RotateX(90);//x轴旋转90度
	//pTransform->RotateZ(180);//z轴旋转180度
	pTransform->Update();
	vtkSmartPointer<vtkTransformPolyDataFilter> pTransformPolyDataFilter = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
	pTransformPolyDataFilter->SetInputData(data3d);
	pTransformPolyDataFilter->SetTransform(pTransform);
	pTransformPolyDataFilter->Update();
 

	data3d->DeepCopy(pTransformPolyDataFilter->GetOutput());

	double bounds_data[6], center_data[3];
	data3d->GetBounds(bounds_data);
	data3d->GetCenter(center_data);


	// Black and white scene with the data in order to print the view
	vtkNew<vtkPolyDataMapper> mapper_data;
	mapper_data->SetInputData(data3d);

	vtkNew<vtkActor> actor_data;
	actor_data->SetMapper(mapper_data);
	actor_data->GetProperty()->SetColor(colors->GetColor3d("Black").GetData());

	vtkNew<vtkRenderer> tmp_rend;
	tmp_rend->SetBackground(colors->GetColor3d("WHite").GetData());

	tmp_rend->AddActor(actor_data);
	tmp_rend->ResetCamera();
	tmp_rend->GetActiveCamera()->SetParallelProjection(1);

	vtkNew<vtkRenderWindow> tmp_rW;
	tmp_rW->SetOffScreenRendering(1);
	tmp_rW->AddRenderer(tmp_rend);

	tmp_rW->Render();

	// Get a print of the window
	vtkNew<vtkWindowToImageFilter> windowToImageFilter;
	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();

	// Extract the silhouette corresponding to the black limit of the image
	vtkNew<vtkContourFilter> ContFilter;
	ContFilter->SetInputConnection(windowToImageFilter->GetOutputPort());
	ContFilter->SetValue(0, 255);
	ContFilter->Update();

	// Make the contour coincide with the data.
	vtkSmartPointer<vtkPolyData> 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);

	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]);

	// Rescale the contour so that it shares the same bounds as the
	// input data
	vtkNew<vtkTransform> transform1;
	transform1->Scale(ratio_x, ratio_y, 1.0);

	vtkNew<vtkTransformPolyDataFilter> tfilter1;
	tfilter1->SetInputData(contour);
	tfilter1->SetTransform(transform1);
	tfilter1->Update();

	contour = tfilter1->GetOutput();

	// Translate the contour so that it shares the same center as the
	// input data
	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];

	vtkNew<vtkTransform> transform2;
	transform2->Translate(trans_x, trans_y, trans_z);

	vtkNew<vtkTransformPolyDataFilter> tfilter2;
	tfilter2->SetInputData(contour);
	tfilter2->SetTransform(transform2);
	tfilter2->Update();

	contour = tfilter2->GetOutput();

	// Render the result : Input data + resulting silhouette

	// Updating the color of the data
	actor_data->GetProperty()->SetColor(
		colors->GetColor3d("MistyRose").GetData());

	// Create a mapper and actor of the silhouette
	vtkNew<vtkPolyDataMapper> mapper_contour;
	mapper_contour->SetInputData(contour);

	vtkNew<vtkActor> actor_contour;
	actor_contour->SetMapper(mapper_contour);
	actor_contour->GetProperty()->SetLineWidth(2.0);

	// 2 renderers and a render window
	vtkNew<vtkRenderer> renderer1;
	renderer1->AddActor(actor_data);

	vtkNew<vtkRenderer> renderer2;
	renderer2->AddActor(actor_contour);

	vtkNew<vtkRenderWindow> renderwindow;
	renderwindow->SetSize(400, 400);
	renderwindow->SetWindowName("ExternalContour");
	renderwindow->AddRenderer(renderer1);

	renderer1->SetViewport(0.0, 0.0, 0.5, 1.0);
	renderer1->SetBackground(colors->GetColor3d("DarkSlateGray").GetData());

	renderwindow->AddRenderer(renderer2);
	renderer2->SetViewport(0.5, 0.0, 1.0, 1.0);
	renderer2->SetBackground(colors->GetColor3d("MidnightBlue").GetData());

	vtkNew<vtkInteractorStyleTrackballCamera> style;
	vtkNew<vtkRenderWindowInteractor> iren;

	iren->SetRenderWindow(renderwindow);
	iren->SetInteractorStyle(style);

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

	return EXIT_SUCCESS;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

恋恋西风

up up up

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值