#ifndef CCLOUDSHOW_H #define CCLOUDSHOW_H #include #include #include #include #include #include #include #include #include #include #include #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 m_viewer; std::atomic 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::Ptr m_displayCloud; pcl::PointCloud::Ptr m_renderPool; // 复用,避免每帧 make_shared std::mutex m_lastCloudMutex; CloudData m_lastCloudData; CloudFrameInfo m_lastFrameInfo; std::vector> m_lastCloudBuffers; // UI 状态 std::atomic m_bQuitRequested{false}; std::atomic m_bSaveRequested{false}; std::atomic m_bStartStopRequested{false}; vtkTextActor* m_pStartStopBtnActor = nullptr; vtkTextActor* m_pProgressActor = nullptr; std::mutex m_textMutex; // ── 保存相关 ── struct SaveTask { CloudData cloudData; // 深拷贝的标准格式 std::vector> buffers; // p3DPoint 指向的实际内存(预分配复用) CloudFrameInfo info; }; std::string m_saveBaseDir = "."; std::atomic m_bSaveActive{false}; std::string m_currentSessionDir; // SaveTask 缓冲池:PushFrame(回调线程)从池取预分配好的 task, // 零堆分配完成数据拷贝,saveLoop 用完后归还。消除回调线程的 malloc 延迟抖动。 std::mutex m_taskPoolMutex; std::vector 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 m_saveQueue; std::atomic m_bFlushAndSave{false}; // true=STOP已点击,保存线程开始写盘 static constexpr int SAVE_THREAD_COUNT = 1; std::atomic m_saveExit{false}; std::vector m_saveThreads; std::atomic m_nSaveSeq{0}; std::atomic m_nSingleSaveSeq{0}; std::atomic m_nSaveDropped{0}; std::atomic m_saveCompleted{0}; std::atomic m_saveTotal{0}; int m_nSaveFrameInterval = 10; // 保存帧间隔,默认每10帧存1帧 int m_nPushFrameCount = 0; // PushFrame 调用计数(回调线程独占) }; #endif // CCLOUDSHOW_H