QT -CloudViewer工具

QT -CloudViewer工具

  • 一、演示效果
  • 二、关键程序
  • 三、程序下载


一、演示效果

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

二、关键程序

void CloudViewer::doOpen(const QStringList& filePathList) {
  // Open point cloud file one by one
  for (int i = 0; i != filePathList.size(); i++) {
    timeStart(); // time start
    mycloud.cloud.reset(new PointCloudT); // Reset cloud
    QFileInfo fileInfo(filePathList[i]);
    std::string filePath = fromQString(fileInfo.filePath());
    std::string fileName = fromQString(fileInfo.fileName());

    // begin loading
    ui.statusBar->showMessage(
      fileInfo.fileName() + ": " + QString::number(i) + "/" + QString::number(filePathList.size())
      + " point cloud loading..."
    );

    mycloud = fileIO.load(fileInfo);
    if (!mycloud.isValid) {
      // TODO: deal with the error, print error info in console?
      debug("invalid cloud.");
      continue;
    }
    mycloud.viewer = viewer;
    mycloud_vec.push_back(mycloud);

    timeCostSecond = timeOff(); // time off

    consoleLog(
      "Open",
      toQString(mycloud.fileName),
      toQString(mycloud.filePath),
      "Time cost: " + timeCostSecond + " s, Points: " + QString::number(mycloud.cloud->points.size())
    );

    // update tree widget
    QTreeWidgetItem *cloudName = new QTreeWidgetItem(QStringList()
      << toQString(mycloud.fileName));
    cloudName->setIcon(0, QIcon(":/Resources/images/icon.png"));
    ui.dataTree->addTopLevelItem(cloudName);

    total_points += mycloud.cloud->points.size();
  }
  ui.statusBar->showMessage("");
  showPointcloudAdd();
  setPropertyTable();
}

// Open point cloud
void CloudViewer::open() {
  QStringList filePathList = QFileDialog::getOpenFileNames(
    this,
    tr("Open point cloud file"),
    toQString(mycloud.fileDir),
    toQString(fileIO.getInputFormatsStr())
  );
  if (filePathList.isEmpty()) return;

  // Clear cache
  // TODO: abstract a function
  mycloud_vec.clear();
  total_points = 0;
  ui.dataTree->clear();
  viewer->removeAllPointClouds();

  doOpen(filePathList);
}

// Add Point Cloud
void CloudViewer::add() {
  QStringList filePathList = QFileDialog::getOpenFileNames(
    this,
    tr("Add point cloud file"),
    toQString(mycloud.fileDir),
    toQString(fileIO.getInputFormatsStr())
  );
  if (filePathList.isEmpty()) return;

  doOpen(filePathList);
}

// Clear all point clouds
void CloudViewer::clear() {
  mycloud_vec.clear();  // 从点云容器中移除所有点云
  viewer->removeAllPointClouds();  // 从viewer中移除所有点云
  viewer->removeAllShapes(); // 这个remove更彻底
  ui.dataTree->clear();  // 将dataTree清空

  ui.propertyTable->clear();  // 清空属性窗口propertyTable
  QStringList header;
  header << "Property" << "Value";
  ui.propertyTable->setHorizontalHeaderLabels(header);

  // 输出窗口
  consoleLog("Clear", "All point clouds", "", "");

  setWindowTitle("CloudViewer");  // 更新窗口标题
  showPointcloud();  // 更新显示
}

// Save point cloud
void CloudViewer::save() {
  if (!mycloud.isValid) {
    QMessageBox::critical(this, tr("Saving file error"),
      tr("There is no point cloud to save"));
    return;
  }

  // get binary flag from sender()
  QAction *action = qobject_cast<QAction *>(sender());
  QVariant v = action->data();
  bool isSaveBinary = (bool)v.value<bool>();

  QString selectedFilter = toQString(fileIO.outputFiltersMap.at(mycloud.fileSuffix));
  QString saveFilePath = QFileDialog::getSaveFileName(
    this,                                    // parent
    toQString("Save point cloud" + string(isSaveBinary ? " (binary)": "")), // caption
    toQString(mycloud.filePath),             // dir
    toQString(fileIO.getOutputFormatsStr()), // filter
    &selectedFilter                          // selected filter
  );
  if (saveFilePath.isEmpty()) return;

  QFileInfo fileInfo(saveFilePath);
  QString saveFileName = fileInfo.fileName();
  string saveFilePathStd = fromQString(saveFilePath);
  string saveFileNameStd = fromQString(saveFileName);

  if (mycloud_vec.size() > 1) {
    savemulti(fileInfo, isSaveBinary);
    return;
  }

  bool saveStatus = fileIO.save(mycloud, fileInfo, isSaveBinary);
  if (!saveStatus) {
    QMessageBox::critical(this, tr("Saving file error"),
      tr("We can not save the file"));
    return;
  }

  consoleLog("Save", saveFileName, saveFilePath, "Single save");

  setWindowTitle(saveFilePath + " - CloudViewer");
  QMessageBox::information(this, tr("save point cloud file"),
    toQString("Save " + saveFileNameStd + " successfully!"));
}

