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

VTK|结合qt创建通用按钮控制显隐(边框、坐标轴、点线面)

文章目录

  • 增加边框BoundingBox
    • 添加addBoundingBox
    • 添加BoundingBox控制按钮
    • 点击按钮之后的槽函数
  • 添加坐标轴
  • 增加点线面显隐控制按钮
    • 添加控制点线面显隐的按钮到三维显示界面
    • 控制面显示槽函数
    • 控制线显示槽函数
    • 控制点显示槽函数

增加边框BoundingBox

增加边框BoundingBox并通过按钮控制显隐
需要的全局变量

    // 显示场景QVTKOpenGLWidget *m_pScene;vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow_;vtkSmartPointer<vtkRenderer> renderer_;// 边框显示vtkSmartPointer<vtkActor> boundingBoxActor_; // 用于存储BoundingBox的Actorbool isBoundingBoxVisible_;                  // 控制BoundingBox的显隐状态vtkSmartPointer<vtkTextActor> boundingBoxButtonActor_; 

添加addBoundingBox

void ThreeDimensionalDisplayPage::addBoundingBox(vtkSmartPointer<vtkPolyData> polyData)
{if (boundingBoxActor_){renderer_->RemoveActor(boundingBoxActor_);boundingBoxActor_ = nullptr;}vtkNew<vtkOutlineFilter> outlineFilter;outlineFilter->SetInputData(polyData);outlineFilter->Update();vtkNew<vtkPolyDataMapper> outlineMapper;outlineMapper->SetInputConnection(outlineFilter->GetOutputPort());boundingBoxActor_ = vtkSmartPointer<vtkActor>::New();boundingBoxActor_->SetMapper(outlineMapper);boundingBoxActor_->GetProperty()->SetColor(1.0, 0.0, 0.0);boundingBoxActor_->GetProperty()->SetLineWidth(2.0);boundingBoxActor_->SetVisibility(isBoundingBoxVisible_); // 根据状态决定是否显示renderer_->AddActor(boundingBoxActor_);
}

添加BoundingBox控制按钮

void ThreeDimensionalDisplayPage::addBoundingBoxControlButton()
{// 避免重复添加if (boundingBoxButtonActor_ && renderer_->HasViewProp(boundingBoxButtonActor_))return;vtkNew<vtkTextActor> textActor;textActor->SetInput("Hide Bounding Box");vtkTextProperty *textProp = textActor->GetTextProperty();textProp->SetFontSize(24);textProp->SetColor(0.0, 0.0, 0.0);           // 黑色文字textProp->SetBackgroundColor(0.8, 0.8, 0.8); // 灰色背景textProp->SetBackgroundOpacity(1.0);textProp->SetFrame(1);textProp->SetFrameColor(0.0, 0.0, 0.0);textActor->SetDisplayPosition(10, 10);renderer_->AddActor2D(textActor);boundingBoxButtonActor_ = textActor;// 注册鼠标点击事件(只注册一次)static bool observerAdded = false;if (!observerAdded){vtkNew<vtkCallbackCommand> clickCallback;clickCallback->SetClientData(this);clickCallback->SetCallback([](vtkObject *caller, unsigned long, void *clientData, void *){auto *self = static_cast<ThreeDimensionalDisplayPage *>(clientData);int *clickPos = static_cast<vtkRenderWindowInteractor *>(caller)->GetEventPosition();int x = clickPos[0];int y = clickPos[1];// 判断是否点击在按钮上(近似判断)int *pos = self->boundingBoxButtonActor_->GetPositionCoordinate()->GetComputedDisplayValue(self->renderer_);int btnX = pos[0];int btnY = pos[1];int width = 220, height = 40;if (x >= btnX && x <= btnX + width &&y >= btnY && y <= btnY + height){self->OnBoundingBoxButtonClicked();} });interactor_->AddObserver(vtkCommand::LeftButtonPressEvent, clickCallback);observerAdded = true;}isBoundingBoxVisible_ = true;
}

点击按钮之后的槽函数


void ThreeDimensionalDisplayPage::OnBoundingBoxButtonClicked()
{if (!boundingBoxActor_)return;isBoundingBoxVisible_ = !isBoundingBoxVisible_;boundingBoxActor_->SetVisibility(isBoundingBoxVisible_);if (boundingBoxButtonActor_){boundingBoxButtonActor_->SetInput(isBoundingBoxVisible_ ? "Hide Bounding Box" : "Show Bounding Box");}renderWindow_->Render();
}

添加坐标轴

