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

CloudCompare|点测量功能源码分析

文章目录

  • 先从接口类开始分析
      • 🔷 类名:`ccPointPickingGenericInterface`
        • 📌 所在文件:
    • 一、类继承结构:
        • ✅ 父类功能:
    • 二、核心用途:
    • 三、核心成员函数详解:
      • 🔹 构造函数
      • 🔹 bool linkWith(ccGLWindowInterface\* win)
      • 🔹 bool start()
      • 🔹 void stop(bool state)
      • 🔹 void onItemPicked(const PickedItem& pi)
      • 🔹 virtual void processPickedPoint(const PickedItem& picked) = 0;
    • 四、核心成员变量:
    • 五、总结:类的职责定位
    • ✅ 使用场景(CloudCompare 中的实际用法)
  • 再分析一下该接口类继承的两个类
      • 一、`ccOverlayDialog` 分析(继承自 `QDialog`)
        • 📌 定义用途
        • 🔧 核心功能点
      • 二、`ccPickingListener` 分析(接口类)
        • 📌 定义用途
        • 🔧 核心功能点
      • 三、结合继承场景分析
        • ✅ 同时拥有:
        • ✅ 可能用途:
        • ✅ 示例结构:
      • 四、设计总结
  • 最后分析继承该接口的两个类
    • ccPointPropertiesDlg
    • ✅ 类 `ccPointPropertiesDlg` 的职责
    • ✅ 类成员组成
      • 成员变量
      • 成员函数(核心)
        • 继承接口的实现
        • 模式切换槽函数(按钮点击触发)
        • 其他功能
    • ✅ `processPickedPoint` 工作流程详解
    • ✅ `linkWith` 功能说明
    • ✅ 总结:`ccPointPropertiesDlg` 的核心价值
    • 🧩 类功能概述
      • ✅ 核心作用:
    • 🔄 类继承与成员结构
    • 🧠 核心成员与方法说明
      • 1. **构造函数与初始化**
      • 2. **点拾取逻辑处理**
      • 3. **实体关联**
      • 4. **导出功能**
      • 5. **撤销/还原逻辑**
      • 6. **辅助 UI 控制**
      • 7. **数据结构成员变量**
    • ✅ 典型使用流程
    • ccPointListPickingDlg
    • 🧭 和 `ccPointPickingGenericInterface` 的区别?
      • 🌟 核心功能概览
      • ✅ 类的结构简析
        • 构造函数
        • 点列表获取
        • 数据关联
        • 导出功能
        • 撤销与退出
      • 💡 实用细节
        • 标签命名
        • 数据结构维护
      • 🔎 可能的拓展方向建议
      • 🧩 与 CloudCompare 的配合

主要涉及到的类
在这里插入图片描述

先从接口类开始分析

当然可以,我们一起来分析 ccPointPickingGenericInterface 这个接口类,它是 CloudCompare 中用于点选操作相关交互工具的通用基类,代码结构清晰、职责单一,适合作为各种需要鼠标选点功能工具的基类。


🔷 类名:ccPointPickingGenericInterface

📌 所在文件:
  • 头文件:ccPointPickingGenericInterface.h
  • 实现文件:ccPointPickingGenericInterface.cpp

一、类继承结构:

class ccPointPickingGenericInterface : public ccOverlayDialog, public ccPickingListener
✅ 父类功能:
  • ccOverlayDialog:CloudCompare 中所有工具浮窗的基类,提供对话框与渲染窗口的绑定、开始/停止的接口。
  • ccPickingListener:CloudCompare 的拾取回调接口,专门用来监听鼠标选中的点等拾取信息。

二、核心用途:

该类是一个抽象基类(接口类),用于实现所有基于鼠标点选操作的工具。例如:点距离测量工具、基准点选取、投影工具等。

它为这些工具提供了统一的拾取点逻辑框架,具体点选处理逻辑由子类实现。


三、核心成员函数详解:

🔹 构造函数