// Save multi point cloud
void CloudViewer::savemulti(const QFileInfo& fileInfo, bool isSaveBinary) {
  string subname = fromQString(fileInfo.fileName());
  QString saveFilePath = fileInfo.filePath();
  PointCloudT::Ptr multi_cloud;
  multi_cloud.reset(new PointCloudT);
  multi_cloud->height = 1;
  int sum = 0;
  for (auto c : mycloud_vec) {
    sum += c.cloud->points.size();
  }
  multi_cloud->width = sum;
  multi_cloud->resize(multi_cloud->height * multi_cloud->width);
  int k = 0;
  for (int i = 0; i != mycloud_vec.size(); ++i) {
    // 注意cloudvec[i]->points.size()和cloudvec[i]->size()的区别
    for (int j = 0; j != mycloud_vec[i].cloud->points.size(); ++j) {
      multi_cloud->points[k].x = mycloud_vec[i].cloud->points[j].x;
      multi_cloud->points[k].y = mycloud_vec[i].cloud->points[j].y;
      multi_cloud->points[k].z = mycloud_vec[i].cloud->points[j].z;
      multi_cloud->points[k].r = mycloud_vec[i].cloud->points[j].r;
      multi_cloud->points[k].g = mycloud_vec[i].cloud->points[j].g;
      multi_cloud->points[k].b = mycloud_vec[i].cloud->points[j].b;
      k++;
    }
  }

  MyCloud multiMyCloud;
  multiMyCloud.cloud = multi_cloud;
  multiMyCloud.isValid = true;

  // save multi_cloud
  bool saveStatus = fileIO.save(multiMyCloud, fileInfo, isSaveBinary);
  if (!saveStatus) {
    QMessageBox::critical(this, tr("Saving file error"),
      tr("We can not save the file"));
    return;
  }

  if (isSaveBinary) {
    consoleLog("Save as binary", QString::fromLocal8Bit(subname.c_str()), saveFilePath, "Multi save (binary)");
  } else {
    consoleLog("Save", QString::fromLocal8Bit(subname.c_str()), saveFilePath, "Multi save");
  }

  // 将保存后的 multi_cloud 设置为当前 mycloud,以便保存之后直接进行操作
  mycloud.cloud = multi_cloud;
  mycloud.filePath = fromQString(saveFilePath);
  mycloud.fileName = subname;

  setWindowTitle(saveFilePath + " - CloudViewer");
  QMessageBox::information(this, tr("save point cloud file"), toQString("Save " + subname + " successfully!"));
}

三、程序下载

https://download.csdn.net/download/u013083044/88628664

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/243992.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

年度巅峰对决:实在智能斩获36氪WISE2023未来商业之王!

近日&#xff0c;36氪「WISE2023商业之王大会」在北京盛大举办&#xff0c;「WISE2023商业之王 年度企业系列名册」随之正式重磅发布&#xff0c;实在智能作为中国AI准独角兽和RPA行业头部企业、超自动化解决方案提供商&#xff0c;凭借较强的综合实力登榜并荣获“WISE2023 未来…

Android蓝牙协议栈fluoride(六) - 设备管理(bt application)

在Android蓝牙协议栈fluoride(五) - 设备管理(bt application)中描述了设备管理中的API、状态机以及事件处理&#xff0c;接下来将描述设备管理中的功耗管理和上报到上层的事件。 功耗管理 连接策略 蓝牙设备有很大比例都是带电池的产品&#xff0c;那么功耗的高低直接决定了…

位1的个数

