cloud compare 学习利用CC代码加快插件开发与总结(三)

2024-08-23 21:36

本文主要是介绍cloud compare 学习利用CC代码加快插件开发与总结(三),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

建议看过前面的文章后,再开始本文的学习

  1. cloud compare二次插件化功能开发详细步骤(一)_cloudcompare插件开发-CSDN博客

  2. cloud compare PCA插件开发详细步骤(二)附代码-CSDN博客

本文完成一个点云变换的插件,同时也是对CC接口的使用做进一步说明,进一步理解CC插件开发流程,学会利用已有CC代码完成插件开发

这个功能是 cc 已有的功能,位于 edit->apply_transformation 这里

文件逻辑组织还和 cloud compare PCA插件开发详细步骤(二)附代码-CSDN博客 中一致,不多赘述

插件全部代码放在 github ,即插即用,欢迎 star

如需帮助,或有问题,欢迎留言、私信或加群【群号:392784757】

ui 层面【从CC搬运并修改】

这里选择从cc搬运修改,还是自行设计再修改,取决于你的插件逻辑 和 CC 已有ui的 相似度

拿到cc源码qCC/ui_templates 下面的 applyTransformationDlg.ui 和对应的qcc下面的 .h .cpp

image-20240823145623247

进行修改,我们只保留第一个使用Matrix 变换的tab,其他删除

image-20240823145137206

也就只保留一个 Matrix 4x4 tab

对应ui的 .h 文件 和 .cpp 进行处理

因为我们删去了3个tab 涉及到的 qt 组件都没了,需要对涉及到的函数进行 删除

删除基于 3个tab 使用的 组件名进行删,最终保留的函数如下

image-20240823145727091

ui逻辑总结

cc插件用到的ui,设计.ui文件,完成 .h .cpp,ui 逻辑函数,在需要用到的时候使用 xxdlg.exec() ,获取用户的各种输入,传回到 插件主逻辑中;cc采用了继承 ui文件编译后ui_xxxDlg.h 中的 Ui::xxxDialog,来封装一层,这种继承方式,使得声明的xxxDlg可以拿到界面上的所有组件,进而可以获取用户设置的组件值(或者使用函数返回)

ui 界面层

QT_BEGIN_NAMESPACEclass Ui_ApplyTransformationDialog // 各种组件
{// ...
};namespace Ui {class ApplyTransformationDialog: public Ui_ApplyTransformationDialog {};
} // namespace Ui

ui 逻辑层

class ccApplyTransformationDlg : public QDialog, public Ui::ApplyTransformationDialog
{Q_OBJECTpublic://! Default constructorexplicit ccApplyTransformationDlg(QWidget* parent = nullptr);//! Returns input matrixccGLMatrixd getTransformation(bool& applyToGlobal) const;protected:void checkMatrixValidityAndAccept();void onMatrixTextChange();void onRotAngleValueChanged(double);void onEulerValueChanged(double);void onFromToValueChanged(double);void loadFromASCIIFile();void loadFromClipboard();void buttonClicked(QAbstractButton*);protected:void updateAll(const ccGLMatrix& mat, bool textForm = true, bool axisAngleForm = true, bool eulerForm = true, bool fromToForm = true);
};

ui 调用

插件主逻辑中调用,并获取用户的输入值(通过函数方式 ccApplyTransformationDlg.getTransformation() )

ccApplyTransformationDlg ccApplyTransformationDlg(m_app->getMainWindow());
if (!ccApplyTransformationDlg.exec())
{return;
}
bool applyToGlobal = false;
ccGLMatrixd transformMatrix =  ccApplyTransformationDlg.getTransformation(applyToGlobal);

用图说话

image-20240823154604852

接口关系说明

mainwindow.h 继承了 ccMainAppInterface ,这也说明了 cc 就是使用的插件化开发范式

image-20240822210601900

插件继承 ccStdPluginInterface

image-20240822210744724

