VTK学习笔记(二十一)vtk裁剪求截面面积

1、代码

#pragma once

#include <vtkActor.h>
#include <vtkCamera.h>
#include <vtkClipPolyData.h>
#include <vtkDataSetMapper.h>
#include <vtkFeatureEdges.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkPlane.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 <vtkStripper.h>
#include <vtkXMLPolyDataReader.h>
#include <vtkMassProperties.h>
#include < vtkTriangleFilter.h>
// Readers
#include <vtkBYUReader.h>
#include <vtkOBJReader.h>
#include <vtkPLYReader.h>
#include <vtkPolyDataReader.h>
#include <vtkSTLReader.h>
#include <vtkXMLPolyDataReader.h>
namespace {
    
    
	vtkSmartPointer<vtkPolyData> ReadPolyData(std::string const& fileName)
	{
    
    
		vtkSmartPointer<vtkPolyData> polyData;
		std::string extension = "";
		if (fileName.find_last_of(".") != std::string::npos){
    
    
			extension = fileName.substr(fileName.find_last_of("."));
		}
		// Make the extension lowercase
		std::transform(extension.begin(), extension.end(), extension.begin(),::tolower);
		if (extension == ".ply"){
    
    
			vtkNew<vtkPLYReader> reader;
			reader->SetFileName(fileName.c_str());
			reader->Update();
			polyData = reader->GetOutput();
		}
		else if (extension == ".vtp"){
    
    
			vtkNew<vtkXMLPolyDataReader> reader;
			reader->SetFileName(fileName.c_str());
			reader->Update();
			polyData = reader->GetOutput();
		}
		else if (extension == ".obj"){
    
    
			vtkNew<vtkOBJReader> reader;
			reader->SetFileName(fileName.c_str());
			reader->Update();
			polyData = reader->GetOutput();
		}
		else if (extension == ".stl"){
    
    
			vtkNew<vtkSTLReader> reader;
			reader->SetFileName(fileName.c_str());
			reader->Update();
			polyData = reader->GetOutput();
		}
		else if (extension == ".vtk"){
    
    
			vtkNew<vtkPolyDataReader> reader;
			reader->SetFileName(fileName.c_str());
			reader->Update();
			polyData = reader->GetOutput();
		}
		else if (extension == ".g"){
    
    
			vtkNew<vtkBYUReader> reader;
			reader->SetGeometryFileName(fileName.c_str());
			reader->Update();
			polyData = reader->GetOutput();
		}
		else{
    
    
			// Return a polydata sphere if the extension is unknown.
			vtkNew<vtkSphereSource> source;
			source->SetThetaResolution(20);
			source->SetPhiResolution(11);
			source->Update();
			polyData = source->GetOutput();
		}
		return polyData;
	}
} // namespace
class Test_Clip_cow {
    
    
public:
	static void Test() {
    
    
		vtkNew<vtkNamedColors> colors;
		auto backgroundColor = colors->GetColor3d("steel_blue");
		auto boundaryColor = colors->GetColor3d("banana");
		auto clipColor = colors->GetColor3d("tomato");
		// PolyData to process
		auto polyData = ReadPolyData("cow.g");

		vtkNew<vtkPlane> plane;
		plane->SetOrigin(polyData->GetCenter());
		plane->SetNormal(1.0, -1.0, -1.0);

		vtkNew<vtkClipPolyData> clipper;
		clipper->SetInputData(polyData);
		clipper->SetClipFunction(plane);
		clipper->GenerateClipScalarsOn();
		clipper->GenerateClippedOutputOn();
		clipper->SetValue(0.5);
		clipper->Update();

		polyData = clipper->GetOutput();

		vtkNew<vtkDataSetMapper> clipMapper;
		clipMapper->SetInputData(polyData);
		clipMapper->ScalarVisibilityOff();

		vtkNew<vtkActor> clipActor;
		clipActor->SetMapper(clipMapper);
		clipActor->GetProperty()->SetDiffuseColor(clipColor.GetData());
		clipActor->GetProperty()->SetInterpolationToFlat();
		clipActor->GetProperty()->EdgeVisibilityOn();

		// Now extract feature edges
		vtkNew<vtkFeatureEdges> boundaryEdges;
		boundaryEdges->SetInputData(polyData);
		boundaryEdges->BoundaryEdgesOn();
		boundaryEdges->FeatureEdgesOff();
		boundaryEdges->NonManifoldEdgesOff();
		boundaryEdges->ManifoldEdgesOff();

		vtkNew<vtkStripper> boundaryStrips;
		boundaryStrips->SetInputConnection(boundaryEdges->GetOutputPort());
		boundaryStrips->Update();

		// Change the polylines into polygons
		vtkNew<vtkPolyData> boundaryPoly;
		boundaryPoly->SetPoints(boundaryStrips->GetOutput()->GetPoints());
		boundaryPoly->SetPolys(boundaryStrips->GetOutput()->GetLines());

		vtkNew<vtkPolyDataMapper> boundaryMapper;
		boundaryMapper->SetInputData(boundaryPoly);

		vtkNew<vtkActor> boundaryActor;
		boundaryActor->SetMapper(boundaryMapper);
		boundaryActor->GetProperty()->SetDiffuseColor(boundaryColor.GetData());

		vtkNew<vtkTriangleFilter> triFilter;
		triFilter->SetInputData(boundaryPoly);
		triFilter->Update();

		vtkSmartPointer<vtkMassProperties> massProp =
			vtkSmartPointer<vtkMassProperties>::New();
		massProp->SetInputData(triFilter->GetOutput());
		float vol = massProp->GetVolume();
		float area = massProp->GetSurfaceArea();
		std::cout << "Surface Area:" << area << std::endl;

		vtkNew<vtkPolyDataMapper> restMapper;
		restMapper->SetInputConnection(clipper->GetClippedOutputPort());
		restMapper->ScalarVisibilityOff();
		vtkNew<vtkActor> restActor;
		restActor->SetMapper(restMapper);
		restActor->GetProperty()->SetRepresentationToWireframe();

		// Create graphics stuff
		vtkNew<vtkRenderer> renderer;
		renderer->SetBackground(backgroundColor.GetData());
		renderer->UseHiddenLineRemovalOn();

		vtkNew<vtkRenderWindow> renderWindow;
		renderWindow->AddRenderer(renderer);
		renderWindow->SetSize(640, 480);

		vtkNew<vtkRenderWindowInteractor> interactor;
		interactor->SetRenderWindow(renderWindow);

		// Add the actors to the renderer, set the background and size
		renderer->AddActor(clipActor);
		renderer->AddActor(boundaryActor);
		renderer->AddActor(restActor);
		// Generate an interesting view
		renderer->ResetCamera();
		renderer->GetActiveCamera()->Azimuth(30);
		renderer->GetActiveCamera()->Elevation(30);
		renderer->GetActiveCamera()->Dolly(1.2);
		renderer->ResetCameraClippingRange();

		renderWindow->Render();
		renderWindow->SetWindowName("CapClip");
		renderWindow->Render();

		interactor->Start();
	}
};


