tempdata 也采用三缓冲架构
This commit is contained in:
@@ -14,7 +14,7 @@ namespace YSG {
|
||||
coordLength *= factor;
|
||||
}
|
||||
};
|
||||
struct AbsAxisTempData : TempData {};
|
||||
struct AbsAxisInputData : InputData {};
|
||||
|
||||
struct AbsAxisPrivate : RenderData {
|
||||
D_Ptr(AbsAxis)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
namespace YSG {
|
||||
struct AxisRenderState;
|
||||
struct AxisTempData;
|
||||
struct AxisInputData;
|
||||
struct AxisPrivate;
|
||||
class LIB_DECL Axis : public AbsAxis {
|
||||
Q_Ptr2(Axis)
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace YSG {
|
||||
|
||||
};
|
||||
|
||||
struct AxisTempData : AbsAxisTempData {
|
||||
struct AxisInputData : AbsAxisInputData {
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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; \
|
||||
} \
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user