需要的全局变量,防止重复创建

    // 坐标轴显示vtkSmartPointer<vtkAxesActor> axes_;vtkSmartPointer<vtkOrientationMarkerWidget> marker_;

创建坐标轴

void ThreeDimensionalDisplayPage::addCoordinateAxes()
{if (!axes_)axes_ = vtkSmartPointer<vtkAxesActor>::New();axes_->SetTotalLength(10.0, 10.0, 10.0);if (!marker_)marker_ = vtkSmartPointer<vtkOrientationMarkerWidget>::New();marker_->SetOrientationMarker(axes_);marker_->SetOutlineColor(0.9300, 0.5700, 0.1300);marker_->SetInteractor(m_pScene->GetInteractor());marker_->SetDefaultRenderer(renderer_);marker_->SetViewport(0.8, 0.0, 1.0, 0.2);marker_->SetEnabled(1);marker_->InteractiveOn();
}

增加点线面显隐控制按钮

需要的全局变量,防止重复创建

    // 添加控制点线面显隐的按钮到三维显示界面void addObjVisibilityControlButtons();// 控制面显示槽函数void toggleSurfaceVisibility();// 控制线显示槽函数void toggleWireframeVisibility();// 控制点显示槽函数void togglePointsVisibility();// 控制obj点线面的显隐vtkSmartPointer<vtkActor> surfaceActor_;vtkSmartPointer<vtkActor> wireframeActor_;vtkSmartPointer<vtkActor> pointsActor_;// 控制obj点线面显隐的按钮vtkSmartPointer<vtkTextActor> surfaceToggleButton_;vtkSmartPointer<vtkTextActor> wireframeToggleButton_;vtkSmartPointer<vtkTextActor> pointsToggleButton_;

添加控制点线面显隐的按钮到三维显示界面

void ThreeDimensionalDisplayPage::addObjVisibilityControlButtons()
{// 如果已经创建过按钮,则直接重新添加到 renderer_if (surfaceToggleButton_){surfaceToggleButton_->SetInput("Hide Surface");wireframeToggleButton_->SetInput("Hide Wireframe");pointsToggleButton_->SetInput("Hide Points");renderer_->AddActor2D(surfaceToggleButton_);renderer_->AddActor2D(wireframeToggleButton_);renderer_->AddActor2D(pointsToggleButton_);return;}// 按钮文字及初始状态std::vector<std::pair<std::string, vtkSmartPointer<vtkTextActor> *>> buttons = {{"Hide Surface", &surfaceToggleButton_},{"Hide Wireframe", &wireframeToggleButton_},{"Hide Points", &pointsToggleButton_}};int startY = 60; // 初始 Y 位置for (auto &[text, actorPtr] : buttons){auto textActor = vtkSmartPointer<vtkTextActor>::New();textActor->SetInput(text.c_str());auto *textProp = textActor->GetTextProperty();textProp->SetFontSize(20);textProp->SetColor(0.0, 0.0, 0.0);textProp->SetBackgroundColor(0.9, 0.9, 0.9);textProp->SetBackgroundOpacity(1.0);textProp->SetFrame(1);textProp->SetFrameColor(0.0, 0.0, 0.0);textActor->SetDisplayPosition(10, startY);renderer_->AddActor2D(textActor);*actorPtr = textActor;startY += 50; // 下一个按钮向下偏移}// 注册鼠标事件(只注册一次)static bool observerAdded = false;if (!observerAdded){vtkNew<vtkCallbackCommand> clickCallback;clickCallback->SetClientData(this);clickCallback->SetCallback([](vtkObject *caller, unsigned long, void *clientData, void *){auto* self = static_cast<ThreeDimensionalDisplayPage*>(clientData);int* clickPos = static_cast<vtkRenderWindowInteractor*>(caller)->GetEventPosition();int x = clickPos[0];int y = clickPos[1];std::vector<std::pair<vtkSmartPointer<vtkTextActor>, std::function<void()>>> buttons = {{self->surfaceToggleButton_, [&]() { self->toggleSurfaceVisibility(); }},{self->wireframeToggleButton_, [&]() { self->toggleWireframeVisibility(); }},{self->pointsToggleButton_, [&]() { self->togglePointsVisibility(); }}};for (auto& [actor, func] : buttons){int* pos = actor->GetPositionCoordinate()->GetComputedDisplayValue(self->renderer_);int bx = pos[0];int by = pos[1];int width = 200, height = 40;if (x >= bx && x <= bx + width &&y >= by && y <= by + height){func();break;}} });interactor_->AddObserver(vtkCommand::LeftButtonPressEvent, clickCallback);observerAdded = true;}
}