题目链接 位1的个数 题目描述 注意点 输入必须是长度为 32 的 二进制串 解答思路 位运算判断每一位是否为1 代码 public class Solution {// you need to treat n as an unsigned valuepublic int hammingWeight(int n) {int res 0;for (int i 0; i < 32; i) {res …

Java并发编程基础总结

进程和线程概念 什么进程 进程是系统运行的基本单位&#xff0c;通俗的理解我们计算机启动的每一个应用程序都是一个进程。如下图所示&#xff0c;在Windows中这一个个exe文件&#xff0c;都是一个进程。而在JVM下&#xff0c;每一个启动的Main方法都可以看作一个进程。 什么…

.Net Reactor 使用心得

主密钥是干嘛的&#xff1f; 1 若要创建有效的许可证文件&#xff0c;必须使用与用于生成受.NET Reactor保护的输出相同的主密钥来创建许可证。 2 主密钥是在创建项目时生成的&#xff01;必须保存该项目才能保留原始密钥。 dll而不是exe 由于使用的是.net6 生成的代码。 …

极智项目 | 实战烟雾火焰检测

欢迎关注我的公众号 [极智视界]&#xff0c;获取我的更多项目分享 大家好&#xff0c;我是极智视界&#xff0c;本文来介绍 实战烟雾火焰检测。 本文介绍的 实战烟雾火焰检测项目&#xff0c;提供完整的可以一键执行的项目工程源码&#xff0c;获取方式有两个&#xff1a; (1…

【离散数学】——期末刷题题库(欧拉图和哈密顿图)

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…

Springboot整合阿里云短信服务

目录 1.注册登录用户 2.点击AccessKey管理&#xff0c;开通使用子用户AccessKey 2.1点击进入AccessKey管理 2.2点击用户创建用户 2.3选择控制台创建 2.4权限修改 3.短信服务 4.创建Springboot项目使用SDK 4.1创建一个springboot项目 4.2导入阿里云短信Maven依赖 4.3…

唇彩行业分析:我国彩妆细分品类市场占比63%

唇部彩妆是指在唇部起到化妆修饰作用的产品&#xff0c;包括口红/唇膏、唇蜜/唇彩/唇釉、唇笔/唇线笔、唇泥四大类。总体来看&#xff0c;目前我国唇部彩妆细分品类主要集中在唇膏/口红、唇蜜/唇彩/唇釉。唇笔/唇线笔市场接受程度较低&#xff0c;这是由于唇笔/唇线笔的主要成分…

shell脚本定时自动备份mysql数据库和mysql恢复数据

1、设置一些测试的数据 创建一个database&#xff0c;一些tables和一些数据 create database test_bom default charset utf8 collate utf8_general_ci; use test_bom;create table users( id int not null primary key auto_increment, name varchar(64) not null, password…

通俗易懂:插入排序算法全解析(C++)

插入排序算法是一种简单直观的排序算法&#xff0c;它的原理就像我们玩扑克牌时整理手中的牌一样。下面我将用通俗易懂的方式来解释插入排序算法的工作原理。 假设我们手上有一副无序的扑克牌&#xff0c;我们的目标是将它们从小到大排列起来。插入排序算法的思想是&#xff0…

web实习三_JavaScript编程

编写 JavaScript 程序实现 输出“九九乘法表”&#xff08; 左下三角形形式 &#xff09;。 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, …

qiankun中子系统变化透传到主系统调用主系统方法

1、首先在主系统中qiankun启动前把变动的参数初始化 2、初始化之后就可以通过全局状态通信把参数透传为全局 3、在微应用子系统main.js的qiankun的mount中获取到全局设备参数属性并是设置为子系统全局 4、在微应用子系统中需要去调主系统方法时就在那个地方改变透传过来的参数 …

如何性能测试中进行业务验证?

在性能测试过程中&#xff0c;验证HTTP code和响应业务code码是比较基础的&#xff0c;但是在一些业务中&#xff0c;这些参数并不能保证接口正常响应了&#xff0c;很可能返回了错误信息&#xff0c;所以这个时候对接口进行业务验证就尤其重要。下面分享一个对某个资源进行业务…

ros2+在Ubuntu上安装gazebo

Binary Installation on Ubuntu(Ubuntu上binary方式安装gazebo) Harmonic binaries are provided for Ubuntu Jammy (22.04) and Ubuntu 24.04 (when its released). &#xff08;在Ubuntu22.04或者24.04上都是安装Harmonic版本的gazebo&#xff09;The Harmonic binaries are…

issue unit

The Issue Unit issue queue用来hold住&#xff0c;已经dispatched&#xff0c;但是还没有执行的uops&#xff1b; 当一条uop的所有的operands已经ready之后&#xff0c;request请求会被拉起来&#xff1b;然后issue select logic将会从request bit 1的slot中&#xff0c;选择…

指令寻址(顺序寻址和跳跃寻址)

目录 一. 顺序寻址1.1 定长指令字结构1.2 变长指令字结构 二. 跳跃寻址 \quad 指令寻址:如何确定下一条指令的存放地址? \quad 一. 顺序寻址 \quad 1.1 定长指令字结构 \quad 主存按字编址 \quad 按字节编址 1.2 变长指令字结构 \quad 同种颜色代表一条指令 由于无法判断当前…

制衣厂生产ERP系统怎么样?制衣厂生产ERP软件哪个好

有很多的制衣厂在订单处理、物料、仓储、销售、仓储、物料编码、车间成本核算、计件工资核算等方面还存在不少改进空间。 而经过多年的发展&#xff0c;现如今制衣行业的竞争比较激烈&#xff0c;如何提升各业务部门协同效率&#xff0c;减少车间物料损耗&#xff0c;简化生产…

idea的快捷键

1.调整字体的大小 文件夹的循序:setting-Editor-Font 界面: 2.删除当前行 文件夹的循序:setting-Keymap-DeleteLine 界面: 3.导入该行需要的类 文件夹的循序:setting-Editor-General-Auto import 界面: 4.格式化代码 文件夹的循序:setting-keymap-Reformat 界面: 5.快速…

【MySQL】——数据类型及字符集

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…