refactor(CloudView): 拆分缩放按钮布局逻辑为独立函数
1. 将原eventFilter中的缩放按钮位置计算代码抽离为updateZoomButtonGeometry独立函数 2. 在创建视图区域时主动调用该函数初始化按钮位置 3. 统一处理GL控件resize时的按钮重定位逻辑,提升代码可读性 4. 修复原代码未在初始化时设置按钮位置的问题 5. 新增按钮置顶操作确保缩放按钮始终显示在最上层
This commit is contained in:
parent
72db40115f
commit
2ee6bcd414
@ -32,6 +32,15 @@ target_include_directories(CloudUtils PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Inc
|
||||
)
|
||||
|
||||
# When CamTool is built with WoodSDK, use its VZ compatibility types first.
|
||||
# This keeps LaserDataLoader's SVzNL* signatures identical to the application
|
||||
# translation units, where WoodSDK maps them to the public SWD* structures.
|
||||
if(TARGET WoodSDK)
|
||||
target_include_directories(CloudUtils BEFORE PUBLIC
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../../App/woodcam-sdk/WoodSDK/VzToWDInc"
|
||||
)
|
||||
endif()
|
||||
|
||||
target_link_libraries(CloudUtils
|
||||
PUBLIC
|
||||
VrCommon
|
||||
|
||||
@ -6,27 +6,23 @@
|
||||
#include <QOpenGLBuffer>
|
||||
#include <QOpenGLShaderProgram>
|
||||
#include <QMatrix4x4>
|
||||
#include <QVector3D>
|
||||
#include <QQuaternion>
|
||||
#include <QMouseEvent>
|
||||
<<<<<<< HEAD
|
||||
#include <QWheelEvent>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
=======
|
||||
#include <QVector3D>
|
||||
#include <QQuaternion>
|
||||
#include <QKeyEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <QWheelEvent>
|
||||
#include <QResizeEvent>
|
||||
#include <deque>
|
||||
#include <vector>
|
||||
>>>>>>> c6df042456fa4411f7b5269f8781f91c45da70c2
|
||||
|
||||
#include "CloudView3DTypes.h"
|
||||
#include "VZNL_Types.h"
|
||||
|
||||
class QToolButton;
|
||||
class QPushButton;
|
||||
class QPinchGesture;
|
||||
class QResizeEvent;
|
||||
class QPushButton;
|
||||
class QPinchGesture;
|
||||
class QResizeEvent;
|
||||
class QTimer;
|
||||
|
||||
/**
|
||||
* @brief 点云显示颜色枚举
|
||||
@ -185,25 +181,36 @@ public:
|
||||
PointCloudGLWidget(QWidget* parent, bool showControlButtons);
|
||||
~PointCloudGLWidget() override;
|
||||
|
||||
<<<<<<< HEAD
|
||||
void addPointCloud(const PointCloudXYZ& cloud, const QString& name = "");
|
||||
void addPointCloud(const PointCloudXYZRGB& cloud, const QString& name = "",
|
||||
bool resetCamera = true);
|
||||
void appendPointCloud(const PointCloudXYZRGB& cloud, const QString& name = "");
|
||||
void removeOldestPointCloud();
|
||||
void clearPointClouds();
|
||||
=======
|
||||
void setControlButtonsVisible(bool visible);
|
||||
bool controlButtonsVisible() const { return m_showControlButtons; }
|
||||
|
||||
void addPointCloud(const PointCloudXYZ& cloud, const QString& name = "", bool resetView = true);
|
||||
void addPointCloud(const PointCloudXYZRGB& cloud, const QString& name = "", bool resetView = true);
|
||||
/** 删除最早添加的一组点云,用于维护滚动显示窗口。 */
|
||||
bool removeOldestPointCloud();
|
||||
bool removeOldestPointCloud(bool refreshDisplay = true);
|
||||
/** 删除最近添加的一组点云,用于回滚未完成的增量加载。 */
|
||||
bool removeNewestPointCloud();
|
||||
void clearPointClouds();
|
||||
>>>>>>> c6df042456fa4411f7b5269f8781f91c45da70c2
|
||||
bool removeNewestPointCloud(bool refreshDisplay = true);
|
||||
void clearPointClouds();
|
||||
|
||||
/** 配置流式点云刷新频率;CamTool 使用 30 Hz。 */
|
||||
void setStreamRefreshRate(int refreshRateHz);
|
||||
int streamRefreshRate() const
|
||||
{
|
||||
return m_streamRefreshRate;
|
||||
}
|
||||
/** 配置流式点云最多保留的源扫描线数。 */
|
||||
void setStreamLineLimit(int maxLines);
|
||||
int streamLineLimit() const
|
||||
{
|
||||
return m_streamLineLimit;
|
||||
}
|
||||
void startStreamRefresh();
|
||||
void stopStreamRefresh(bool flushPending = true);
|
||||
/** 缓存一批本地线号从 0 开始的扫描线,下一次刷新时统一提交。 */
|
||||
void queuePointCloudBatch(PointCloudXYZ cloud, int sourceLineCount, const QString& name = QString());
|
||||
void flushPointCloudBatches();
|
||||
void clearPointCloudBatches();
|
||||
|
||||
void setPointCloudColor(PointCloudColor color);
|
||||
void setPointSize(float size);
|
||||
|
||||
@ -406,8 +413,10 @@ signals:
|
||||
float dx,
|
||||
float dy,
|
||||
float dz);
|
||||
void lineSelected(const SelectedLineInfo& line);
|
||||
void viewAnglesChanged(float rotX, float rotY, float rotZ);
|
||||
void lineSelected(const SelectedLineInfo& line);
|
||||
void viewAnglesChanged(float rotX, float rotY, float rotZ);
|
||||
/** 30 Hz 刷新边界;数据源应在该信号处理中批量填充缓存。 */
|
||||
void streamRefreshRequested();
|
||||
|
||||
protected:
|
||||
bool event(QEvent* event) override;
|
||||
@ -423,6 +432,13 @@ protected:
|
||||
void resizeEvent(QResizeEvent* event) override;
|
||||
|
||||
private:
|
||||
struct QueuedPointCloudBatch
|
||||
{
|
||||
PointCloudXYZ cloud;
|
||||
QString name;
|
||||
int sourceLineCount;
|
||||
};
|
||||
|
||||
struct PointCloudData
|
||||
{
|
||||
std::vector<float> vertices;
|
||||
@ -434,9 +450,11 @@ private:
|
||||
bool pseudoColor;
|
||||
bool hasLineInfo; // 是否有线信息
|
||||
QString name;
|
||||
int colorIndex; // 点云颜色索引
|
||||
int totalLines; // 总线数
|
||||
int pointsPerLine; // 每线点数(网格化点云)
|
||||
int colorIndex; // 点云颜色索引
|
||||
int totalLines; // 总线数
|
||||
int pointsPerLine; // 每线点数(网格化点云)
|
||||
bool streamBatch;
|
||||
int sourceLineCount;
|
||||
|
||||
// 自定义点大小分组(RGBA 中 A > 1 的点按大小分组)
|
||||
struct PointSizeGroup {
|
||||
@ -450,14 +468,19 @@ private:
|
||||
QOpenGLBuffer vertexBuffer; // 顶点 VBO
|
||||
QOpenGLBuffer colorBuffer; // 颜色 VBO
|
||||
bool vboCreated; // VBO 是否已创建
|
||||
QVector3D minBound;
|
||||
QVector3D maxBound;
|
||||
bool hasBounds;
|
||||
|
||||
PointCloudData()
|
||||
: hasColor(false), pseudoColor(false), hasLineInfo(false), colorIndex(0)
|
||||
, totalLines(0), pointsPerLine(0)
|
||||
, hasCustomPointSizes(false)
|
||||
: hasColor(false), pseudoColor(false), hasLineInfo(false), colorIndex(0)
|
||||
, totalLines(0), pointsPerLine(0)
|
||||
, streamBatch(false), sourceLineCount(0)
|
||||
, hasCustomPointSizes(false)
|
||||
, vertexBuffer(QOpenGLBuffer::VertexBuffer)
|
||||
, colorBuffer(QOpenGLBuffer::VertexBuffer)
|
||||
, vboCreated(false)
|
||||
, hasBounds(false)
|
||||
{}
|
||||
|
||||
// 移动构造函数(QOpenGLBuffer 不支持拷贝)
|
||||
@ -471,14 +494,19 @@ private:
|
||||
, pseudoColor(other.pseudoColor)
|
||||
, hasLineInfo(other.hasLineInfo)
|
||||
, name(std::move(other.name))
|
||||
, colorIndex(other.colorIndex)
|
||||
, totalLines(other.totalLines)
|
||||
, pointsPerLine(other.pointsPerLine)
|
||||
, customPointSizeGroups(std::move(other.customPointSizeGroups))
|
||||
, colorIndex(other.colorIndex)
|
||||
, totalLines(other.totalLines)
|
||||
, pointsPerLine(other.pointsPerLine)
|
||||
, streamBatch(other.streamBatch)
|
||||
, sourceLineCount(other.sourceLineCount)
|
||||
, customPointSizeGroups(std::move(other.customPointSizeGroups))
|
||||
, hasCustomPointSizes(other.hasCustomPointSizes)
|
||||
, vertexBuffer(QOpenGLBuffer::VertexBuffer)
|
||||
, colorBuffer(QOpenGLBuffer::VertexBuffer)
|
||||
, vboCreated(false)
|
||||
, minBound(other.minBound)
|
||||
, maxBound(other.maxBound)
|
||||
, hasBounds(other.hasBounds)
|
||||
{
|
||||
// VBO 需要在 GL 上下文中重建,标记为未创建
|
||||
other.vboCreated = false;
|
||||
@ -502,11 +530,16 @@ private:
|
||||
pseudoColor = other.pseudoColor;
|
||||
hasLineInfo = other.hasLineInfo;
|
||||
name = std::move(other.name);
|
||||
colorIndex = other.colorIndex;
|
||||
totalLines = other.totalLines;
|
||||
pointsPerLine = other.pointsPerLine;
|
||||
customPointSizeGroups = std::move(other.customPointSizeGroups);
|
||||
colorIndex = other.colorIndex;
|
||||
totalLines = other.totalLines;
|
||||
pointsPerLine = other.pointsPerLine;
|
||||
streamBatch = other.streamBatch;
|
||||
sourceLineCount = other.sourceLineCount;
|
||||
customPointSizeGroups = std::move(other.customPointSizeGroups);
|
||||
hasCustomPointSizes = other.hasCustomPointSizes;
|
||||
minBound = other.minBound;
|
||||
maxBound = other.maxBound;
|
||||
hasBounds = other.hasBounds;
|
||||
// VBO 需要重建
|
||||
other.vboCreated = false;
|
||||
}
|
||||
@ -515,13 +548,15 @@ private:
|
||||
|
||||
// 禁止拷贝
|
||||
PointCloudData(const PointCloudData&) = delete;
|
||||
PointCloudData& operator=(const PointCloudData&) = delete;
|
||||
};
|
||||
|
||||
void computeBoundingBox();
|
||||
PointCloudData& operator=(const PointCloudData&) = delete;
|
||||
};
|
||||
|
||||
void computeBoundingBox();
|
||||
void updateProjection(const QMatrix4x4& modelView);
|
||||
float fittedCameraDistance(float padding = 1.05f) const;
|
||||
float minimumCameraDistance() const;
|
||||
/** 按当前缩放把点大小从逻辑像素换到实际绘制像素,避免放大后点散成看不见的碎点。 */
|
||||
float effectivePointSize() const;
|
||||
QVector3D colorForIndex(int colorIndex) const;
|
||||
SelectedPointInfo pickPoint(int screenX, int screenY);
|
||||
void drawSelectedPoints();
|
||||
@ -534,21 +569,26 @@ private:
|
||||
void drawBasicShapeSegments(); // 绘制基础图形
|
||||
void drawBasicShapePoints();
|
||||
void drawLineSegmentList(const QVector<LineSegment>& segments);
|
||||
<<<<<<< HEAD
|
||||
void drawPosePoints(); // 绘制姿态点
|
||||
void drawAxisLabels(); // 绘制坐标轴 XYZ 标注
|
||||
void drawSelectionInfoOverlay(); // 右上角显示选点和测量结果
|
||||
=======
|
||||
|
||||
void drawPosePoints(); // 绘制姿态点
|
||||
void drawAxisLabels(); // 绘制坐标轴 XYZ 标注
|
||||
void drawSelectionInfoOverlay(); // 右上角显示选点和测量结果
|
||||
QVector3D pseudoColorForZ(float z) const;
|
||||
void rebuildPseudoColors(PointCloudData& data, size_t firstVertex);
|
||||
void updatePseudoColors();
|
||||
void createControlButtons();
|
||||
void updateControlButtonGeometry();
|
||||
>>>>>>> c6df042456fa4411f7b5269f8781f91c45da70c2
|
||||
void uploadToVBO(PointCloudData& data); // 上传数据到 VBO
|
||||
void releaseVBO(PointCloudData& data); // 释放 VBO 资源
|
||||
|
||||
void uploadToVBO(PointCloudData& data); // 上传数据到 VBO
|
||||
void releaseVBO(PointCloudData& data); // 释放 VBO 资源
|
||||
void expandCloudBounds(PointCloudData& data, float x, float y, float z);
|
||||
void addPointCloudInternal(const PointCloudXYZ& cloud, const QString& name, bool resetViewAfterAdd, bool refreshDisplay);
|
||||
void trimQueuedPointCloudBatches();
|
||||
void trimDisplayedStreamBatches(bool refreshDisplay);
|
||||
bool removeOldestStreamPointCloud(bool refreshDisplay);
|
||||
void discardLeadingLines(QueuedPointCloudBatch& batch, int lineCount);
|
||||
void discardLeadingStreamLines(PointCloudData& data, int lineCount);
|
||||
void recomputeCloudBounds(PointCloudData& data);
|
||||
|
||||
std::deque<PointCloudData> m_pointClouds;
|
||||
|
||||
@ -570,17 +610,8 @@ private:
|
||||
void createOverlayControls();
|
||||
void repositionOverlayControls();
|
||||
void showViewAngleDialog();
|
||||
<<<<<<< HEAD
|
||||
void updateViewAngleDisplay();
|
||||
bool handlePinchGesture(QPinchGesture* gesture);
|
||||
|
||||
// Each entry owns QOpenGLBuffer objects. deque avoids relocating existing
|
||||
// entries when new scan lines are appended or the oldest one is removed.
|
||||
std::deque<PointCloudData> m_pointClouds;
|
||||
=======
|
||||
void updateViewAngleDisplay();
|
||||
bool handlePinchGesture(QPinchGesture* gesture);
|
||||
>>>>>>> c6df042456fa4411f7b5269f8781f91c45da70c2
|
||||
|
||||
QMatrix4x4 m_projection;
|
||||
QMatrix4x4 m_view;
|
||||
@ -653,8 +684,16 @@ private:
|
||||
QVector<QToolButton*> m_viewButtons;
|
||||
QPushButton* m_viewAngleButton; // 左下角旋转角度显示按钮
|
||||
|
||||
QToolButton* m_zoomInButton;
|
||||
QToolButton* m_zoomOutButton;
|
||||
};
|
||||
QToolButton* m_zoomInButton;
|
||||
QToolButton* m_zoomOutButton;
|
||||
|
||||
// 高速输入先进入 CPU 有界缓存,再由 GUI 线程按固定频率批量提交 OpenGL。
|
||||
QTimer* m_streamRefreshTimer;
|
||||
std::deque<QueuedPointCloudBatch> m_queuedPointCloudBatches;
|
||||
int m_queuedPointCloudLineCount;
|
||||
int m_streamDisplayedLineCount;
|
||||
int m_streamRefreshRate;
|
||||
int m_streamLineLimit;
|
||||
};
|
||||
|
||||
#endif // POINT_CLOUD_GL_WIDGET_H
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -83,9 +83,10 @@ private:
|
||||
QString fileName;
|
||||
};
|
||||
|
||||
void buildStartupSequence(const StartupFiles& files);
|
||||
bool loadStartupItem(const StartupItem& item);
|
||||
bool loadCurrentStartupSequenceItem();
|
||||
void buildStartupSequence(const StartupFiles& files);
|
||||
bool loadStartupItem(const StartupItem& item);
|
||||
bool loadCurrentStartupSequenceItem();
|
||||
void updateZoomButtonGeometry();
|
||||
|
||||
private slots:
|
||||
/**
|
||||
|
||||
@ -1245,24 +1245,40 @@ void CloudViewMainWindow::setPointCloudRange(const PointCloudXYZRange& range)
|
||||
}
|
||||
}
|
||||
|
||||
bool CloudViewMainWindow::eventFilter(QObject* obj, QEvent* event)
|
||||
{
|
||||
if (obj == m_glWidget && event->type() == QEvent::Resize &&
|
||||
m_btnZoomIn && m_btnZoomOut) {
|
||||
const auto* resizeEvent = static_cast<QResizeEvent*>(event);
|
||||
const int width = resizeEvent->size().width();
|
||||
const int height = resizeEvent->size().height();
|
||||
const int buttonWidth = m_btnZoomIn->width();
|
||||
const int buttonHeight = m_btnZoomIn->height();
|
||||
const int margin = 8;
|
||||
const int gap = 4;
|
||||
const int x = width - buttonWidth - margin;
|
||||
const int y = qMax(0, (height - buttonHeight * 2 - gap) / 2);
|
||||
m_btnZoomIn->move(x, y);
|
||||
m_btnZoomOut->move(x, y + buttonHeight + gap);
|
||||
}
|
||||
return QMainWindow::eventFilter(obj, event);
|
||||
}
|
||||
bool CloudViewMainWindow::eventFilter(QObject* obj, QEvent* event)
|
||||
{
|
||||
if (obj == m_glWidget && event->type() == QEvent::Resize &&
|
||||
m_btnZoomIn && m_btnZoomOut) {
|
||||
updateZoomButtonGeometry();
|
||||
}
|
||||
return QMainWindow::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
void CloudViewMainWindow::updateZoomButtonGeometry()
|
||||
{
|
||||
if (!m_glWidget || !m_btnZoomIn || !m_btnZoomOut)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const int widgetWidth = m_glWidget->width();
|
||||
const int widgetHeight = m_glWidget->height();
|
||||
if (widgetWidth <= 0 || widgetHeight <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const int buttonWidth = m_btnZoomIn->width();
|
||||
const int buttonHeight = m_btnZoomIn->height();
|
||||
const int margin = 8;
|
||||
const int gap = 4;
|
||||
const int x = qMax(0, widgetWidth - buttonWidth - margin);
|
||||
const int y = qMax(0, (widgetHeight - buttonHeight * 2 - gap) / 2);
|
||||
m_btnZoomIn->move(x, y);
|
||||
m_btnZoomOut->move(x, y + buttonHeight + gap);
|
||||
m_btnZoomIn->raise();
|
||||
m_btnZoomOut->raise();
|
||||
}
|
||||
|
||||
void CloudViewMainWindow::closeEvent(QCloseEvent* event)
|
||||
{
|
||||
@ -1417,11 +1433,13 @@ QWidget* CloudViewMainWindow::createViewerArea()
|
||||
m_btnZoomOut->setAutoRepeat(true);
|
||||
m_btnZoomOut->setAutoRepeatDelay(300);
|
||||
m_btnZoomOut->setAutoRepeatInterval(50);
|
||||
connect(m_btnZoomOut, &QToolButton::clicked, m_glWidget, &PointCloudGLWidget::zoomOut);
|
||||
|
||||
m_glWidget->installEventFilter(this);
|
||||
|
||||
// 连接信号
|
||||
connect(m_btnZoomOut, &QToolButton::clicked, m_glWidget, &PointCloudGLWidget::zoomOut);
|
||||
|
||||
m_glWidget->installEventFilter(this);
|
||||
// 初始创建时可能没有收到 resize 事件,立即将按钮放到视口右侧居中。
|
||||
updateZoomButtonGeometry();
|
||||
|
||||
// 连接信号
|
||||
connect(m_glWidget, &PointCloudGLWidget::pointSelected, this, &CloudViewMainWindow::onPointSelected);
|
||||
connect(m_glWidget, &PointCloudGLWidget::twoPointsSelected, this, &CloudViewMainWindow::onTwoPointsSelected);
|
||||
connect(m_glWidget, &PointCloudGLWidget::lineSelected, this, &CloudViewMainWindow::onLineSelected);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user