【VTK】VTK框选表面拾取面片——仅选中前表面

2023-05-16

VTK框选表面拾取面片——仅选中前表面


接上一篇 VTK框选表面拾取三角面片——通过观察者命令模式

上一篇最后遗留一个问题,框选表面后,会把模型背面的面片也一起选中。所以这篇内容是解决该问题的。


效果预览

在这里插入图片描述
在这里插入图片描述


功能说明

通过鼠标框选模型表面的面片,然后利用红色边框显示被框选的三角面片,实现仅选中前表面部分的面片,不会把背面的面片也选中


方法介绍

  • 利用vtkInteractorStyleRubberBandPick交互方式实现框选。(通过R键切换交互模式和框选模式)

  • 利用vtkAreaPicker收集框选的信息。VTK还提供了vtkCellPicker,但是CellPicker只能选中某个对象,不能框选一个集合。

  • 使用vtkCellLocator中的IntersectWithLine函数,用光线投射法寻找靠近摄像头一侧的面片cell,然后利用vtkPolyDataConnectivityFilter找出与最近面片cell相连的表面,该表面即要显示的前表面。

  • 源代码中已经写好详细注释。


源代码

完整代码可以直接编译运行

#include <vtkPolyData.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkInteractorStyleRubberBandPick.h>
#include <vtkAreaPicker.h>
#include <vtkCommand.h>
#include <vtkCallbackCommand.h>
#include <vtkIdFilter.h>
#include <vtkExtractPolyDataGeometry.h>
#include <vtkSphereSource.h>
#include <vtkPlanes.h>
#include <vtkDataSetMapper.h>
#include <vtkProperty.h>
#include <vtkCellLocator.h>
#include <vtkCamera.h>
#include <vtkPolyDataConnectivityFilter.h>

/*
* 定义命令:
* 使用vtkInteractorStyleRubberBandPick交互方式时,会自动触发vtkAreaPicker
* 交互时框选的信息会存储在vtkAreaPicker中
* 将vtkAreaPicker的结束拾取事件绑定vtkPickerCallback
* 类似QT中信号与槽的机制
* vtkAreaPicker触发结束拾取信号,然后执行vtkPickerCallback中的Execute函数
*/
class vtkPickerCallback : public vtkCommand
{
public:
	//@brief 定义New函数(固定格式)
	static vtkPickerCallback* New() {return new vtkPickerCallback;}
	//@brief 定义Execute函数(vtkCommand中的Execute为纯虚函数,必须要实现)
	virtual void Execute(vtkObject* caller, unsigned long, void*);
	void SetPolyData(vtkPolyData* input);
	void SetRenderer(vtkRenderer* input);
	
private:
	vtkPolyData* polyData;				//需要处理的几何数据
	vtkRenderer* renderer;				//需要调用的渲染器

	vtkDataSetMapper* mapper;			//用于显示框选面片的mapper
	vtkActor* actor;					//用于显示框选面片的actor
};

int main()
{
	//****************创建球体*****************
	vtkSphereSource* sphere = vtkSphereSource::New();
	sphere->SetThetaResolution(18);
	sphere->SetPhiResolution(18);
	sphere->SetRadius(10);
	sphere->SetCenter(0, 0, 0);
	sphere->Update();

	//****************创建Mapper***************
	vtkPolyDataMapper* mapper = vtkPolyDataMapper::New();
	mapper->SetInputConnection(sphere->GetOutputPort());
	//换成此语句效果一致:mapper->SetInputData(sphere->GetOutput());
	
	//****************创建Actor****************
	vtkActor* actor = vtkActor::New();
	actor->SetMapper(mapper);

	//****************创建渲染器***************
	vtkRenderer* renderer = vtkRenderer::New();
	renderer->AddActor(actor);

	//****************创建渲染窗口*************
	vtkRenderWindow* renderWindow = vtkRenderWindow::New();
	renderWindow->AddRenderer(renderer);
	
	//****************创建交互器***************
	vtkRenderWindowInteractor* renderWindowInteractor = vtkRenderWindowInteractor::New();

	//****************创建交互方式*************
	vtkInteractorStyleRubberBandPick* interactorStyle = vtkInteractorStyleRubberBandPick::New();

	//****************创建拾取回调函数*********
	vtkPickerCallback* callback = vtkPickerCallback::New();
	callback->SetPolyData(sphere->GetOutput());
	callback->SetRenderer(renderer);

	//****************创建区域拾取器***********
	vtkAreaPicker* areaPicker = vtkAreaPicker::New();
	areaPicker->AddObserver(vtkCommand::EndPickEvent, callback);		//为“结束拾取”事件绑定“拾取回调函数”
	
	renderWindowInteractor->SetRenderWindow(renderWindow);				//为交互器设置渲染窗口
	renderWindowInteractor->SetInteractorStyle(interactorStyle);		//为交互器设置交互方式
	renderWindowInteractor->SetPicker(areaPicker);						//为交互器设置拾取器

	renderWindowInteractor->Start();

	return 0;
}

