vtk中鼠标拖vtkActor在Render移动

5 篇文章 1 订阅
1 篇文章 0 订阅
该博客展示了如何使用VTK库创建一个交互式3D场景,包括选择和移动3D对象。通过自定义MouseInteractorStyle2类,实现了鼠标左键点击选择对象并进行平移操作的功能。示例中创建了平面和球体,并设置了交互风格,允许用户在渲染窗口中直接操作3D元素。
摘要由CSDN通过智能技术生成
#include <vtkSmartPointer.h>
#include <vtkSphereSource.h>
#include <vtkPolyData.h>
#include <vtkTransform.h>
#include <vtkTransformPolyDataFilter.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkPropPicker.h>
#include <vtkCommand.h>
#include <vtkSmartPointer.h>
#include <vtkJPEGReader.h>
#include <vtkImageActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleImage.h>

#include <vtkDistanceWidget.h>
#include <vtkDistanceRepresentation.h>
#include <vtkAngleWidget.h>
#include <vtkProperty2D.h>
#include <vtkLeaderActor2D.h>
#include <vtkAngleRepresentation2D.h>
#include <vtkBiDimensionalWidget.h>
#include <vtkBiDimensionalRepresentation2D.h>


#include <vtkLineRepresentation.h>
#include "vtkLineWidget2.h"
#include <vtkProperty.h>
#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include "vtkWidgetEventTranslator.h"
#include "vtkWidgetCallbackMapper.h"
#include "vtkWidgetEvent.h"

#include <vtkHandleRepresentation.h>
//#include <vtkDistanceRepresentation3D.h>
#include <vtkDistanceRepresentation2D.h>
#include <vtkPointHandleRepresentation2D.h>
#include "vtkNamedColors.h"


//如果出现错误请加上下面的声明
#include "vtkAutoInit.h" 
VTK_MODULE_INIT(vtkRenderingOpenGL2); // VTK was built with vtkRenderingOpenGL2
VTK_MODULE_INIT(vtkInteractionStyle);
//VTK_MODULE_INIT(vtkRenderingvolumeOpenGL2)
VTK_MODULE_INIT(vtkRenderingFreeType)

class MouseInteractorStyle2 : public vtkInteractorStyleTrackballCamera
{
public:
	static MouseInteractorStyle2* New();
	vtkTypeMacro(MouseInteractorStyle2, vtkInteractorStyleTrackballCamera);
	virtual void OnLeftButtonDown()
	{
		int* clickPos = this->GetInteractor()->GetEventPosition();

		// Pick from this location.
		vtkSmartPointer<vtkPropPicker>  picker =
			vtkSmartPointer<vtkPropPicker>::New();
		picker->Pick(clickPos[0], clickPos[1], 0, this->GetDefaultRenderer());

		double* pos = picker->GetPickPosition();
		std::cout << "Pick position (world coordinates) is: "
			<< pos[0] << " " << pos[1]
			<< " " << pos[2] << std::endl;

		std::cout << "Picked actor: " << picker->GetActor() << std::endl;
		if (picker->GetActor())
		{
			m_pSelectActor = picker->GetActor();
			m_bStatus = true;
			return;
		}

		//this->GetInteractor()->GetRenderWindow()->GetRenderers()->GetDefaultRenderer()->AddActor(actor);
		//this->GetDefaultRenderer()->AddActor(actor);
		// Forward events
		vtkInteractorStyleTrackballCamera::OnLeftButtonDown();
	}
	virtual void OnMouseMove()
	{
		if (m_pSelectActor == nullptr)
			return;

		vtkRenderWindowInteractor* rwi = this->Interactor;
		if (m_bStatus == true)
		{
			double* obj_center = m_pSelectActor->GetCenter();
			double disp_obj_center[3], new_pick_point[4];
			double old_pick_point[4], motion_vector[3];
			this->ComputeWorldToDisplay(obj_center[0], obj_center[1], obj_center[2],
				disp_obj_center);

			this->ComputeDisplayToWorld(rwi->GetEventPosition()[0],
				rwi->GetEventPosition()[1],
				disp_obj_center[2],
				new_pick_point);

			this->ComputeDisplayToWorld(rwi->GetLastEventPosition()[0],
				rwi->GetLastEventPosition()[1],
				disp_obj_center[2],
				old_pick_point);

			motion_vector[0] = new_pick_point[0] - old_pick_point[0];
			motion_vector[1] = new_pick_point[1] - old_pick_point[1];
			motion_vector[2] = new_pick_point[2] - old_pick_point[2];
			if (m_pSelectActor->GetUserMatrix() != NULL)
			{
				vtkTransform* t = vtkTransform::New();
				t->PostMultiply();
				t->SetMatrix(m_pSelectActor->GetUserMatrix());
				t->Translate(motion_vector[0], motion_vector[1], motion_vector[2]);
				m_pSelectActor->GetUserMatrix()->DeepCopy(t->GetMatrix());
				t->Delete();
			}
			else
			{
				//在当前位置增加偏移量
				m_pSelectActor->AddPosition(motion_vector[0],
					motion_vector[1],
					motion_vector[2]);
			}

			rwi->Render();
		}
		vtkInteractorStyleTrackballCamera::OnMouseMove();
	}
	virtual void OnLeftButtonUp()
	{
		m_bStatus = false;
		vtkInteractorStyleTrackballCamera::OnLeftButtonUp();
	}

private:
	vtkSmartPointer<vtkActor> m_pSelectActor = nullptr;

