VTK系列1:在屏幕绘制多边形

VTK中在屏幕绘制多边形

背景介绍

最近项目需要实现一个多边形的功能,通过vtkInteractorStyleDrawPolygon虽然可以进行绘制,但其使用方法是要鼠标左键按下不松,移动时绘制多边形,导致屏幕会闪烁,因此需要自定义绘制方法。

具体需求

1、鼠标左键按下,记录当前点

2、鼠标移动时,绘制上一个点到鼠标当前位置的线

3、当记录的点大于3时,以鼠标当前位置绘制多边形

4、右键结束绘制

实现方法

要实现以上功能,需要自定义VTK交互,继承vtkInteractorStyleTrackballCamera,使用 vtkPoints 存储屏幕像素坐标,通过 vtkActor2D 和 vtkPolyDataMapper2D 显示线条。

接下来看下主要调用方法:通过一个按钮控制是否绘制多边形

cpp 复制代码
void MainWindow::OnClipPointCloudBtn(bool bChecked)
{
	if (bChecked)
	{
		if (m_polygonStyle == nullptr)
		{
			m_polygonStyle = vtkSmartPointer<PolygonRubberBandStyle>::New();
			m_polygonStyle->AddToRenderer(m_Controls->RegistrationWidget_2->renderWindow()->GetRenderers()->GetFirstRenderer());

		}
		this->m_Controls->RegistrationWidget_2->renderWindow()->GetInteractor()->SetInteractorStyle(m_polygonStyle);
	}
	else
	{
		// 恢复为标准 TrackballCamera(或其他默认)
		auto defaultStyle = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
		//恢复交互样式
     this->m_Controls->RegistrationWidget_2->renderWindow()->GetInteractor()->SetInteractorStyle(defaultStyle);
	}

	
}

头文件

cpp 复制代码
class PolygonRubberBandStyle :
	public vtkInteractorStyleTrackballCamera
{
public:
	static PolygonRubberBandStyle* New() { return new PolygonRubberBandStyle; }

	vtkTypeMacro(PolygonRubberBandStyle, vtkInteractorStyleTrackballCamera);
public:
	void AddToRenderer(vtkRenderer* ren);
	PolygonRubberBandStyle();

	// 鼠标按下:确定一个新顶点
	void OnLeftButtonDown() override;
	// 鼠标移动:绘制预览线
	void OnMouseMove() override;
	void OnRightButtonDown() override;

private:
	void Update2DDrawing(int curX, int curY);
	void ExecuteClipping();
private:
	std::vector<std::vector<double>> PixelPoints; // 存储像素坐标
	vtkSmartPointer<vtkPoints> Points2D;
	vtkSmartPointer<vtkPolyData> PolyData2D;
	vtkSmartPointer<vtkActor2D> Actor2D;

};

cpp文件

cpp 复制代码
PolygonRubberBandStyle::PolygonRubberBandStyle()
{
	// 1. 设置 2D 辅助线 (Overlay)
	this->Points2D = vtkSmartPointer<vtkPoints>::New();
	this->Points2D->SetDataTypeToDouble(); // 关键:强制设为 Double 类型
	this->PolyData2D = vtkSmartPointer<vtkPolyData>::New();
	this->PolyData2D->SetPoints(this->Points2D);

	auto mapper2D = vtkSmartPointer<vtkPolyDataMapper2D>::New();
	mapper2D->SetInputData(this->PolyData2D);

	this->Actor2D = vtkSmartPointer<vtkActor2D>::New();
	this->Actor2D->SetMapper(mapper2D);
	this->Actor2D->GetProperty()->SetColor(0.0, 1.0, 0.0); // 绿色 2D 线
	this->Actor2D->GetProperty()->SetLineWidth(2.0);
}

// 鼠标按下:确定一个新顶点
void PolygonRubberBandStyle::OnLeftButtonDown() {
	int* pos = this->GetInteractor()->GetEventPosition();
	this->PixelPoints.push_back({ (double)pos[0], (double)pos[1], 0.0 });
	this->Update2DDrawing(pos[0], pos[1]);
}

// 鼠标移动:绘制预览线
void PolygonRubberBandStyle::OnMouseMove() {
	if (!this->PixelPoints.empty()) {
		int* pos = this->GetInteractor()->GetEventPosition();
		this->Update2DDrawing(pos[0], pos[1]);
	}
	vtkInteractorStyleTrackballCamera::OnMouseMove();
}
void PolygonRubberBandStyle::OnRightButtonDown()
{
	if (this->PixelPoints.size() < 3) return;
	// 清理并刷新
	this->PixelPoints.clear();
	this->Points2D->Reset();
	this->PolyData2D->Modified();
	this->GetInteractor()->GetRenderWindow()->Render();
}


void PolygonRubberBandStyle::Update2DDrawing(int curX, int curY) {
	this->Points2D->Reset();
	for (const auto& pt : this->PixelPoints) {
		this->Points2D->InsertNextPoint(pt[0], pt[1], 0);
	}
	this->Points2D->InsertNextPoint(curX, curY, 0); // 预览当前鼠标

	auto polyLine = vtkSmartPointer<vtkPolyLine>::New();
	int n = this->Points2D->GetNumberOfPoints();
	polyLine->GetPointIds()->SetNumberOfIds(n + 1);
	for (int i = 0; i < n; ++i) polyLine->GetPointIds()->SetId(i, i);
	polyLine->GetPointIds()->SetId(n, 0); // 闭合

	auto cells = vtkSmartPointer<vtkCellArray>::New();
	cells->InsertNextCell(polyLine);
	this->PolyData2D->SetLines(cells);
	this->PolyData2D->Modified();
	this->GetInteractor()->GetRenderWindow()->Render();
}

void PolygonRubberBandStyle::AddToRenderer(vtkRenderer* ren) {
	this->SetDefaultRenderer(ren);
	ren->AddActor2D(this->Actor2D);
}
相关推荐
于小猿Sup6 小时前
VMware在Ubuntu22.04驱动Livox Mid360s
linux·c++·嵌入式硬件·自动驾驶
小小编程路8 小时前
C++ 多线程与并发
java·jvm·c++
程序leo源9 小时前
Qt窗口详解
开发语言·数据库·c++·qt·青少年编程·c#
zh_xuan10 小时前
解决VS Code 控制台中文乱码
c++·vscode·乱码
郭涤生10 小时前
飞凌 RK3588 开发板同显 / 异显模式切换
c++·rk3588
计算机安禾10 小时前
【c++面向对象编程】第38篇:设计原则(二):里氏替换、接口隔离与依赖倒置
开发语言·c++
code_whiter11 小时前
C++1进阶(继承)
开发语言·c++
智者知已应修善业11 小时前
【51单片机LED闪烁10次数码管显示0-9】2023-12-14
c++·经验分享·笔记·算法·51单片机
智者知已应修善业11 小时前
【51单片机2按键控制1个敞亮LED灯闪烁和熄灭】2023-11-3
c++·经验分享·笔记·算法·51单片机
2401_8638014612 小时前
OBJ、FBX 与 GLTF 选择用于设计导入的最佳 3D 模型格式:实用的比较可帮助设计人员选择正确的 3D 格式,同时保持几何形状、纹理和性能不变。
3d