最近在开发vtk的相关功能,项目中用到了数据裁剪,vtk中提供了多种数据裁剪算法,常用的有:vtkClipClosedSurface、vtkClipPolyData,还有其他的裁剪算法,如vtkClipDataSet、vtkClipVolume、vtkClipConvexPolyData 。本文主要介绍vtkClipClosedSurface和vtkClipPolyData。
两者差异:vtkClipPolvData切割带有锯齿形状日不是封闭的模型;vtkClipClosedSurace通过插值确保切割面为光滑目封闭的。
- vtkClipPolyData
使用用户指定的隐式函数(user-specified implicit function)或输入标量数据(input scalar data)剪裁多边形数据;vtkClipPolyData是一种Filter,接受vtkImplicitFunction派生出的任何子类或者标量数据集,vtkClipPolyData实现的剪切功能实际上“剪切”数据集的单元格,返回指定隐式函数(或大于标量值)内的所有内容,包括单元格的“片段”(将此与vtkExtractGeometry进行比较,该几何图形将拉出整个未切割单元格。)此筛选器的输出为多边形数据(vtkPolyData)。
要使用此Filter,必须决定是否使用隐式函数剪裁,还是使用输入标量数据。
1)定义隐式函数
2)使用SetClipFunction方法设置它
3)如果未指定ClipFunction,则使用方法GenerateClipScalarsOn开启,或者是GenerateClipScalars关闭(默认值),则将使用输入的标量数据来剪裁多数据。 - vtkClipClosedSurface
用途:通过一组切割平面实现对闭合曲面的切割。将输入数据切割未由多边形面组成的闭合由。
约束:输入的曲面不应该有开放的边缘,也不能有任何被两个以上的面共享的边缘。
vtkFeatureEdges 过滤器器可以用来验证一个数据集是否满足这些条件。输入的面不应该是自相交的,即曲面的各面应该只与它们的边缘相接触。
选项:
a.如果"生成轮廓"(GenerateOutline)是打干的,这个过滤器将在剪裁平面与数据相交处生戒一个轮廓;
b. PassPointData;若打开表示将点数据传递给输出,若新点产生时,点数据将会进行插值。此变量默认关闭。
c. ScalarMode选项将在输出中添加单元格标量,这样生成的面就可以用与原始面不同的颜色显示。可以用与原始表面不同的颜色来显示。
注意:
(1)一组切割平面应该是一组凸平面,否则成的结果可能为空;
(2) 生成的结果为多个平面围成的部分。
(3)若ScalarMode设置为On时,则是标量来映射Mapper的颜色;此时通过actor->GetProperty()->SetColor(color);
设置颜色时不生效;解决方案:关闭Mapper的ScalarVisibility,颜色设置才能生效。
代码:
#include <vtkActor.h>
#include <vtkAreaPicker.h>
#include <vtkDataSetMapper.h>
#include <vtkDataSetSurfaceFilter.h>
#include <vtkExtractPolyDataGeometry.h>
#include <vtkIdFilter.h>
#include <vtkIdTypeArray.h>
#include <vtkInteractorStyleRubberBandPick.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkObjectFactory.h>
#include <vtkPlanes.h>
#include <vtkPointData.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkRendererCollection.h>
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkUnstructuredGrid.h>
#include <vtkVersion.h>
#include <vtkVertexGlyphFilter.h>
#include <vtkPolyDataReader.h>
#include <vtkSTLReader.h>
#include "vtkClipClosedSurface.h"
#include "vtkPlaneCollection.h"
#include "vtkAxesActor.h"
#define VTKISRBP_ORIENT 0
#define VTKISRBP_SELECT 1
namespace {
// Define interaction style
class HighlightInteractorStyle : public vtkInteractorStyleRubberBandPick
{
public:
static HighlightInteractorStyle* New();
vtkTypeMacro(HighlightInteractorStyle, vtkInteractorStyleRubberBandPick);
HighlightInteractorStyle() : vtkInteractorStyleRubberBandPick()
{
this->SelectedMapper = vtkSmartPointer<vtkDataSetMapper>::New();
this->SelectedActor = vtkSmartPointer<vtkActor>::New();
this->SelectedActor->SetMapper(SelectedMapper);
}
virtual void OnLeftButtonUp() override
{
// Forward events
vtkInteractorStyleRubberBandPick::OnLeftButtonUp();
if (this->CurrentMode == VTKISRBP_SELECT)
{
vtkNew<vtkNamedColors> colors;
vtkPlanes* frustum = static_cast<vtkAreaPicker*>(this->GetInteractor()->GetPicker())->GetFrustum();
vtkNew<vtkPlaneCollection> planeCollection;
int pCount = frustum->GetNumberOfPlanes() - 2;
for (int i = 0; i < pCount; i++)
{
double normal[3];
frustum->GetPlane(i)->GetNormal(normal);
double origin[3];
frustum->GetPlane(i)->GetOrigin(origin);
vtkNew<vtkPlane> plane;
plane->SetOrigin(origin[0], origin[1], origin[2]);
plane->SetNormal(-normal[0], -normal[1], -normal[2]);
planeCollection->AddItem(plane);
}
vtkNew<vtkClipClosedSurface> clipper;
clipper->SetInputData(this->PolyData);
clipper->SetClippingPlanes(planeCollection);
clipper->Update();
if (m_SrcActor != nullptr)
m_SrcActor->VisibilityOff();
this->SelectedMapper->SetInputData(clipper->GetOutput());
this->SelectedActor->GetProperty()->SetColor(1.0000, 0.3882, 0.2784);
this->GetInteractor()->GetRenderWindow()->GetRenderers()->GetFirstRenderer()->AddActor(SelectedActor);
this->GetInteractor()->GetRenderWindow()->Render();
this->HighlightProp(NULL);
}
}
void SetPolyData(vtkSmartPointer<vtkPolyData> polyData)
{
this->PolyData = polyData;
}
vtkActor* m_SrcActor = nullptr;
private:
vtkSmartPointer<vtkPolyData> PolyData;
vtkSmartPointer<vtkActor> SelectedActor;
vtkSmartPointer<vtkDataSetMapper> SelectedMapper;
};
vtkStandardNewMacro(HighlightInteractorStyle);
} // namespace
int main(int argc, char* argv[])
{
vtkNew<vtkSphereSource> source;
source->SetPhiResolution(49);
source->SetThetaResolution(200);
source->Update();
auto polyData = source->GetOutput();
// Create a mapper and actor
vtkNew<vtkPolyDataMapper> mapper;
mapper->SetInputData(polyData);
mapper->ScalarVisibilityOff();
vtkNew<vtkActor> actor;
actor->SetMapper(mapper);
actor->GetProperty()->SetPointSize(5);
vtkNew<vtkAxesActor> axes;
// Visualize
vtkNew<vtkRenderer> renderer;
renderer->UseHiddenLineRemovalOn();
vtkNew<vtkRenderWindow> renderWindow;
renderWindow->AddRenderer(renderer);
renderWindow->SetSize(640, 480);
renderWindow->SetWindowName("HighlightSelection");
vtkNew<vtkAreaPicker> areaPicker;
vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
renderWindowInteractor->SetPicker(areaPicker);
renderWindowInteractor->SetRenderWindow(renderWindow);
renderer->AddActor(actor);
renderer->AddActor(axes);
renderWindow->Render();
vtkNew<HighlightInteractorStyle> style;
style->m_SrcActor = actor;
style->SetPolyData(polyData);
style->SetCurrentRenderer(renderer);
renderWindowInteractor->SetInteractorStyle(style);
renderWindowInteractor->Start();
return EXIT_SUCCESS;
}
vtkClipClosedSurface
vtkClipPolydata的代码参考:VTK笔记——多边形剪切(vtkClipPolyData)
VTK折线裁剪封闭曲面 三角剖分 Delaunay2D参考博客:VTK 三角剖分 Delaunay2D(五)—— 折线裁剪封闭曲面
其他的参考博客还有:
- vk裁剪的平面裁剪Vtk裁剪功能之平面裁剪vtkClipClosedSurface(vtk小记)
- VTK裁剪【1】-VTK中Clip/Trim总结 VTK裁剪【1】-VTK中Clip/Trim总结
3.VTK笔记-裁剪分割-几何裁剪-vtkClipPolyDat VTK笔记-裁剪分割-几何裁剪-vtkClipPolyData - VTK多个多边形数据的合并 - vtkAppendPolyData VTK多个多边形数据的合并 - vtkAppendPolyData