explicit ccPointPickingGenericInterface(ccPickingHub* pickingHub, QWidget* parent = nullptr);
  • 接收一个 ccPickingHub* 对象,用于注册监听点选事件。
  • ccPickingHub 是点选事件调度中心,可以同时支持多个监听器。

🔹 bool linkWith(ccGLWindowInterface* win)

bool ccPointPickingGenericInterface::linkWith(ccGLWindowInterface* win)
  • 将该拾取界面绑定到一个 ccGLWindowInterface(渲染窗口)。
  • 如果之前绑定了窗口,需要断开旧窗口的信号连接。
  • 注意:ccOverlayDialog::linkWith(win) 是基类实现的绑定逻辑,必须调用。

🔹 bool start()

bool ccPointPickingGenericInterface::start()
  • 启用点选监听器功能。
  • 通过 m_pickingHub->addListener(this, true, true, POINT_PICKING) 注册本对象到 ccPickingHub
  • 会将窗口设置为不可关闭状态,避免误操作。
  • ccOverlayDialog::start() 调用后进入浮窗显示状态。

🔹 void stop(bool state)

void ccPointPickingGenericInterface::stop(bool state)
  • 取消监听点选事件。
  • 将窗口恢复为可关闭状态。
  • 调用 ccOverlayDialog::stop(state) 通知父类退出浮窗状态。

🔹 void onItemPicked(const PickedItem& pi)

void ccPointPickingGenericInterface::onItemPicked(const PickedItem& pi)
  • 实现自 ccPickingListener,当用户通过鼠标在窗口中拾取了一个点,会调用此函数。
  • 调用 processPickedPoint(pi),由子类进一步处理。

🔹 virtual void processPickedPoint(const PickedItem& picked) = 0;

  • 纯虚函数,必须由子类实现。
  • 子类实现具体的拾取点响应逻辑(例如:记录点、更新UI、计算距离等)。

四、核心成员变量:

ccPickingHub* m_pickingHub;
  • 点选事件调度器,管理多个窗口/多个监听器。
  • 非空指针,由构造函数传入。

五、总结:类的职责定位

功能实现方式
绑定渲染窗口linkWith()
注册监听点拾取start()
处理拾取结果onItemPicked() 调用 processPickedPoint()
停止拾取并解绑stop()
留给子类扩展逻辑processPickedPoint()(纯虚函数)

✅ 使用场景(CloudCompare 中的实际用法)

你可以看到该类作为如下功能的基础类:

  • 点对点测量工具
  • 三角测量工具
  • 坐标记录工具
  • 捕捉标注点工具

子类继承这个接口后只需实现 processPickedPoint(),即可实现各种响应逻辑,避免重复构建点选管理逻辑。


再分析一下该接口类继承的两个类

你目前提供的两个基类是:

  1. ccOverlayDialog:是一个基于 QDialog 的界面类,用于作为叠加式的工具对话框;
  2. ccPickingListener:是一个抽象接口类,用于响应 3D 视图中的点/面拾取事件。

下面对这两个类进行详细分析,并结合它们在 CloudCompare 中可能的继承用途进行总结。


