vtkCellPicker 拾取 三角面片

 1.vtkSelectedNode

也可以用于鼠标选择部分,更精确,比画矩形选取;

2.实现方案

CellPickerInteractorStyle类派生于vtkInteraTrackballCamera,并通过重载该函数类的OnLeftButtonDown()函数来处理鼠标左键消息。PolyData:被拾取模型数据,需要通过外部设置。在响应鼠标左键消息时,首先定义vtkCellPicker对象,使用Pick()函数实现拾取。拾取完毕后,即可通过GetCellId()函数来得到当前拾取的单元索取号; 可以实现单元格选择;

这里就涉及了vtkPolyData的局部数据提取功能。实现该功能时使用了几个新的类。

  • vtkIdTypeArray:对象存储当前选中的单位的索引号,每次只选取一个单元,因此每次该对象仅有一个索引号;
  • vtkSelectedNode对象与vtkSelection对象通常搭配使用,vtkSelection实际上是一个vtkSelectionNode的数组,而vtkSelectionNode则声明了要提取的数据的类型,这里SetFiledType()设置数据的类型为单元,SeiContentType()设置数据的内容为索引号。
  • vtkExtractSelection:实现了数据提取功能,其第一个输入为被提取的vtkPolyData,第二个输入为vtkSelection对象,标记要提取的数据类型。

提取完毕,即可将提取的结果保存至一个vtkActor对象,并添加至当前的vtkRenderer中显示。

3.效果

 

 

 4 code

#include "vtkAutoInit.h"
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);

VTK_MODULE_INIT(vtkRenderingVolumeOpenGL2);
VTK_MODULE_INIT(vtkRenderingFreeType);

 
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkProperty.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>

#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkDataSetMapper.h>
#include <vtkCellPicker.h>
#include <vtkSelectionNode.h>
#include <vtkSelection.h>
#include <vtkRendererCollection.h>
#include <vtkExtractSelection.h>
#include <vtkObjectFactory.h>
#include <vtkNamedColors.h>

#include <vtkUnstructuredGrid.h>
#include <vtkNamedColors.h>


// Catch mouse events
class MouseInteractorStyle : public vtkInteractorStyleTrackballCamera
{
public:
	static MouseInteractorStyle* New();

	MouseInteractorStyle()
	{
		selectedMapper = vtkSmartPointer<vtkDataSetMapper>::New();
		selectedActor = vtkSmartPointer<vtkActor>::New();
	}

	virtual void OnLeftButtonDown() override
	{
		vtkNew<vtkNamedColors> colors;

		// Get the location of the click (in window coordinates)
		int* pos = this->GetInteractor()->GetEventPosition();

		vtkNew<vtkCellPicker> picker;
		picker->SetTolerance(0.0005);

		// Pick from this location.
		picker->Pick(pos[0], pos[1], 0, this->GetDefaultRenderer());

		double* worldPosition = picker->GetPickPosition();
		std::cout << "Cell id is: " << picker->GetCellId() << std::endl;

		if (picker->GetCellId() != -1)
		{

			std::cout << "Pick position is: (" << worldPosition[0] << ", "
				<< worldPosition[1] << ", " << worldPosition[2] << ")" << endl;

			vtkNew<vtkIdTypeArray> ids;
			ids->SetNumberOfComponents(1);
			ids->InsertNextValue(picker->GetCellId());

			vtkNew<vtkSelectionNode> selectionNode;
			selectionNode->SetFieldType(vtkSelectionNode::CELL);
			selectionNode->SetContentType(vtkSelectionNode::INDICES);
			selectionNode->SetSelectionList(ids);

			vtkNew<vtkSelection> selection;
			selection->AddNode(selectionNode);

			vtkNew<vtkExtractSelection> extractSelection;
			extractSelection->SetInputData(0, this->Data);
			extractSelection->SetInputData(1, selection);
			extractSelection->Update();

			// In selection
			vtkNew<vtkUnstructuredGrid> selected;
			selected->ShallowCopy(extractSelection->GetOutput());

			std::cout << "Number of points in the selection: "
				<< selected->GetNumberOfPoints() << std::endl;
			std::cout << "Number of cells in the selection : "
				<< selected->GetNumberOfCells() << std::endl;
			selectedMapper->SetInputData(selected);
			selectedActor->SetMapper(selectedMapper);
			selectedActor->GetProperty()->EdgeVisibilityOn();
			selectedActor->GetProperty()->SetColor(
				colors->GetColor3d("Tomato").GetData());

			selectedActor->GetProperty()->SetLineWidth(3);

			this->Interactor->GetRenderWindow()
				->GetRenderers()
				->GetFirstRenderer()
				->AddActor(selectedActor);
		}
		// Forward events
		vtkInteractorStyleTrackballCamera::OnLeftButtonDown();
	}

	vtkSmartPointer<vtkPolyData> Data;
	vtkSmartPointer<vtkDataSetMapper> selectedMapper;
	vtkSmartPointer<vtkActor> selectedActor;
};

vtkStandardNewMacro(MouseInteractorStyle);

 

//vtkSmartPointer <vtkPolyData> ReadStl(char *fileName)
//{
//	vtkSmartPointer<vtkSTLReader> reader = vtkSmartPointer<vtkSTLReader>::New();
//	reader->SetFileName(fileName);
//	reader->Update();
//	vtkSmartPointer <vtkPolyData> poly = reader->GetOutput();
//	return poly;
//}