void vtkPickerCallback::Execute(vtkObject* caller, unsigned long, void*)
{
	//通过反射获取调用者
	vtkAreaPicker* areaPicker = static_cast<vtkAreaPicker*>(caller);
	//获取框选的视锥体(由六个面组成)
	vtkPlanes* frustum = areaPicker->GetFrustum();
	//提前标记几何数据的CellId(目前没有,用于后面实现删除面片的)
	vtkIdFilter* idFilter = vtkIdFilter::New();
	idFilter->SetInputData(polyData);
	idFilter->SetCellIdsArrayName("OriginalCellId");
	idFilter->Update();
	//提取视锥体内的模型
	vtkExtractPolyDataGeometry* extract = vtkExtractPolyDataGeometry::New();
	extract->SetInputConnection(idFilter->GetOutputPort());
	extract->SetImplicitFunction(frustum);
	extract->Update();
	if (!extract->GetOutput()->GetPolys())
	{
		return;
	}
	//创建面片定位器
	vtkCellLocator* locator = vtkCellLocator::New();
	locator->SetDataSet(extract->GetOutput());
	locator->BuildLocator();
	//----------利用光线投射的方法寻找更靠近摄像机的面片------------
	double rayStart[3];				//光线起点坐标:设置为摄像机位置
	double rayDirection[3];			//光线方向向量:设置为框选数据包围盒的中心
	renderer->GetActiveCamera()->GetPosition(rayStart);
	extract->GetOutput()->GetCenter(rayDirection);
	double xyz[3];
	double t;
	double pcoords[3];
	int subId;
	vtkIdType cellId = -1;			//记录光线击中的面片Id号
	locator->IntersectWithLine(rayStart, rayDirection, 0.0001, t, xyz, pcoords, subId, cellId);
	//-----------利用找到的面片获取相连的面
	vtkPolyDataConnectivityFilter* connectivity = vtkPolyDataConnectivityFilter::New();
	connectivity->SetInputConnection(extract->GetOutputPort());
	connectivity->SetExtractionModeToCellSeededRegions();
	connectivity->InitializeSeedList();
	connectivity->AddSeed(cellId);
	connectivity->Update();
	//设置actor
	mapper->SetInputConnection(connectivity->GetOutputPort());
	mapper->ScalarVisibilityOff();
	actor->GetProperty()->SetColor(1, 0, 0);
	actor->GetProperty()->SetPointSize(5);
	actor->GetProperty()->SetRepresentationToWireframe();
	//渲染器加入显示框选的actor
	renderer->AddActor(actor);

}

void vtkPickerCallback::SetPolyData(vtkPolyData* input)
{
	polyData = input;
}

void vtkPickerCallback::SetRenderer(vtkRenderer* input)
{
	renderer = input;
	//初始化用于显示框选面片的mapper和actor
	mapper = vtkDataSetMapper::New();
	actor = vtkActor::New();
	actor->SetMapper(mapper);
}


存在问题

源代码为了说明算法,所以算法的是实现以精简为目标,因此没有去释放内存。

而且算法会存在小Bug(框选无面片的时候和边缘的时候可能会报警告),通过调整rayStart和rayDirection两个向量来改善。

