当前位置: 首页 > news >正文

VTK|箱体切割器

文章目录

  • 效果
  • 实现类头文件
  • 实现类源文件
  • 如何调用
  • 项目git链接

效果

请添加图片描述

实现类头文件

/*** @file BoxClipperController.h* @brief 该头文件定义了 BoxClipperController 类,用于管理基于盒子的网格数据裁剪操作。* @details 该类提供了使用 vtkBoxWidget 对网格数据进行裁剪的功能,允许用户通过交互方式调整裁剪盒子的位置和大小,*          并实时更新裁剪结果。* @author qtree* @date 2025年5月16日*/
#ifndef BOXCLIPPERCONTROLLER_H
#define BOXCLIPPERCONTROLLER_H#include <vtkSmartPointer.h>
#include <vtkCallbackCommand.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkObjectBase.h>class vtkRenderWindowInteractor;
class vtkBoxWidget;
class vtkPlanes;
class vtkClipPolyData;
class vtkPolyData;
class vtkActor;
class vtkRenderer;/*** @class BoxClipperController* @brief 用于管理基于盒子的网格数据裁剪操作的控制器类。** 该类提供了使用 vtkBoxWidget 对网格数据进行裁剪的功能,允许用户通过交互方式调整裁剪盒子的位置和大小,* 并实时更新裁剪结果。*/
class BoxClipperController
{
public:/*** @brief 构造函数。** 初始化 BoxClipperController 实例,并关联渲染窗口交互器和渲染器。** @param interactor 用于处理用户交互的渲染窗口交互器。* @param renderer 用于渲染裁剪结果的渲染器。*/BoxClipperController(vtkRenderWindowInteractor *interactor, vtkRenderer *renderer);/*** @brief 设置输入数据并替换原始的 Actor。** 该方法设置用于裁剪的输入网格数据,并将原始的 Actor 替换为裁剪后的 Actor。** @param input 用于裁剪的输入网格数据。* @param originalActor 原始的 Actor,将被裁剪后的 Actor 替换。*/void SetInputDataAndReplaceOriginal(vtkSmartPointer<vtkPolyData> input, vtkActor *originalActor);/*** @brief 启用或禁用裁剪功能。** 该方法控制 vtkBoxWidget 的显示和交互状态,从而启用或禁用裁剪功能。** @param enabled 若为 true,则启用裁剪功能;若为 false,则禁用裁剪功能。*/void SetEnabled(bool enabled);/*** @brief 获取裁剪后的 Actor。** 返回经过裁剪操作后生成的 Actor。** @return 裁剪后的 Actor 的智能指针。*/vtkSmartPointer<vtkActor> GetClippedActor();private:vtkSmartPointer<vtkBoxWidget> boxWidget;               ///< 用于用户交互的盒子小部件,用于定义裁剪区域vtkSmartPointer<vtkPlanes> clipPlanes;                 ///< 由盒子小部件定义的裁剪平面vtkSmartPointer<vtkClipPolyData> clipper;              ///< 用于执行裁剪操作的 VTK 过滤器vtkSmartPointer<vtkActor> clippedActor;                ///< 裁剪后的网格数据对应的 ActorvtkSmartPointer<vtkPolyData> inputData;                ///< 用于裁剪的输入网格数据vtkSmartPointer<vtkRenderer> renderer;                 ///< 用于渲染裁剪结果的渲染器vtkSmartPointer<vtkRenderWindowInteractor> interactor; ///< 用于处理用户交互的渲染窗口交互器vtkActor *originalActor;                               ///< 原始的 Actor,将被裁剪后的 Actor 替换/*** @brief 更新裁剪结果。** 当盒子小部件的位置或大小发生变化时,该方法会重新执行裁剪操作并更新裁剪后的 Actor。*/void UpdateClipping();
};#endif // BOXCLIPPERCONTROLLER_H

实现类源文件

