tempdata 也采用三缓冲架构

This commit is contained in:
2026-07-23 11:39:46 +08:00
parent a3a385f8da
commit e2ecf8081f
22 changed files with 395 additions and 251 deletions
+1 -1
View File
@@ -14,7 +14,7 @@ namespace YSG {
coordLength *= factor;
}
};
struct AbsAxisTempData : TempData {};
struct AbsAxisInputData : InputData {};
struct AbsAxisPrivate : RenderData {
D_Ptr(AbsAxis)
+1 -1
View File
@@ -3,7 +3,7 @@
namespace YSG {
struct AxisRenderState;
struct AxisTempData;
struct AxisInputData;
struct AxisPrivate;
class LIB_DECL Axis : public AbsAxis {
Q_Ptr2(Axis)
+1 -1
View File
@@ -9,7 +9,7 @@ namespace YSG {
};
struct AxisTempData : AbsAxisTempData {
struct AxisInputData : AbsAxisInputData {
};
+1 -1
View File
@@ -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)
+4 -4
View File
@@ -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<int, bool> ret = pd->mTimeTicker.getNewDataTickInfo();
auto td = reinterpret_cast<TimeAxisTempData*>(pd->mEditTempData);
td->mAllTime.push_back(time);
auto input = reinterpret_cast<TimeAxisInputData*>(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;
}
+7 -2
View File
@@ -65,9 +65,13 @@ namespace YSG {
int mTick{};
};
struct TimeAxisTempData : AbsAxisTempData {
struct TimeAxisInputData : AbsAxisInputData {
std::list<TimeTick> mData;
std::list<QTime> 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;
-1
View File
@@ -192,7 +192,6 @@ public: \
void set_##name(Type name) { \
className##Private* pd = d(); \
className##RenderState* sc = reinterpret_cast<className##RenderState*>(pd->state(State_Edit)); \
className##TempData* td = reinterpret_cast<className##TempData*>(pd->mEditTempData); \
SpinLockGuard _guard(&pd->mBufferLock); \
sc->##name = name; \
} \
+18 -4
View File
@@ -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 {
+120 -32
View File
@@ -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<std::int64_t>(a - b) > 0;
}
#define INIT_GET(className) className##Private* privateData = d(); \
className##RenderState* renderState = reinterpret_cast<className##RenderState*>(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<RenderState*, 3> mStateBuffers{};
Triple_Role_Buffer_Control mInputControl;
std::array<InputBufferSlot, 3> 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<std::int64_t>(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<ClassName##Private*>(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<ClassName##Private*>(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<ClassName##RenderState*>(state(State_Render));} \
ClassName##RenderState* readyState() override {return reinterpret_cast<ClassName##RenderState*>(state(State_Ready));} \
ClassName##RenderState* editState() override {return reinterpret_cast<ClassName##RenderState*>(state(State_Edit));} \
ClassName##TempData* renderTempData() override {return reinterpret_cast<ClassName##TempData*>(mRenderTempData);} \
ClassName##TempData* editTempData() override {return reinterpret_cast<ClassName##TempData*>(mEditTempData);} \
ClassName##InputData* renderInputData() override {return reinterpret_cast<ClassName##InputData*>(inputData(Input_Render));} \
ClassName##InputData* editInputData() override {return reinterpret_cast<ClassName##InputData*>(inputData(Input_Edit));} \
friend class ClassName; \
void syncStatePipeline() override { \
Triple_Buffer_Lease readyLease = mStateControl.wait_mark_use_role(State_Ready); \
auto ready = reinterpret_cast<ClassName##RenderState*>(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<ClassName##RenderState*>(stateByIndex(view[State_Ready])); \
auto render = reinterpret_cast<ClassName##RenderState*>(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<ClassName##RenderState*>(state(State_Render));} \
ClassName##RenderState* readyState() override {return reinterpret_cast<ClassName##RenderState*>(state(State_Ready));} \
ClassName##RenderState* editState() override {return reinterpret_cast<ClassName##RenderState*>(state(State_Edit));} \
ClassName##TempData* renderTempData() override {return reinterpret_cast<ClassName##TempData*>(mRenderTempData);} \
ClassName##TempData* editTempData() override {return reinterpret_cast<ClassName##TempData*>(mEditTempData);} \
ClassName##InputData* renderInputData() override {return reinterpret_cast<ClassName##InputData*>(inputData(Input_Render));} \
ClassName##InputData* editInputData() override {return reinterpret_cast<ClassName##InputData*>(inputData(Input_Edit));} \
friend class ClassName; \
void syncStatePipeline() override { \
Triple_Buffer_Lease readyLease = mStateControl.wait_mark_use_role(State_Ready); \
auto ready = reinterpret_cast<ClassName##RenderState*>(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<ClassName##RenderState*>(stateByIndex(view[State_Ready])); \
auto render = reinterpret_cast<ClassName##RenderState*>(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<ClassName##RenderState*>(state(State_Render));} \
ClassName##RenderState* readyState() override {return reinterpret_cast<ClassName##RenderState*>(state(State_Ready));} \
ClassName##RenderState* editState() override {return reinterpret_cast<ClassName##RenderState*>(state(State_Edit));} \
ClassName##TempData* renderTempData() override {return reinterpret_cast<ClassName##TempData*>(mRenderTempData);} \
ClassName##TempData* editTempData() override {return reinterpret_cast<ClassName##TempData*>(mEditTempData);} \
ClassName##InputData* renderInputData() override {return reinterpret_cast<ClassName##InputData*>(inputData(Input_Render));} \
ClassName##InputData* editInputData() override {return reinterpret_cast<ClassName##InputData*>(inputData(Input_Edit));} \
friend class ClassName; \
void syncStatePipeline() override { \
Triple_Buffer_Lease readyLease = mStateControl.wait_mark_use_role(State_Ready); \
auto ready = reinterpret_cast<ClassName##RenderState*>(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<ClassName##RenderState*>(stateByIndex(view[State_Ready])); \
auto render = reinterpret_cast<ClassName##RenderState*>(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<className##RenderState*>(pd->state(State_Edit));\
className##TempData* td = reinterpret_cast<className##TempData*>(pd->mEditTempData); \
SpinLockGuard _guard(&pd->mBufferLock); \
RenderEditGuard _editGuard(pd);
#define INIT_INPUT(className) className##Private* pd = d(); \
className##InputData* input = reinterpret_cast<className##InputData*>(pd->inputData(Input_Edit)); \
SpinLockGuard _guard(&pd->mBufferLock); \
RenderInputGuard _inputGuard(pd);
}
+1 -2
View File
@@ -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);
}
+32 -35
View File
@@ -15,20 +15,18 @@ namespace YSG {
void Afterglow::set_frequentPointSize(int t) {
AfterglowPrivate* pd = d();
AfterglowRenderState* sc = reinterpret_cast<AfterglowRenderState*>(pd->state(State_Edit));
AfterglowTempData* td = reinterpret_cast<AfterglowTempData*>(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<AfterglowRenderState*>(pd->state(State_Edit));
AfterglowTempData* td = reinterpret_cast<AfterglowTempData*>(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<double> &powerRangeData) {
if(!ok()) return;
INIT_SET(Afterglow)
sc->pushData(powerRangeData);
}
void AfterglowRenderState::pushData(const QVector<double> &powerRangeData) {
if (powerRangeData.size() != frequentPointSize) {
AfterglowPrivate* pd = d();
SpinLockGuard _guard(&pd->mBufferLock);
AfterglowRenderState* sc = reinterpret_cast<AfterglowRenderState*>(pd->state(State_Edit));
if(powerRangeData.size() != sc->frequentPointSize) {
qDebug() << QString("pushData(const QVector<double> &powerRangeData) error 数组大小不匹配 需要%1, 实际为%2")
.arg(frequentPointSize).arg(powerRangeData.size());
.arg(sc->frequentPointSize).arg(powerRangeData.size());
return;
}
if (curIndex == initStrongValue) {
auto input = reinterpret_cast<AfterglowInputData*>(pd->inputData(Input_Edit));
input->mDataList.push_back(powerRangeData);
pd->markInputDirty();
}
void AfterglowPrivate::pushData(const QVector<double>& 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<AfterglowPrivate*>(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<int> indexList(frequentPointSize);
double rate = (double)powerPointSize/powerRange.size();
for (int i = 0; i < frequentPointSize; ++i) {
int lineIndex = (int) ((powerRangeData[i] - powerRange.lower) * rate);
QVector<int> 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;
+37 -23
View File
@@ -11,34 +11,39 @@ namespace YSG {
struct AfterglowRenderState : RenderState, Afterglow_Prop {
int curIndex = 0;
QVector<double> cachedPowerData;
QVector<double> oldCachePowerData;
QVector<double> 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<double> &powerRangeData);
};
struct AfterglowTempData : TempData {};
struct AfterglowInputData : InputData {
std::list<QVector<double>> mDataList;
void clear() override {
mDataList.clear();
}
};
struct AfterglowPrivate : RenderData {
D_Ptr(Afterglow)
QImage image;
SpinLock dataLock;
QAtomicInteger<bool> OK = false;
int curIndex = 0;
int cacheFrequentPointSize{};
int cachePowerPointSize{};
int cacheBufferSize{};
QVector<double> cachedPowerData;
QVector<double> oldCachePowerData;
QVector<double> 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<double>& 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<QRgb*>(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<double>& data : input->mDataList) {
pushData(data, s);
}
clearRenderInput();
}
};
template <typename That>
+2 -2
View File
@@ -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);
}
}
+6 -4
View File
@@ -10,8 +10,11 @@
namespace YSG {
struct AudioFrequentTempData : TempData {
struct AudioFrequentInputData : InputData {
std::list<double> 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);
+2 -2
View File
@@ -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) {
+6 -2
View File
@@ -9,8 +9,11 @@ namespace YSG {
int mRemainTimes{};
int maxTotalTimes{};
};
struct PlanisphereTempData : TempData {
struct PlanisphereInputData : InputData {
std::list<PlanisphereData> 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();
}
+107 -8
View File
@@ -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<Spectrum*>(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<double>& 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<double>::max();
double max = std::numeric_limits<double>::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<double>& ys, const QPen& pen, const QBrush& brush) {
if(frequents.empty()) return;
int n = frequents.size();
QVector<QPointF> 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<double> &lineData){
if(!ok()) return;
INIT_SET(Spectrum)
sc->setFrenquentData(lineData);
SpectrumPrivate* pd = d();
SpinLockGuard _guard(&pd->mBufferLock);
SpectrumRenderState* sc = reinterpret_cast<SpectrumRenderState*>(pd->state(State_Edit));
if(lineData.size() != sc->frequentPointSize) {
qDebug() << "setFrenquentData 数据大小不对 " << lineData.size() << " mFrequentPointSize == " << sc->frequentPointSize;
return;
}
auto input = reinterpret_cast<SpectrumInputData*>(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);
}
}
+28 -114
View File
@@ -21,18 +21,15 @@ namespace YSG {
return qFuzzyCompare(frequent, other.frequent) && drawLine == other.drawLine;
}
};
struct SpectrumTempData : TempData {};
struct SpectrumInputData : InputData {
std::list<QVector<double>> mDataList;
void clear() override {
mDataList.clear();
}
};
struct SpectrumRenderState : RenderState, HoverInfoRenderState, Spectrum_PROP {
QVector<Marker> markerList;
int curSelectIndex = -1;
double minMarkerKey{};
double minMarkerValue{};
double maxMarkerKey{};
double maxMarkerValue{};
QVector<double> frequents;
QVector<double> 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<double>& lineData) {
if(lineData.size() != frequentPointSize) {
qDebug() << "setFrenquentData 数据大小不对 " << lineData.size() << " mFrequentPointSize == " << frequentPointSize;
return;
}
curPowers = lineData;
curPowers.detach();
double min = std::numeric_limits<double>::max();
double max = std::numeric_limits<double>::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<double>& ys, const QPen& pen, const QBrush& brush) {
if(frequents.empty()) return;
int n = frequents.size();
QVector<QPointF> 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<double> frequents;
QVector<double> maxPowers, curPowers, minPowers;
void updateFrequentPointSize(int frequentPointSize, Range frequentRange);
void setFrequentData(const QVector<double>& lineData, const SpectrumRenderState* s);
[[nodiscard]] double getY(const double& x, bool& ok);
void drawLine(QPainter* painter, const SpectrumRenderState* s, const QVector<double>& 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<double>& 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;
}
+6 -2
View File
@@ -16,12 +16,16 @@ namespace YSG {
void SweepFrequent::giveData(const QVector<double>& data) {
if(!ok()) return;
INIT_SET(SweepFrequent)
SweepFrequentPrivate* pd = d();
SpinLockGuard _guard(&pd->mBufferLock);
SweepFrequentRenderState* sc = reinterpret_cast<SweepFrequentRenderState*>(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<SweepFrequentInputData*>(pd->inputData(Input_Edit));
input->mData.push_front(data);
pd->markInputDirty();
}
+7 -4
View File
@@ -12,8 +12,11 @@ namespace YSG {
};
struct SweepFrequentTempData : YSG::TempData {
std::list<QVector<double>> mData;
struct SweepFrequentInputData : YSG::InputData {
std::list<QVector<double>> 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 {
+2 -2
View File
@@ -12,8 +12,8 @@ namespace YSG {
void WaterFall::giveData(int tick, const QVector<double>& 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) {
+6 -4
View File
@@ -19,8 +19,11 @@ namespace YSG {
int mTick;
QVector<double> mFrequent;
};
struct WaterFallTempData : TempData {
struct WaterFallInputData : InputData {
std::list<WaterFallData> 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();