From e2ecf8081fb15acd4fefa46e7d85e87cde338189 Mon Sep 17 00:00:00 2001 From: wyc <1104749580@qq.com> Date: Thu, 23 Jul 2026 11:39:46 +0800 Subject: [PATCH] =?UTF-8?q?tempdata=20=E4=B9=9F=E9=87=87=E7=94=A8=E4=B8=89?= =?UTF-8?q?=E7=BC=93=E5=86=B2=E6=9E=B6=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- YSGraphic_Core/Axis/AbsAxis_p.h | 2 +- YSGraphic_Core/Axis/Axis.h | 2 +- YSGraphic_Core/Axis/Axis_p.h | 2 +- YSGraphic_Core/Axis/FrequentAxis_p.h | 2 +- YSGraphic_Core/Axis/TimeAxis.cpp | 8 +- YSGraphic_Core/Axis/TimeAxis_p.h | 9 +- YSGraphic_Core/GlobalTypes.h | 1 - YSGraphic_Core/RenderAble.cpp | 22 ++- YSGraphic_Core/RenderAble.h | 152 ++++++++++++++++----- YSGraphic_Core/base/MutiSelectRect_p.h | 3 +- YSGraphic_Core/plottable/Afterglow.cpp | 67 +++++---- YSGraphic_Core/plottable/Afterglow_p.h | 60 ++++---- YSGraphic_Core/plottable/AudioFrequent.cpp | 4 +- YSGraphic_Core/plottable/AudioFrequent_p.h | 10 +- YSGraphic_Core/plottable/Planisphere.cpp | 4 +- YSGraphic_Core/plottable/Planisphere_p.h | 8 +- YSGraphic_Core/plottable/Spectrum.cpp | 115 ++++++++++++++-- YSGraphic_Core/plottable/Spectrum_p.h | 142 ++++--------------- YSGraphic_Core/plottable/SweepFrequent.cpp | 8 +- YSGraphic_Core/plottable/SweepFrequent_p.h | 11 +- YSGraphic_Core/plottable/WaterFall.cpp | 4 +- YSGraphic_Core/plottable/WaterFall_p.h | 10 +- 22 files changed, 395 insertions(+), 251 deletions(-) diff --git a/YSGraphic_Core/Axis/AbsAxis_p.h b/YSGraphic_Core/Axis/AbsAxis_p.h index 1db6162..c17233f 100644 --- a/YSGraphic_Core/Axis/AbsAxis_p.h +++ b/YSGraphic_Core/Axis/AbsAxis_p.h @@ -14,7 +14,7 @@ namespace YSG { coordLength *= factor; } }; - struct AbsAxisTempData : TempData {}; + struct AbsAxisInputData : InputData {}; struct AbsAxisPrivate : RenderData { D_Ptr(AbsAxis) diff --git a/YSGraphic_Core/Axis/Axis.h b/YSGraphic_Core/Axis/Axis.h index 856e79c..c2bbfee 100644 --- a/YSGraphic_Core/Axis/Axis.h +++ b/YSGraphic_Core/Axis/Axis.h @@ -3,7 +3,7 @@ namespace YSG { struct AxisRenderState; - struct AxisTempData; + struct AxisInputData; struct AxisPrivate; class LIB_DECL Axis : public AbsAxis { Q_Ptr2(Axis) diff --git a/YSGraphic_Core/Axis/Axis_p.h b/YSGraphic_Core/Axis/Axis_p.h index 259a66e..f556c85 100644 --- a/YSGraphic_Core/Axis/Axis_p.h +++ b/YSGraphic_Core/Axis/Axis_p.h @@ -9,7 +9,7 @@ namespace YSG { }; - struct AxisTempData : AbsAxisTempData { + struct AxisInputData : AbsAxisInputData { }; diff --git a/YSGraphic_Core/Axis/FrequentAxis_p.h b/YSGraphic_Core/Axis/FrequentAxis_p.h index cfafd29..d73fa93 100644 --- a/YSGraphic_Core/Axis/FrequentAxis_p.h +++ b/YSGraphic_Core/Axis/FrequentAxis_p.h @@ -4,7 +4,7 @@ #include "AbsAxis_p.h" #include "Axis_p.h" namespace YSG { - struct FrequentAxisTempData : AxisTempData {}; + struct FrequentAxisInputData : AxisInputData {}; struct FrequentAxisRenderState : AxisRenderState {}; struct FrequentAxisPrivate : AxisPrivate { D_Ptr(FrequentAxis) diff --git a/YSGraphic_Core/Axis/TimeAxis.cpp b/YSGraphic_Core/Axis/TimeAxis.cpp index 4a9e36e..51cd556 100644 --- a/YSGraphic_Core/Axis/TimeAxis.cpp +++ b/YSGraphic_Core/Axis/TimeAxis.cpp @@ -11,12 +11,12 @@ namespace YSG { if(!ok()) return -1; TimeAxisPrivate* pd = d(); SpinLockGuard _guard(&pd->mBufferLock); - RenderEditGuard _editGuard(pd); + RenderInputGuard _inputGuard(pd); std::pair ret = pd->mTimeTicker.getNewDataTickInfo(); - auto td = reinterpret_cast(pd->mEditTempData); - td->mAllTime.push_back(time); + auto input = reinterpret_cast(pd->inputData(Input_Edit)); + input->mAllTime.push_back(time); if(ret.second) { - td->mData.push_front({time, ret.first}); + input->mData.push_front({time, ret.first}); } return ret.first; } diff --git a/YSGraphic_Core/Axis/TimeAxis_p.h b/YSGraphic_Core/Axis/TimeAxis_p.h index 5dc1c57..065a66f 100644 --- a/YSGraphic_Core/Axis/TimeAxis_p.h +++ b/YSGraphic_Core/Axis/TimeAxis_p.h @@ -65,9 +65,13 @@ namespace YSG { int mTick{}; }; - struct TimeAxisTempData : AbsAxisTempData { + struct TimeAxisInputData : AbsAxisInputData { std::list mData; std::list mAllTime; + void clear() override { + mData.clear(); + mAllTime.clear(); + } }; @@ -93,7 +97,7 @@ namespace YSG { void prepareData() override { SpinLockGuard guard(&mBufferLock); syncStatePipeline(); - auto d = renderTempData(); + auto d = renderInputData(); auto s = renderState(); auto sc = editState(); bool refreshSpace = false; @@ -141,6 +145,7 @@ namespace YSG { d->mAllTime.clear(); mData.splice(mData.begin(), d->mData); + clearRenderInput(); while (!mData.empty()) { int tick = mData.back().mTick; diff --git a/YSGraphic_Core/GlobalTypes.h b/YSGraphic_Core/GlobalTypes.h index fb40ba3..fef36cb 100644 --- a/YSGraphic_Core/GlobalTypes.h +++ b/YSGraphic_Core/GlobalTypes.h @@ -192,7 +192,6 @@ public: \ void set_##name(Type name) { \ className##Private* pd = d(); \ className##RenderState* sc = reinterpret_cast(pd->state(State_Edit)); \ - className##TempData* td = reinterpret_cast(pd->mEditTempData); \ SpinLockGuard _guard(&pd->mBufferLock); \ sc->##name = name; \ } \ diff --git a/YSGraphic_Core/RenderAble.cpp b/YSGraphic_Core/RenderAble.cpp index cedfa79..ec71c25 100644 --- a/YSGraphic_Core/RenderAble.cpp +++ b/YSGraphic_Core/RenderAble.cpp @@ -101,6 +101,17 @@ namespace YSG { RenderEditGuard::~RenderEditGuard() { if(mData && mData->qPtr) mData->qPtr->markStateDirty(); } + RenderInputGuard::RenderInputGuard(RenderData* data) : mData(data) { + } + RenderInputGuard::~RenderInputGuard() { + if(mData) mData->markInputDirty(); + } + void RenderData::markInputDirty() { + InputBufferSlot& slot = inputSlot(Input_Edit); + slot.version = ++mInputVersion; + slot.pending = true; + if(qPtr) qPtr->markRenderDirty(); + } void RenderAble::init(Plot* plot, QString layerName) { if(layerName.isEmpty()) { layerName = plot->mDefaultLayerName; @@ -109,13 +120,13 @@ namespace YSG { mPlot = plot; if(!dPtr) dPtr = createRenderData(); dPtr->clearStateBuffers(); - delete dPtr->mRenderTempData; - delete dPtr->mEditTempData; + dPtr->clearInputBuffers(); dPtr->mStateBuffers[State_Edit] = createRenderState(); dPtr->mStateBuffers[State_Ready] = createRenderState(); dPtr->mStateBuffers[State_Render] = createRenderState(); - dPtr->mRenderTempData = createTempData(); - dPtr->mEditTempData = createTempData(); + dPtr->mInputBuffers[Input_Edit].data = createInputData(); + dPtr->mInputBuffers[Input_Ready].data = createInputData(); + dPtr->mInputBuffers[Input_Render].data = createInputData(); for(RenderState* state : dPtr->mStateBuffers) { state->dPtr = dPtr; } @@ -125,6 +136,9 @@ namespace YSG { } void RenderAble::markStateDirty() { if(dPtr) ++dPtr->state(State_Edit)->version; + markRenderDirty(); + } + void RenderAble::markRenderDirty() { if(mPlot) mPlot->markRenderStateDirty(); } bool RenderAble::ok() const { diff --git a/YSGraphic_Core/RenderAble.h b/YSGraphic_Core/RenderAble.h index d584ca2..3e09f89 100644 --- a/YSGraphic_Core/RenderAble.h +++ b/YSGraphic_Core/RenderAble.h @@ -235,15 +235,24 @@ enum State_Role : std::uint8_t { State_Ready, State_Render }; +enum Input_Role : std::uint8_t { + Input_Edit, + Input_Ready, + Input_Render +}; enum Color_Role : std::uint8_t { Color_Front, Color_Ready, Color_Render }; +inline bool buffer_version_newer(std::uint64_t a, std::uint64_t b) { + return static_cast(a - b) > 0; +} #define INIT_GET(className) className##Private* privateData = d(); \ className##RenderState* renderState = reinterpret_cast(d()->state(src)); -struct TempData { - virtual ~TempData() = default; +struct InputData { + virtual ~InputData() = default; + virtual void clear() {} }; struct RenderState { virtual ~RenderState() = default; @@ -251,12 +260,20 @@ struct RenderState { RenderData* dPtr{}; SRC src(); }; +struct InputBufferSlot { + InputData* data{}; + std::uint64_t version = 0; + bool pending = false; +}; struct RenderData { SpinLock mBufferLock; RenderAble* qPtr{}; bool mRenderStart = false; Triple_Role_Buffer_Control mStateControl; std::array mStateBuffers{}; + Triple_Role_Buffer_Control mInputControl; + std::array mInputBuffers{}; + std::uint64_t mInputVersion = 0; RenderState* state(std::uint8_t role) const { return stateByIndex(mStateControl.read_view()[role]); } @@ -279,18 +296,53 @@ struct RenderData { } mStateControl.reset(); } - TempData *mRenderTempData{}, *mEditTempData{}; + InputData* inputData(std::uint8_t role) const { + return inputSlot(role).data; + } + InputData* inputDataByIndex(std::uint8_t index) const { + return mInputBuffers[index].data; + } + InputBufferSlot& inputSlot(std::uint8_t role) { + return inputSlotByIndex(mInputControl.read_view()[role]); + } + const InputBufferSlot& inputSlot(std::uint8_t role) const { + return inputSlotByIndex(mInputControl.read_view()[role]); + } + InputBufferSlot& inputSlotByIndex(std::uint8_t index) { + return mInputBuffers[index]; + } + const InputBufferSlot& inputSlotByIndex(std::uint8_t index) const { + return mInputBuffers[index]; + } + void markInputDirty(); + void clearInputRole(std::uint8_t role) { + InputBufferSlot& slot = inputSlot(role); + slot.data->clear(); + slot.pending = false; + } + void clearRenderInput() { + clearInputRole(Input_Render); + } + void clearInputBuffers() { + for(InputBufferSlot& slot : mInputBuffers) { + delete slot.data; + slot.data = nullptr; + slot.version = 0; + slot.pending = false; + } + mInputVersion = 0; + mInputControl.reset(); + } protected: virtual void syncStatePipeline() = 0; virtual RenderState* renderState() = 0; virtual RenderState* readyState() = 0; virtual RenderState* editState() = 0; - virtual TempData* renderTempData() = 0; - virtual TempData* editTempData() = 0; + virtual InputData* renderInputData() = 0; + virtual InputData* editInputData() = 0; virtual ~RenderData() { clearStateBuffers(); - delete mRenderTempData; - delete mEditTempData; + clearInputBuffers(); } virtual void draw(QPainter* painter) {} virtual void prepareData() { @@ -322,10 +374,10 @@ struct BaseRenderData : RenderData { RenderState* editState() override { return nullptr; } - TempData* renderTempData() override { + InputData* renderInputData() override { return nullptr; } - TempData* editTempData() override { + InputData* editInputData() override { return nullptr; } void syncStatePipeline() override {} @@ -336,6 +388,11 @@ struct LIB_DECL RenderEditGuard { ~RenderEditGuard(); RenderData* mData{}; }; +struct LIB_DECL RenderInputGuard { + explicit RenderInputGuard(RenderData* data); + ~RenderInputGuard(); + RenderData* mData{}; +}; struct RenderAble { enum class JobState { Idle, @@ -378,8 +435,8 @@ struct RenderAble { virtual RenderState* createRenderState() { return new RenderState; } - virtual TempData* createTempData() { - return new TempData; + virtual InputData* createInputData() { + return new InputData; } virtual void init(Plot* plot, QString layerName = ""); virtual void draw(QPainter* painter) { @@ -422,9 +479,10 @@ struct RenderAble { dPtr->wheelEvent(event); }; static bool version_newer(std::uint64_t a, std::uint64_t b) { - return static_cast(a - b) > 0; + return buffer_version_newer(a, b); } void markStateDirty(); + void markRenderDirty(); QString mObjectName; RenderData* dPtr{}; Plot* mPlot{}; @@ -446,19 +504,19 @@ private: ClassName##Private* d() {return reinterpret_cast(dPtr);} \ RenderData* createRenderData() override; \ RenderState* createRenderState() override; \ - TempData* createTempData() override; \ + InputData* createInputData() override; \ protected: \ ClassName(); \ friend struct ClassName##Private; \ friend struct ClassName##RenderState; \ - friend struct ClassName##TempData; \ + friend struct ClassName##InputData; \ public: #define Q_Ptr(ClassName) \ ClassName(); \ ClassName##Private* d() {return reinterpret_cast(dPtr);} \ RenderData* createRenderData() override; \ RenderState* createRenderState() override; \ - TempData* createTempData() override; + InputData* createInputData() override; #define Q_Ptr_cpp(ClassName) \ ClassName::ClassName() { \ dPtr = new ClassName##Private; \ @@ -466,26 +524,35 @@ private: } \ RenderData* ClassName::createRenderData() {return new ClassName##Private;} \ RenderState* ClassName::createRenderState() {return new ClassName##RenderState;} \ - TempData* ClassName::createTempData() {return new ClassName##TempData;} + InputData* ClassName::createInputData() {return new ClassName##InputData;} #define D_Ptr_3(ClassName) \ ClassName##RenderState* renderState() override {return reinterpret_cast(state(State_Render));} \ ClassName##RenderState* readyState() override {return reinterpret_cast(state(State_Ready));} \ ClassName##RenderState* editState() override {return reinterpret_cast(state(State_Edit));} \ - ClassName##TempData* renderTempData() override {return reinterpret_cast(mRenderTempData);} \ - ClassName##TempData* editTempData() override {return reinterpret_cast(mEditTempData);} \ + ClassName##InputData* renderInputData() override {return reinterpret_cast(inputData(Input_Render));} \ + ClassName##InputData* editInputData() override {return reinterpret_cast(inputData(Input_Edit));} \ friend class ClassName; \ void syncStatePipeline() override { \ Triple_Buffer_Lease readyLease = mStateControl.wait_mark_use_role(State_Ready); \ auto ready = reinterpret_cast(stateByIndex(readyLease.index)); \ auto edit = editState(); \ - if(RenderAble::version_newer(edit->version, ready->version)) *ready = *edit; \ + if(buffer_version_newer(edit->version, ready->version)) *ready = *edit; \ mStateControl.unmark_use(readyLease); \ mStateControl.wait_swap_role(State_Ready, State_Render, [this](const Triple_Buffer_View& view) { \ auto ready = reinterpret_cast(stateByIndex(view[State_Ready])); \ auto render = reinterpret_cast(stateByIndex(view[State_Render])); \ - return RenderAble::version_newer(ready->version, render->version); \ + return buffer_version_newer(ready->version, render->version); \ + }); \ + mInputControl.wait_swap_role(Input_Edit, Input_Ready, [this](const Triple_Buffer_View& view) { \ + const InputBufferSlot& edit = inputSlotByIndex(view[Input_Edit]); \ + const InputBufferSlot& ready = inputSlotByIndex(view[Input_Ready]); \ + return edit.pending && buffer_version_newer(edit.version, ready.version); \ + }); \ + mInputControl.wait_swap_role(Input_Ready, Input_Render, [this](const Triple_Buffer_View& view) { \ + const InputBufferSlot& ready = inputSlotByIndex(view[Input_Ready]); \ + const InputBufferSlot& render = inputSlotByIndex(view[Input_Render]); \ + return ready.pending && buffer_version_newer(ready.version, render.version); \ }); \ - std::swap(mRenderTempData, mEditTempData); \ if(!mRenderStart) mRenderStart = true; \ } #define D_Ptr(ClassName) \ @@ -493,21 +560,30 @@ private: ClassName##RenderState* renderState() override {return reinterpret_cast(state(State_Render));} \ ClassName##RenderState* readyState() override {return reinterpret_cast(state(State_Ready));} \ ClassName##RenderState* editState() override {return reinterpret_cast(state(State_Edit));} \ - ClassName##TempData* renderTempData() override {return reinterpret_cast(mRenderTempData);} \ - ClassName##TempData* editTempData() override {return reinterpret_cast(mEditTempData);} \ + ClassName##InputData* renderInputData() override {return reinterpret_cast(inputData(Input_Render));} \ + ClassName##InputData* editInputData() override {return reinterpret_cast(inputData(Input_Edit));} \ friend class ClassName; \ void syncStatePipeline() override { \ Triple_Buffer_Lease readyLease = mStateControl.wait_mark_use_role(State_Ready); \ auto ready = reinterpret_cast(stateByIndex(readyLease.index)); \ auto edit = editState(); \ - if(RenderAble::version_newer(edit->version, ready->version)) *ready = *edit; \ + if(buffer_version_newer(edit->version, ready->version)) *ready = *edit; \ mStateControl.unmark_use(readyLease); \ mStateControl.wait_swap_role(State_Ready, State_Render, [this](const Triple_Buffer_View& view) { \ auto ready = reinterpret_cast(stateByIndex(view[State_Ready])); \ auto render = reinterpret_cast(stateByIndex(view[State_Render])); \ - return RenderAble::version_newer(ready->version, render->version); \ + return buffer_version_newer(ready->version, render->version); \ + }); \ + mInputControl.wait_swap_role(Input_Edit, Input_Ready, [this](const Triple_Buffer_View& view) { \ + const InputBufferSlot& edit = inputSlotByIndex(view[Input_Edit]); \ + const InputBufferSlot& ready = inputSlotByIndex(view[Input_Ready]); \ + return edit.pending && buffer_version_newer(edit.version, ready.version); \ + }); \ + mInputControl.wait_swap_role(Input_Ready, Input_Render, [this](const Triple_Buffer_View& view) { \ + const InputBufferSlot& ready = inputSlotByIndex(view[Input_Ready]); \ + const InputBufferSlot& render = inputSlotByIndex(view[Input_Render]); \ + return ready.pending && buffer_version_newer(ready.version, render.version); \ }); \ - std::swap(mRenderTempData, mEditTempData); \ if(!mRenderStart) mRenderStart = true; \ } #define D_Ptr2(ClassName) \ @@ -515,26 +591,38 @@ private: ClassName##RenderState* renderState() override {return reinterpret_cast(state(State_Render));} \ ClassName##RenderState* readyState() override {return reinterpret_cast(state(State_Ready));} \ ClassName##RenderState* editState() override {return reinterpret_cast(state(State_Edit));} \ - ClassName##TempData* renderTempData() override {return reinterpret_cast(mRenderTempData);} \ - ClassName##TempData* editTempData() override {return reinterpret_cast(mEditTempData);} \ + ClassName##InputData* renderInputData() override {return reinterpret_cast(inputData(Input_Render));} \ + ClassName##InputData* editInputData() override {return reinterpret_cast(inputData(Input_Edit));} \ friend class ClassName; \ void syncStatePipeline() override { \ Triple_Buffer_Lease readyLease = mStateControl.wait_mark_use_role(State_Ready); \ auto ready = reinterpret_cast(stateByIndex(readyLease.index)); \ auto edit = editState(); \ - if(RenderAble::version_newer(edit->version, ready->version)) *ready = *edit; \ + if(buffer_version_newer(edit->version, ready->version)) *ready = *edit; \ mStateControl.unmark_use(readyLease); \ mStateControl.wait_swap_role(State_Ready, State_Render, [this](const Triple_Buffer_View& view) { \ auto ready = reinterpret_cast(stateByIndex(view[State_Ready])); \ auto render = reinterpret_cast(stateByIndex(view[State_Render])); \ - return RenderAble::version_newer(ready->version, render->version); \ + return buffer_version_newer(ready->version, render->version); \ + }); \ + mInputControl.wait_swap_role(Input_Edit, Input_Ready, [this](const Triple_Buffer_View& view) { \ + const InputBufferSlot& edit = inputSlotByIndex(view[Input_Edit]); \ + const InputBufferSlot& ready = inputSlotByIndex(view[Input_Ready]); \ + return edit.pending && buffer_version_newer(edit.version, ready.version); \ + }); \ + mInputControl.wait_swap_role(Input_Ready, Input_Render, [this](const Triple_Buffer_View& view) { \ + const InputBufferSlot& ready = inputSlotByIndex(view[Input_Ready]); \ + const InputBufferSlot& render = inputSlotByIndex(view[Input_Render]); \ + return ready.pending && buffer_version_newer(ready.version, render.version); \ }); \ - std::swap(mRenderTempData, mEditTempData); \ if(!mRenderStart) mRenderStart = true; \ } #define INIT_SET(className) className##Private* pd = d(); \ className##RenderState* sc = reinterpret_cast(pd->state(State_Edit));\ - className##TempData* td = reinterpret_cast(pd->mEditTempData); \ SpinLockGuard _guard(&pd->mBufferLock); \ RenderEditGuard _editGuard(pd); +#define INIT_INPUT(className) className##Private* pd = d(); \ + className##InputData* input = reinterpret_cast(pd->inputData(Input_Edit)); \ + SpinLockGuard _guard(&pd->mBufferLock); \ + RenderInputGuard _inputGuard(pd); } diff --git a/YSGraphic_Core/base/MutiSelectRect_p.h b/YSGraphic_Core/base/MutiSelectRect_p.h index b5644a2..681ecfd 100644 --- a/YSGraphic_Core/base/MutiSelectRect_p.h +++ b/YSGraphic_Core/base/MutiSelectRect_p.h @@ -27,7 +27,7 @@ namespace YSG { } }; - struct MutiSelectRectTempData : YSG::TempData { + struct MutiSelectRectInputData : YSG::InputData { }; @@ -94,7 +94,6 @@ namespace YSG { void keyReleaseEvent(QKeyEvent* event) override { MutiSelectRectRenderState* sc = editState(); - MutiSelectRectTempData* td = editTempData(); SpinLockGuard _guard(&mBufferLock); } diff --git a/YSGraphic_Core/plottable/Afterglow.cpp b/YSGraphic_Core/plottable/Afterglow.cpp index c33d8c1..dfa7d05 100644 --- a/YSGraphic_Core/plottable/Afterglow.cpp +++ b/YSGraphic_Core/plottable/Afterglow.cpp @@ -15,20 +15,18 @@ namespace YSG { void Afterglow::set_frequentPointSize(int t) { AfterglowPrivate* pd = d(); AfterglowRenderState* sc = reinterpret_cast(pd->state(State_Edit)); - AfterglowTempData* td = reinterpret_cast(pd->mEditTempData); SpinLockGuard _guard(&pd->mBufferLock); RenderEditGuard _editGuard(pd); sc->frequentPointSize = std::move(t); - sc->update_PointSize(sc->frequentPointSize, sc->powerPointSize); + sc->bufferSize = sc->frequentPointSize * sc->powerPointSize; } void Afterglow::set_powerPointSize(int t) { AfterglowPrivate* pd = d(); AfterglowRenderState* sc = reinterpret_cast(pd->state(State_Edit)); - AfterglowTempData* td = reinterpret_cast(pd->mEditTempData); SpinLockGuard _guard(&pd->mBufferLock); RenderEditGuard _editGuard(pd); sc->powerPointSize = std::move(t); - sc->update_PointSize(sc->frequentPointSize, sc->powerPointSize); + sc->bufferSize = sc->frequentPointSize * sc->powerPointSize; } @@ -44,56 +42,55 @@ namespace YSG { void Afterglow::giveData(const QVector &powerRangeData) { if(!ok()) return; - INIT_SET(Afterglow) - sc->pushData(powerRangeData); - } - - void AfterglowRenderState::pushData(const QVector &powerRangeData) { - - if (powerRangeData.size() != frequentPointSize) { + AfterglowPrivate* pd = d(); + SpinLockGuard _guard(&pd->mBufferLock); + AfterglowRenderState* sc = reinterpret_cast(pd->state(State_Edit)); + if(powerRangeData.size() != sc->frequentPointSize) { qDebug() << QString("pushData(const QVector &powerRangeData) error 数组大小不匹配 需要%1, 实际为%2") - .arg(frequentPointSize).arg(powerRangeData.size()); + .arg(sc->frequentPointSize).arg(powerRangeData.size()); return; } - if (curIndex == initStrongValue) { + auto input = reinterpret_cast(pd->inputData(Input_Edit)); + input->mDataList.push_back(powerRangeData); + pd->markInputDirty(); + } + + void AfterglowPrivate::pushData(const QVector& powerRangeData, const AfterglowRenderState* s) { + if(curIndex == s->initStrongValue) { curIndex = 0; - double oldRemain = 1.0 - attenuationRate; - double cacheRemain = attenuationRate / (double) initStrongValue; //这一次的概率 [0,1] - for (int i = 0; i < bufferSize; ++i) { - //std::cout << mCachedPowerData[i] << " " ; + double oldRemain = 1.0 - s->attenuationRate; + double cacheRemain = s->attenuationRate / (double)s->initStrongValue; + for(int i = 0; i < cacheBufferSize; ++i) { mutexPowerData[i] = oldRemain*oldCachePowerData[i] + cacheRemain*cachedPowerData[i]; cachedPowerData[i] = 0; } - //std::cout << std::endl; { - auto d = reinterpret_cast(dPtr); - SpinLockGuard g(&d->dataLock); - std::memmove(oldCachePowerData.data(), mutexPowerData.data(), bufferSize * sizeof(double)); - d->OK.storeRelease(true); + SpinLockGuard g(&dataLock); + std::memmove(oldCachePowerData.data(), mutexPowerData.data(), cacheBufferSize * sizeof(double)); + OK.storeRelease(true); } } - QVector indexList(frequentPointSize); - double rate = (double)powerPointSize/powerRange.size(); - for (int i = 0; i < frequentPointSize; ++i) { - int lineIndex = (int) ((powerRangeData[i] - powerRange.lower) * rate); + QVector indexList(s->frequentPointSize); + double rate = (double)s->powerPointSize/s->powerRange.size(); + for(int i = 0; i < s->frequentPointSize; ++i) { + int lineIndex = (int)((powerRangeData[i] - s->powerRange.lower) * rate); if (lineIndex < 0) lineIndex = 0; - if (lineIndex > powerPointSize - 1) lineIndex = powerPointSize - 1; + if (lineIndex > s->powerPointSize - 1) lineIndex = s->powerPointSize - 1; indexList[i] = lineIndex; } - - if (!interpolate) { //插值 填入没有的概率地方 - for (int i = 0; i < frequentPointSize; ++i) { - int index = indexList[i] * frequentPointSize + i; + if(!s->interpolate) { + for(int i = 0; i < s->frequentPointSize; ++i) { + int index = indexList[i] * s->frequentPointSize + i; cachedPowerData[index]++; } } else { int lastLower = -1, lastUpper = -1; - for (int i = 0; i < frequentPointSize; ++i) { + for(int i = 0; i < s->frequentPointSize; ++i) { int y = indexList[i]; - cachedPowerData[y * frequentPointSize + i]++; + cachedPowerData[y * s->frequentPointSize + i]++; if (y - lastUpper >= 2) { for (int curY = lastUpper + 1; curY < y; ++curY) { - cachedPowerData[curY * frequentPointSize + i]++; + cachedPowerData[curY * s->frequentPointSize + i]++; } lastUpper = y; lastLower = lastLower + 1; @@ -101,7 +98,7 @@ namespace YSG { } if (lastLower - y >= 2) { for (int curY = y + 1; curY < lastLower; ++curY) { - cachedPowerData[curY * frequentPointSize + i]++; + cachedPowerData[curY * s->frequentPointSize + i]++; } lastUpper = lastLower - 1; lastLower = y; diff --git a/YSGraphic_Core/plottable/Afterglow_p.h b/YSGraphic_Core/plottable/Afterglow_p.h index f3cbe76..e251a8e 100644 --- a/YSGraphic_Core/plottable/Afterglow_p.h +++ b/YSGraphic_Core/plottable/Afterglow_p.h @@ -11,34 +11,39 @@ namespace YSG { struct AfterglowRenderState : RenderState, Afterglow_Prop { - int curIndex = 0; - QVector cachedPowerData; - QVector oldCachePowerData; - QVector mutexPowerData; - // 等比数列求和公式 a1*(1-q^n)/(1-q) n->inf 时为 a1/(1-q) - [[nodiscard]] int strengthValue() const { return (int) ((double) initStrongValue / (1.0 - attenuationRate)); } - void update_PointSize(int frequentPointSize, int powerPointSize) { - this->frequentPointSize = frequentPointSize; - this->powerPointSize = powerPointSize; - bufferSize = frequentPointSize * powerPointSize; - cachedPowerData.resize(bufferSize); - cachedPowerData.fill(0); - oldCachePowerData.resize(bufferSize); - oldCachePowerData.fill(0); - mutexPowerData.resize(bufferSize); - mutexPowerData.fill(0); - curIndex = 0; - } - void pushData(const QVector &powerRangeData); }; - - - struct AfterglowTempData : TempData {}; + struct AfterglowInputData : InputData { + std::list> mDataList; + void clear() override { + mDataList.clear(); + } + }; struct AfterglowPrivate : RenderData { D_Ptr(Afterglow) QImage image; SpinLock dataLock; QAtomicInteger OK = false; + int curIndex = 0; + int cacheFrequentPointSize{}; + int cachePowerPointSize{}; + int cacheBufferSize{}; + QVector cachedPowerData; + QVector oldCachePowerData; + QVector mutexPowerData; + [[nodiscard]] int strengthValue(const AfterglowRenderState* s) const {return (int)((double)s->initStrongValue / (1.0 - s->attenuationRate));} + void updateCacheSize(int frequentPointSize, int powerPointSize) { + cacheFrequentPointSize = frequentPointSize; + cachePowerPointSize = powerPointSize; + cacheBufferSize = frequentPointSize * powerPointSize; + cachedPowerData.resize(cacheBufferSize); + cachedPowerData.fill(0); + oldCachePowerData.resize(cacheBufferSize); + oldCachePowerData.fill(0); + mutexPowerData.resize(cacheBufferSize); + mutexPowerData.fill(0); + curIndex = 0; + } + void pushData(const QVector& powerRangeData, const AfterglowRenderState* s); void draw(QPainter* painter) override { AfterglowRenderState* s = renderState(); PerformanceShower *shower = q()->mPlot->d->mShower; @@ -61,7 +66,7 @@ namespace YSG { //double rate = 1.0/s->strengthValue() * 256.0; for (int row = 0; row < rowCount; ++row) { QRgb* scanLine = reinterpret_cast(image.scanLine(row)); - double* list = s->oldCachePowerData.data() + row*colCount; + double* list = oldCachePowerData.data() + row*colCount; for (int col = 0; col < colCount; ++col) { int colorOffset = (int)(list[col] * 255); if (colorOffset < 0 || colorOffset > 255) { @@ -94,6 +99,15 @@ namespace YSG { void prepareData() override { SpinLockGuard guard(&mBufferLock); syncStatePipeline(); + AfterglowRenderState* s = renderState(); + if(cacheFrequentPointSize != s->frequentPointSize || cachePowerPointSize != s->powerPointSize) { + updateCacheSize(s->frequentPointSize, s->powerPointSize); + } + AfterglowInputData* input = renderInputData(); + for(const QVector& data : input->mDataList) { + pushData(data, s); + } + clearRenderInput(); } }; template diff --git a/YSGraphic_Core/plottable/AudioFrequent.cpp b/YSGraphic_Core/plottable/AudioFrequent.cpp index 47a2df9..9f98570 100644 --- a/YSGraphic_Core/plottable/AudioFrequent.cpp +++ b/YSGraphic_Core/plottable/AudioFrequent.cpp @@ -32,7 +32,7 @@ namespace YSG { void AudioFrequent::giveData(int tick, double data) { Q_UNUSED(tick) if(!ok()) return; - INIT_SET(AudioFrequent) - td->mDataList.push_front(data); + INIT_INPUT(AudioFrequent) + input->mDataList.push_front(data); } } diff --git a/YSGraphic_Core/plottable/AudioFrequent_p.h b/YSGraphic_Core/plottable/AudioFrequent_p.h index 2e02178..5df7067 100644 --- a/YSGraphic_Core/plottable/AudioFrequent_p.h +++ b/YSGraphic_Core/plottable/AudioFrequent_p.h @@ -10,8 +10,11 @@ namespace YSG { - struct AudioFrequentTempData : TempData { + struct AudioFrequentInputData : InputData { std::list mDataList; + void clear() override { + mDataList.clear(); + } }; struct AudioFrequentRenderState : RenderState, AudioFrequent_Prop {}; @@ -22,7 +25,7 @@ namespace YSG { SpinLockGuard guard(&mBufferLock); syncStatePipeline(); AudioFrequentRenderState *s = renderState(); - AudioFrequentTempData *d = renderTempData(); + AudioFrequentInputData *d = renderInputData(); if(mMutiBuffer.buffers.empty() || mMutiBuffer.n != s->timePointSize) { mMutiBuffer.resize({sizeof(double)}, s->timePointSize, s->timePointSize * 10); PerformanceShower *shower = q()->mPlot->d->mShower; @@ -34,7 +37,7 @@ namespace YSG { for(double& power : d->mDataList) { mMutiBuffer.pushData({&power}); } - d->mDataList.clear(); + clearRenderInput(); } @@ -46,7 +49,6 @@ namespace YSG { .arg(s->timeAxis->timePointSize())); } painter->save(); - AudioFrequentTempData *d = renderTempData(); QPolygonF polyline; int start = (int)s->timeAxis->startCoord(); QPen newPen = QPen(s->color); diff --git a/YSGraphic_Core/plottable/Planisphere.cpp b/YSGraphic_Core/plottable/Planisphere.cpp index 61a2441..8753f12 100644 --- a/YSGraphic_Core/plottable/Planisphere.cpp +++ b/YSGraphic_Core/plottable/Planisphere.cpp @@ -19,8 +19,8 @@ namespace YSG { void Planisphere::giveData(QPointF pos) { if(!ok()) return; if(!mPlot->isVisible()) return; - INIT_SET(Planisphere) - td->mDataList.push_back({pos}); + INIT_INPUT(Planisphere) + input->mDataList.push_back({pos}); } Planisphere::Builder::Builder(Axis* IAxis, Axis* QAxis) { diff --git a/YSGraphic_Core/plottable/Planisphere_p.h b/YSGraphic_Core/plottable/Planisphere_p.h index dce857c..dfc0ab4 100644 --- a/YSGraphic_Core/plottable/Planisphere_p.h +++ b/YSGraphic_Core/plottable/Planisphere_p.h @@ -9,8 +9,11 @@ namespace YSG { int mRemainTimes{}; int maxTotalTimes{}; }; - struct PlanisphereTempData : TempData { + struct PlanisphereInputData : InputData { std::list mDataList; + void clear() override { + mDataList.clear(); + } }; struct PlanisphereRenderState : RenderState, Planisphere_Prop { @@ -66,7 +69,7 @@ namespace YSG { void prepareData() override { SpinLockGuard guard(&mBufferLock); syncStatePipeline(); - PlanisphereTempData *d = renderTempData(); + PlanisphereInputData *d = renderInputData(); PlanisphereRenderState *s = renderState(); int times = qMax(5, (s->continueMillisecond * q()->mPlot->d->mRefreshTimesPreSecond) / 1000); for(PlanisphereData& data : d->mDataList) { @@ -74,6 +77,7 @@ namespace YSG { data.mRemainTimes = times; } dataList.splice(dataList.end(), d->mDataList); + clearRenderInput(); refresh(); } diff --git a/YSGraphic_Core/plottable/Spectrum.cpp b/YSGraphic_Core/plottable/Spectrum.cpp index 128a49c..b94e061 100644 --- a/YSGraphic_Core/plottable/Spectrum.cpp +++ b/YSGraphic_Core/plottable/Spectrum.cpp @@ -29,13 +29,11 @@ namespace YSG { void Spectrum::set_frequentPointSize(int frequentPointSize) { INIT_SET(Spectrum) sc->frequentPointSize = frequentPointSize; - sc->updateFrequentPointSize(sc->frequentPointSize, sc->frequentRange); } void Spectrum::set_frequentRange(Range frequentRange){ INIT_SET(Spectrum) sc->frequentRange = frequentRange; - sc->updateFrequentPointSize(sc->frequentPointSize, sc->frequentRange); } @@ -72,13 +70,106 @@ namespace YSG { PROP_R(QPen, markerPen); PROP_R(QPen, middleFrequentPen); PROP_R(QBrush, sweepRectBrush); - sc->updateFrequentPointSize(sc->frequentPointSize, sc->frequentRange); return ret; } Spectrum* SpectrumPrivate::q() { return reinterpret_cast(qPtr); } + void SpectrumPrivate::updateFrequentPointSize(int frequentPointSize, Range frequentRange) { + if(frequentPointSize == 0) return; + cacheFrequentPointSize = frequentPointSize; + cacheFrequentRange = frequentRange; + maxPowers.resize(frequentPointSize); + curPowers.resize(frequentPointSize); + minPowers.resize(frequentPointSize); + frequents.resize(frequentPointSize); + double cur = frequentRange.lower; + double step = frequentRange.length() / (frequentPointSize - 1); + frequents[0] = frequentRange.lower; + for(int i = 1; i < frequentPointSize; ++i) { + cur += step; + frequents[i] = cur; + } + maxPowers.fill(frequentRange.lower); + minPowers.fill(frequentRange.upper); + } + void SpectrumPrivate::setFrequentData(const QVector& lineData, const SpectrumRenderState* s) { + if(lineData.size() != s->frequentPointSize) { + qDebug() << "setFrenquentData 数据大小不对 " << lineData.size() << " mFrequentPointSize == " << s->frequentPointSize; + return; + } + curPowers = lineData; + curPowers.detach(); + double min = std::numeric_limits::max(); + double max = std::numeric_limits::min(); + int minIndex = 0, maxIndex = 0; + for(int i = 0; i < s->frequentPointSize; ++i) { + double& curData = curPowers[i]; + if(s->useMaxLine && curData > maxPowers.at(i)) { + maxPowers[i] = curData; + } + if(s->useMinLine && curData < minPowers.at(i)) { + minPowers[i] = curData; + } + if(s->useMaxMarker && curData > max) { + max = curData; + maxIndex = i; + } + if(s->useMinMarker && curData < min) { + min = curData; + minIndex = i; + } + } + maxMarkerKey = frequents[maxIndex]; + maxMarkerValue = curPowers[maxIndex]; + minMarkerKey = frequents[minIndex]; + minMarkerValue = curPowers[minIndex]; + } + double SpectrumPrivate::getY(const double& x, bool& ok) { + SpinLockGuard dd(&mBufferLock); + int i = binary_search(x, frequents, ok); + if(!ok) return -1; + const double& x1 = frequents.at(i); + const double& x2 = frequents.at(i + 1); + const double& y1 = curPowers.at(i); + const double& y2 = curPowers.at(i + 1); + double k = (y2 - y1) / (x2 - x1); + double b = y1 - k * x1; + return (int)(k * x + b); + } + void SpectrumPrivate::drawLine(QPainter* painter, const SpectrumRenderState* s, const QVector& ys, const QPen& pen, const QBrush& brush) { + if(frequents.empty()) return; + int n = frequents.size(); + QVector points(n+2); + double upperBoundPixel = s->powerAxis->coordToPixel(s->powerAxis->coordRange().upper, SRC::Render); + points.first() = QPointF(s->frequentAxis->coordToPixel(frequents.first(), SRC::Render), upperBoundPixel); + points.last() = QPointF(s->frequentAxis->coordToPixel(frequents.last(), SRC::Render), upperBoundPixel); + for(int i = 0; i < n; ++i) { + double x = s->frequentAxis->coordToPixel(frequents.at(i), SRC::Render); + double y = s->powerAxis->coordToPixel(ys.at(i), SRC::Render); + points[i + 1] = QPointF(x, y); + } + painter->setPen(pen); + if(pen.style() != Qt::NoPen) painter->drawPolyline(points.data() + 1, n); + painter->setBrush(brush); + if(brush.style() != Qt::NoBrush) painter->drawPolygon(points.data(), n + 2); + } + void SpectrumPrivate::drawSpectrum(QPainter* painter, SpectrumRenderState* s) { + if(s->useMaxLine) drawLine(painter, s, maxPowers, s->maxPen, s->maxBrush); + drawLine(painter, s, curPowers, s->curPen, s->curBrush); + if(s->useMinLine) drawLine(painter, s, minPowers, s->minPen, s->minBrush); + if(s->useMaxMarker) s->drawMarker(painter, maxMarkerKey, maxMarkerValue, false, false); + if(s->useMinMarker) s->drawMarker(painter, minMarkerKey, minMarkerValue, false, false); + for(Marker& customMarker : s->markerList) { + bool ok; + double value = getY(customMarker.frequent, ok); + if(ok) s->drawMarker(painter, customMarker.frequent, value, customMarker.drawLine, s->markerList.indexOf(customMarker) == s->curSelectIndex); + } + if(s->useSweepFrequentRect) { + s->drawAxisRect(painter, s->sweepFrequentRange, s->middleSweepFrequent); + } + } void SpectrumPrivate::draw(QPainter* painter) { auto s = renderState(); PerformanceShower *shower = q()->mPlot->d->mShower; @@ -86,7 +177,7 @@ namespace YSG { shower->mInfoMap["mFrequentPointSize"] = PerformanceLine(QString("mFrequentPointSize:%1") .arg(s->frequentPointSize)); } - s->draw(painter); + drawSpectrum(painter, s); if(q()->hoverOK(q())) { q()->drawHover(painter, s->frequentAxis, s->powerAxis); } @@ -95,8 +186,16 @@ namespace YSG { void Spectrum::giveData(const QVector &lineData){ if(!ok()) return; - INIT_SET(Spectrum) - sc->setFrenquentData(lineData); + SpectrumPrivate* pd = d(); + SpinLockGuard _guard(&pd->mBufferLock); + SpectrumRenderState* sc = reinterpret_cast(pd->state(State_Edit)); + if(lineData.size() != sc->frequentPointSize) { + qDebug() << "setFrenquentData 数据大小不对 " << lineData.size() << " mFrequentPointSize == " << sc->frequentPointSize; + return; + } + auto input = reinterpret_cast(pd->inputData(Input_Edit)); + input->mDataList.push_back(lineData); + pd->markInputDirty(); } void Spectrum::addCustomMarker(double frequent){ @@ -180,8 +279,8 @@ namespace YSG { } double Spectrum::getPower(double frequent, bool& ok, SRC src) { - INIT_GET(Spectrum) - return renderState->getY(frequent, ok); + Q_UNUSED(src) + return d()->getY(frequent, ok); } } diff --git a/YSGraphic_Core/plottable/Spectrum_p.h b/YSGraphic_Core/plottable/Spectrum_p.h index 8f76661..0c843ab 100644 --- a/YSGraphic_Core/plottable/Spectrum_p.h +++ b/YSGraphic_Core/plottable/Spectrum_p.h @@ -21,18 +21,15 @@ namespace YSG { return qFuzzyCompare(frequent, other.frequent) && drawLine == other.drawLine; } }; - struct SpectrumTempData : TempData {}; - + struct SpectrumInputData : InputData { + std::list> mDataList; + void clear() override { + mDataList.clear(); + } + }; struct SpectrumRenderState : RenderState, HoverInfoRenderState, Spectrum_PROP { QVector markerList; int curSelectIndex = -1; - double minMarkerKey{}; - double minMarkerValue{}; - double maxMarkerKey{}; - double maxMarkerValue{}; - QVector frequents; - QVector maxPowers, curPowers, minPowers; - void unSelect() { curSelectIndex = -1; } @@ -64,108 +61,6 @@ namespace YSG { markerList[index].frequent = frequent; } - void updateFrequentPointSize(int frequentPointSize, Range frequentRange) { - if(frequentPointSize == 0) return; - maxPowers.resize(frequentPointSize); - curPowers.resize(frequentPointSize); - minPowers.resize(frequentPointSize); - frequents.resize(frequentPointSize); - double cur = frequentRange.lower; - double step = frequentRange.length() / (frequentPointSize - 1); - frequents[0] = frequentRange.lower; - for(int i = 1; i < frequentPointSize; ++i) { - cur += step; - frequents[i] = cur; - } - maxPowers.fill(frequentRange.lower); - minPowers.fill(frequentRange.upper); - } - - void setFrenquentData(const QVector& lineData) { - if(lineData.size() != frequentPointSize) { - qDebug() << "setFrenquentData 数据大小不对 " << lineData.size() << " mFrequentPointSize == " << frequentPointSize; - return; - } - curPowers = lineData; - curPowers.detach(); - double min = std::numeric_limits::max(); - double max = std::numeric_limits::min(); - int minIndex = 0, maxIndex = 0; - for (int i = 0; i < frequentPointSize; ++i) { - double &curData = curPowers[i]; - if (useMaxLine && curData > maxPowers.at(i)) { - maxPowers[i] = curData; - } - if (useMinLine && curData < minPowers.at(i)) { - minPowers[i] = curData; - } - if (useMaxMarker) { - if (curData > max) { - max = curData; - maxIndex = i; - } - } - if (useMinMarker) { - if (curData < min) { - min = curData; - minIndex = i; - } - } - } - maxMarkerKey = frequents[maxIndex]; - maxMarkerValue = curPowers[maxIndex]; - minMarkerKey = frequents[minIndex]; - minMarkerValue = curPowers[minIndex]; - } - - [[nodiscard]] double getY(const double &x, bool& ok) { - SpinLockGuard dd(&dPtr->mBufferLock); - int i = binary_search(x, frequents, ok); - if(!ok) return -1; - const double &x1 = frequents.at(i); - const double &x2 = frequents.at(i + 1); - const double &y1 = curPowers.at(i); - const double &y2 = curPowers.at(i + 1); - double k = (y2 - y1) / (x2 - x1); - double b = y1 - k * x1; - return (int) (k * x + b); - } - - void drawLine(QPainter* painter, const QVector& ys, const QPen& pen, const QBrush& brush) { - if(frequents.empty()) return; - int n = frequents.size(); - QVector points(n+2); - double upperBoundPixel = powerAxis->coordToPixel(powerAxis->coordRange().upper, SRC::Render); - points.first() = QPointF(frequentAxis->coordToPixel(frequents.first(), SRC::Render), upperBoundPixel); - points.last() = QPointF(frequentAxis->coordToPixel(frequents.last(), SRC::Render), upperBoundPixel); - for (int i = 0; i < n; ++i) { - double x = frequentAxis->coordToPixel(frequents.at(i), SRC::Render); - double y = powerAxis->coordToPixel(ys.at(i), SRC::Render); - points[i + 1] = QPointF(x, y); - } - painter->setPen(pen); - if(pen.style() != Qt::NoPen) painter->drawPolyline(points.data() + 1, n); - painter->setBrush(brush); - if(brush.style() != Qt::NoBrush) painter->drawPolygon(points.data(), n + 2); - } - - void draw(QPainter* painter) { - if(useMaxLine) drawLine(painter, maxPowers, maxPen, maxBrush); - drawLine(painter, curPowers, curPen, curBrush); - if(useMinLine) drawLine(painter, minPowers, minPen, minBrush); - if (useMaxMarker) drawMarker(painter, maxMarkerKey, maxMarkerValue, false, false); - if (useMinMarker) drawMarker(painter, minMarkerKey, minMarkerValue, false, false); - for (Marker &customMarker: markerList) { - bool ok; - double value = getY(customMarker.frequent, ok); - if(ok) drawMarker(painter, customMarker.frequent, value, customMarker.drawLine, - markerList.indexOf(customMarker) == curSelectIndex); - } - if (useSweepFrequentRect) { - drawAxisRect(painter, sweepFrequentRange, middleSweepFrequent); - } - } - void drawMarker(QPainter *painter, double key, double value, bool isLine = false, bool isSelected = false) { double x = frequentAxis->coordToPixel(key, SRC::Render); double y = powerAxis->coordToPixel(value, SRC::Render); @@ -205,20 +100,39 @@ namespace YSG { struct SpectrumPrivate : RenderData { D_Ptr_3(Spectrum) Spectrum* q(); + double minMarkerKey{}; + double minMarkerValue{}; + double maxMarkerKey{}; + double maxMarkerValue{}; + int cacheFrequentPointSize{}; + Range cacheFrequentRange{}; + QVector frequents; + QVector maxPowers, curPowers, minPowers; + void updateFrequentPointSize(int frequentPointSize, Range frequentRange); + void setFrequentData(const QVector& lineData, const SpectrumRenderState* s); + [[nodiscard]] double getY(const double& x, bool& ok); + void drawLine(QPainter* painter, const SpectrumRenderState* s, const QVector& ys, const QPen& pen, const QBrush& brush); + void drawSpectrum(QPainter* painter, SpectrumRenderState* s); void draw(QPainter* painter) override; void prepareData() override { SpinLockGuard guard(&mBufferLock); syncStatePipeline(); auto s = renderState(); - auto sc = editState(); - + if(cacheFrequentPointSize != s->frequentPointSize || cacheFrequentRange != s->frequentRange) { + updateFrequentPointSize(s->frequentPointSize, s->frequentRange); + } + auto input = renderInputData(); + for(const QVector& data : input->mDataList) { + setFrequentData(data, s); + } + clearRenderInput(); } bool selectTest(const QPointF& pos) override { auto sc = editState(); double frequent = sc->frequentAxis->pixelToCoord(pos.x(), SRC::Render); bool ok; - double power = sc->getY(frequent, ok); + double power = getY(frequent, ok); if(!ok) return false; return qAbs(power - sc->powerAxis->pixelToCoord(pos.y(), SRC::Render)) < 4; } diff --git a/YSGraphic_Core/plottable/SweepFrequent.cpp b/YSGraphic_Core/plottable/SweepFrequent.cpp index a0db226..ca63194 100644 --- a/YSGraphic_Core/plottable/SweepFrequent.cpp +++ b/YSGraphic_Core/plottable/SweepFrequent.cpp @@ -16,12 +16,16 @@ namespace YSG { void SweepFrequent::giveData(const QVector& data) { if(!ok()) return; - INIT_SET(SweepFrequent) + SweepFrequentPrivate* pd = d(); + SpinLockGuard _guard(&pd->mBufferLock); + SweepFrequentRenderState* sc = reinterpret_cast(pd->state(State_Edit)); if(data.size() != sc->blockFrequentPointSize) { qDebug() << "error data size == " << data.size() << " BlockFrquentPointSize" << sc->blockFrequentPointSize; return; } - td->mData.push_front(data); + auto input = reinterpret_cast(pd->inputData(Input_Edit)); + input->mData.push_front(data); + pd->markInputDirty(); } diff --git a/YSGraphic_Core/plottable/SweepFrequent_p.h b/YSGraphic_Core/plottable/SweepFrequent_p.h index 8a7fc22..22cbf16 100644 --- a/YSGraphic_Core/plottable/SweepFrequent_p.h +++ b/YSGraphic_Core/plottable/SweepFrequent_p.h @@ -12,8 +12,11 @@ namespace YSG { }; - struct SweepFrequentTempData : YSG::TempData { - std::list> mData; + struct SweepFrequentInputData : YSG::InputData { + std::list> mData; + void clear() override { + mData.clear(); + } }; struct SweepFrequentPrivate : YSG::RenderData { @@ -46,7 +49,7 @@ namespace YSG { SpinLockGuard guard(&mBufferLock); syncStatePipeline(); SweepFrequentRenderState *s = renderState(); - SweepFrequentTempData *d = renderTempData(); + SweepFrequentInputData *d = renderInputData(); if( mBlockFrquentPointSize != s->blockFrequentPointSize || mBlockNum != s->blockNum || @@ -66,7 +69,7 @@ namespace YSG { mFristLoop = false; } } - d->mData.clear(); + clearRenderInput(); } void draw(QPainter* painter) override { diff --git a/YSGraphic_Core/plottable/WaterFall.cpp b/YSGraphic_Core/plottable/WaterFall.cpp index 4eee7c0..c34ce11 100644 --- a/YSGraphic_Core/plottable/WaterFall.cpp +++ b/YSGraphic_Core/plottable/WaterFall.cpp @@ -12,8 +12,8 @@ namespace YSG { void WaterFall::giveData(int tick, const QVector& data) { if(!ok()) return; - INIT_SET(WaterFall) - td->mDataList.push_back({tick, data}); + INIT_INPUT(WaterFall) + input->mDataList.push_back({tick, data}); } WaterFall::Builder::Builder(FrequentAxis* frequentAxis, TimeAxis* timeAxis) { diff --git a/YSGraphic_Core/plottable/WaterFall_p.h b/YSGraphic_Core/plottable/WaterFall_p.h index d89e24b..f3dc28e 100644 --- a/YSGraphic_Core/plottable/WaterFall_p.h +++ b/YSGraphic_Core/plottable/WaterFall_p.h @@ -19,8 +19,11 @@ namespace YSG { int mTick; QVector mFrequent; }; - struct WaterFallTempData : TempData { + struct WaterFallInputData : InputData { std::list mDataList; + void clear() override { + mDataList.clear(); + } }; struct WaterFallRenderState : RenderState, HoverInfoRenderState, WaterFall_Prop { }; @@ -88,7 +91,7 @@ namespace YSG { void prepareData() override { SpinLockGuard guard(&mBufferLock); syncStatePipeline(); - WaterFallTempData* data = renderTempData(); + WaterFallInputData* data = renderInputData(); const WaterFallRenderState* s = renderState(); int colCount = s->frequentPointSize, rowCount = s->timeAxis->timePointSize(); if(!ringBuffer.match(colCount, rowCount)) { @@ -105,7 +108,7 @@ namespace YSG { } ringBuffer.pushData(frequentData.data(), wd.mTick); } - data->mDataList.clear(); + clearRenderInput(); } void draw(QPainter* painter) override { WaterFallRenderState* s = renderState(); @@ -114,7 +117,6 @@ namespace YSG { shower->mInfoMap["FrequentRectCount"] = PerformanceLine(QString("FrequentRectCount:%1 timePointSize: %2") .arg(s->frequentPointSize).arg(s->timeAxis->timePointSize())); } - WaterFallTempData* data = renderTempData(); AbsAxis *hAxis = s->frequentAxis; TimeAxis *vAxis = s->timeAxis; Range hRange = s->frequentRange, vRange = s->timeAxis->coordRange();