控制面显示槽函数


void ThreeDimensionalDisplayPage::toggleSurfaceVisibility()
{if (surfaceActor_){bool visible = surfaceActor_->GetVisibility();surfaceActor_->SetVisibility(!visible);if (surfaceToggleButton_)surfaceToggleButton_->SetInput(visible ? "Show Surface" : "Hide Surface");renderWindow_->Render();}
}

控制线显示槽函数

void ThreeDimensionalDisplayPage::toggleWireframeVisibility()
{if (wireframeActor_){bool visible = wireframeActor_->GetVisibility();wireframeActor_->SetVisibility(!visible);if (wireframeToggleButton_)wireframeToggleButton_->SetInput(visible ? "Show Wireframe" : "Hide Wireframe");renderWindow_->Render();}
}

控制点显示槽函数


void ThreeDimensionalDisplayPage::togglePointsVisibility()
{if (pointsActor_){bool visible = pointsActor_->GetVisibility();pointsActor_->SetVisibility(!visible);if (pointsToggleButton_)pointsToggleButton_->SetInput(visible ? "Show Points" : "Hide Points");renderWindow_->Render();}
}

也可以使用qpushbutton进行控制,逻辑更加简单,不需要场景里添加按钮了,创建按钮后直接连接toggleSurfaceVisibility即可。

相关文章:

VTK|结合qt创建通用按钮控制显隐(边框、坐标轴、点线面)

文章目录 增加边框BoundingBox添加addBoundingBox添加BoundingBox控制按钮点击按钮之后的槽函数 添加坐标轴增加点线面显隐控制按钮添加控制点线面显隐的按钮到三维显示界面控制面显示槽函数控制线显示槽函数控制点显示槽函数 增加边框BoundingBox 增加边框BoundingBox并通过按…...

CentOS 7.9 安装详解:手动分区完全指南

CentOS 7.9 安装详解&#xff1a;手动分区完全指南 为什么需要手动分区&#xff1f;CentOS 7.9 基本分区说明1. /boot/efi 分区2. /boot 分区3. swap 交换分区4. / (根) 分区 可选分区&#xff08;进阶设置&#xff09;5. /home 分区6. /var 分区7. /tmp 分区 分区方案建议标准…...

在过滤器中获取body中的json数据并且使得后续的controller层也能获取使用

前景提示&#xff1a; ①我需要在filter中获取到json数据->对key名首字母进行排序&#xff0c;然后拼接&#xff0c;进行验签 ②所以就需要在filer获取到json的数据&#xff0c;因为请求数据是一次性读取的流。如果过滤器中调用了request.json或request.get_json()&#xff…...

如何使用测试软件 Jmeter

第一步&#xff0c;点击 编辑 添加线程组 第二步&#xff0c;右键单击线程组&#xff0c;添加取样器 HTTP 请求 第三步&#xff0c;设置请求路径 第四步&#xff0c;添加 查看结果树 用于查看请求响应 最后点击绿色小三角启动即可...

2025盘古石初赛WP

来不及做&#xff0c;还有n道题待填坑 文章目录 手机取证 Mobile Forensics分析安卓手机检材&#xff0c;手机的IMSI是&#xff1f; [答案格式&#xff1a;660336842291717]养鱼诈骗投资1000&#xff0c;五天后收益是&#xff1f; [答案格式&#xff1a;123]分析苹果手机检材&a…...

系统分析与设计期末复习

第一章 系统的五个特性 整体性、目的性、相关性、环境适应性、层次性 软件系统的四个特性 复杂性、一致性、可变性、不可见性 第二章 系统规划 系统开发生命周期 系统规划->系统分析->系统设计->系统实施->系统运行维护->系统规划 诺兰阶段模型 阶段&a…...

最大公约数gcd和最小公倍数lcm

一、相关公式及其性质 文章只服务于竞赛&#xff0c;所以不会涉及证明。 辗转相除法&#xff1a;gcd(a, b) gcd(b, a % b); 直到 b 0&#xff0c;就可以知道上一层递归中的 a % b 0&#xff0c;所以上一层的 b 就是答案&#xff0c;也就是这一层递归的 a gcd(a, b) * lcm…...

IBM BAW(原BPM升级版)使用教程第八讲

续前篇&#xff01; 一、流程开发功能模块使用逻辑和顺序 前面我们已经对 流程、用户界面、公开的自动化服务、服务、事件、团队、数据、性能、文件各个模块进行了详细讲解&#xff0c;现在统一进行全面统一讲解。 在 IBM Business Automation Workflow (BAW) 中&#xff0c;…...