#include "BoxClipperController.h"#include <vtkBoxWidget.h>
#include <vtkPlanes.h>
#include <vtkPolyData.h>
#include <vtkClipPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkCommand.h>
#include <vtkProperty.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>BoxClipperController::BoxClipperController(vtkRenderWindowInteractor *interactor, vtkRenderer *renderer): interactor(interactor), renderer(renderer)
{originalActor = nullptr;// 裁剪用平面集(由 BoxWidget 生成)clipPlanes = vtkSmartPointer<vtkPlanes>::New();// 裁剪器:使用 box widget 的平面集进行裁剪clipper = vtkSmartPointer<vtkClipPolyData>::New();// 映射器连接裁剪器的输出vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();mapper->SetInputConnection(clipper->GetOutputPort());// 显示裁剪后模型的 actorclippedActor = vtkSmartPointer<vtkActor>::New();clippedActor->SetMapper(mapper);// 初始化 box widget 控件boxWidget = vtkSmartPointer<vtkBoxWidget>::New();boxWidget->SetInteractor(interactor); // 控制器绑定boxWidget->SetPlaceFactor(1.0);       // 控制缩放比例boxWidget->HandlesOn();               // 显示操作手柄// 添加裁剪更新事件监听器vtkSmartPointer<vtkCallbackCommand> callback = vtkSmartPointer<vtkCallbackCommand>::New();callback->SetClientData(this); // 把当前类传入回调中callback->SetCallback([](vtkObject *caller, unsigned long, void *clientData, void *callData){auto self = static_cast<BoxClipperController *>(clientData);self->UpdateClipping(); // 当 box widget 改变时更新裁剪});boxWidget->AddObserver(vtkCommand::InteractionEvent, callback); // 绑定观察者
}
// 设置原始输入数据与原始 actor(不拥有生命周期)
void BoxClipperController::SetInputDataAndReplaceOriginal(vtkSmartPointer<vtkPolyData> input, vtkActor *original)
{originalActor = original; // 不用智能指针,不控制生命周期inputData = input;clipper->SetInputData(inputData);boxWidget->SetInputData(inputData);boxWidget->PlaceWidget();UpdateClipping(); // 更新 planes 和裁剪结果
}void BoxClipperController::SetEnabled(bool enabled)
{boxWidget->SetEnabled(enabled ? 1 : 0); // 开启或关闭 box 控件if (enabled){if (originalActor && renderer->HasViewProp(originalActor)){renderer->RemoveActor(originalActor); // 移除原始 actor}renderer->AddActor(clippedActor); // 启用裁剪后显示 actor}else{renderer->RemoveActor(clippedActor);if (originalActor){renderer->AddActor(originalActor);}}renderer->GetRenderWindow()->Render();
}void BoxClipperController::UpdateClipping()
{vtkSmartPointer<vtkPlanes> planes = vtkSmartPointer<vtkPlanes>::New();boxWidget->GetPlanes(planes);     // 获取当前 box widget 对应的平面clipper->SetClipFunction(planes); // 使用这些平面裁剪clipper->InsideOutOn();           // 保留 box 内部数据clipper->Update();                // 更新裁剪结果
}vtkSmartPointer<vtkActor> BoxClipperController::GetClippedActor()
{return clippedActor;
}

如何调用

头文件声明

// 箱形剪控制器
std::unique_ptr<BoxClipperController> boxClipper_;
bool boxClipper_enabled_;

构造函数里初始化
切割需要把原来的模型隐藏才能看出切割后的,所以把原始数据和原模型都传递到类中控制显隐


boxClipper_ = std::make_unique<BoxClipperController>(interactor_, renderer_);
boxClipper_enabled_ = false;
boxClipper_->SetInputDataAndReplaceOriginal(cylinderSource->GetOutput(), testActor);

控制箱体切割器显隐按钮槽函数


connect(cross_section, &QPushButton::clicked, this, [=](){ boxClipper_enabled_ = !boxClipper_enabled_;boxClipper_->SetEnabled(boxClipper_enabled_); });

更新数据之后调用


boxClipper_->SetInputDataAndReplaceOriginal(vertexGlyphFilter->GetOutput(),ply_point_actor_);
boxClipper_enabled_ = false;
boxClipper_->SetEnabled(boxClipper_enabled_);

项目git链接

gitee:https://gitee.com/strange-tree-qian/vtktest
github:https://github.com/qishuqian666/project-vtk-test

http://www.xdnf.cn/news/532225.html

相关文章:

  • 【python】windows修改 pip 默认安装路径
  • 如何用 OceanBase 的 LOAD DATA 旁路导入进行大表迁移
  • git merge和git rebase的区别
  • GPT-4.1特点?如何使用GPT-4.1模型,GPT-4.1编码和图像理解能力实例展示
  • 宏汇编以及浮点程序设计实验
  • 解决leetcode第3539题.魔法序列的数组乘积之和
  • NW860NW894美光闪存颗粒NX770NX789
  • 学习黑客PowerShell的历史、架构与工作原理深度解析
  • 什么是RDMA?
  • 苍穹外卖 - Day03
  • Solana 一键发币 + 自动建池:技术逻辑与挑战解析
  • 《Head First 设计模式》第二章 - 笔记
  • 手动制做一个Transformer
  • C++初阶-vector的使用
  • python-leetcode 67.寻找两个正序数组中的中位数
  • 如何在 Windows 11 或 10 上安装 Fliqlo 时钟屏保
  • CSS attr() 函数详解
  • HJ3 明明的随机数【牛客网】
  • 11.4/Q1,GBD数据库最新文章解读
  • threejs制作上升的小球
  • Kruise Rollout多批次发布
  • 3D 数据交换格式(.3DXML)简介
  • PyTorch Geometric(PyG):基于PyTorch的图神经网络(GNN)开发框架
  • 如何评估开源商城小程序源码的基础防护能力?
  • SCAU18924--二叉树的宽度多解
  • uniapp打包H5,输入网址空白情况
  • 样本复杂性:机器学习的数据效率密码
  • 【Vite】静态资源的动态访问
  • Libero离线IP安装
  • JWT : JSON Web Token