一、ccOverlayDialog 分析(继承自 QDialog

📌 定义用途

该类是 CloudCompare 中所有工具对话框(如测量、剪裁、绘图等)的通用基类,它:

  • 是一个轻量的、无边框窗口(通过 FramelessWindowHint | Tool 设置);
  • 能够被挂接到一个 3D 显示窗口 ccGLWindowInterface
  • 通过事件过滤器监听快捷键输入等;
  • 提供 start() / stop() 流程控制接口;
  • 使用信号槽机制和主窗口通信。
🔧 核心功能点
  • 窗口与渲染窗口联动:通过 linkWith(ccGLWindowInterface* win) 绑定到具体的渲染视图;

  • 生命周期管理start()stop(bool accepted) 管理工具的运行状态;

  • 快捷键支持:可通过 addOverriddenShortcut(Qt::Key key) 添加快捷键;

  • 自动监听 Esc 退出

  • 事件过滤器:过滤并响应窗口事件、快捷键事件、Show 事件;

  • 信号

    • processFinished(bool):工具流程结束时发出;
    • shortcutTriggered(int):自定义快捷键被触发;
    • shown():窗口展示时发出;

二、ccPickingListener 分析(接口类)

📌 定义用途

该类是 CloudCompare 中与鼠标拾取(pick)相关的功能接口,用于响应:

  • 用户在视图中点击点、三角形、实体中心等事件;
  • 获取拾取的 3D 点、点击位置、面片索引等。
🔧 核心功能点
  • 纯虚函数

    virtual void onItemPicked(const PickedItem& pi) = 0;
    

    子类必须实现该函数,响应用户拾取行为。

  • 数据结构 PickedItem
    提供了拾取位置、目标实体、点索引、3D 坐标、barycentric 坐标等详细信息。


三、结合继承场景分析

一个继承了 ccOverlayDialogccPickingListener 的类将:

✅ 同时拥有:
  1. 图形界面能力(窗口、启动/停止、快捷键等);
  2. 拾取事件响应能力(点击点、面、中心的处理);
✅ 可能用途:

这种多重继承设计非常适合构建 “带界面的拾取工具”,例如:

  • 点到点测量工具(用户点击两个点计算距离);
  • 选点标记工具(点击点以附加标签);
  • 模型注释工具(点击位置添加批注);
  • 三角面拾取工具(点击面片选定,做进一步分析如法向计算等)。
✅ 示例结构:
class MyPickingDialog : public ccOverlayDialog, public ccPickingListener
{Q_OBJECT
public:MyPickingDialog(QWidget* parent = nullptr);//实现拾取处理逻辑void onItemPicked(const PickedItem& pi) override;//界面初始化和开始逻辑void startPicking();private://内部状态,比如拾取的点集合、选中实体等
};

四、设计总结

基类功能类型特点说明
ccOverlayDialogUI框架QDialog 弹窗形式工具,能绑定视图、接收快捷键等
ccPickingListener拾取接口响应用户在三维视图中点击选择点、面、中心的事件
🧩 多继承配合工具设计模板能设计“带界面的交互工具”,响应鼠标点选并处理对应逻辑

如你正在设计测量工具或交互工具界面,这两个类正是 CloudCompare 插件或内部功能的标准模式,可以直接扩展复用。需要帮助实现具体类或功能时可继续提供具体需求。

最后分析继承该接口的两个类

CloudCompare 中继承自 ccPointPickingGenericInterface 的两个类之一 —— ccPointPropertiesDlg,它主要是一个用于点拾取和属性显示的对话框类。现在我们来详细分析这个类以及其在项目中的作用:


ccPointPropertiesDlg

✅ 类 ccPointPropertiesDlg 的职责

该类继承自 ccPointPickingGenericInterface,用于管理如下几种拾取/测量模式:

模式名功能说明
POINT_INFO显示单个点的属性信息(如坐标、标量值等)
POINT_POINT_DISTANCE计算两个点之间的距离
POINTS_ANGLE计算三个点所构成夹角
RECT_ZONE矩形区域选择(2D 区域)

✅ 类成员组成

成员变量

Mode m_pickingMode;              // 当前拾取模式
cc2DLabel* m_label;              // 用于显示点、距离、角度的2D标签
cc2DViewportLabel* m_rect2DLabel; // 用于绘制矩形区域的2D标签

成员函数(核心)

继承接口的实现
bool start() override;          // 开始拾取,默认启用点信息模式
void stop(bool state) override; // 停止拾取,清除状态
bool linkWith(ccGLWindowInterface* win) override; // 绑定窗口,注册事件
void processPickedPoint(const PickedItem&) override; // 处理拾取点
模式切换槽函数(按钮点击触发)
void activatePointPropertiesDisplay();
void activateDistanceDisplay();
void activateAngleDisplay();
void activate2DZonePicking();
其他功能
void exportCurrentLabel();  // 导出当前标签为实体(可用于保存或进一步操作)
void initializeState();     // 重置当前状态
void update2DZone(int x, int y, Qt::MouseButtons buttons); // 鼠标拖动区域时调用
void processClickedPoint(int x, int y); // 处理2D区域点击
void close2DZone();        // 鼠标释放时结束矩形选择

processPickedPoint 工作流程详解

这是该类最核心的处理逻辑,它会根据当前模式执行如下动作:

  • POINT_INFO: 清空旧标签,记录当前点,显示坐标等信息
  • POINT_POINT_DISTANCE: 最多记录两个点,自动清空之前的点
  • POINTS_ANGLE: 最多记录三个点,显示角度
  • RECT_ZONE: 此模式不处理拾取点(鼠标点击位置会进入 processClickedPoint

并且在每次点选后,会输出点信息至控制台日志(ccLog::Print())。


linkWith 功能说明

此函数将标签与 ccGLWindowInterface 绑定,注册信号槽响应(如鼠标移动、点击等)。它还负责在不同窗口切换时的清理/注册逻辑,确保标签显示不混乱。


✅ 总结:ccPointPropertiesDlg 的核心价值

该类提供了直观、可视化的点拾取交互工具,具备以下特性:

  • 统一的界面交互(继承自 ccPointPickingGenericInterface
  • 丰富的测量模式支持(点信息、距离、角度、2D区域)
  • 实时的图形反馈(标签显示)
  • 可输出为实体,供后续分析/保存

它是 CloudCompare 交互式测量功能中的核心组件之一。


你贴出的 ccPointListPickingDlg 类是 CloudCompare 中 点列表拾取功能的完整交互对话框类,是一个核心 UI 类,继承自 ccPointPickingGenericInterface,并结合 Qt Designer 的 UI 界面类(Ui::PointListPickingDlg)。这个类的主要功能是让用户通过图形界面 依次拾取点并管理点列表、导出数据或生成新对象(如 polyline、点云等)。


🧩 类功能概述

✅ 核心作用:

功能描述
拾取点支持交互方式拾取多个点,显示在列表中
导出点列表支持导出为 ASCII 文件(多种格式)、点云或 polyline
撤销拾取可撤销最近点或全部点(通过 UI 按钮)
支持取消还原用户取消拾取时恢复原始状态
交互性强拾取过程中标记点、重绘窗口、修改标注尺寸和索引等

🔄 类继承与成员结构

class ccPointListPickingDlg: public ccPointPickingGenericInterface,  // 拾取点通用接口(虚函数 processPickedPoint), public Ui::PointListPickingDlg          // Qt UI 界面(控件等)
  • ccPointPickingGenericInterface:抽象接口类,提供通用的点拾取机制(定义了 processPickedPoint() 虚函数)。
  • Ui::PointListPickingDlg:由 Qt Designer 生成的界面类,包含按钮、表格等控件。

🧠 核心成员与方法说明

1. 构造函数与初始化

ccPointListPickingDlg(ccPickingHub* pickingHub, QWidget* parent);
  • 初始化 UI,注册按钮槽函数,准备拾取逻辑。
  • 注册到 ccPickingHub(CloudCompare 的中心拾取系统)。

2. 点拾取逻辑处理

void processPickedPoint(const PickedItem& picked) override;
  • 重写接口函数。
  • 每当用户在视图中拾取一个点时,这个函数被调用。
  • 内部会创建 2D Label 或将点加入 m_toBeAdded 等待后续处理。
  • 同时更新 UI 表格展示新点。

3. 实体关联

void linkWithEntity(ccHObject* entity);
  • 设置当前操作对象,比如某个点云或网格。
  • 后续拾取的数据和导出操作都围绕该实体进行。

4. 导出功能

void exportToNewCloud();
void exportToNewPolyline();
void exportToASCII(ExportFormat format);  // 支持多种导出格式
  • exportToNewCloud():将拾取的点生成一个新的 ccPointCloud

  • exportToNewPolyline():按拾取顺序连接成 polyline。

  • exportToASCII(format)

    • XYZ:基本坐标
    • IXYZ:带点索引
    • GXYZ:带全局索引
    • LXYZ:带标签或注释等

5. 撤销/还原逻辑

void removeLastEntry();      // 撤销最近一个
void cancelAndExit();        // 取消所有新建标注
void applyAndExit();         // 确认当前拾取
  • 内部通过 m_toBeDeleted, m_toBeAdded 管理新增/待删除对象,支持撤销。
  • 若用户按下“取消”,不会改变原始数据结构。

6. 辅助 UI 控制

void markerSizeChanged(int);
void startIndexChanged(int);
void updateList();
  • 响应用户在 UI 中调节标注大小、编号起始值等行为。
  • updateList() 会更新 Qt 表格显示当前所有拾取的点及其属性。

7. 数据结构成员变量

成员变量含义
ccHObject* m_associatedEntity当前操作的点云或网格
ccHObject* m_orderedLabelsContainer顺序存储生成的 cc2DLabel 对象
ccHObject::Container m_toBeDeleted记录在取消时应删除的对象
ccHObject::Container m_toBeAdded记录在取消时应恢复的新增对象
unsigned m_lastPreviousID启动前已有标注的最大 ID(用于防止 ID 冲突)

✅ 典型使用流程

  1. 用户点击进入拾取模式(UI上启动 ccPointListPickingDlg 对话框)。
  2. 视图绑定 → 通过 linkWithEntity() 绑定点云或网格。
  3. 用户点击拾取点processPickedPoint() 被调用,生成 2D label,记录坐标。
  4. 在表格中实时展示点编号和坐标。
  5. 可选择导出、生成新云、Polyline、ASCII 文件
  6. 用户取消或确认拾取结果,内部通过 m_toBeDeleted / m_toBeAdded 管理撤销。

ccPointListPickingDlg

🧭 和 ccPointPickingGenericInterface 的区别?

类名作用
ccPointPickingGenericInterface抽象接口类,定义拾取流程中的通用行为
ccPointListPickingDlgUI 层封装类,真正实现交互功能、管理拾取逻辑、绑定实体、导出

CloudCompare 中不同拾取功能(如三点测角、线段测距)都可能继承 ccPointPickingGenericInterface,但使用不同 UI 封装类。


你提供的这份 ccPointListPickingDlg 类实现是 CloudCompare 中负责“点列表拾取与导出”的 UI 类之一。它允许用户在 3D 视图中交互式选择点、查看坐标、导出为点云或折线、保存为 ASCII 文本等。以下是对这段代码关键模块的结构性分析与说明:


🌟 核心功能概览

功能实现方式
拾取点列表管理cc2DLabel 组合在 m_orderedLabelsContainer 中管理
拾取点的导出(ASCII/Cloud/Polyline)exportToASCII_*exportToNewCloud()exportToNewPolyline()
操作撤销(移除最后拾取点)removeLastEntry()
拾取序号设置与更新startIndexSpinBoxstartIndexChanged()
坐标系选择(局部/全局)showGlobalCoordsCheckBoxupdateList()
UI 按钮与菜单构建构造函数中创建 QMenu 并绑定 QAction
持久化用户选项(文件路径等)使用 QSettings

✅ 类的结构简析

构造函数
  • 创建导出按钮菜单
  • 连接按钮和控件信号槽
  • 恢复上次的设置(起始编号、坐标系)
  • updateList():刷新当前点列表显示(表格视图)
点列表获取
unsigned ccPointListPickingDlg::getPickedPoints(std::vector<cc2DLabel*>& pickedPoints)
  • 获取当前容器 m_orderedLabelsContainer 中所有可见的 cc2DLabel(注意:排除 cc2DViewportLabel
数据关联
void ccPointListPickingDlg::linkWithEntity(ccHObject* entity)
  • 绑定一个点云或模型对象,扫描其子层级寻找已存在的 “Picked points list” 容器并加载其中的 label。
  • 同时开启/禁用“全局坐标”选项(如果该对象进行了 Shift)
导出功能
  • exportToNewCloud():将拾取点导出为新的 ccPointCloud,可用于保存/后续处理
  • exportToNewPolyline():生成 ccPolyline,常用于测量路径等用途
  • exportToASCII_xyz() 等:将点导出为指定格式文本(X,Y,Z、标签、局部/全局索引)
撤销与退出
  • removeLastEntry():根据唯一 ID 判断是否是旧点,从添加或删除列表中更新状态
  • cancelAndExit():恢复之前的标签状态(还原不可见等)
  • applyAndExit():确认拾取点后从数据库中删除旧标签,清除临时缓存

💡 实用细节

标签命名
static const char s_defaultLabelBaseName[] = "Point #";

可用于后续自动命名拾取点,例如 “Point #0”, “Point #1” 等。

数据结构维护
  • m_toBeDeleted: 存储用户在当前会话中删除的旧点(在取消时恢复)
  • m_toBeAdded: 当前会话中新增的点(在撤销时删除)

🔎 可能的拓展方向建议

拓展项建议实现
支持多维数据导出exportToASCII_* 中加入强度、颜色、法线等字段
导入功能支持从 ASCII 导入点列表并创建 label
支持区域选择添加标签批量在选区中拾取点作为 label
兼容多实体当前 m_associatedEntity 是单一对象,未来可以扩展为多个实体支持

🧩 与 CloudCompare 的配合

此类一般配合:

  • ccPickingHub:处理鼠标点击拾取事件(点击点)
  • cc2DLabel:显示每个拾取点的2D标签信息
  • MainWindow::TheInstance()->addToDB():统一添加/管理对象
  • ccGLWindowInterface:响应标注大小调整、重绘等 UI 操作

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

相关文章:

  • 如何手搓一个查询天气的mcp server
  • 嵌入式学习笔记 - 新版Keil软件模拟时钟Xtal灰色不可更改的问题
  • Spring AI 官方文档 AIGC入门到实战 (1) 认识Spring AI
  • Docker 环境搭建与三大数据库(MySQL/Redis/MongoDB)部署教程
  • 探索C++标准模板库(STL):String接口实践+底层的模拟实现(中篇)
  • 0527漏洞原理:XSS笔记
  • 《深入解析UART协议及其硬件实现》-- 第二篇:UART硬件架构设计与FPGA实现
  • pikachu靶场通关笔记05 XSS关卡01-反射型GET
  • WPS自动换行
  • Rust 学习笔记:循环和迭代器的性能比较
  • Windows下安装并使用kubectl查看K8S日志
  • 可视化提示词(Prompt)在训练过程中的优化过程:visualize_prompt_evolution
  • AI 产品的 MVP 构建逻辑:Prompt 工程 ≠ 产品工程?
  • 【Prompt Engineering】摸索出的一些小套路
  • 弱光环境下如何手持相机拍摄静物:摄影曝光之等效曝光认知
  • 【Android笔记】记一次 CMake 构建 Filament Android 库的完整排错过程(安卓交叉编译、CMake、Ninja)
  • GC1267F:单相全波风扇电机预驱动芯片解析
  • 如何发布npm包?
  • 国标GB28181视频平台EasyGBS视频实时监控:打造城市环境监控全场景解决方案
  • LeetCode 1871. 跳跃游戏 VII(中等)
  • EasyRTC嵌入式音视频实时通话SDK助力AI与IoT智能硬件打造音视频交互多场景应用
  • 力扣热题100之二叉树的中序遍历
  • 【掌握文件操作】(下):文件的顺序读写、文件的随机读写、文件读取结束的判定、文件缓冲区
  • 【开源工具】跳过网页APP禁止粘贴限制:自动输入键盘模拟工具
  • day12 leetcode-hot100-21(矩阵4)
  • MySQL XtraBackup---笔记
  • 初识Docker:容器化技术的入门指南
  • 关于JavaScript、TypeScript Module的配置和用法
  • Vue 3.0 状态管理Pinia详解
  • JWT安全:接收无签名令牌.【签名算法设置为none绕过验证】