视觉革命来袭!ComfyUI-LTXVideo 让视频创作更高效

探索LTX-Video 支持的ComfyUI 在数字化视频创作领域&#xff0c;视频制作效果的提升对创作者来说无疑是一项重要的突破。LTX-Video支持的ComfyUI便是这样一款提供自定义节点的工具集&#xff0c;它专为改善视频质量、提升生成速度而开发。接下来&#xff0c;我们将详细介绍其功…...

从电动化到智能化,法雷奥“猛攻”中国汽车市场

当前&#xff0c;全球汽车产业正在经历前所未有的变革&#xff0c;外资Tier1巨头开始向中国智能电动汽车市场发起新一轮“猛攻”。 在4月23日-5月2日上海国际车展期间&#xff0c;博世、采埃孚、大陆集团、法雷奥等全球百强零部件厂商纷纷发布战略新品与转型计划。在这其中&am…...

鸿蒙开发——3.ArkTS声明式开发:构建第一个ArkTS应用

鸿蒙开发——3.ArkTS声明式开发:构建第一个ArkTS应用 一、创建ArkTS工程二、ArkTS工程目录结构&#xff08;Stage模型&#xff09;三、构建第一个页面四、构建第二个页面五、实现页面之间的跳转六、模拟器运行 一、创建ArkTS工程 1、若首次打开DevEco Studio&#xff0c;请点击…...

word换行符和段落标记

换行符&#xff1a;只换行不分段 作用&#xff1a;我们需要对它进行分段&#xff0c;但它是一个信息群组&#xff0c;我希望它们有同样的段落格式&#xff01; 快捷键&#xff1a;shiftenter 段落标记&#xff1a;分段 快捷键&#xff1a;enter 修改字体格式或段落格式 …...

AI时代的数据可视化:未来已来

你有没有想过&#xff0c;数据可视化在未来会变成什么样&#xff1f;随着人工智能&#xff08;AI&#xff09;的飞速发展&#xff0c;数据可视化已经不再是简单的图表和图形&#xff0c;而是一个充满无限可能的智能领域。AI时代的可视化不仅能自动解读数据&#xff0c;还能预测…...

spark基本介绍

Spark 是基于内存计算的分布式大数据处理框架&#xff0c;由加州大学伯克利分校 AMPLab 开发&#xff0c;现已成为 Apache 顶级项目。以下是其核心要点&#xff1a; 核心特点 1. 内存计算&#xff1a;数据可驻留内存&#xff0c;大幅提升迭代计算&#xff08;如机器学习、图计算…...

深入理解 TCP:重传机制、滑动窗口、流量控制与拥塞控制

TCP&#xff08;Transmission Control Protocol&#xff09;是一个面向连接、可靠传输的协议&#xff0c;支撑着绝大多数互联网通信。在实现可靠性的背后&#xff0c;TCP 引入了多个关键机制&#xff1a;重传机制、滑动窗口、流量控制 和 拥塞控制。这些机制共同协作&#xff0…...

MySQL 窗口函数入门到精通

目录 常用窗口函数速查表 1. 什么是"窗口"&#xff08;不是你想的那种窗口&#xff09; "窗口"≠电脑界面的窗口 那么&#xff0c;SQL 中的"窗口"是什么&#xff1f; 用表格形式理解"窗口"概念 2. 窗口函数解决了什么问题 场景…...

uniapp-商城-51-后台 商家信息(logo处理)

前面对页面基本进行了梳理和说明&#xff0c;特别是对验证规则进行了阐述&#xff0c;并对自定义规则的兼容性进行了特别补充&#xff0c;应该说是干货满满。不知道有没有小伙伴已经消化了。 下面我们继续前进&#xff0c;说说页面上的logo上传组件&#xff0c;主要就是uni-fil…...

✍️【TS类型体操进阶】挑战类型极限,成为类型魔法师!♂️✨

哈喽类型战士们&#xff01;今天我们要玩转TS类型体操&#xff0c;让你的类型系统像体操运动员一样灵活优雅~ 学会这些绝招&#xff0c;保准你的代码类型稳如老狗&#xff01;&#xff08;文末附类型体操段位表&#xff09;&#x1f680; 一、什么是类型体操&#xff1f; &…...

联邦学习图像分类实战:基于FATE与PyTorch的隐私保护机器学习系统构建指南

