#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleRubberBandPick.h>
#include <vtkAreaPicker.h>
#include <vtkCommand.h>
#include <vtkCallbackCommand.h>
#include <vtkIdFilter.h>
#include <vtkExtractPolyDataGeometry.h>
#include <vtkSphereSource.h>
#include <vtkPlanes.h>
#include <vtkDataSetMapper.h>
#include <vtkProperty.h>
#include <vtkCellLocator.h>
#include <vtkCamera.h>
#include <vtkPolyDataConnectivityFilter.h>
#include <vtkIdTypeArray.h>
#include <vtkCellData.h>
/*
* 定义命令:
* 使用vtkInteractorStyleRubberBandPick交互方式时,会自动触发vtkAreaPicker
* 交互时框选的信息会存储在vtkAreaPicker中
* 将vtkAreaPicker的结束拾取事件绑定vtkPickerCallback
* 类似QT中信号与槽的机制
* vtkAreaPicker触发结束拾取信号,然后执行vtkPickerCallback中的Execute函数
*/
class vtkPickerCallback : public vtkCommand
{
public:
//@brief 定义New函数(固定格式)
static vtkPickerCallback* New() {return new vtkPickerCallback;}
//@brief 定义Execute函数(vtkCommand中的Execute为纯虚函数,必须要实现)
virtual void Execute(vtkObject* caller, unsigned long, void*);
void SetPolyData(vtkPolyData* input);
void SetRenderer(vtkRenderer* input);
private:
vtkPolyData* polyData; //需要处理的几何数据
vtkRenderer* renderer; //需要调用的渲染器
vtkDataSetMapper* mapper; //用于显示框选面片的mapper
vtkActor* actor; //用于显示框选面片的actor
};
int main()
{
//****************创建球体*****************
vtkSphereSource* sphere = vtkSphereSource::New();
sphere->SetThetaResolution(18);
sphere->SetPhiResolution(18);
sphere->SetRadius(10);
sphere->SetCenter(0, 0, 0);
sphere->Update();
//****************创建Mapper***************
vtkPolyDataMapper* mapper = vtkPolyDataMapper::New();
mapper->SetInputConnection(sphere->GetOutputPort());
//换成此语句效果一致:mapper->SetInputData(sphere->GetOutput());
//****************创建Actor****************
vtkActor* actor = vtkActor::New();
actor->SetMapper(mapper);
//****************创建渲染器***************
vtkRenderer* renderer = vtkRenderer::New();
renderer->AddActor(actor);
//****************创建渲染窗口*************
vtkRenderWindow* renderWindow = vtkRenderWindow::New();
renderWindow->AddRenderer(renderer);
//****************创建交互器***************
vtkRenderWindowInteractor* renderWindowInteractor = vtkRenderWindowInteractor::New();
//****************创建交互方式*************
vtkInteractorStyleRubberBandPick* interactorStyle = vtkInteractorStyleRubberBandPick::New();
//****************创建拾取回调函数*********
vtkPickerCallback* callback = vtkPickerCallback::New();
callback->SetPolyData(sphere->GetOutput());
callback->SetRenderer(renderer);
//****************创建区域拾取器***********
vtkAreaPicker* areaPicker = vtkAreaPicker::New();
areaPicker->AddObserver(vtkCommand::EndPickEvent, callback); //为“结束拾取”事件绑定“拾取回调函数”
renderWindowInteractor->SetRenderWindow(renderWindow); //为交互器设置渲染窗口
renderWindowInteractor->SetInteractorStyle(interactorStyle); //为交互器设置交互方式
renderWindowInteractor->SetPicker(areaPicker); //为交互器设置拾取器
renderWindowInteractor->Start();
return 0;
}
void vtkPickerCallback::Execute(vtkObject* caller, unsigned long, void*)
{
//通过反射获取调用者
vtkAreaPicker* areaPicker = static_cast<vtkAreaPicker*>(caller);
//获取框选的视锥体(由六个面组成)
vtkPlanes* frustum = areaPicker->GetFrustum();
//提前标记几何数据的CellId
vtkIdFilter* idFilter = vtkIdFilter::New();
idFilter->SetInputData(polyData);
idFilter->SetCellIdsArrayName("OriginalCellId");
idFilter->Update();
//提取视锥体内的模型
vtkExtractPolyDataGeometry* extract = vtkExtractPolyDataGeometry::New();
extract->SetInputConnection(idFilter->GetOutputPort());
extract->SetImplicitFunction(frustum);
extract->Update();
if (!extract->GetOutput()->GetPolys())
{
return;
}
//创建面片定位器
vtkCellLocator* locator = vtkCellLocator::New();
locator->SetDataSet(extract->GetOutput());
locator->BuildLocator();
//----------利用光线投射的方法寻找更靠近摄像机的面片------------
double rayStart[3]; //光线起点坐标:设置为摄像机位置
double rayDirection[3]; //光线方向向量:设置为框选数据包围盒的中心
renderer->GetActiveCamera()->GetPosition(rayStart);
extract->GetOutput()->GetCenter(rayDirection);
double xyz[3];
double t;
double pcoords[3];
int subId;
vtkIdType cellId = -1; //记录光线击中的面片Id号
locator->IntersectWithLine(rayStart, rayDirection, 0.0001, t, xyz, pcoords, subId, cellId);
//-----------利用找到的面片获取相连的面
vtkPolyDataConnectivityFilter* connectivity = vtkPolyDataConnectivityFilter::New();
connectivity->SetInputConnection(extract->GetOutputPort());
connectivity->SetExtractionModeToCellSeededRegions();
connectivity->InitializeSeedList();
connectivity->AddSeed(cellId);
connectivity->Update();
//--------删除框选面片----------
//提取框选面片的原始面片ID
vtkIdTypeArray* ids = dynamic_cast<vtkIdTypeArray*>(connectivity->GetOutput()->GetCellData()->GetArray("OriginalCellId"));
//要删除面片前必须先执行建立拓扑链接
polyData->BuildLinks();
if (!ids)
{
return;
}
for (int i = 0; i < ids->GetNumberOfValues(); i++)
{
vtkIdType id = ids->GetValue(i);
polyData->DeleteCell(id);
}
//提交删除面片操作
polyData->RemoveDeletedCells();
polyData->Modified();
//刷新渲染器
renderer->Render();
}
void vtkPickerCallback::SetPolyData(vtkPolyData* input)
{
polyData = input;
}
void vtkPickerCallback::SetRenderer(vtkRenderer* input)
{
renderer = input;
//初始化用于显示框选面片的mapper和actor
mapper = vtkDataSetMapper::New();
actor = vtkActor::New();
actor->SetMapper(mapper);
}
06-23
2239
![](https://csdnimg.cn/release/blogv2/dist/pc/img/readCountWhite.png)