int main(int, char*[])
{
	 vtkNew<vtkNamedColors> colors;

	//vtkNew<vtkPlaneSource> planeSource;
	//planeSource->Update();

	//vtkSmartPointer<vtkXMLPolyDataReader> reader =
	//	vtkSmartPointer<vtkXMLPolyDataReader>::New();
	//reader->SetFileName("./KneeCTFemurSeg.vtp");
	//reader->Update();

	auto polyjg = ReadStl("./soft-Femur.stl");

	//vtkNew<vtkTriangleFilter> triangleFilter;
	triangleFilter->SetInputData
	//triangleFilter->SetInputData(reader->GetOutput());
	//triangleFilter->Update();
	  vtkSmartPointer<vtkSphereSource> sphereSource =
		      vtkSmartPointer<vtkSphereSource>::New();
	  sphereSource->Update();
	vtkNew<vtkPolyDataMapper> mapper;
	mapper->SetInputConnection(sphereSource->GetOutputPort());

	vtkNew<vtkActor> actor;
	actor->GetProperty()->SetColor(colors->GetColor3d("SeaGreen").GetData());
	actor->SetMapper(mapper);

	vtkNew<vtkRenderer> renderer;
	vtkNew<vtkRenderWindow> renderWindow;
	renderWindow->AddRenderer(renderer);
	renderWindow->SetWindowName("CellPicking");

	vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
	renderWindowInteractor->SetRenderWindow(renderWindow);
	renderWindowInteractor->Initialize();

	// Set the custom stype to use for interaction.
	vtkNew<MouseInteractorStyle> style;
	style->SetDefaultRenderer(renderer);
	style->Data = sphereSource->GetOutput();

	renderWindowInteractor->SetInteractorStyle(style);

	renderer->AddActor(actor);
	renderer->ResetCamera();

	renderer->SetBackground(colors->GetColor3d("PaleTurquoise").GetData());

	renderWindow->Render();
	renderWindowInteractor->Start();

	return EXIT_SUCCESS;
}
 

VTK(Visualization Toolkit)中,创建一个正方体并进行斜切处理,并使用`vtkCellPicker`来拾取所有经过斜切后的,需要涉及几何模型的生成、渲染以及事件处理。以下是使用VTK 9.3的一个简化的示例代码,包含了创建正方体、切割、绘制及拾取操作: ```cpp // 包含必要的头文件 #include <vtkSmartPointer.h> #include <vtkCubeSource.h> // 创建立方体 #include <vtkXMLPolyDataWriter.h> // 用于保存切割后的数据 #include <vtkRenderer.h> #include <vtkRenderWindow.h> #include <vtkRenderWindowInteractor.h> #include <vtkPolyDataMapper.h> #include <vtkActor.h> #include <vtkCellPicker.h> int main(int argc, char *argv[]) { // 初始化VTK环境 vtkSmartPointer<vtkRenderWindow> renWin = vtkSmartPointer<vtkRenderWindow>::New(); vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New(); renWin->AddRenderer(renderer); // 创建立方体贴图源 vtkSmartPointer<vtkCubeSource> cubeSource = vtkSmartPointer<vtkCubeSource>::New(); cubeSource->SetXLength(10); cubeSource->SetYLength(10); cubeSource->SetZLength(10); // 斜切处理 - 这部分通常需要自定义算法或库来完成,这里简化为将每个顶点移动45度 for (unsigned int i = 0; i < 6; ++i) { float x = sin(M_PI / 4) * 10; float y = cos(M_PI / 4) * 10; // 更改立方体的顶点位置,模拟斜切 double vertices[8][3] = { // 原始顶点坐标 {0, 0, 0}, {10, 0, 0}, {10, 10, 0}, {0, 10, 0}, {0, 0, 10}, {10, 0, 10}, {10, 10, 10}, {0, 10, 10} }; vertices[i*4+0][0] += x; vertices[i*4+0][1] += y; vertices[i*4+1][0] += x; vertices[i*4+1][1] -= y; vertices[i*4+2][0] -= x; vertices[i*4+2][1] -= y; vertices[i*4+3][0] -= x; vertices[i*4+3][1] += y; } // 将处理后的顶点设置回输入 cubeSource->SetOutputPointsData(vtkDataSetAttributes::CreatePolyData(points)); // 映射、演员和渲染 vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); mapper->SetInputConnection(cubeSource->GetOutputPort()); vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New(); actor->SetMapper(mapper); renderer->AddActor(actor); // 拾取vtkSmartPointer<vtkCellPicker> cellPicker = vtkSmartPointer<vtkCellPicker>::New(); cellPicker->SetTolerance(0.01); // 设置拾取容差 // 事件循环 renWin->AddObserver(vtkCommand::InteractionEvent, cellPicker, &PickCallback); vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New(); iren->SetRenderWindow(renWin); iren->Start(); return 0; } // 拾取回调函数 void PickCallback(vtkObject*, unsigned long event, void*) { if (event == vtkCommand::LeftButtonPressEvent) { // 获取当前被点击的cell vtkIdType cellId = cellPicker->GetCellId(); // 根据实际需要,此处可以获取选定的信息并处理 std::cout << "Selected cell ID: " << cellId << std::endl; } } ``` 注意:这个代码示例假设了斜切操作已经被简单地应用到了顶点上。在实际项目中,您可能需要使用更复杂的算法来确保每个都是沿着45度角并且有10像素的宽度。此外,VTK中的`vtkCellPicker`主要用于选择几何体的一部分,它并不是针对经过切割后的复杂形状设计的,因此对于斜切后的模型,可能需要自定义一些额外的处理来精确地确定哪些被选中。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

恋恋西风

up up up

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值