GrabBag/Tools/CloudView/Inc/PointCloudGLWidget.h

222 lines
6.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef POINT_CLOUD_GL_WIDGET_H
#define POINT_CLOUD_GL_WIDGET_H
#include <QOpenGLWidget>
#include <QOpenGLFunctions>
#include <QMatrix4x4>
#include <QVector3D>
#include <QMouseEvent>
#include <QWheelEvent>
#include <vector>
#include "PointCloudConverter.h"
/**
* @brief 点云显示颜色枚举
*/
enum class PointCloudColor
{
White,
Red,
Green,
Blue,
Yellow,
Cyan,
Magenta,
Original
};
/**
* @brief 选中的点信息
*/
struct SelectedPointInfo
{
bool valid;
size_t index;
float x, y, z;
int cloudIndex;
int lineIndex; // 所属线索引
int pointIndexInLine; // 点在线中的索引
SelectedPointInfo() : valid(false), index(0), x(0), y(0), z(0), cloudIndex(-1), lineIndex(-1), pointIndexInLine(-1) {}
};
/**
* @brief 选线模式
*/
enum class LineSelectMode
{
Vertical, // 纵向选线(同一条扫描线)
Horizontal // 横向选线(所有线的相同索引点)
};
/**
* @brief 选中的线信息
*/
struct SelectedLineInfo
{
bool valid;
int cloudIndex; // 点云索引
int lineIndex; // 线索引(纵向选线时使用)
int pointIndex; // 点索引(横向选线时使用)
int pointCount; // 该线上的点数
LineSelectMode mode; // 选线模式
SelectedLineInfo() : valid(false), cloudIndex(-1), lineIndex(-1), pointIndex(-1), pointCount(0), mode(LineSelectMode::Vertical) {}
};
/**
* @brief 点云 OpenGL 渲染控件
*/
class PointCloudGLWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
Q_OBJECT
public:
explicit PointCloudGLWidget(QWidget* parent = nullptr);
~PointCloudGLWidget() override;
void addPointCloud(const PointCloudXYZ& cloud, const QString& name = "");
void addPointCloud(const PointCloudXYZRGB& cloud, const QString& name = "");
void clearPointClouds();
void setPointCloudColor(PointCloudColor color);
void setPointSize(float size);
void resetView();
QVector<SelectedPointInfo> getSelectedPoints() const { return m_selectedPoints; }
SelectedLineInfo getSelectedLine() const { return m_selectedLine; }
void clearSelectedPoints();
void clearSelectedLine();
float calculateDistance(const SelectedPointInfo& p1, const SelectedPointInfo& p2);
/**
* @brief 通过线索引选择线(纵向)
*/
bool selectLineByIndex(int lineIndex);
/**
* @brief 通过点索引选择横向线(所有线的相同索引点)
*/
bool selectHorizontalLineByIndex(int pointIndex);
/**
* @brief 设置选线模式
*/
void setLineSelectMode(LineSelectMode mode) { m_lineSelectMode = mode; }
/**
* @brief 设置是否启用测距功能
*/
void setMeasureDistanceEnabled(bool enabled) { m_measureDistanceEnabled = enabled; }
/**
* @brief 获取测距功能是否启用
*/
bool isMeasureDistanceEnabled() const { return m_measureDistanceEnabled; }
/**
* @brief 获取选中线上的所有点坐标
* @return 点坐标列表,每个元素为 (x, y, z)
*/
QVector<QVector3D> getSelectedLinePoints() const;
/**
* @brief 设置列表高亮点(与选点功能区分)
* @param point 点坐标,如果为空则清除高亮
*/
void setListHighlightPoint(const QVector3D& point);
/**
* @brief 清除列表高亮点
*/
void clearListHighlightPoint();
/**
* @brief 获取第一个点云的数据(用于旋转和保存)
*/
bool getFirstCloudData(PointCloudXYZ& cloud) const;
/**
* @brief 替换第一个点云(用于显示旋转后的数据)
*/
void replaceFirstCloud(const PointCloudXYZ& cloud, const QString& name);
/**
* @brief 获取点云数量
*/
size_t getCloudCount() const { return m_pointClouds.size(); }
signals:
void pointSelected(const SelectedPointInfo& point);
void twoPointsSelected(const SelectedPointInfo& p1, const SelectedPointInfo& p2, float distance);
void lineSelected(const SelectedLineInfo& line);
protected:
void initializeGL() override;
void resizeGL(int w, int h) override;
void paintGL() override;
void mousePressEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override;
void wheelEvent(QWheelEvent* event) override;
private:
void computeBoundingBox();
void setCurrentColor(PointCloudColor color);
void setColorByIndex(int colorIndex); // 根据索引设置颜色
SelectedPointInfo pickPoint(int screenX, int screenY);
void drawSelectedPoints();
void drawMeasurementLine();
void drawAxis();
void drawSelectedLine(); // 绘制选中的线
struct PointCloudData
{
std::vector<float> vertices;
std::vector<float> colors;
std::vector<int> lineIndices; // 每个点所属的线索引
std::vector<int> originalIndices; // 每个显示点在原始点云中的索引用于计算原始index
bool hasColor;
bool hasLineInfo; // 是否有线信息
QString name;
int colorIndex; // 点云颜色索引
int totalLines; // 总线数
int pointsPerLine; // 每线点数(网格化点云)
};
std::vector<PointCloudData> m_pointClouds;
QMatrix4x4 m_projection;
QMatrix4x4 m_view;
QMatrix4x4 m_model;
float m_distance;
float m_rotationX;
float m_rotationY;
QVector3D m_center;
QVector3D m_pan;
QVector3D m_minBound;
QVector3D m_maxBound;
QPoint m_lastMousePos;
bool m_leftButtonPressed;
bool m_rightButtonPressed;
bool m_middleButtonPressed;
PointCloudColor m_currentColor;
float m_pointSize;
LineSelectMode m_lineSelectMode;
bool m_measureDistanceEnabled;
QVector<SelectedPointInfo> m_selectedPoints;
SelectedLineInfo m_selectedLine;
static const int MAX_SELECTED_POINTS = 2;
// 列表高亮点(与选点功能区分)
bool m_hasListHighlightPoint;
QVector3D m_listHighlightPoint;
int m_colorIndex; // 颜色轮换索引
static const int COLOR_COUNT = 7; // 可用颜色数量
};
#endif // POINT_CLOUD_GL_WIDGET_H