需要用到该算法的话,别忘了自行Debug完善代码

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【VTK】VTK框选表面拾取面片——仅选中前表面 的相关文章

  • vtk加载rgb点云ply文件和灰白ply文件

    vkt官方的例子是加载灰白的ply文件 但是当项目中用到rgb的ply文件就是显示不出来图像 具体的加载方法如下 vtk加载RGB点云文件 include vtkAutoInit h VTK MODULE INIT vtkRendering
  • VTK-6.3.0编译(支持Qt编程)以及QVTKwidget插件安装

    重新整理一下VTK编译过程 尤其是涉及到Qt方面的选项配置 计算机系统 win10 x64 VTK版本 VTK 6 3 0 Qt版本 Qt 5 4 2 msvc 2013 x64 opengl Cmake版本 Cmake3 5 第一步 创建
  • vtk python3环境安装配置

    vtk python3环境安装配置 安装miniconda 下载地址 https docs conda io en latest miniconda html https docs conda io en latest miniconda
  • 用cmake gui配置VS2022中vs2017工具集

    问题描述 vs2022中安装了vs2017 vs2019等工具集 想用cmake gui配置vs2017编译器进行项目生成 选择 Visual Studio 15 2017会提示找不到 选择Visual Studio 17 2022用的就是
  • VTK笔记-使用vtkUnstructuredGrid类构建非结构化数据

    非结构化数据 非结构化点 非结构化点是在空间中离散随意分布的点 没有拓扑结构 几何机构也是完全没有规则的 非结构化点由顶点和多点的单元组成 非结构化点是一种简单但很重要的数据集类型 在部分可视化工作中会使用它来表示无结构的数据 非结构化网格
  • 关于医学影像中的轴位面(横断面)、冠状面、矢状面

    冠状位矢状位轴位图解 第1页 概述 该页主题为冠状位矢状位轴位图解的图片集 内容包含有冠状位 矢状位 横断位具体怎么辨别 谢谢 ct 解剖 颞骨大体解剖 轴位及冠状位ct断层图像 解剖 颞骨大体解剖 轴位及冠状位ct断层图像 图1 a 矢状
  • vtk中的点云曲面重建

    对于光学扫描设备 如激光雷达 采集到的非规则点云数据 最重要的需求之一就是进行表面重建 Surface Reconstruction 对成片密集分布的点云以三角片拟合 形成连续 精确 良态的曲面表示 目前主流的算法可分为剖分类 组合类和拟合
  • 使用Python+VTK获取3D体渲染模型任意角度切面(更新中)

    目录 效果图 实现目标 安装依赖 Code 其他需求 效果图 废话少说先上效果图 右边红色的plane是想要获取3D模型对应切面的平面 左边是这个切面的切片的图像 实现目标 定义一个任意角度的切面 都能把体绘制模型的这个切面的图像获取 并且
  • Python VTK numpy数据3D可视化

    在Python的3D图像处理中 通常用numpy array来进行非常方便的计算或者转化 这里记录一下numpy数据的VTK可视化基本流程 包括面绘制 Surfase Rendering 和体绘制 Volume Rendering 除去数据
  • VTK(0)---CMake工程

    VTK 0 CMake工程 目录 前言 一 指定cmake版本 二 设置工程 三 针对Qt 自动使用moc uic rcc程序预处理 h文件 ui文件等 四 平台移植问题 五 设置编译模式 六 找到包 七 包含头文件等 八 链接库文件 九
  • VTK配置步骤(WIN7 64位 + VS2012 + VTK-5.10.1)

    前面的废话可以不看 我很啰嗦 由于项目中需要用到VTK 上周三就开始编译VTK源码 中间出现了一系列问题 首先是下载的高版本代码顺利编译后 自己新建的工程总是提示链接错误 尽管所有的库文件都加入了 还是不正确 之后下载了vtk较低版本5 8
  • C++11 chrono计时

    我的C 文章列表 C 中Duration Time point和Clocks 万里归来少年心的博客 CSDN博客 time point C 11中的chrono库 实现时间相关的功能 1 time point time point表示一个时
  • 在同一个 UI 中使用 QVTKWidget 和 QOpenGLWidget?

    我正在开发一个使用自定义子类的项目QOpenGLWidget显示一些效果图 结束时paintGL 它调用小部件的方法update 方法触发重绘事件 如果它可见 现在我想添加一个额外的QVTKWidget到我的用户界面 我通过使用这样的东西来
  • 来自 Fortran 代码的 RECTILINEAR_GRID 的二进制 VTK

    我有一个 fortran 代码来生成二进制 VTK 格式的网格 此代码生成一个二进制 VTK 文件 如下所示 vtk DataFile Version 3 0 vtk output BINARY DATASET RECTILINEAR GR
  • 如何获取 std::vector 中 vtkDoubleArray 的值

    我想复制 a 的元素vtkDoubleArray转换为 C std vector as in 如何将 vtkDoubleArray 转换为 Eigen matrix https stackoverflow com questions 246
  • CMakeExternalProject_Add() 和 FindPackage()

    是否有正确的方法来查找图书馆 通过FindPackage 是用ExternalProject Add 问题是 CMake 无法在 CMake 时找到该库 因为外部库是在编译时构建的 我知道在超级构建中构建库和项目时可以组合这两个 CMake
  • 在 Python 中保存 VTK 中的数据数组

    Question 如何从 Python 中的 VTK 中提取数据集数组并将其保存在新文件中 e g 对于具有幅度数据集的 VTKforce 移位 and current仅提取移位并将其保存在较小的文件中 Problem 我在远程服务器上有数
  • Python/vtk - 在 vtkPolyData 对象中单独设置每个点的大小?

    我使用以下代码来填充点云 如何在vtk中以不同的颜色显示点云 https stackoverflow com questions 7591204 how to display point cloud in vtk in different
  • Qt 创建者 + MITK (Linux)

    我正在尝试使用MITK 与 Qt Creator 我已经通过 ccmake 成功编译并使用了 VTK 和 ITK 我已经编译了 MITK超级建造模式 它下载 CTK VTK ITK 等 然后我就配置好了 我已经用 make 编译了 大约两个
  • Numpy uint8_t 数组到 vtkImageData

    我正在尝试拍摄一个或三个通道的 2D 图像并使用 VTK 中显示它们vtkImageActor 据我了解 要显示的当前帧可以通过调用来更新SetImageData on vtkImageActor并提供一个实例vtkImageData 我已

