增加3D数据的移除功能

This commit is contained in:
杰仔 2026-08-12 14:48:18 +08:00
parent 47fef439e3
commit 74072f9620
4 changed files with 79 additions and 17 deletions

16
CMakeLists.txt Normal file
View File

@ -0,0 +1,16 @@
cmake_minimum_required(VERSION 3.14)
project(WoodCamUtils LANGUAGES CXX)
option(WOODCAM_BUILD_CLOUDVIEW3D "Build the Qt/OpenGL CloudView3D utility" ON)
# VrCommon is a header-oriented compatibility module. Keep it as an interface
# target so consumers get the canonical VZNL_Types.h include path.
add_library(VrCommon INTERFACE)
target_include_directories(VrCommon INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}/VrCommon/Inc
)
if(WOODCAM_BUILD_CLOUDVIEW3D)
add_subdirectory(CloudView3D)
endif()

View File

@ -0,0 +1,42 @@
cmake_minimum_required(VERSION 3.14)
find_package(Qt5 REQUIRED COMPONENTS Core Gui Widgets OpenGL)
if(NOT TARGET VrCommon)
add_library(VrCommon INTERFACE)
target_include_directories(VrCommon INTERFACE
${CMAKE_CURRENT_SOURCE_DIR}/../VrCommon/Inc
)
endif()
add_library(CloudView3D STATIC
Src/PointCloudGLWidget.cpp
Inc/CloudView3D.h
Inc/CloudView3DTypes.h
Inc/PointCloudGLWidget.h
)
set_target_properties(CloudView3D PROPERTIES
CXX_STANDARD 17
CXX_STANDARD_REQUIRED ON
AUTOMOC ON
)
target_include_directories(CloudView3D PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/Inc
${CMAKE_CURRENT_SOURCE_DIR}/../VrCommon/Inc
)
target_link_libraries(CloudView3D PUBLIC
VrCommon
Qt5::Core
Qt5::Gui
Qt5::Widgets
Qt5::OpenGL
)
if(WIN32)
target_link_libraries(CloudView3D PUBLIC opengl32 glu32)
elseif(UNIX AND NOT APPLE)
target_link_libraries(CloudView3D PUBLIC GL GLU)
endif()

View File