	bool m_bStatus = false;
};

vtkStandardNewMacro(MouseInteractorStyle2);
#include <vtkPlaneSource.h>
int main(int, char[])
{
	vtkSmartPointer<vtkPlaneSource> planeSource =
		vtkSmartPointer<vtkPlaneSource>::New();
	planeSource->SetCenter(0, 0, 0);
	//planeSource->SetRadius(2);
	planeSource->Update();
	// Create a polydata object
	vtkPolyData *polydata = planeSource->GetOutput();

	vtkSmartPointer<vtkPolyDataMapper> mapper =
		vtkSmartPointer<vtkPolyDataMapper>::New();
	mapper->SetInputData(polydata);

	vtkSmartPointer<vtkActor> actor =
		vtkSmartPointer<vtkActor>::New();
	actor->SetMapper(mapper);

	std::cout << "Actor address: " << actor << std::endl;
	vtkSmartPointer<vtkSphereSource> planeSource1 =
		vtkSmartPointer<vtkSphereSource>::New();
	planeSource1->SetCenter(10, 10, 10);
	planeSource1->SetRadius(2);
	planeSource1->Update();
	// Create a polydata object
	vtkPolyData* polydata1 = planeSource1->GetOutput();

	// Create a mapper
	vtkSmartPointer<vtkPolyDataMapper> mapper1 =
		vtkSmartPointer<vtkPolyDataMapper>::New();

	mapper1->SetInputData(polydata1);

	// Create an actor
	vtkSmartPointer<vtkActor> actor1 =
		vtkSmartPointer<vtkActor>::New();
	actor1->SetMapper(mapper1);
	std::cout << "Actor1 address: " << actor1 << std::endl;
	//std::cout << "a address: " << a << std::endl;
	// A renderer and render window
	vtkSmartPointer<vtkRenderer> renderer =
		vtkSmartPointer<vtkRenderer>::New();
	vtkSmartPointer<vtkRenderWindow> renderWindow =
		vtkSmartPointer<vtkRenderWindow>::New();
	renderWindow->AddRenderer(renderer);

	// An interactor
	vtkSmartPointer<vtkRenderWindowInteractor> renderWindowInteractor =
		vtkSmartPointer<vtkRenderWindowInteractor>::New();
	renderWindowInteractor->SetRenderWindow(renderWindow);

	// Set the custom stype to use for interaction.
	vtkSmartPointer<MouseInteractorStyle2> style =
		vtkSmartPointer<MouseInteractorStyle2>::New();
	style->SetDefaultRenderer(renderer);
	//style->setNeedSelectActor(actor1);

	renderWindowInteractor->SetInteractorStyle(style);

	// Add the actors to the scene
	renderer->AddActor(actor);
	renderer->AddActor(actor1);
	renderer->SetBackground(0, 0, 1);

	// Render and interact
	renderWindow->Render();
	renderWindowInteractor->Initialize();
	renderWindowInteractor->Start();

	return EXIT_SUCCESS;
}
如果您只想对单个Actor进行鼠标交互,可以使用vtkPropPicker类。该类允许您选择场景的任何Actor并将其与鼠标事件相关联。 以下是一个简单的示例程序,演示如何使用vtkPropPicker选择一个Actor并将其与鼠标事件相关联: ```python import vtk # 创建一个场景并添加一个Actor sphere = vtk.vtkSphereSource() sphere.SetCenter(0, 0, 0) sphere.SetRadius(1.0) mapper = vtk.vtkPolyDataMapper() mapper.SetInputConnection(sphere.GetOutputPort()) actor = vtk.vtkActor() actor.SetMapper(mapper) renderer = vtk.vtkRenderer() renderer.AddActor(actor) # 创建一个RenderWindow并将Renderer添加到其 window = vtk.vtkRenderWindow() window.AddRenderer(renderer) # 创建一个Interactor并将其与RenderWindow相关联 interactor = vtk.vtkRenderWindowInteractor() interactor.SetRenderWindow(window) # 创建一个PropPicker并将其与Renderer相关联 picker = vtk.vtkPropPicker() picker.PickFromListOn() picker.AddPickList(actor) renderer.SetPicker(picker) # 定义鼠标事件处理程序 def onMouseDown(obj, event): # 获取当前鼠标位置 x, y = interactor.GetEventPosition() # 使用PropPicker选择Actor picker.PickProp(x, y, renderer) # 获取选择的Actor actor = picker.GetActor() # 如果选择了Actor,则输出Actor的名称 if actor: print("Selected actor:", actor.GetProperty().GetClassName()) # 将鼠标事件处理程序添加到Interactor interactor.AddObserver("LeftButtonPressEvent", onMouseDown) # 启动交互式窗口 interactor.Initialize() window.Render() interactor.Start() ``` 这个程序创建了一个场景,并在其添加了一个球体Actor。它还创建了一个PropPicker,并将其与Renderer相关联。在鼠标事件处理程序,它使用PropPicker选择Actor,并输出所选Actor的名称。 请注意,在这个示例,我们只将一个Actor添加到PickList。如果您想选择多个Actor,可以将它们全部添加到PickList
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Pailugou

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值