引言 在数据孤岛与隐私保护需求并存的今天&#xff0c;联邦学习&#xff08;Federated Learning&#xff09;作为分布式机器学习范式&#xff0c;为医疗影像分析、金融风控、智能交通等领域提供了创新解决方案。本文将基于FATE框架与PyTorch深度学习框架&#xff0c;详细阐述如…...

springboot 加载 tomcat 源码追踪

加载 TomcatServletWebServerFactory 从 SpringApplication.run(&#xff09;方法进入 进入到 refresh () 方法 选择实现类 ServletWebServerApplicationContext 进入到 AbstractApplicationContext onRefresh() 方法创建容器 找到加载bean 得到 webServer 实例 点击 get…...

AI实战笔记(1)AI 的 6 大核心方向 + 学习阶段路径

一、机器学习&#xff08;ML&#xff09; 目标&#xff1a;用数据“训练”模型&#xff0c;完成分类、回归、聚类等任务。 学习阶段&#xff1a; &#xff08;1&#xff09;基础数学&#xff1a;线性代数、概率统计、微积分&#xff08;适度&#xff09; &#xff08;2&#xf…...

使用countDownLatch导致的线程安全问题,线程不安全的List-ArrayList,线程安全的List-CopyOnWriteArrayList

示例代码 package com.example.demo.service;import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;public class UnSafeCDTest {Executor…...

C++ - 仿 RabbitMQ 实现消息队列(1)(环境搭建)

C - 仿 RabbitMQ 实现消息队列&#xff08;1&#xff09;&#xff08;环境搭建&#xff09; 什么是消息队列核心特点核心组件工作原理常见消息队列实现应用场景优缺点 项目配置开发环境技术选型 更换软件源安装一些工具安装epel 软件源安装 lrzsz 传输工具安装git安装 cmake安装…...

66、微服务保姆教程(九)微服务的高可用性

微服务的高可用性与扩展 服务的高可用性 集群搭建与负载均衡。服务的故障容错与自愈。分布式事务与一致性 分布式事务的挑战与解决方案。使用 RocketMQ 实现分布式事务。微服务的监控与可观测性 metrics 和日志的收集与分析。sentinel 的监控功能。容器化与云原生 将微服务部署…...

RK3568-OpenHarmony(1) : OpenHarmony 5.1的编译

概述: 本文主要描述了&#xff0c;如何在ubuntu-20.04操作系统上&#xff0c;编译RK3568平台的OpenHarmony 5.1版本。 搭建编译环境 a. 安装软件包 sudo apt-get install git-lfs ruby genext2fs build-essential git curl libncurses5-dev libncursesw5-dev openjdk-11-jd…...

eFish-SBC-RK3576工控板外部RTC测试操作指南

备注&#xff1a; 1&#xff09;测试时一定要接电池&#xff0c;否则外部RTC断电后无法工作导致测试失败&#xff1b; 2&#xff09;如果连接了网络&#xff0c;系统会自动同步NTP时钟&#xff0c;所以需要关闭自动同步时钟。 关闭自动同步NTP时钟方法&#xff1a; 先查看是…...

vue3的深入组件-组件 v-model

组件 v-model 基本用法​ v-model 可以在组件上使用以实现双向绑定。 从 Vue 3.4 开始&#xff0c;推荐的实现方式是使用 defineModel() 宏&#xff1a; <script setup> const model defineModel()function update() {model.value } </script><template>…...

【MySQL】数据库、数据表的基本操作

个人主页&#xff1a;Guiat 归属专栏&#xff1a;MySQL 文章目录 1. MySQL基础命令1.1 连接MySQL1.2 基本命令概览 2. 数据库操作2.1 创建数据库2.2 查看数据库2.3 选择数据库2.4 修改数据库2.5 删除数据库2.6 数据库备份与恢复 3. 表操作基础3.1 创建表3.2 查看表信息3.3 创建…...

TCP的连接管理

三次握手 什么是三次握手&#xff1f; 1. 第一次握手&#xff08;客户端 → 服务器&#xff09; 客户端发送一个 SYN 报文&#xff0c;请求建立连接。 报文中包含一个初始序列号 SEQ x。 表示&#xff1a;我想和你建立连接&#xff0c;我的序列号是 x。 2. 第二次握手&a…...

DAMA第10章深度解析:参考数据与主数据管理的核心要义与实践指南

引言 在数字化转型的浪潮中&#xff0c;数据已成为企业的核心资产。然而&#xff0c;数据孤岛、冗余和不一致问题严重制约了数据价值的释放。DAMA&#xff08;数据管理协会&#xff09;提出的参考数据&#xff08;Reference Data&#xff09;与主数据&#xff08;Master Data&…...