2026-06-13 13:24:31 +08:00

125 lines
4.3 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 CCLOUDSHOW_H
#define CCLOUDSHOW_H
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <vtkTextActor.h>
#include <atomic>
#include <condition_variable>
#include <deque>
#include <mutex>
#include <string>
#include <thread>
#include <vector>
#include "ICloudShow.h"
class vtkOrientationMarkerWidget;
class CCloudShow : public ICloudShow
{
public:
CCloudShow();
~CCloudShow() override;
int Show(const CloudData& cloudData,
const CloudFrameInfo& info,
const std::string& windowName = "PointCloud") override;
int Start(const std::string& windowName = "PointCloud", void* hwnd = nullptr) override;
int Stop() override;
int SpinOnce(int ms = 1) override;
bool IsRunning() const override;
void PushFrame(const CloudData& cloudData,
const CloudFrameInfo& info) override;
void SetSaveBaseDir(const std::string& dir) override;
void SetSaveFrameInterval(int interval) override;
bool IsSaveActive() const override;
bool IsQuitRequested() const override;
bool IsSaveRequested() const override;
void ClearSaveRequest() override;
private:
static void keyboardCallback(const pcl::visualization::KeyboardEvent& event, void* cookie);
// UI
void handleStartStopToggle();
void updateStartStopButton();
void updateProgressText();
// 保存线程
void saveLoop();
// ── 显示相关 ──
std::shared_ptr<pcl::visualization::PCLVisualizer> m_viewer;
std::atomic<bool> m_bRunning{false};
std::mutex m_cloudMutex;
bool m_bUpdated = false;
bool m_bFirstCloud = true;
std::string m_windowName;
vtkOrientationMarkerWidget* m_axesWidget = nullptr;
// 当前待显示的 PCL 云 + 最近一帧 CloudData供单帧保存
// 注意m_lastCloudData / m_lastCloudBuffers / m_lastFrameInfo 被 PushFrame回调线程
// 和 SpinOnce主线程同时访问需 m_lastCloudMutex 保护
pcl::PointCloud<pcl::PointXYZI>::Ptr m_displayCloud;
pcl::PointCloud<pcl::PointXYZI>::Ptr m_renderPool; // 复用,避免每帧 make_shared
std::mutex m_lastCloudMutex;
CloudData m_lastCloudData;
CloudFrameInfo m_lastFrameInfo;
std::vector<std::vector<uint8_t>> m_lastCloudBuffers;
// UI 状态
std::atomic<bool> m_bQuitRequested{false};
std::atomic<bool> m_bSaveRequested{false};
std::atomic<bool> m_bStartStopRequested{false};
vtkTextActor* m_pStartStopBtnActor = nullptr;
vtkTextActor* m_pProgressActor = nullptr;
std::mutex m_textMutex;
// ── 保存相关 ──
struct SaveTask
{
CloudData cloudData; // 深拷贝的标准格式
std::vector<std::vector<uint8_t>> buffers; // p3DPoint 指向的实际内存(预分配复用)
CloudFrameInfo info;
};
std::string m_saveBaseDir = ".";
std::atomic<bool> m_bSaveActive{false};
std::string m_currentSessionDir;
// SaveTask 缓冲池PushFrame回调线程从池取预分配好的 task
// 零堆分配完成数据拷贝saveLoop 用完后归还。消除回调线程的 malloc 延迟抖动。
std::mutex m_taskPoolMutex;
std::vector<SaveTask> m_taskPool; // 空闲 task 栈
SaveTask acquireTask();
void releaseTask(SaveTask& task);
void packIntoTask(SaveTask& task,
const ICloudShow::CloudData& cloudData,
const CloudFrameInfo& info);
std::mutex m_saveMutex;
std::condition_variable m_saveCv;
std::deque<SaveTask> m_saveQueue;
std::atomic<bool> m_bFlushAndSave{false}; // true=STOP已点击保存线程开始写盘
static constexpr int SAVE_THREAD_COUNT = 1;
std::atomic<bool> m_saveExit{false};
std::vector<std::thread> m_saveThreads;
std::atomic<int> m_nSaveSeq{0};
std::atomic<int> m_nSingleSaveSeq{0};
std::atomic<int> m_nSaveDropped{0};
std::atomic<int> m_saveCompleted{0};
std::atomic<int> m_saveTotal{0};
int m_nSaveFrameInterval = 10; // 保存帧间隔默认每10帧存1帧
int m_nPushFrameCount = 0; // PushFrame 调用计数(回调线程独占)
};
#endif // CCLOUDSHOW_H