查看点云的软件增加线点的显示
This commit is contained in:
parent
a892b1a7ee
commit
f8e9f4f13f
@ -2,7 +2,7 @@
|
||||
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
|
||||
|
||||
#define MyAppName "点云查看器"
|
||||
#define MyAppVersion "1.0.1"
|
||||
#define MyAppVersion "1.0.2"
|
||||
#define MyAppPublisher ""
|
||||
#define MyAppURL ""
|
||||
#define MyAppExeName "CloudView.exe"
|
||||
|
||||
@ -15,11 +15,16 @@
|
||||
#include <QStatusBar>
|
||||
#include <QLineEdit>
|
||||
#include <QRadioButton>
|
||||
#include <QCheckBox>
|
||||
#include <QDialog>
|
||||
#include <memory>
|
||||
|
||||
#include "PointCloudGLWidget.h"
|
||||
#include "PointCloudConverter.h"
|
||||
|
||||
class QTextEdit;
|
||||
class QTableWidget;
|
||||
|
||||
/**
|
||||
* @brief 点云查看器主窗口
|
||||
* 左侧显示点云,右侧为操作区域
|
||||
@ -83,6 +88,16 @@ private slots:
|
||||
*/
|
||||
void onLineSelectModeChanged(bool checked);
|
||||
|
||||
/**
|
||||
* @brief 显示选中线上的所有点坐标
|
||||
*/
|
||||
void onShowLinePoints();
|
||||
|
||||
/**
|
||||
* @brief 线上点列表项被点击
|
||||
*/
|
||||
void onLinePointTableClicked(int row, int column);
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief 初始化界面
|
||||
@ -124,6 +139,16 @@ private:
|
||||
*/
|
||||
void updateSelectedPointsDisplay();
|
||||
|
||||
/**
|
||||
* @brief 从原始数据获取线上点(包含0,0,0)
|
||||
*/
|
||||
QVector<QVector3D> getOriginalLinePoints(const SelectedLineInfo& lineInfo);
|
||||
|
||||
/**
|
||||
* @brief 更新线上点对话框内容
|
||||
*/
|
||||
void updateLinePointsDialog();
|
||||
|
||||
// 点云显示控件
|
||||
PointCloudGLWidget* m_glWidget;
|
||||
|
||||
@ -136,6 +161,7 @@ private:
|
||||
QPushButton* m_btnResetView;
|
||||
|
||||
// 选点测距控件
|
||||
QCheckBox* m_cbMeasureDistance;
|
||||
QPushButton* m_btnClearPoints;
|
||||
QLabel* m_lblPoint1;
|
||||
QLabel* m_lblPoint2;
|
||||
@ -143,6 +169,7 @@ private:
|
||||
|
||||
// 选线拟合控件
|
||||
QPushButton* m_btnClearLine;
|
||||
QPushButton* m_btnShowLinePoints;
|
||||
QLineEdit* m_lineNumberInput;
|
||||
QPushButton* m_btnSelectByNumber;
|
||||
QRadioButton* m_rbVertical;
|
||||
@ -162,6 +189,11 @@ private:
|
||||
|
||||
// 原始完整点云数据(包含0,0,0点,用于旋转)
|
||||
PointCloudXYZ m_originalCloud;
|
||||
|
||||
// 线上点对话框
|
||||
QDialog* m_linePointsDialog;
|
||||
QTableWidget* m_linePointsTable;
|
||||
QVector<QVector3D> m_currentLinePoints; // 当前线的原始点坐标
|
||||
};
|
||||
|
||||
#endif // CLOUD_VIEW_MAIN_WINDOW_H
|
||||
|
||||
@ -103,6 +103,33 @@ public:
|
||||
*/
|
||||
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 获取第一个点云的数据(用于旋转和保存)
|
||||
*/
|
||||
@ -178,10 +205,15 @@ private:
|
||||
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; // 可用颜色数量
|
||||
};
|
||||
|
||||
@ -1,5 +1,10 @@
|
||||
#include "CloudViewMainWindow.h"
|
||||
#include <QFileInfo>
|
||||
#include <QDialog>
|
||||
#include <QTextEdit>
|
||||
#include <QTableWidget>
|
||||
#include <QHeaderView>
|
||||
#include <QVector3D>
|
||||
#include "VrLog.h"
|
||||
|
||||
CloudViewMainWindow::CloudViewMainWindow(QWidget* parent)
|
||||
@ -9,6 +14,8 @@ CloudViewMainWindow::CloudViewMainWindow(QWidget* parent)
|
||||
, m_cloudCount(0)
|
||||
, m_currentLineNum(0)
|
||||
, m_currentLinePtNum(0)
|
||||
, m_linePointsDialog(nullptr)
|
||||
, m_linePointsTable(nullptr)
|
||||
{
|
||||
setupUI();
|
||||
LOG_INFO("CloudViewMainWindow initialized\n");
|
||||
@ -131,6 +138,19 @@ QGroupBox* CloudViewMainWindow::createMeasureGroup()
|
||||
lblTip->setStyleSheet("color: gray; font-size: 10px;");
|
||||
layout->addWidget(lblTip);
|
||||
|
||||
// 测距复选框
|
||||
m_cbMeasureDistance = new QCheckBox("启用测距", group);
|
||||
m_cbMeasureDistance->setChecked(false);
|
||||
connect(m_cbMeasureDistance, &QCheckBox::toggled, this, [this](bool checked) {
|
||||
m_glWidget->setMeasureDistanceEnabled(checked);
|
||||
// 切换模式时清除已选点
|
||||
m_glWidget->clearSelectedPoints();
|
||||
m_lblPoint1->setText("--");
|
||||
m_lblPoint2->setText("--");
|
||||
m_lblDistance->setText("--");
|
||||
});
|
||||
layout->addWidget(m_cbMeasureDistance);
|
||||
|
||||
// 清除选点按钮
|
||||
m_btnClearPoints = new QPushButton("清除选点", group);
|
||||
connect(m_btnClearPoints, &QPushButton::clicked, this, &CloudViewMainWindow::onClearSelectedPoints);
|
||||
@ -203,6 +223,11 @@ QGroupBox* CloudViewMainWindow::createLineGroup()
|
||||
connect(m_btnClearLine, &QPushButton::clicked, this, &CloudViewMainWindow::onClearLinePoints);
|
||||
layout->addWidget(m_btnClearLine);
|
||||
|
||||
// 显示线上点按钮
|
||||
m_btnShowLinePoints = new QPushButton("显示线上点", group);
|
||||
connect(m_btnShowLinePoints, &QPushButton::clicked, this, &CloudViewMainWindow::onShowLinePoints);
|
||||
layout->addWidget(m_btnShowLinePoints);
|
||||
|
||||
// 线索引信息
|
||||
QHBoxLayout* indexLayout = new QHBoxLayout();
|
||||
QLabel* lblIndexTitle = new QLabel("索引:", group);
|
||||
@ -335,10 +360,19 @@ void CloudViewMainWindow::onPointSelected(const SelectedPointInfo& point)
|
||||
}
|
||||
|
||||
updateSelectedPointsDisplay();
|
||||
statusBar()->showMessage(QString("已选中点: (%1, %2, %3)")
|
||||
|
||||
// 状态栏显示:坐标、线号、索引号
|
||||
QString statusMsg = QString("选中点: (%1, %2, %3)")
|
||||
.arg(point.x, 0, 'f', 3)
|
||||
.arg(point.y, 0, 'f', 3)
|
||||
.arg(point.z, 0, 'f', 3));
|
||||
.arg(point.z, 0, 'f', 3);
|
||||
if (point.lineIndex >= 0) {
|
||||
statusMsg += QString(" | 线号: %1").arg(point.lineIndex);
|
||||
if (point.pointIndexInLine >= 0) {
|
||||
statusMsg += QString(" | 索引号: %1").arg(point.pointIndexInLine);
|
||||
}
|
||||
}
|
||||
statusBar()->showMessage(statusMsg);
|
||||
}
|
||||
|
||||
void CloudViewMainWindow::onTwoPointsSelected(const SelectedPointInfo& p1, const SelectedPointInfo& p2, float distance)
|
||||
@ -353,15 +387,19 @@ void CloudViewMainWindow::updateSelectedPointsDisplay()
|
||||
auto selectedPoints = m_glWidget->getSelectedPoints();
|
||||
|
||||
if (selectedPoints.size() >= 1 && selectedPoints[0].valid) {
|
||||
QString text = QString("(%1, %2, %3)")
|
||||
.arg(selectedPoints[0].x, 0, 'f', 3)
|
||||
.arg(selectedPoints[0].y, 0, 'f', 3)
|
||||
.arg(selectedPoints[0].z, 0, 'f', 3);
|
||||
QString text;
|
||||
if (selectedPoints[0].lineIndex >= 0) {
|
||||
text += QString("\n线索引:%1").arg(selectedPoints[0].lineIndex);
|
||||
if (selectedPoints[0].pointIndexInLine >= 0) {
|
||||
text += QString(" 点索引:%1").arg(selectedPoints[0].pointIndexInLine);
|
||||
}
|
||||
text = QString("线索引:%1 点索引:%2\nx: %3 y: %4 z: %5")
|
||||
.arg(selectedPoints[0].lineIndex)
|
||||
.arg(selectedPoints[0].pointIndexInLine)
|
||||
.arg(selectedPoints[0].x, 0, 'f', 3)
|
||||
.arg(selectedPoints[0].y, 0, 'f', 3)
|
||||
.arg(selectedPoints[0].z, 0, 'f', 3);
|
||||
} else {
|
||||
text = QString("x: %1 y: %2 z: %3")
|
||||
.arg(selectedPoints[0].x, 0, 'f', 3)
|
||||
.arg(selectedPoints[0].y, 0, 'f', 3)
|
||||
.arg(selectedPoints[0].z, 0, 'f', 3);
|
||||
}
|
||||
m_lblPoint1->setText(text);
|
||||
} else {
|
||||
@ -369,15 +407,19 @@ void CloudViewMainWindow::updateSelectedPointsDisplay()
|
||||
}
|
||||
|
||||
if (selectedPoints.size() >= 2 && selectedPoints[1].valid) {
|
||||
QString text = QString("(%1, %2, %3)")
|
||||
.arg(selectedPoints[1].x, 0, 'f', 3)
|
||||
.arg(selectedPoints[1].y, 0, 'f', 3)
|
||||
.arg(selectedPoints[1].z, 0, 'f', 3);
|
||||
QString text;
|
||||
if (selectedPoints[1].lineIndex >= 0) {
|
||||
text += QString("\n线索引:%1").arg(selectedPoints[1].lineIndex);
|
||||
if (selectedPoints[1].pointIndexInLine >= 0) {
|
||||
text += QString(" 点索引:%1").arg(selectedPoints[1].pointIndexInLine);
|
||||
}
|
||||
text = QString("线索引:%1 点索引:%2\nx: %3 y: %4 z: %5")
|
||||
.arg(selectedPoints[1].lineIndex)
|
||||
.arg(selectedPoints[1].pointIndexInLine)
|
||||
.arg(selectedPoints[1].x, 0, 'f', 3)
|
||||
.arg(selectedPoints[1].y, 0, 'f', 3)
|
||||
.arg(selectedPoints[1].z, 0, 'f', 3);
|
||||
} else {
|
||||
text = QString("x: %1 y: %2 z: %3")
|
||||
.arg(selectedPoints[1].x, 0, 'f', 3)
|
||||
.arg(selectedPoints[1].y, 0, 'f', 3)
|
||||
.arg(selectedPoints[1].z, 0, 'f', 3);
|
||||
}
|
||||
m_lblPoint2->setText(text);
|
||||
} else {
|
||||
@ -400,6 +442,7 @@ void CloudViewMainWindow::onLineSelectModeChanged(bool checked)
|
||||
void CloudViewMainWindow::onClearLinePoints()
|
||||
{
|
||||
m_glWidget->clearSelectedLine();
|
||||
m_glWidget->clearListHighlightPoint(); // 清除列表选中的高亮点
|
||||
m_lblLineIndex->setText("--");
|
||||
m_lblLinePointCount->setText("--");
|
||||
statusBar()->showMessage("已清除选线");
|
||||
@ -407,25 +450,32 @@ void CloudViewMainWindow::onClearLinePoints()
|
||||
|
||||
void CloudViewMainWindow::onLineSelected(const SelectedLineInfo& line)
|
||||
{
|
||||
// 重新选线时清除列表高亮点
|
||||
m_glWidget->clearListHighlightPoint();
|
||||
|
||||
if (!line.valid) {
|
||||
m_lblLineIndex->setText("--");
|
||||
m_lblLinePointCount->setText("--");
|
||||
return;
|
||||
}
|
||||
|
||||
// 状态栏显示:线号/索引号、线点数
|
||||
if (line.mode == LineSelectMode::Vertical) {
|
||||
m_lblLineIndex->setText(QString::number(line.lineIndex));
|
||||
statusBar()->showMessage(QString("已选中索引 %1 的线,共 %2 个点")
|
||||
statusBar()->showMessage(QString("选中线 | 线号: %1 | 线点数: %2")
|
||||
.arg(line.lineIndex)
|
||||
.arg(line.pointCount));
|
||||
} else {
|
||||
// 横向选线:显示索引(从0开始)
|
||||
// 横向选线:显示索引号
|
||||
m_lblLineIndex->setText(QString::number(line.pointIndex));
|
||||
statusBar()->showMessage(QString("已选中索引 %1 的横向线,共 %2 个点")
|
||||
statusBar()->showMessage(QString("选中横向线 | 索引号: %1 | 线点数: %2")
|
||||
.arg(line.pointIndex)
|
||||
.arg(line.pointCount));
|
||||
}
|
||||
m_lblLinePointCount->setText(QString::number(line.pointCount));
|
||||
|
||||
// 如果线上点对话框已打开,刷新内容
|
||||
updateLinePointsDialog();
|
||||
}
|
||||
|
||||
void CloudViewMainWindow::onSelectLineByNumber()
|
||||
@ -464,3 +514,194 @@ void CloudViewMainWindow::onSelectLineByNumber()
|
||||
}
|
||||
}
|
||||
|
||||
QVector<QVector3D> CloudViewMainWindow::getOriginalLinePoints(const SelectedLineInfo& lineInfo)
|
||||
{
|
||||
QVector<QVector3D> points;
|
||||
|
||||
if (!lineInfo.valid || m_originalCloud.empty()) {
|
||||
return points;
|
||||
}
|
||||
|
||||
if (lineInfo.mode == LineSelectMode::Vertical) {
|
||||
// 纵向选线:获取同一条扫描线上的所有点
|
||||
for (size_t i = 0; i < m_originalCloud.points.size(); ++i) {
|
||||
if (i < m_originalCloud.lineIndices.size() &&
|
||||
m_originalCloud.lineIndices[i] == lineInfo.lineIndex) {
|
||||
const auto& pt = m_originalCloud.points[i];
|
||||
points.append(QVector3D(pt.x, pt.y, pt.z));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 横向选线:获取所有线的相同索引点
|
||||
if (m_currentLinePtNum > 0 && lineInfo.pointIndex >= 0) {
|
||||
for (size_t i = 0; i < m_originalCloud.points.size(); ++i) {
|
||||
int originalIdx = static_cast<int>(i);
|
||||
if (originalIdx % m_currentLinePtNum == lineInfo.pointIndex) {
|
||||
const auto& pt = m_originalCloud.points[i];
|
||||
points.append(QVector3D(pt.x, pt.y, pt.z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return points;
|
||||
}
|
||||
|
||||
void CloudViewMainWindow::updateLinePointsDialog()
|
||||
{
|
||||
if (!m_linePointsDialog || !m_linePointsTable) {
|
||||
return;
|
||||
}
|
||||
|
||||
SelectedLineInfo lineInfo = m_glWidget->getSelectedLine();
|
||||
if (!lineInfo.valid) {
|
||||
m_linePointsTable->setRowCount(0);
|
||||
m_linePointsDialog->setWindowTitle("线上点坐标");
|
||||
m_currentLinePoints.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// 从原始数据获取线上点(包含0,0,0)
|
||||
m_currentLinePoints = getOriginalLinePoints(lineInfo);
|
||||
|
||||
// 更新标题
|
||||
QString title;
|
||||
if (lineInfo.mode == LineSelectMode::Vertical) {
|
||||
title = QString("线上点坐标 - 线号: %1 (共 %2 个点)")
|
||||
.arg(lineInfo.lineIndex)
|
||||
.arg(m_currentLinePoints.size());
|
||||
} else {
|
||||
title = QString("线上点坐标 - 索引号: %1 (共 %2 个点)")
|
||||
.arg(lineInfo.pointIndex)
|
||||
.arg(m_currentLinePoints.size());
|
||||
}
|
||||
m_linePointsDialog->setWindowTitle(title);
|
||||
|
||||
// 更新表格
|
||||
m_linePointsTable->setRowCount(m_currentLinePoints.size());
|
||||
|
||||
// 斑马线颜色
|
||||
QColor evenColor(245, 245, 245); // 浅灰色
|
||||
QColor oddColor(255, 255, 255); // 白色
|
||||
|
||||
for (int i = 0; i < m_currentLinePoints.size(); ++i) {
|
||||
const QVector3D& pt = m_currentLinePoints[i];
|
||||
QColor rowColor = (i % 2 == 0) ? evenColor : oddColor;
|
||||
|
||||
// 序号
|
||||
QTableWidgetItem* indexItem = new QTableWidgetItem(QString::number(i));
|
||||
indexItem->setTextAlignment(Qt::AlignCenter);
|
||||
indexItem->setBackground(rowColor);
|
||||
indexItem->setFlags(indexItem->flags() & ~Qt::ItemIsEditable);
|
||||
m_linePointsTable->setItem(i, 0, indexItem);
|
||||
|
||||
// X
|
||||
QTableWidgetItem* xItem = new QTableWidgetItem(QString::number(pt.x(), 'f', 3));
|
||||
xItem->setTextAlignment(Qt::AlignCenter);
|
||||
xItem->setBackground(rowColor);
|
||||
xItem->setFlags(xItem->flags() & ~Qt::ItemIsEditable);
|
||||
m_linePointsTable->setItem(i, 1, xItem);
|
||||
|
||||
// Y
|
||||
QTableWidgetItem* yItem = new QTableWidgetItem(QString::number(pt.y(), 'f', 3));
|
||||
yItem->setTextAlignment(Qt::AlignCenter);
|
||||
yItem->setBackground(rowColor);
|
||||
yItem->setFlags(yItem->flags() & ~Qt::ItemIsEditable);
|
||||
m_linePointsTable->setItem(i, 2, yItem);
|
||||
|
||||
// Z
|
||||
QTableWidgetItem* zItem = new QTableWidgetItem(QString::number(pt.z(), 'f', 3));
|
||||
zItem->setTextAlignment(Qt::AlignCenter);
|
||||
zItem->setBackground(rowColor);
|
||||
zItem->setFlags(zItem->flags() & ~Qt::ItemIsEditable);
|
||||
m_linePointsTable->setItem(i, 3, zItem);
|
||||
}
|
||||
}
|
||||
|
||||
void CloudViewMainWindow::onShowLinePoints()
|
||||
{
|
||||
SelectedLineInfo lineInfo = m_glWidget->getSelectedLine();
|
||||
if (!lineInfo.valid) {
|
||||
QMessageBox::warning(this, "提示", "请先选择一条线");
|
||||
return;
|
||||
}
|
||||
|
||||
// 如果对话框已存在,刷新内容并显示
|
||||
if (m_linePointsDialog) {
|
||||
updateLinePointsDialog();
|
||||
m_linePointsDialog->raise();
|
||||
m_linePointsDialog->activateWindow();
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建对话框
|
||||
m_linePointsDialog = new QDialog(this);
|
||||
m_linePointsDialog->resize(450, 500);
|
||||
m_linePointsDialog->setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
// 对话框关闭时清理指针
|
||||
connect(m_linePointsDialog, &QDialog::destroyed, this, [this]() {
|
||||
m_linePointsDialog = nullptr;
|
||||
m_linePointsTable = nullptr;
|
||||
m_currentLinePoints.clear();
|
||||
m_glWidget->clearListHighlightPoint();
|
||||
});
|
||||
|
||||
QVBoxLayout* layout = new QVBoxLayout(m_linePointsDialog);
|
||||
|
||||
// 提示标签
|
||||
QLabel* lblTip = new QLabel("点击行在3D视图中高亮显示", m_linePointsDialog);
|
||||
lblTip->setStyleSheet("color: gray; font-size: 10px;");
|
||||
layout->addWidget(lblTip);
|
||||
|
||||
// 创建表格控件
|
||||
m_linePointsTable = new QTableWidget(m_linePointsDialog);
|
||||
m_linePointsTable->setColumnCount(4);
|
||||
m_linePointsTable->setHorizontalHeaderLabels({"序号", "X", "Y", "Z"});
|
||||
m_linePointsTable->setFont(QFont("Consolas", 9));
|
||||
m_linePointsTable->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
m_linePointsTable->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||
m_linePointsTable->verticalHeader()->setVisible(false);
|
||||
|
||||
// 设置列宽
|
||||
m_linePointsTable->setColumnWidth(0, 60); // 序号
|
||||
m_linePointsTable->setColumnWidth(1, 110); // X
|
||||
m_linePointsTable->setColumnWidth(2, 110); // Y
|
||||
m_linePointsTable->setColumnWidth(3, 110); // Z
|
||||
|
||||
// 表头样式
|
||||
m_linePointsTable->horizontalHeader()->setStretchLastSection(true);
|
||||
m_linePointsTable->horizontalHeader()->setDefaultAlignment(Qt::AlignCenter);
|
||||
|
||||
connect(m_linePointsTable, &QTableWidget::cellClicked,
|
||||
this, &CloudViewMainWindow::onLinePointTableClicked);
|
||||
layout->addWidget(m_linePointsTable);
|
||||
|
||||
// 关闭按钮
|
||||
QPushButton* btnClose = new QPushButton("关闭", m_linePointsDialog);
|
||||
connect(btnClose, &QPushButton::clicked, m_linePointsDialog, &QDialog::close);
|
||||
layout->addWidget(btnClose);
|
||||
|
||||
// 填充数据
|
||||
updateLinePointsDialog();
|
||||
|
||||
m_linePointsDialog->show();
|
||||
}
|
||||
|
||||
void CloudViewMainWindow::onLinePointTableClicked(int row, int column)
|
||||
{
|
||||
Q_UNUSED(column);
|
||||
|
||||
if (row >= 0 && row < m_currentLinePoints.size()) {
|
||||
const QVector3D& pt = m_currentLinePoints[row];
|
||||
m_glWidget->setListHighlightPoint(pt);
|
||||
|
||||
// 在状态栏显示选中点信息
|
||||
statusBar()->showMessage(QString("列表选中点 %1: (%2, %3, %4)")
|
||||
.arg(row)
|
||||
.arg(pt.x(), 0, 'f', 3)
|
||||
.arg(pt.y(), 0, 'f', 3)
|
||||
.arg(pt.z(), 0, 'f', 3));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -29,6 +29,8 @@ PointCloudGLWidget::PointCloudGLWidget(QWidget* parent)
|
||||
, m_currentColor(PointCloudColor::White)
|
||||
, m_pointSize(1.0f)
|
||||
, m_lineSelectMode(LineSelectMode::Vertical)
|
||||
, m_measureDistanceEnabled(false)
|
||||
, m_hasListHighlightPoint(false)
|
||||
, m_colorIndex(0)
|
||||
{
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
@ -378,6 +380,70 @@ float PointCloudGLWidget::calculateDistance(const SelectedPointInfo& p1, const S
|
||||
return std::sqrt(dx * dx + dy * dy + dz * dz);
|
||||
}
|
||||
|
||||
QVector<QVector3D> PointCloudGLWidget::getSelectedLinePoints() const
|
||||
{
|
||||
QVector<QVector3D> points;
|
||||
|
||||
if (!m_selectedLine.valid || m_selectedLine.cloudIndex < 0) {
|
||||
return points;
|
||||
}
|
||||
|
||||
if (m_selectedLine.cloudIndex >= static_cast<int>(m_pointClouds.size())) {
|
||||
return points;
|
||||
}
|
||||
|
||||
const auto& cloudData = m_pointClouds[m_selectedLine.cloudIndex];
|
||||
if (!cloudData.hasLineInfo) {
|
||||
return points;
|
||||
}
|
||||
|
||||
if (m_selectedLine.mode == LineSelectMode::Vertical) {
|
||||
// 纵向选线:获取同一条扫描线上的所有点
|
||||
for (size_t i = 0; i < cloudData.lineIndices.size(); ++i) {
|
||||
if (cloudData.lineIndices[i] == m_selectedLine.lineIndex) {
|
||||
size_t vertIdx = i * 3;
|
||||
if (vertIdx + 2 < cloudData.vertices.size()) {
|
||||
points.append(QVector3D(
|
||||
cloudData.vertices[vertIdx],
|
||||
cloudData.vertices[vertIdx + 1],
|
||||
cloudData.vertices[vertIdx + 2]));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 横向选线:获取所有线的相同索引点
|
||||
if (cloudData.pointsPerLine > 0 && m_selectedLine.pointIndex >= 0) {
|
||||
for (size_t i = 0; i < cloudData.originalIndices.size(); ++i) {
|
||||
int originalIdx = cloudData.originalIndices[i];
|
||||
if (originalIdx % cloudData.pointsPerLine == m_selectedLine.pointIndex) {
|
||||
size_t vertIdx = i * 3;
|
||||
if (vertIdx + 2 < cloudData.vertices.size()) {
|
||||
points.append(QVector3D(
|
||||
cloudData.vertices[vertIdx],
|
||||
cloudData.vertices[vertIdx + 1],
|
||||
cloudData.vertices[vertIdx + 2]));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return points;
|
||||
}
|
||||
|
||||
void PointCloudGLWidget::setListHighlightPoint(const QVector3D& point)
|
||||
{
|
||||
m_hasListHighlightPoint = true;
|
||||
m_listHighlightPoint = point;
|
||||
update();
|
||||
}
|
||||
|
||||
void PointCloudGLWidget::clearListHighlightPoint()
|
||||
{
|
||||
m_hasListHighlightPoint = false;
|
||||
update();
|
||||
}
|
||||
|
||||
void PointCloudGLWidget::computeBoundingBox()
|
||||
{
|
||||
if (m_pointClouds.empty()) {
|
||||
@ -533,20 +599,25 @@ SelectedPointInfo PointCloudGLWidget::pickPoint(int screenX, int screenY)
|
||||
|
||||
void PointCloudGLWidget::drawSelectedPoints()
|
||||
{
|
||||
if (m_selectedPoints.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
glPointSize(10.0f);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
glBegin(GL_POINTS);
|
||||
|
||||
// 绘制选中的点(橙色)
|
||||
for (const auto& pt : m_selectedPoints) {
|
||||
if (pt.valid) {
|
||||
glColor3f(1.0f, 0.5f, 0.0f);
|
||||
glColor3f(1.0f, 0.5f, 0.0f); // 橙色
|
||||
glVertex3f(pt.x, pt.y, pt.z);
|
||||
}
|
||||
}
|
||||
|
||||
// 绘制列表高亮点(蓝色,与选点区分)
|
||||
if (m_hasListHighlightPoint) {
|
||||
glColor3f(0.0f, 0.5f, 1.0f); // 蓝色
|
||||
glVertex3f(m_listHighlightPoint.x(), m_listHighlightPoint.y(), m_listHighlightPoint.z());
|
||||
}
|
||||
|
||||
glEnd();
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
@ -712,16 +783,24 @@ void PointCloudGLWidget::mousePressEvent(QMouseEvent* event)
|
||||
doneCurrent();
|
||||
|
||||
if (point.valid) {
|
||||
if (m_selectedPoints.size() >= MAX_SELECTED_POINTS) {
|
||||
if (m_measureDistanceEnabled) {
|
||||
// 启用测距:最多保留两个点
|
||||
if (m_selectedPoints.size() >= MAX_SELECTED_POINTS) {
|
||||
m_selectedPoints.clear();
|
||||
}
|
||||
m_selectedPoints.append(point);
|
||||
|
||||
emit pointSelected(point);
|
||||
|
||||
if (m_selectedPoints.size() == 2) {
|
||||
float distance = calculateDistance(m_selectedPoints[0], m_selectedPoints[1]);
|
||||
emit twoPointsSelected(m_selectedPoints[0], m_selectedPoints[1], distance);
|
||||
}
|
||||
} else {
|
||||
// 未启用测距:只保留一个点
|
||||
m_selectedPoints.clear();
|
||||
}
|
||||
m_selectedPoints.append(point);
|
||||
|
||||
emit pointSelected(point);
|
||||
|
||||
if (m_selectedPoints.size() == 2) {
|
||||
float distance = calculateDistance(m_selectedPoints[0], m_selectedPoints[1]);
|
||||
emit twoPointsSelected(m_selectedPoints[0], m_selectedPoints[1], distance);
|
||||
m_selectedPoints.append(point);
|
||||
emit pointSelected(point);
|
||||
}
|
||||
|
||||
update();
|
||||
|
||||
@ -3,6 +3,8 @@
|
||||
#include <QIcon>
|
||||
#include "CloudViewMainWindow.h"
|
||||
|
||||
#define APP_VERSION "1.0.2"
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
@ -18,14 +20,14 @@ int main(int argc, char* argv[])
|
||||
// 设置应用信息
|
||||
app.setApplicationName("CloudView");
|
||||
app.setOrganizationName("CloudView");
|
||||
app.setApplicationVersion("1.0.1");
|
||||
app.setApplicationVersion(APP_VERSION);
|
||||
|
||||
// 设置应用程序图标
|
||||
app.setWindowIcon(QIcon(":/logo.png"));
|
||||
|
||||
// 创建并显示主窗口
|
||||
CloudViewMainWindow mainWindow;
|
||||
mainWindow.setWindowTitle("点云查看器 v1.0.1");
|
||||
mainWindow.setWindowTitle(QString("点云查看器 v%1").arg(APP_VERSION));
|
||||
mainWindow.resize(1280, 720);
|
||||
mainWindow.show();
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user