PCL vtk calculates the volume and surface area of point clouds

1. Calculation of volume and surface area in CC 

 2. Calculate the volume and surface area in PCL

 vtkMassProperties   to calculate volume and surface area, but it must be a triangulated model, not a polygonal model

If vtkTriangleFilter is another model, it will be converted to a triangulated model


// 计算点云的体积和表面积
// 输入的不能是点云,只能是三角化之后的点云模型
int  vtkCalc_Area_Volume(pcl::PolygonMesh  &model, float surface_area, float volume)
{
	vtkSmartPointer<vtkPLYReader> reader = vtkSmartPointer<vtkPLYReader>::New();

	// mesh  ply 格式的模型
	reader->SetFileName("C:\\Users\\Albert\\Desktop\\Halcon2PCL\\bundy.ply");
	reader->Update();

	// 三角化, vtkMassProperties 这个只能计算三角化的模型
	vtkSmartPointer<vtkTriangleFilter> triangle = vtkSmartPointer<vtkTriangleFilter>::New();
	triangle->SetInputData(reader->GetOutput());
	triangle->Update();
	//  vtkMassProperties  来计算体积和表面积
	vtkSmartPointer<vtkMassProperties>  ploy = vtkSmartPointer<vtkMassProperties>::New();
	ploy->SetInputData(triangle->GetOutput());
	ploy->Update();

	  volume = ploy->GetVolume();//  体积

	  // 计算三角形的面积 并求和
	  surface_area = ploy->GetSurfaceArea(); // 表面积

	  cout << "体积: "<< volume << endl;
	  cout << "面积: " << surface_area << endl;
	  double maxArea = ploy->GetMaxCellArea();//最大单元面积
	  double minArea = ploy->GetMinCellArea();//最小单元面积
	  cout << "单元最大面积:   " << maxArea << endl;
	  cout << "单元最小面积:   " << minArea << endl;
	return 0;
}

 

Three, vtk slice method to find the volume

// 平面切点云模型并求体积
int vtk_Plane_Cut_Model_Volume(std::string stlfile, double &spacing, double &vol)
{
	vtkSmartPointer<vtkPLYReader> reader = vtkSmartPointer<vtkPLYReader>::New();
	reader->SetFileName(stlfile.c_str());  // 读入模型
	reader->Update();

	vtkSmartPointer<vtkPolyData> polyData = vtkSmartPointer<vtkPolyData>::New();
	polyData = reader->GetOutput();


	// 设定平面模型
	vtkSmartPointer<vtkPlane> plane = vtkSmartPointer<vtkPlane>::New();
	//设置切割平面起点
	plane->SetOrigin(polyData->GetCenter());
	cout << "切割平面起点" << plane << endl;
	//设置切割方向为X方向,其实设置Y 方向也可以,只是这里的参数这设置的好的话会减少切的次数
	plane->SetNormal(1, 0, 0);


	// 拿到输入的最小\大坐标
	double min_bound[3], max_bound[3];
	min_bound[0] = polyData->GetBounds()[0];
	min_bound[1] = polyData->GetBounds()[2];
	min_bound[2] = polyData->GetBounds()[4];


	max_bound[0] = polyData->GetBounds()[1];
	max_bound[1] = polyData->GetBounds()[3];
	max_bound[2] = polyData->GetBounds()[5];


	// 拿到点云模型的质心
	double  center[3];
	center[0] = polyData->GetCenter()[0];
	center[1] = polyData->GetCenter()[1];
	center[2] = polyData->GetCenter()[2];
	std::cout << "  中心点:" << center[0] << "," << center[1] << "," << center[2] << endl;
	

	// 计算极值点到中心点的距离
	Eigen::Vector3d  min(min_bound);
	Eigen::Vector3d  max(max_bound);
	Eigen::Vector3d  center_v(center);
	double  dist_min_center  = (min - center_v).norm();
	double  dist_max_center = (max - center_v).norm();
	cout << "距离:      "<< dist_min_center<<"           "<< dist_max_center << endl;

	// 计算切片的次数
	int  number = (int)(dist_min_center + dist_max_center) / spacing;
	vtkSmartPointer<vtkCutter> cutter = vtkSmartPointer<vtkCutter>::New();
	 // 设置切割平面
	cutter->SetCutFunction(plane);
	// 输入切割的模型
	cutter->SetInputData(polyData);
	// 设置切片的范围
	cutter->GenerateValues(number,-dist_min_center, dist_max_center);
	cutter->Update();

	std::cout << "  切片个数:" << number << "     切片间距:     " << (dist_min_center + dist_max_center) / (number - 1) << endl;
	// 
	vtkSmartPointer<vtkStripper> cut_Stripper = vtkSmartPointer<vtkStripper>::New();
	cut_Stripper->SetInputConnection(cutter->GetOutputPort());
	cut_Stripper->Update();



	vtkSmartPointer<vtkPolyData> cutPolyData = vtkSmartPointer<vtkPolyData>::New();
	cutPolyData->SetPoints(cut_Stripper->GetOutput()->GetPoints());
	cutPolyData->SetPolys(cut_Stripper->GetOutput()->GetLines());

	//三角化
	vtkSmartPointer<vtkTriangleFilter> cutTriangles = vtkSmartPointer<vtkTriangleFilter>::New();
	cutTriangles->SetInputData(cutPolyData);
	cutTriangles->Update();


	//  计算体积和面积
	vtkSmartPointer<vtkMassProperties> mass = vtkSmartPointer<vtkMassProperties>::New();
	mass->SetInputData(cutTriangles->GetOutput());

	cout << mass->GetSurfaceArea() << endl;
	 vol = (dist_min_center + dist_max_center) / (number - 1)  * mass->GetSurfaceArea();

	return 0;
}

Guess you like

Origin blog.csdn.net/weixin_39354845/article/details/131511150