int main()
{
    
    
	Test_Clip_cow::Test();
	return 0;
}



2、CMakeLists.txt

cmake_minimum_required(VERSION 3.3 FATAL_ERROR)

project(testfilter)

set(VTK_DIR D:/ProgramFiles/vtk-9.0/lib/cmake/vtk-9.0)
find_package(VTK COMPONENTS
  vtkCommonColor
  vtkCommonCore
  vtkCommonDataModel
  vtkFiltersSources
  vtkIOImage
  vtkImagingStencil
  vtkFiltersCore
  vtkRenderingCore
  vtkFiltersHybrid
  vtkInteractionStyle
  vtkRenderingFreeType
  vtkRenderingOpenGL2
  vtkRenderingVolumeOpenGL2
  vtkImagingCore
  vtkImagingColor
  vtkImagingSources
  vtkInteractionStyle
  vtkRenderingContextOpenGL2
  vtkRenderingGL2PSOpenGL2
  vtkRenderingCore
  vtkIOGeometry
  vtkIOXML
  vtkIOPLY
  QUIET
)

if (NOT VTK_FOUND)
  message("Skipping testfilter: ${VTK_NOT_FOUND_MESSAGE}")
  return()
endif()
message (STATUS "VTK_VERSION: ${VTK_VERSION}")

if (VTK_VERSION VERSION_LESS "8.90.0")
  # old system
  include(${VTK_USE_FILE})
endif()