随机推荐

  • docker run启动镜像容器时忘记添加开机自启动解决方法

    问题描述 在使用以下命令启动mysql容器时 xff0c 忘记添加了 restart 61 always 开启开机自启动 xff0c 导致每次开机 重启后 xff0c 需要重新通过一系列命令手动重启对应的容器 xff0c 极其不方便 doc
  • docker 安装RabbitMQ

    系列文章目录 第一章 RabbitMQ安装 提示 xff1a 写完文章后 xff0c 目录可以自动生成 xff0c 如何生成可参考右边的帮助文档 文章目录 系列文章目录前言一 RabbitMQ安装1 dockerHub 选择镜像2 Cent
  • 记 Content type ‘application/octet-stream‘ not supported

    项目场景 xff1a 实现一个入参方式为 64 RequestPart 43 64 RequestParam files 的接口 xff0c 即该接口要包含文件上传和其它 实体类 入参 示例代码 xff1a 64 PostMapping v
  • Go语言环境搭建

    一 下载开发工具 1 1 Go语言官网 1 2 进入Go官网 xff0c 点击Download xff0c 进入开发工具下载界面 xff0c 根据个人系统选择对应的安装包进行下载 windows 对应下载链接 二 安装开发工具 2 1 双击
  • Go入门教程--Hello,World.

    零 文本编辑器实现Hello World 官方给出的教程主要针对Linux 或Mac系统 但也没关系 xff0c 在windows 中实现也很简单 0 1 创建文件夹 xff0c 名称任意 xff0c 如 xff1a hello 0 2 创
  • 在AWS上开通EC2服务器并部署tomcat

    1 登录aws 2 点击服务 计算 EC2 3 点击启动实例 4 选择linux镜像 5 选择一个实例类型 6 配置实例详细信息 xff0c 保持默认 xff0c 点击下一步 7 添加存储 xff08 选择linux根目录硬盘大小和类型 x
  • android studio gradle 使用阿里源 (修改 settings.gradle)

    默认的地址下载速度极慢 依赖项几个小时也下载不完 改为 阿里源 1分钟就下载ok了 代码 修改根目录中 的 settings gradle 文件 内容 pluginManagement span class token punctuatio
  • 实用!Windows 远程控制 Ubuntu 系统

    点击上方 xff0c 选择 设为星标 优质文章 xff0c 及时送达 上一篇 xff1a 来源 xff1a 头条 互联网上的小蜘蛛 有时需要在实际的电脑上安装Ubuntu的操作系统来搭建免费的网站平台 这就需要使用远程的客户端Windows
  • 并查集——洛谷P3367

    题目描述 如题 xff0c 现在有一个并查集 xff0c 你需要完成合并和查询操作 输入输出格式 输入格式 xff1a 第一行包含两个整数N M xff0c 表示共有N个元素和M个操作 接下来M行 xff0c 每行包含三个整数Zi Xi Y
  • Web项目通过webservice编写一个接口,部署在远程服务器上

    在我的上一片文章中 xff0c 我在本地新建了一个普通的类来编写WebService xff0c 使用终端类 Endpoint 发布这个WebService xff0c 以此来实现让其他类调用这个接口 xff0c 实现接口中定义的功能 通过
  • ubuntu与win10共享LE蓝牙鼠标

    类似的教程网上有很多 xff0c 大部分是找到蓝牙设备目录下info文件中的 linkKey 中的key值复制到win10下注册表中 xff0c 但是对于蓝牙5 0或LE设备来说 xff0c 是没有linKey的 xff0c 这里我也参考了
  • FileZilla搭建FTP服务器图解教程,并允许外网访问NAT内网

    FTP是用来在两台计算机之间传输文件 xff0c 是Internet中应用非常广泛的服务之一 FTP服务是网络中经常采用的资源共享方式之一 FTP协议有PORT和PASV两种工作模式 xff0c 即主动模式和被动模式 今天我分享一个最近我自
  • 十进制转换八进制(C语言基础)

    题目描述编程 xff0c 输入一个 xff11 xff10 进制正整数 xff0c 然后输出它所对应的八进制数 输入无输出无样例输入10样例输出12 include lt stdio h gt int main int num m 61 0
  • 【Godot】对 Godot 节点设计的思考

    对 Godot 中节点设计的思考 单个节点的功能设计的想法 xff0c 体会 Godot 的设计思想 低耦合 设计单个节点可复用的节点时 xff0c 调用方法尽量只对当前节点可获取到的变量或方法进行使用 xff0c 比如我写一个可以控制 K
  • 【Godot】行为树(一)了解与设计行为树代码

    行为树介绍 行为树是个节点树 xff0c 父节点通过不断遍历子节点 xff0c 根据不同类型的节点执行不同的分支 最终调用叶节点执行功能 行为树也不难理解 xff0c 他就像代码逻辑一样 xff0c 只是用节点的方式展现出来 xff0c 而
  • 【Godot 4.0】一个简单的匿名方法的使用lambda

    Godot 4 0 beta3 Godot 4 0 中添加了 lambda 表达式 xff0c 匿名方法等很多方便的特性 xff0c 这里我写个用于扫描目录下所有文件的功能 可以看到代码非常简洁 span class token keywo
  • aur报错(错误:一个或多个文件没有通过有效性检查)

    当我们从aur里安装软件时 xff0c 有时会出现这种报错 xff08 如安装deepin wine wechat xff09 61 61 gt 错误 xff1a 一个或多个文件没有通过有效性检查 xff01 Error downloadi
  • Java使用不同方式获取两个集合List的交集、补集、并集(相加)、差集(相减)

    1 明确概念 首先知道几个单词的意思 xff1a 并集 61 union 交集 61 intersection 补集 61 complement 析取 61 disjunction 减去 61 subtract 1 1 并集 对于两个给定集
  • 【VTK】VTK框选表面拾取三角面片——通过观察者命令模式

    VTK框选拾取三角面片 最近需要实现拾取三角面片的交互功能 xff0c 看了官方示例和网友分享 xff0c 都是使用vtkInteractorStyleRubberBandPick搭配vtkAreaPicker 但是具体实现方法都是选择继承
  • 【VTK】VTK框选表面拾取面片——仅选中前表面

    VTK框选表面拾取面片 仅选中前表面 接上一篇 VTK框选表面拾取三角面片 通过观察者命令模式 上一篇最后遗留一个问题 xff0c 框选表面后 xff0c 会把模型背面的面片也一起选中 所以这篇内容是解决该问题的 效果预览 功能说明 通过鼠