ccStdPluginInterface中 有 ccMainAppInterface的指针 m_app,可以获取到比 ccStdPluginInterface 中更高级的函数

image-20240822210904578

所以 m_app 可以拿到很多有用的方法

  1. 将获取到的点云 从 db_tree 分离 / 放回
  2. zoomOnSelectedEntities()
  3. refreshAll()

但是mainwindow 自定义的方法 确无法直接拿到【但其中也是使用很多基于接口的方法来完成】,需要做本地化修改,对直接使用接口的方法 替换成 用 m_app 调用

所以,理论上 cc 能做的事,我们如果插件逻辑需要用到 都可以拿过来 进行改造后 使用,减少开发,本文便是一个简单示例

插件主逻辑

接下来的插件主逻辑 编写 和

cloud compare PCA插件开发详细步骤(二)附代码-CSDN博客 中 qPCA.cpp 实现部分,实现基本一致,完成

  1. 构造函数
  2. onNewSelection()
  3. getActions()
  4. doAction()

的实现

核心函数【从CC搬运并修改实现】

我们接下来要继续的就是 doAction() 中的核心函数

void applyTransformation(ccMainAppInterface* m_app, const ccGLMatrixd& mat, bool applyToGlobal);

的实现过程

首先我们知道 cc 是已经实现过这个函数的了,在 mainwindow.cpp 中 ,因此先直接搬过来

void MainWindow::applyTransformation(const ccGLMatrixd& mat, bool applyToGlobal)
{}

会发现 很多 报错地方,进行一一解决

void applyTransformation(ccMainAppInterface* m_app, const ccGLMatrixd& mat, bool applyToGlobal)
{}

我们首先删除MainWindow::,增加 插件中使用的接口指针m_app

首先会发现很多 直接调用的函数,报错

包括

getTopLevelSelectedEntities();haveOneSelection();putObjectBackIntoDBTree()zoomOnSelectedEntities();refreshAll();

我们尝试用 m_app 去调用

m_app->putObjectBackIntoDBTree(entity, objContext);
m_app->zoomOnSelectedEntities();
m_app->refreshAll();

可以调用

然后再去看其他函数,发现他们虽不能用 m_app 调用,但他们的实现中也直接或间接用到了 ccMainAppInterface 的方法,因此我们传入 m_app ,进行本地化 替换修改

比如,getTopLevelSelectedEntities(); 修改后

ccHObject::Container getTopLevelSelectedEntities(ccMainAppInterface* m_app)
{// m_selectedEntities 在 mainwindow 是成员变量可以直接获取到 这里我们使用 m_app 进行获取const ccHObject::Container& m_selectedEntities = m_app->getSelectedEntities();ccHObject::Container topLevelSelectedEntities;for (size_t i = 0; i < m_selectedEntities.size(); ++i){ccHObject* entity = m_selectedEntities[i];bool hasParentsInselection = false;for (size_t j = 0; j < m_selectedEntities.size(); ++j){if (i == j)continue;ccHObject* otherEntity = m_selectedEntities[j];if (otherEntity->isAncestorOf(entity)){hasParentsInselection = true;break;}}if (!hasParentsInselection){topLevelSelectedEntities.push_back(entity);}}return topLevelSelectedEntities;
}

其他的一些报错,无关乎主要逻辑的删除即可

一些数据结构报错的,找到对应的头文件引入即可

这样我们的核心函数就修改完成了,往往比自己写的更优秀

在修改的过程 也可以进一步学习cc的逻辑,优化我们之前的写插件的处理思路

如,cc在处理点云时,不直接对 db_tree上点云进行处理,而是从 db_tree 分离后再处理,然后再放回

如需帮助,或有问题,欢迎留言、私信或加群【群号:392784757】

这篇关于cloud compare 学习利用CC代码加快插件开发与总结(三)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1100557

相关文章

Qt实现网络数据解析的方法总结