file(GLOB_RECURSE mains ${CMAKE_CURRENT_SOURCE_DIR} *.cpp)
message(STATUS ${mains})
foreach(mainfile IN LISTS mains)
    # Get file name without directory
    get_filename_component(mainname ${mainfile} NAME_WE)
	Message("mainname:", ${mainname})
    add_executable(${mainname} ${mainfile})	
    target_link_libraries (${mainname} ${VTK_LIBRARIES})
	# vtk_module_autoinit is needed
   if (NOT VTK_VERSION VERSION_LESS "8.90.0")
     # vtk_module_autoinit is needed
     vtk_module_autoinit(
        TARGETS ${mainname}
        MODULES ${VTK_LIBRARIES}
        )
      endif()
	
endforeach()

3、运行输出

Surface Area:13.0365

在这里插入图片描述

4、面积正确性验证

从上面的例子不容易知道面积计算是否正确,下面换一个数据测试

4.1、代码

#pragma once

#include <vtkActor.h>
#include <vtkCamera.h>
#include <vtkClipPolyData.h>
#include <vtkDataSetMapper.h>
#include <vtkFeatureEdges.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkPlane.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 <vtkStripper.h>
#include <vtkXMLPolyDataReader.h>
#include <vtkMassProperties.h>
#include < vtkTriangleFilter.h>
#include <vtkCubeSource.h>
// Readers
#include <vtkBYUReader.h>
#include <vtkOBJReader.h>
#include <vtkPLYReader.h>
#include <vtkPolyDataReader.h>
#include <vtkSTLReader.h>
#include <vtkXMLPolyDataReader.h>
namespace {
    
    
	vtkSmartPointer<vtkPolyData> ReadPolyData(std::string const& fileName)
	{
    
    
		vtkSmartPointer<vtkPolyData> polyData;
		std::string extension = "";
		if (fileName.find_last_of(".") != std::string::npos){
    
    
			extension = fileName.substr(fileName.find_last_of("."));
		}
		// Make the extension lowercase
		std::transform(extension.begin(), extension.end(), extension.begin(),::tolower);
		if (extension == ".ply"){
    
    
			vtkNew<vtkPLYReader> reader;
			reader->SetFileName(fileName.c_str());
			reader->Update();
			polyData = reader->GetOutput();
		}
		else if (extension == ".vtp"){
    
    
			vtkNew<vtkXMLPolyDataReader> reader;
			reader->SetFileName(fileName.c_str());
			reader->Update();
			polyData = reader->GetOutput();
		}
		else if (extension == ".obj"){
    
    
			vtkNew<vtkOBJReader> reader;
			reader->SetFileName(fileName.c_str());
			reader->Update();
			polyData = reader->GetOutput();
		}
		else if (extension == ".stl"){
    
    
			vtkNew<vtkSTLReader> reader;
			reader->SetFileName(fileName.c_str());
			reader->Update();
			polyData = reader->GetOutput();
		}
		else if (extension == ".vtk"){
    
    
			vtkNew<vtkPolyDataReader> reader;
			reader->SetFileName(fileName.c_str());
			reader->Update();
			polyData = reader->GetOutput();
		}
		else if (extension == ".g"){
    
    
			vtkNew<vtkBYUReader> reader;
			reader->SetGeometryFileName(fileName.c_str());
			reader->Update();
			polyData = reader->GetOutput();
		}
		else{
    
    
			// Return a polydata sphere if the extension is unknown.
			vtkNew<vtkSphereSource> source;
			source->SetThetaResolution(20);
			source->SetPhiResolution(11);
			source->Update();
			polyData = source->GetOutput();
		}
		return polyData;
	}
} // namespace
class Test_Clip_cow {
    
    
public:
	static void Test() {
    
    
		vtkNew<vtkNamedColors> colors;
		auto backgroundColor = colors->GetColor3d("steel_blue");
		auto boundaryColor = colors->GetColor3d("banana");
		auto clipColor = colors->GetColor3d("tomato");
		// PolyData to process
		//auto polyData = ReadPolyData("cow.g");


		vtkSmartPointer<vtkCubeSource> cubeSource =
			vtkSmartPointer<vtkCubeSource>::New();
		cubeSource->Update();

		auto polyData = cubeSource->GetOutput();
		
		vtkNew<vtkPlane> plane;
		plane->SetOrigin(polyData->GetCenter());
		plane->SetNormal(1.0, -1.0, -1.0);

		vtkNew<vtkClipPolyData> clipper;
		clipper->SetInputData(polyData);
		clipper->SetClipFunction(plane);
		clipper->GenerateClipScalarsOn();
		clipper->GenerateClippedOutputOn();
		clipper->SetValue(0.5);
		clipper->Update();

		polyData = clipper->GetOutput();

		vtkNew<vtkDataSetMapper> clipMapper;
		clipMapper->SetInputData(polyData);
		clipMapper->ScalarVisibilityOff();

		vtkNew<vtkActor> clipActor;
		clipActor->SetMapper(clipMapper);
		clipActor->GetProperty()->SetDiffuseColor(clipColor.GetData());
		clipActor->GetProperty()->SetInterpolationToFlat();
		clipActor->GetProperty()->EdgeVisibilityOn();

		// Now extract feature edges
		vtkNew<vtkFeatureEdges> boundaryEdges;
		boundaryEdges->SetInputData(polyData);
		boundaryEdges->BoundaryEdgesOn();
		boundaryEdges->FeatureEdgesOff();
		boundaryEdges->NonManifoldEdgesOff();
		boundaryEdges->ManifoldEdgesOff();

		vtkNew<vtkStripper> boundaryStrips;
		boundaryStrips->SetInputConnection(boundaryEdges->GetOutputPort());
		boundaryStrips->Update();

		// Change the polylines into polygons
		vtkNew<vtkPolyData> boundaryPoly;
		boundaryPoly->SetPoints(boundaryStrips->GetOutput()->GetPoints());
		boundaryPoly->SetPolys(boundaryStrips->GetOutput()->GetLines());

		vtkNew<vtkPolyDataMapper> boundaryMapper;
		boundaryMapper->SetInputData(boundaryPoly);

		vtkNew<vtkActor> boundaryActor;
		boundaryActor->SetMapper(boundaryMapper);
		boundaryActor->GetProperty()->SetDiffuseColor(boundaryColor.GetData());

		vtkNew<vtkTriangleFilter> triFilter;
		triFilter->SetInputData(boundaryPoly);
		triFilter->Update();

		vtkSmartPointer<vtkMassProperties> massProp =
			vtkSmartPointer<vtkMassProperties>::New();
		massProp->SetInputData(triFilter->GetOutput());
		float vol = massProp->GetVolume();
		float area = massProp->GetSurfaceArea();
		std::cout << "Surface Area:" << area << std::endl;

		vtkNew<vtkPolyDataMapper> restMapper;
		restMapper->SetInputConnection(clipper->GetClippedOutputPort());
		restMapper->ScalarVisibilityOff();
		vtkNew<vtkActor> restActor;
		restActor->SetMapper(restMapper);
		restActor->GetProperty()->SetRepresentationToWireframe();

		// Create graphics stuff
		vtkNew<vtkRenderer> renderer;
		renderer->SetBackground(backgroundColor.GetData());
		renderer->UseHiddenLineRemovalOn();

		vtkNew<vtkRenderWindow> renderWindow;
		renderWindow->AddRenderer(renderer);
		renderWindow->SetSize(640, 480);

		vtkNew<vtkRenderWindowInteractor> interactor;
		interactor->SetRenderWindow(renderWindow);

		// Add the actors to the renderer, set the background and size
		renderer->AddActor(clipActor);
		renderer->AddActor(boundaryActor);
		renderer->AddActor(restActor);
		// Generate an interesting view
		renderer->ResetCamera();
		renderer->GetActiveCamera()->Azimuth(30);
		renderer->GetActiveCamera()->Elevation(30);
		renderer->GetActiveCamera()->Dolly(1.2);
		renderer->ResetCameraClippingRange();

		renderWindow->Render();
		renderWindow->SetWindowName("CapClip");
		renderWindow->Render();

		interactor->Start();
	}
};


int main()
{
    
    
	Test_Clip_cow::Test();
	return 0;
}

4.2、执行结果

Surface Area:0.866025

在这里插入图片描述
正方体过三个顶点的截面,截面面积 0.866025 0.866025 0.866025

根据计算三角形面积的海伦公式
S = p ( p − a ) ( p − b ) ( p − c ) S = \sqrt{p(p-a)(p-b)(p-c)} S=p(pa)(pb)(pc)
其中
a = b = c = 2 a = b = c = \sqrt{2} a=b=c=2
p = a + b + c 2 p = \frac{a+b+c}{2} p=2a+b+c

代入海伦公式,可以求得三角形面积为 3 2 = 0.866025 \frac{\sqrt{3}}{2} = 0.866025 23 =0.866025

猜你喜欢

转载自blog.csdn.net/juluwangriyue/article/details/123513458