开发环境:
- Windows 11 家庭中文版
- Microsoft Visual Studio Community 2019
- VTK-9.3.0.rc0
- vtk-example
demo解决问题:对多面体数据进行裁剪和加盖的功能。
关键点:
- 创建了一个平面,并将其定位在输入多面体数据的中心位置,同时指定了一个特定的法线。(法线影响平面裁剪角度)
- 使用vtkClipPolyData类来使用之前定义的平面对输入的多面体数据进行裁剪。裁剪后的数据被更新并存储起来。
- 创建了一个vtkDataSetMapper和vtkActor分别用于裁剪后的多面体数据的渲染,同时指定了特定的颜色和属性。
- 使用vtkFeatureEdges提取裁剪后数据的特征边,并将其转换为多边形,然后赋予不同的颜色。
/*
这段代码的功能是提取多面体数据的特征边。具体来说:
通过vtkNew创建了一个名为boundaryEdges的vtkFeatureEdges对象,并使用SetInputData方法将输入的多面体数据传入。
紧接着对boundaryEdges进行了一系列设置:
BoundaryEdgesOn()开启了边界特征的提取。
FeatureEdgesOff()关闭了特征边的提取。
NonManifoldEdgesOff()关闭了非流形边的提取。
ManifoldEdgesOff()关闭了流形边的提取。
接下来,代码创建了一个名为boundaryStrips的vtkStripper对象,并使用SetInputConnection方法将boundaryEdges的输出端口连接到boundaryStrips上。最后,调用了Update()方法来执行特征边的提取操作。
*/
// 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();
prj name: CapClip
#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>
// 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);
}
//
// Demonstrate the use of clipping and capping on polyhedral data
//
int main(int argc, char* argv[])
{
// Define colors
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(argc > 1 ? argv[1] : "");
vtkNew<vtkPlane> plane;
plane->SetOrigin(polyData->GetCenter());
plane->SetNormal(1.0, -1.0, -1.0);//平面的法线朝向影响裁剪角度
//plane->SetNormal(-1.0, -1.0, 1.0);
vtkNew<vtkClipPolyData> clipper;
clipper->SetInputData(polyData);
clipper->SetClipFunction(plane);
clipper->SetValue(0);
clipper->Update();
polyData = clipper->GetOutput();
vtkNew<vtkDataSetMapper> clipMapper;
clipMapper->SetInputData(polyData);
vtkNew<vtkActor> clipActor;
clipActor->SetMapper(clipMapper);
clipActor->GetProperty()->SetDiffuseColor(clipColor.GetData());
clipActor->GetProperty()->SetInterpolationToFlat();
clipActor->GetProperty()->EdgeVisibilityOn();
/*
这段代码的功能是提取多面体数据的特征边。具体来说:
通过vtkNew创建了一个名为boundaryEdges的vtkFeatureEdges对象,并使用SetInputData方法将输入的多面体数据传入。
紧接着对boundaryEdges进行了一系列设置:
BoundaryEdgesOn()开启了边界特征的提取。
FeatureEdgesOff()关闭了特征边的提取。
NonManifoldEdgesOff()关闭了非流形边的提取。
ManifoldEdgesOff()关闭了流形边的提取。
接下来,代码创建了一个名为boundaryStrips的vtkStripper对象,并使用SetInputConnection方法将boundaryEdges的输出端口连接到boundaryStrips上。最后,调用了Update()方法来执行特征边的提取操作。
*/
// 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());
// 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);
// 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();
return EXIT_SUCCESS;
}
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