@ -12,7 +12,7 @@ win32-msvc {
INCLUDEPATH += $$PWD/Inc
INCLUDEPATH += $$PWD/../VrUtils/Inc
INCLUDEPATH += $$PWD/../VrCommon/Inc
INCLUDEPATH += $$PWD/../../Device/SDK/VzNLSDK/Inc
# VZNL_Types.h is maintained in the shared Utils module.
HEADERS += \
Inc/CloudView3D.h \

View File

@ -1,10 +1,14 @@
#include "PointCloudGLWidget.h"
#include <QDebug>
#include <QDebug>
#include <QtMath>
#include <QPainter>
#include <cfloat>
#include <map>
#include "VrLog.h"
#define CLOUD_LOG_INFO(...) \
qInfo().noquote() << QString::asprintf(__VA_ARGS__).trimmed()
#define CLOUD_LOG_WARN(...) \
qWarning().noquote() << QString::asprintf(__VA_ARGS__).trimmed()
// OpenGL/GLU 头文件
#ifdef _WIN32
@ -105,7 +109,7 @@ void PointCloudGLWidget::initializeGL()
{
initializeOpenGLFunctions();
LOG_INFO("[CloudView] OpenGL initialized, version: %s\n", reinterpret_cast<const char*>(glGetString(GL_VERSION)));
CLOUD_LOG_INFO("[CloudView] OpenGL initialized, version: %s\n", reinterpret_cast<const char*>(glGetString(GL_VERSION)));
glClearColor(0.15f, 0.15f, 0.15f, 1.0f);
glEnable(GL_DEPTH_TEST);
@ -142,7 +146,7 @@ void PointCloudGLWidget::paintGL()
if (++frameCount % 100 == 0) {
// 从四元数转换为欧拉角用于显示
QVector3D euler = m_rotation.toEulerAngles();
LOG_INFO("[CloudView] Current rotation: pitch=%.1f, yaw=%.1f, roll=%.1f\n",
CLOUD_LOG_INFO("[CloudView] Current rotation: pitch=%.1f, yaw=%.1f, roll=%.1f\n",
euler.x(), euler.y(), euler.z());
}
@ -242,10 +246,10 @@ void PointCloudGLWidget::paintGL()
void PointCloudGLWidget::addPointCloud(const PointCloudXYZ& cloud, const QString& name)
{
LOG_INFO("[CloudView] addPointCloud called, cloud size: %zu\n", cloud.size());
CLOUD_LOG_INFO("[CloudView] addPointCloud called, cloud size: %zu\n", cloud.size());
if (cloud.empty()) {
LOG_WARN("[CloudView] Cloud is empty, returning\n");
CLOUD_LOG_WARN("[CloudView] Cloud is empty, returning\n");
return;
}
@ -309,7 +313,7 @@ void PointCloudGLWidget::addPointCloud(const PointCloudXYZ& cloud, const QString
data.pointsPerLine = static_cast<int>(cloud.size()) / data.totalLines;
}
LOG_INFO("[CloudView] Valid vertices count: %zu, colorIndex: %d, totalLines: %d, pointsPerLine: %d\n",
CLOUD_LOG_INFO("[CloudView] Valid vertices count: %zu, colorIndex: %d, totalLines: %d, pointsPerLine: %d\n",
data.vertices.size() / 3, data.colorIndex, data.totalLines, data.pointsPerLine);
m_pointClouds.push_back(std::move(data));
@ -320,10 +324,10 @@ void PointCloudGLWidget::addPointCloud(const PointCloudXYZ& cloud, const QString
doneCurrent();
computeBoundingBox();
LOG_INFO("[CloudView] BoundingBox min: (%.3f, %.3f, %.3f) max: (%.3f, %.3f, %.3f)\n",
CLOUD_LOG_INFO("[CloudView] BoundingBox min: (%.3f, %.3f, %.3f) max: (%.3f, %.3f, %.3f)\n",
m_minBound.x(), m_minBound.y(), m_minBound.z(),
m_maxBound.x(), m_maxBound.y(), m_maxBound.z());
LOG_INFO("[CloudView] Center: (%.3f, %.3f, %.3f) Distance: %.3f\n",
CLOUD_LOG_INFO("[CloudView] Center: (%.3f, %.3f, %.3f) Distance: %.3f\n",
m_center.x(), m_center.y(), m_center.z(), m_distance);
resetView();
@ -420,7 +424,7 @@ void PointCloudGLWidget::addPointCloud(const PointCloudXYZRGB& cloud, const QStr
group.indices = std::move(pair.second);
data.customPointSizeGroups.push_back(std::move(group));
}
LOG_INFO("[CloudView] Found %zu custom point size groups\n", data.customPointSizeGroups.size());
CLOUD_LOG_INFO("[CloudView] Found %zu custom point size groups\n", data.customPointSizeGroups.size());
}
// 计算每线点数
@ -493,7 +497,7 @@ void PointCloudGLWidget::resetView()
m_rotation = QQuaternion::fromEulerAngles(m_rotationX, m_rotationY, m_rotationZ);
m_pan = QVector3D(0, 0, 0);
LOG_INFO("[CloudView] resetView: size=(%.3f, %.3f, %.3f) maxSize=%.3f distance=%.3f\n",
CLOUD_LOG_INFO("[CloudView] resetView: size=(%.3f, %.3f, %.3f) maxSize=%.3f distance=%.3f\n",
size.x(), size.y(), size.z(), maxSize, m_distance);
emit viewAnglesChanged(m_rotationX, m_rotationY, m_rotationZ);
@ -530,7 +534,7 @@ void PointCloudGLWidget::setViewAngles(float rotX, float rotY, float rotZ)
// 从欧拉角转换为四元数(ZYX顺序)
m_rotation = QQuaternion::fromEulerAngles(rotX, rotY, rotZ);
LOG_INFO("[CloudView] setViewAngles: rotX=%.1f, rotY=%.1f, rotZ=%.1f\n", rotX, rotY, rotZ);
CLOUD_LOG_INFO("[CloudView] setViewAngles: rotX=%.1f, rotY=%.1f, rotZ=%.1f\n", rotX, rotY, rotZ);
emit viewAnglesChanged(m_rotationX, m_rotationY, m_rotationZ);
update();
@ -646,7 +650,7 @@ void PointCloudGLWidget::updateSelectedPointCoord(int index, float x, float y, f
m_selectedPoints[index].y = y;
m_selectedPoints[index].z = z;
LOG_INFO("[CloudView] Updated selected point %d to (%.3f, %.3f, %.3f)\n", index, x, y, z);
CLOUD_LOG_INFO("[CloudView] Updated selected point %d to (%.3f, %.3f, %.3f)\n", index, x, y, z);
// 刷新显示
update();
@ -671,7 +675,7 @@ void PointCloudGLWidget::setSelectedPointCoord(int index, float x, float y, floa
m_selectedPoints[index].lineIndex = -1;
m_selectedPoints[index].pointIndexInLine = -1;
LOG_INFO("[CloudView] Set selected point %d to (%.3f, %.3f, %.3f)\n", index, x, y, z);
CLOUD_LOG_INFO("[CloudView] Set selected point %d to (%.3f, %.3f, %.3f)\n", index, x, y, z);
// 刷新显示
update();
@ -1032,10 +1036,10 @@ SelectedPointInfo PointCloudGLWidget::pickPoint(int screenX, int screenY)
}
}
LOG_INFO("[CloudView] Point selected: (%.3f, %.3f, %.3f) lineIndex=%d pointIndexInLine=%d screenDist=%.1f\n",
CLOUD_LOG_INFO("[CloudView] Point selected: (%.3f, %.3f, %.3f) lineIndex=%d pointIndexInLine=%d screenDist=%.1f\n",
bestX, bestY, bestZ, bestLineIndex, result.pointIndexInLine, std::sqrt(minScreenDist));
} else {
LOG_INFO("[CloudView] No point selected, minScreenDist=%.1f\n", std::sqrt(minScreenDist));
CLOUD_LOG_INFO("[CloudView] No point selected, minScreenDist=%.1f\n", std::sqrt(minScreenDist));
}
return result;