《Qt实现网络数据解析的方法总结》在Qt中解析网络数据通常涉及接收原始字节流,并将其转换为有意义的应用层数据,这篇文章为大家介绍了详细步骤和示例,感兴趣的小伙伴可以了解下... 目录1. 网络数据接收2. 缓冲区管理(处理粘包/拆包)3. 常见数据格式解析3.1 jsON解析3.2 XML解析3.3 自定义

Java学习手册之Filter和Listener使用方法

《Java学习手册之Filter和Listener使用方法》:本文主要介绍Java学习手册之Filter和Listener使用方法的相关资料,Filter是一种拦截器,可以在请求到达Servl... 目录一、Filter(过滤器)1. Filter 的工作原理2. Filter 的配置与使用二、Listen

Go语言开发实现查询IP信息的MCP服务器

《Go语言开发实现查询IP信息的MCP服务器》随着MCP的快速普及和广泛应用,MCP服务器也层出不穷,本文将详细介绍如何在Go语言中使用go-mcp库来开发一个查询IP信息的MCP... 目录前言mcp-ip-geo 服务器目录结构说明查询 IP 信息功能实现工具实现工具管理查询单个 IP 信息工具的实现服

利用Python调试串口的示例代码

《利用Python调试串口的示例代码》在嵌入式开发、物联网设备调试过程中,串口通信是最基础的调试手段本文将带你用Python+ttkbootstrap打造一款高颜值、多功能的串口调试助手,需要的可以了... 目录概述:为什么需要专业的串口调试工具项目架构设计1.1 技术栈选型1.2 关键类说明1.3 线程模

Python Transformers库(NLP处理库)案例代码讲解

《PythonTransformers库(NLP处理库)案例代码讲解》本文介绍transformers库的全面讲解,包含基础知识、高级用法、案例代码及学习路径,内容经过组织,适合不同阶段的学习者,对... 目录一、基础知识1. Transformers 库简介2. 安装与环境配置3. 快速上手示例二、核心模

Java的栈与队列实现代码解析

《Java的栈与队列实现代码解析》栈是常见的线性数据结构,栈的特点是以先进后出的形式,后进先出,先进后出,分为栈底和栈顶,栈应用于内存的分配,表达式求值,存储临时的数据和方法的调用等,本文给大家介绍J... 目录栈的概念(Stack)栈的实现代码队列(Queue)模拟实现队列(双链表实现)循环队列(循环数组

Python实现图片分割的多种方法总结

《Python实现图片分割的多种方法总结》图片分割是图像处理中的一个重要任务,它的目标是将图像划分为多个区域或者对象,本文为大家整理了一些常用的分割方法,大家可以根据需求自行选择... 目录1. 基于传统图像处理的分割方法(1) 使用固定阈值分割图片(2) 自适应阈值分割(3) 使用图像边缘检测分割(4)

Windows Docker端口占用错误及解决方案总结

《WindowsDocker端口占用错误及解决方案总结》在Windows环境下使用Docker容器时,端口占用错误是开发和运维中常见且棘手的问题,本文将深入剖析该问题的成因,介绍如何通过查看端口分配... 目录引言Windows docker 端口占用错误及解决方案汇总端口冲突形成原因解析诊断当前端口情况解

使用Java将DOCX文档解析为Markdown文档的代码实现

《使用Java将DOCX文档解析为Markdown文档的代码实现》在现代文档处理中,Markdown(MD)因其简洁的语法和良好的可读性,逐渐成为开发者、技术写作者和内容创作者的首选格式,然而,许多文... 目录引言1. 工具和库介绍2. 安装依赖库3. 使用Apache POI解析DOCX文档4. 将解析

C++使用printf语句实现进制转换的示例代码

《C++使用printf语句实现进制转换的示例代码》在C语言中,printf函数可以直接实现部分进制转换功能,通过格式说明符(formatspecifier)快速输出不同进制的数值,下面给大家分享C+... 目录一、printf 原生支持的进制转换1. 十进制、八进制、十六进制转换2. 显示进制前缀3. 指