Utils/CloudViewApp/Inc/CloudViewMainWindow.h

426 lines
10 KiB
C
Raw Normal View History

2026-02-19 00:45:00 +08:00
#ifndef CLOUD_VIEW_MAIN_WINDOW_H
#define CLOUD_VIEW_MAIN_WINDOW_H
#include <QMainWindow>
#include <QWidget>
#include <QPushButton>
#include <QToolButton>
2026-02-19 00:45:00 +08:00
#include <QLabel>
#include <QListWidget>
#include <QGroupBox>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QSplitter>
#include <QFileDialog>
#include <QMessageBox>
#include <QStatusBar>
#include <QLineEdit>
#include <QRadioButton>
#include <QCheckBox>
2026-08-08 17:41:02 +08:00
#include <QComboBox>
#include <QDialog>
#include <QStringList>
#include <memory>
2026-02-19 00:45:00 +08:00
2026-08-08 17:41:02 +08:00
#include "CloudView3D.h"
#include "PointCloudConverter.h"
2026-02-19 00:45:00 +08:00
2026-08-08 17:41:02 +08:00
class QTextEdit;
class QTableWidget;
class QCloseEvent;
2026-02-19 00:45:00 +08:00
/**
* @brief 点云查看器主窗口
* 左侧显示点云,右侧为操作区域
*/
class CloudViewMainWindow : public QMainWindow
{
Q_OBJECT
2026-08-08 17:41:02 +08:00
public:
struct StartupFiles
{
QStringList displayFiles;
QStringList bboxFiles;
QStringList circleFiles;
QStringList rectangleFiles;
QStringList surfaceFiles;
QStringList triangleFiles;
bool sequential = false;
};
explicit CloudViewMainWindow(QWidget* parent = nullptr);
~CloudViewMainWindow() override;
bool loadStartupFiles(const StartupFiles& files);
bool loadDisplayFile(const QString& fileName);
bool loadCircleShapeFile(const QString& fileName);
bool loadRectangleShapeFile(const QString& fileName);
bool loadSurfaceShapeFile(const QString& fileName);
2026-07-11 18:33:31 +08:00
bool loadTriangleShapeFile(const QString& fileName);
void fitViewToContent();
void setPointCloudRange(const PointCloudXYZRange& range);
const PointCloudXYZRange& pointCloudRange() const { return m_pointCloudRange; }
2026-07-11 18:33:31 +08:00
2026-08-08 17:41:02 +08:00
protected:
bool eventFilter(QObject* obj, QEvent* event) override;
void closeEvent(QCloseEvent* event) override;
private:
enum class StartupFileType
{
Display,
BBox,
Circle,
Rectangle,
Surface,
Triangle
};
struct StartupItem
{
StartupFileType type;
QString fileName;
};
void buildStartupSequence(const StartupFiles& files);
bool loadStartupItem(const StartupItem& item);
bool loadCurrentStartupSequenceItem();
private slots:
2026-02-19 00:45:00 +08:00
/**
* @brief 打开文件
*/
void onOpenFile();
/**
* @brief 打开姿态点文件
*/
void onOpenPoseFile();
/**
* @brief 打开包围盒JSON文件
*/
void onOpenBBoxFile();
2026-02-19 00:45:00 +08:00
/**
* @brief 清除所有点云
*/
void onClearAll();
/**
* @brief 重置视图
*/
void onResetView();
/**
* @brief 清除选中的点
*/
void onClearSelectedPoints();
/**
* @brief 清除选线
*/
void onClearLinePoints();
/**
* @brief 处理点选中事件
*/
void onPointSelected(const SelectedPointInfo& point);
/**
* @brief 处理两点选中事件(测距)
*/
void onTwoPointsSelected(const SelectedPointInfo& p1, const SelectedPointInfo& p2, float distance);
/**
* @brief 处理线选中事件
*/
void onLineSelected(const SelectedLineInfo& line);
/** @brief 同步 CloudView3D 当前视角到 CloudView 自己的角度输入框 */
void onViewAnglesChanged(float rotX, float rotY, float rotZ);
void onPseudoColorSettings();
void onPointCloudRangeSettings();
void onShowDataFormatHelp();
2026-02-19 00:45:00 +08:00
2026-03-01 18:14:19 +08:00
/**
* @brief 点1坐标编辑完成(回车)
*/
void onPoint1CoordChanged();
/**
* @brief 点2坐标编辑完成(回车)
*/
void onPoint2CoordChanged();
2026-02-19 00:45:00 +08:00
/**
* @brief 通过输入线号选择线
*/
void onSelectLineByNumber();
/**
* @brief 选线模式切换(纵向/横向)
*/
void onLineSelectModeChanged(bool checked);
/**
* @brief 显示选中线上的所有点坐标
*/
void onShowLinePoints();
/**
* @brief 线上点列表项被点击
*/
void onLinePointTableClicked(int row, int column);
/**
* @brief 显示点1的姿态
*/
void onShowPose1();
/**
* @brief 显示点2的姿态
*/
void onShowPose2();
/**
* @brief 显示输入的线段
*/
void onShowInputLine();
/**
* @brief 清除输入的线段
*/
void onClearInputLine();
/**
* @brief 欧拉角旋转顺序改变
*/
void onEulerOrderChanged(int index);
/**
* @brief 眼在手外矩阵变换(直接应用矩阵到点云)
2026-02-19 00:45:00 +08:00
*/
void onEyeToHandTransform();
2026-02-19 00:45:00 +08:00
/**
* @brief 眼在手上矩阵变换(手眼矩阵 + 机械臂位姿)
2026-02-19 00:45:00 +08:00
*/
void onEyeInHandTransform();
2026-02-19 00:45:00 +08:00
void onGeneratePointCloud();
void onRotateCloudByZ();
void onSavePointCloud(); // 保存 txt 点云
void onSavePlyPcdCloud(); // 保存 ply/pcd 点云
2026-07-03 12:46:19 +08:00
void onBatchConvertTxtToPly(); // 批量转换 txt -> ply
2026-08-08 17:41:02 +08:00
void onConvertEulerMatrix();
void onShowCircleShape();
void onShowRectangleShape();
void onShowSurfaceShape();
void onShowTriangleShape();
2026-02-19 00:45:00 +08:00
/**
* @brief 姿态补偿计算
*/
void onPoseCompensation();
2026-02-19 00:45:00 +08:00
private:
/**
* @brief 初始化界面
*/
void setupUI();
2026-02-19 00:45:00 +08:00
/**
* @brief 创建左侧点云显示区域
*/
QWidget* createViewerArea();
/**
* @brief 创建视图方向工具栏(CloudView 自己的视图/旋转按钮)
*/
QWidget* createViewToolbar();
2026-02-19 00:45:00 +08:00
/**
* @brief 创建右侧操作区域
*/
QWidget* createControlPanel();
/**
* @brief 创建文件操作组
*/
QGroupBox* createFileGroup();
/**
* @brief 创建选点测距组
*/
QGroupBox* createMeasureGroup();
/**
* @brief 创建选点测距页面
*/
QWidget* createMeasurePage();
/**
* @brief 创建选线页面
*/
QWidget* createLinePage();
/**
* @brief 创建选线拟合组
*/
QGroupBox* createLineGroup();
/**
* @brief 创建点云列表组
*/
QGroupBox* createCloudListGroup();
/**
* @brief 更新选点信息显示
*/
2026-08-08 17:41:02 +08:00
void updateSelectedPointsDisplay();
void clearMeasureResultDisplay();
void updateMeasureResultDisplay(const SelectedPointInfo& p1,
const SelectedPointInfo& p2,
float distance,
const QString& statusPrefix = QString());
/**
2026-02-19 00:45:00 +08:00
* @brief 从原始数据获取线上点(包含0,0,0)
*/
QVector<QVector3D> getOriginalLinePoints(const SelectedLineInfo& lineInfo);
/**
* @brief 更新线上点对话框内容
*/
void updateLinePointsDialog();
2026-02-22 16:54:45 +08:00
/**
* @brief 加载点云文件
* @return 是否成功加载到点云数据
*/
bool loadPointCloudFile(const QString& fileName);
/**
* @brief 加载图形块文件(Segment/Poly/Rect/Surface 格式)
2026-02-22 16:54:45 +08:00
* @return 是否成功加载到线段数据
*/
bool loadSegmentFile(const QString& fileName);
/**
* @brief 加载包围盒JSON文件
* @return 是否成功加载到包围盒数据
*/
bool loadBoundingBoxFile(const QString& fileName);
2026-08-08 17:41:02 +08:00
void applyTransformToAllClouds(const QMatrix4x4& matrix);
void addGeneratedCloud(const PointCloudXYZ& cloud, const QString& name);
void showBasicShape(const QString& shapeName,
const QVector<LineSegment>& segments,
const QVector<BasicShapePoint>& points = QVector<BasicShapePoint>());
void showBasicSurface(const QString& shapeName, const QVector<SurfaceQuad>& surfaces, const QVector<LineSegment>& outlines);
2026-02-19 00:45:00 +08:00
// 点云显示控件
PointCloudGLWidget* m_glWidget;
// 点云转换器
std::unique_ptr<PointCloudConverter> m_converter;
// 文件操作控件
QPushButton* m_btnOpenFile;
QPushButton* m_btnOpenBBox;
QPushButton* m_btnPointCloudRange;
QPushButton* m_btnClearAll;
// 视图角度输入控件
QLineEdit* m_editRotX;
QLineEdit* m_editRotY;
QLineEdit* m_editRotZ;
2026-02-19 00:45:00 +08:00
// 选点测距控件
QCheckBox* m_cbMeasureDistance;
QPushButton* m_btnClearPoints;
2026-08-08 17:41:02 +08:00
QLabel* m_lblPoint1;
QLabel* m_lblPoint2;
QLabel* m_lblDistance;
QLabel* m_lblDeltaXYZ;
2026-02-19 00:45:00 +08:00
2026-03-01 18:14:19 +08:00
// 点1坐标编辑控件
QLineEdit* m_editPoint1X;
QLineEdit* m_editPoint1Y;
QLineEdit* m_editPoint1Z;
// 点2坐标编辑控件
QLineEdit* m_editPoint2X;
QLineEdit* m_editPoint2Y;
QLineEdit* m_editPoint2Z;
2026-02-19 00:45:00 +08:00
// 点1姿态输入控件
QLineEdit* m_editRx1;
QLineEdit* m_editRy1;
QLineEdit* m_editRz1;
QPushButton* m_btnShowPose1;
// 点2姿态输入控件
QLineEdit* m_editRx2;
QLineEdit* m_editRy2;
QLineEdit* m_editRz2;
QPushButton* m_btnShowPose2;
// 姿态坐标轴缩放
QLineEdit* m_editPoseScale;
2026-02-19 00:45:00 +08:00
// 欧拉角旋转顺序选择
QComboBox* m_comboEulerOrder;
// 选线拟合控件
QPushButton* m_btnClearLine;
QPushButton* m_btnShowLinePoints;
QLineEdit* m_lineNumberInput;
QPushButton* m_btnSelectByNumber;
QRadioButton* m_rbVertical;
QRadioButton* m_rbHorizontal;
QLabel* m_lblLineIndex;
QLabel* m_lblLinePointCount;
// 输入线段控件
QLineEdit* m_editLineX1;
QLineEdit* m_editLineY1;
QLineEdit* m_editLineZ1;
QLineEdit* m_editLineX2;
QLineEdit* m_editLineY2;
QLineEdit* m_editLineZ2;
QPushButton* m_btnShowLine;
QPushButton* m_btnClearLine2;
// 点云列表
QListWidget* m_cloudList;
// 已加载的点云数量
int m_cloudCount;
// 当前点云的线信息(用于旋转)
int m_currentLineNum;
int m_currentLinePtNum;
// 原始完整点云数据(包含0,0,0点,用于旋转)
PointCloudXYZ m_originalCloud;
PointCloudXYZRange m_pointCloudRange;
2026-02-19 00:45:00 +08:00
// 线上点对话框
QDialog* m_linePointsDialog;
QTableWidget* m_linePointsTable;
QVector<QVector3D> m_currentLinePoints; // 当前线的原始点坐标
// CloudView 自己的悬浮缩放按钮
2026-07-11 18:33:31 +08:00
QToolButton* m_btnZoomIn;
QToolButton* m_btnZoomOut;
2026-02-19 00:45:00 +08:00
2026-08-08 17:41:02 +08:00
// 启动参数序列显示
QVector<StartupItem> m_startupSequence;
int m_startupSequenceIndex;
bool m_startupSequentialMode;
};
2026-02-19 00:45:00 +08:00
#endif // CLOUD_VIEW_MAIN_WINDOW_H