tempdata 也采用三缓冲架构
This commit is contained in:
@@ -14,7 +14,7 @@ namespace YSG {
|
|||||||
coordLength *= factor;
|
coordLength *= factor;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
struct AbsAxisTempData : TempData {};
|
struct AbsAxisInputData : InputData {};
|
||||||
|
|
||||||
struct AbsAxisPrivate : RenderData {
|
struct AbsAxisPrivate : RenderData {
|
||||||
D_Ptr(AbsAxis)
|
D_Ptr(AbsAxis)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
namespace YSG {
|
namespace YSG {
|
||||||
struct AxisRenderState;
|
struct AxisRenderState;
|
||||||
struct AxisTempData;
|
struct AxisInputData;
|
||||||
struct AxisPrivate;
|
struct AxisPrivate;
|
||||||
class LIB_DECL Axis : public AbsAxis {
|
class LIB_DECL Axis : public AbsAxis {
|
||||||
Q_Ptr2(Axis)
|
Q_Ptr2(Axis)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace YSG {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AxisTempData : AbsAxisTempData {
|
struct AxisInputData : AbsAxisInputData {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include "AbsAxis_p.h"
|
#include "AbsAxis_p.h"
|
||||||
#include "Axis_p.h"
|
#include "Axis_p.h"
|
||||||
namespace YSG {
|
namespace YSG {
|
||||||
struct FrequentAxisTempData : AxisTempData {};
|
struct FrequentAxisInputData : AxisInputData {};
|
||||||
struct FrequentAxisRenderState : AxisRenderState {};
|
struct FrequentAxisRenderState : AxisRenderState {};
|
||||||
struct FrequentAxisPrivate : AxisPrivate {
|
struct FrequentAxisPrivate : AxisPrivate {
|
||||||
D_Ptr(FrequentAxis)
|
D_Ptr(FrequentAxis)
|
||||||
|
|||||||
@@ -11,12 +11,12 @@ namespace YSG {
|
|||||||
if(!ok()) return -1;
|
if(!ok()) return -1;
|
||||||
TimeAxisPrivate* pd = d();
|
TimeAxisPrivate* pd = d();
|
||||||
SpinLockGuard _guard(&pd->mBufferLock);
|
SpinLockGuard _guard(&pd->mBufferLock);
|
||||||
RenderEditGuard _editGuard(pd);
|
RenderInputGuard _inputGuard(pd);
|
||||||
std::pair<int, bool> ret = pd->mTimeTicker.getNewDataTickInfo();
|
std::pair<int, bool> ret = pd->mTimeTicker.getNewDataTickInfo();
|
||||||
auto td = reinterpret_cast<TimeAxisTempData*>(pd->mEditTempData);
|
auto input = reinterpret_cast<TimeAxisInputData*>(pd->inputData(Input_Edit));
|
||||||
td->mAllTime.push_back(time);
|
input->mAllTime.push_back(time);
|
||||||
if(ret.second) {
|
if(ret.second) {
|
||||||
td->mData.push_front({time, ret.first});
|
input->mData.push_front({time, ret.first});
|
||||||
}
|
}
|
||||||
return ret.first;
|
return ret.first;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,9 +65,13 @@ namespace YSG {
|
|||||||
int mTick{};
|
int mTick{};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TimeAxisTempData : AbsAxisTempData {
|
struct TimeAxisInputData : AbsAxisInputData {
|
||||||
std::list<TimeTick> mData;
|
std::list<TimeTick> mData;
|
||||||
std::list<QTime> mAllTime;
|
std::list<QTime> mAllTime;
|
||||||
|
void clear() override {
|
||||||
|
mData.clear();
|
||||||
|
mAllTime.clear();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -93,7 +97,7 @@ namespace YSG {
|
|||||||
void prepareData() override {
|
void prepareData() override {
|
||||||
SpinLockGuard guard(&mBufferLock);
|
SpinLockGuard guard(&mBufferLock);
|
||||||
syncStatePipeline();
|
syncStatePipeline();
|
||||||
auto d = renderTempData();
|
auto d = renderInputData();
|
||||||
auto s = renderState();
|
auto s = renderState();
|
||||||
auto sc = editState();
|
auto sc = editState();
|
||||||
bool refreshSpace = false;
|
bool refreshSpace = false;
|
||||||
@@ -141,6 +145,7 @@ namespace YSG {
|
|||||||
d->mAllTime.clear();
|
d->mAllTime.clear();
|
||||||
|
|
||||||
mData.splice(mData.begin(), d->mData);
|
mData.splice(mData.begin(), d->mData);
|
||||||
|
clearRenderInput();
|
||||||
|
|
||||||
while (!mData.empty()) {
|
while (!mData.empty()) {
|
||||||
int tick = mData.back().mTick;
|
int tick = mData.back().mTick;
|
||||||
|
|||||||
@@ -192,7 +192,6 @@ public: \
|
|||||||
void set_##name(Type name) { \
|
void set_##name(Type name) { \
|
||||||
className##Private* pd = d(); \
|
className##Private* pd = d(); \
|
||||||
className##RenderState* sc = reinterpret_cast<className##RenderState*>(pd->state(State_Edit)); \
|
className##RenderState* sc = reinterpret_cast<className##RenderState*>(pd->state(State_Edit)); \
|
||||||
className##TempData* td = reinterpret_cast<className##TempData*>(pd->mEditTempData); \
|
|
||||||
SpinLockGuard _guard(&pd->mBufferLock); \
|
SpinLockGuard _guard(&pd->mBufferLock); \
|
||||||
sc->##name = name; \
|
sc->##name = name; \
|
||||||
} \
|
} \
|
||||||
|
|||||||
@@ -101,6 +101,17 @@ namespace YSG {
|
|||||||
RenderEditGuard::~RenderEditGuard() {
|
RenderEditGuard::~RenderEditGuard() {
|
||||||
if(mData && mData->qPtr) mData->qPtr->markStateDirty();
|
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) {
|
void RenderAble::init(Plot* plot, QString layerName) {
|
||||||
if(layerName.isEmpty()) {
|
if(layerName.isEmpty()) {
|
||||||
layerName = plot->mDefaultLayerName;
|
layerName = plot->mDefaultLayerName;
|
||||||
@@ -109,13 +120,13 @@ namespace YSG {
|
|||||||
mPlot = plot;
|
mPlot = plot;
|
||||||
if(!dPtr) dPtr = createRenderData();
|
if(!dPtr) dPtr = createRenderData();
|
||||||
dPtr->clearStateBuffers();
|
dPtr->clearStateBuffers();
|
||||||
delete dPtr->mRenderTempData;
|
dPtr->clearInputBuffers();
|
||||||
delete dPtr->mEditTempData;
|
|
||||||
dPtr->mStateBuffers[State_Edit] = createRenderState();
|
dPtr->mStateBuffers[State_Edit] = createRenderState();
|
||||||
dPtr->mStateBuffers[State_Ready] = createRenderState();
|
dPtr->mStateBuffers[State_Ready] = createRenderState();
|
||||||
dPtr->mStateBuffers[State_Render] = createRenderState();
|
dPtr->mStateBuffers[State_Render] = createRenderState();
|
||||||
dPtr->mRenderTempData = createTempData();
|
dPtr->mInputBuffers[Input_Edit].data = createInputData();
|
||||||
dPtr->mEditTempData = createTempData();
|
dPtr->mInputBuffers[Input_Ready].data = createInputData();
|
||||||
|
dPtr->mInputBuffers[Input_Render].data = createInputData();
|
||||||
for(RenderState* state : dPtr->mStateBuffers) {
|
for(RenderState* state : dPtr->mStateBuffers) {
|
||||||
state->dPtr = dPtr;
|
state->dPtr = dPtr;
|
||||||
}
|
}
|
||||||
@@ -125,6 +136,9 @@ namespace YSG {
|
|||||||
}
|
}
|
||||||
void RenderAble::markStateDirty() {
|
void RenderAble::markStateDirty() {
|
||||||
if(dPtr) ++dPtr->state(State_Edit)->version;
|
if(dPtr) ++dPtr->state(State_Edit)->version;
|
||||||
|
markRenderDirty();
|
||||||
|
}
|
||||||
|
void RenderAble::markRenderDirty() {
|
||||||
if(mPlot) mPlot->markRenderStateDirty();
|
if(mPlot) mPlot->markRenderStateDirty();
|
||||||
}
|
}
|
||||||
bool RenderAble::ok() const {
|
bool RenderAble::ok() const {
|
||||||
|
|||||||
+120
-32
@@ -235,15 +235,24 @@ enum State_Role : std::uint8_t {
|
|||||||
State_Ready,
|
State_Ready,
|
||||||
State_Render
|
State_Render
|
||||||
};
|
};
|
||||||
|
enum Input_Role : std::uint8_t {
|
||||||
|
Input_Edit,
|
||||||
|
Input_Ready,
|
||||||
|
Input_Render
|
||||||
|
};
|
||||||
enum Color_Role : std::uint8_t {
|
enum Color_Role : std::uint8_t {
|
||||||
Color_Front,
|
Color_Front,
|
||||||
Color_Ready,
|
Color_Ready,
|
||||||
Color_Render
|
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(); \
|
#define INIT_GET(className) className##Private* privateData = d(); \
|
||||||
className##RenderState* renderState = reinterpret_cast<className##RenderState*>(d()->state(src));
|
className##RenderState* renderState = reinterpret_cast<className##RenderState*>(d()->state(src));
|
||||||
struct TempData {
|
struct InputData {
|
||||||
virtual ~TempData() = default;
|
virtual ~InputData() = default;
|
||||||
|
virtual void clear() {}
|
||||||
};
|
};
|
||||||
struct RenderState {
|
struct RenderState {
|
||||||
virtual ~RenderState() = default;
|
virtual ~RenderState() = default;
|
||||||
@@ -251,12 +260,20 @@ struct RenderState {
|
|||||||
RenderData* dPtr{};
|
RenderData* dPtr{};
|
||||||
SRC src();
|
SRC src();
|
||||||
};
|
};
|
||||||
|
struct InputBufferSlot {
|
||||||
|
InputData* data{};
|
||||||
|
std::uint64_t version = 0;
|
||||||
|
bool pending = false;
|
||||||
|
};
|
||||||
struct RenderData {
|
struct RenderData {
|
||||||
SpinLock mBufferLock;
|
SpinLock mBufferLock;
|
||||||
RenderAble* qPtr{};
|
RenderAble* qPtr{};
|
||||||
bool mRenderStart = false;
|
bool mRenderStart = false;
|
||||||
Triple_Role_Buffer_Control mStateControl;
|
Triple_Role_Buffer_Control mStateControl;
|
||||||
std::array<RenderState*, 3> mStateBuffers{};
|
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 {
|
RenderState* state(std::uint8_t role) const {
|
||||||
return stateByIndex(mStateControl.read_view()[role]);
|
return stateByIndex(mStateControl.read_view()[role]);
|
||||||
}
|
}
|
||||||
@@ -279,18 +296,53 @@ struct RenderData {
|
|||||||
}
|
}
|
||||||
mStateControl.reset();
|
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:
|
protected:
|
||||||
virtual void syncStatePipeline() = 0;
|
virtual void syncStatePipeline() = 0;
|
||||||
virtual RenderState* renderState() = 0;
|
virtual RenderState* renderState() = 0;
|
||||||
virtual RenderState* readyState() = 0;
|
virtual RenderState* readyState() = 0;
|
||||||
virtual RenderState* editState() = 0;
|
virtual RenderState* editState() = 0;
|
||||||
virtual TempData* renderTempData() = 0;
|
virtual InputData* renderInputData() = 0;
|
||||||
virtual TempData* editTempData() = 0;
|
virtual InputData* editInputData() = 0;
|
||||||
virtual ~RenderData() {
|
virtual ~RenderData() {
|
||||||
clearStateBuffers();
|
clearStateBuffers();
|
||||||
delete mRenderTempData;
|
clearInputBuffers();
|
||||||
delete mEditTempData;
|
|
||||||
}
|
}
|
||||||
virtual void draw(QPainter* painter) {}
|
virtual void draw(QPainter* painter) {}
|
||||||
virtual void prepareData() {
|
virtual void prepareData() {
|
||||||
@@ -322,10 +374,10 @@ struct BaseRenderData : RenderData {
|
|||||||
RenderState* editState() override {
|
RenderState* editState() override {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
TempData* renderTempData() override {
|
InputData* renderInputData() override {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
TempData* editTempData() override {
|
InputData* editInputData() override {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
void syncStatePipeline() override {}
|
void syncStatePipeline() override {}
|
||||||
@@ -336,6 +388,11 @@ struct LIB_DECL RenderEditGuard {
|
|||||||
~RenderEditGuard();
|
~RenderEditGuard();
|
||||||
RenderData* mData{};
|
RenderData* mData{};
|
||||||
};
|
};
|
||||||
|
struct LIB_DECL RenderInputGuard {
|
||||||
|
explicit RenderInputGuard(RenderData* data);
|
||||||
|
~RenderInputGuard();
|
||||||
|
RenderData* mData{};
|
||||||
|
};
|
||||||
struct RenderAble {
|
struct RenderAble {
|
||||||
enum class JobState {
|
enum class JobState {
|
||||||
Idle,
|
Idle,
|
||||||
@@ -378,8 +435,8 @@ struct RenderAble {
|
|||||||
virtual RenderState* createRenderState() {
|
virtual RenderState* createRenderState() {
|
||||||
return new RenderState;
|
return new RenderState;
|
||||||
}
|
}
|
||||||
virtual TempData* createTempData() {
|
virtual InputData* createInputData() {
|
||||||
return new TempData;
|
return new InputData;
|
||||||
}
|
}
|
||||||
virtual void init(Plot* plot, QString layerName = "");
|
virtual void init(Plot* plot, QString layerName = "");
|
||||||
virtual void draw(QPainter* painter) {
|
virtual void draw(QPainter* painter) {
|
||||||
@@ -422,9 +479,10 @@ struct RenderAble {
|
|||||||
dPtr->wheelEvent(event);
|
dPtr->wheelEvent(event);
|
||||||
};
|
};
|
||||||
static bool version_newer(std::uint64_t a, std::uint64_t b) {
|
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 markStateDirty();
|
||||||
|
void markRenderDirty();
|
||||||
QString mObjectName;
|
QString mObjectName;
|
||||||
RenderData* dPtr{};
|
RenderData* dPtr{};
|
||||||
Plot* mPlot{};
|
Plot* mPlot{};
|
||||||
@@ -446,19 +504,19 @@ private:
|
|||||||
ClassName##Private* d() {return reinterpret_cast<ClassName##Private*>(dPtr);} \
|
ClassName##Private* d() {return reinterpret_cast<ClassName##Private*>(dPtr);} \
|
||||||
RenderData* createRenderData() override; \
|
RenderData* createRenderData() override; \
|
||||||
RenderState* createRenderState() override; \
|
RenderState* createRenderState() override; \
|
||||||
TempData* createTempData() override; \
|
InputData* createInputData() override; \
|
||||||
protected: \
|
protected: \
|
||||||
ClassName(); \
|
ClassName(); \
|
||||||
friend struct ClassName##Private; \
|
friend struct ClassName##Private; \
|
||||||
friend struct ClassName##RenderState; \
|
friend struct ClassName##RenderState; \
|
||||||
friend struct ClassName##TempData; \
|
friend struct ClassName##InputData; \
|
||||||
public:
|
public:
|
||||||
#define Q_Ptr(ClassName) \
|
#define Q_Ptr(ClassName) \
|
||||||
ClassName(); \
|
ClassName(); \
|
||||||
ClassName##Private* d() {return reinterpret_cast<ClassName##Private*>(dPtr);} \
|
ClassName##Private* d() {return reinterpret_cast<ClassName##Private*>(dPtr);} \
|
||||||
RenderData* createRenderData() override; \
|
RenderData* createRenderData() override; \
|
||||||
RenderState* createRenderState() override; \
|
RenderState* createRenderState() override; \
|
||||||
TempData* createTempData() override;
|
InputData* createInputData() override;
|
||||||
#define Q_Ptr_cpp(ClassName) \
|
#define Q_Ptr_cpp(ClassName) \
|
||||||
ClassName::ClassName() { \
|
ClassName::ClassName() { \
|
||||||
dPtr = new ClassName##Private; \
|
dPtr = new ClassName##Private; \
|
||||||
@@ -466,26 +524,35 @@ private:
|
|||||||
} \
|
} \
|
||||||
RenderData* ClassName::createRenderData() {return new ClassName##Private;} \
|
RenderData* ClassName::createRenderData() {return new ClassName##Private;} \
|
||||||
RenderState* ClassName::createRenderState() {return new ClassName##RenderState;} \
|
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) \
|
#define D_Ptr_3(ClassName) \
|
||||||
ClassName##RenderState* renderState() override {return reinterpret_cast<ClassName##RenderState*>(state(State_Render));} \
|
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* readyState() override {return reinterpret_cast<ClassName##RenderState*>(state(State_Ready));} \
|
||||||
ClassName##RenderState* editState() override {return reinterpret_cast<ClassName##RenderState*>(state(State_Edit));} \
|
ClassName##RenderState* editState() override {return reinterpret_cast<ClassName##RenderState*>(state(State_Edit));} \
|
||||||
ClassName##TempData* renderTempData() override {return reinterpret_cast<ClassName##TempData*>(mRenderTempData);} \
|
ClassName##InputData* renderInputData() override {return reinterpret_cast<ClassName##InputData*>(inputData(Input_Render));} \
|
||||||
ClassName##TempData* editTempData() override {return reinterpret_cast<ClassName##TempData*>(mEditTempData);} \
|
ClassName##InputData* editInputData() override {return reinterpret_cast<ClassName##InputData*>(inputData(Input_Edit));} \
|
||||||
friend class ClassName; \
|
friend class ClassName; \
|
||||||
void syncStatePipeline() override { \
|
void syncStatePipeline() override { \
|
||||||
Triple_Buffer_Lease readyLease = mStateControl.wait_mark_use_role(State_Ready); \
|
Triple_Buffer_Lease readyLease = mStateControl.wait_mark_use_role(State_Ready); \
|
||||||
auto ready = reinterpret_cast<ClassName##RenderState*>(stateByIndex(readyLease.index)); \
|
auto ready = reinterpret_cast<ClassName##RenderState*>(stateByIndex(readyLease.index)); \
|
||||||
auto edit = editState(); \
|
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.unmark_use(readyLease); \
|
||||||
mStateControl.wait_swap_role(State_Ready, State_Render, [this](const Triple_Buffer_View& view) { \
|
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 ready = reinterpret_cast<ClassName##RenderState*>(stateByIndex(view[State_Ready])); \
|
||||||
auto render = reinterpret_cast<ClassName##RenderState*>(stateByIndex(view[State_Render])); \
|
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; \
|
if(!mRenderStart) mRenderStart = true; \
|
||||||
}
|
}
|
||||||
#define D_Ptr(ClassName) \
|
#define D_Ptr(ClassName) \
|
||||||
@@ -493,21 +560,30 @@ private:
|
|||||||
ClassName##RenderState* renderState() override {return reinterpret_cast<ClassName##RenderState*>(state(State_Render));} \
|
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* readyState() override {return reinterpret_cast<ClassName##RenderState*>(state(State_Ready));} \
|
||||||
ClassName##RenderState* editState() override {return reinterpret_cast<ClassName##RenderState*>(state(State_Edit));} \
|
ClassName##RenderState* editState() override {return reinterpret_cast<ClassName##RenderState*>(state(State_Edit));} \
|
||||||
ClassName##TempData* renderTempData() override {return reinterpret_cast<ClassName##TempData*>(mRenderTempData);} \
|
ClassName##InputData* renderInputData() override {return reinterpret_cast<ClassName##InputData*>(inputData(Input_Render));} \
|
||||||
ClassName##TempData* editTempData() override {return reinterpret_cast<ClassName##TempData*>(mEditTempData);} \
|
ClassName##InputData* editInputData() override {return reinterpret_cast<ClassName##InputData*>(inputData(Input_Edit));} \
|
||||||
friend class ClassName; \
|
friend class ClassName; \
|
||||||
void syncStatePipeline() override { \
|
void syncStatePipeline() override { \
|
||||||
Triple_Buffer_Lease readyLease = mStateControl.wait_mark_use_role(State_Ready); \
|
Triple_Buffer_Lease readyLease = mStateControl.wait_mark_use_role(State_Ready); \
|
||||||
auto ready = reinterpret_cast<ClassName##RenderState*>(stateByIndex(readyLease.index)); \
|
auto ready = reinterpret_cast<ClassName##RenderState*>(stateByIndex(readyLease.index)); \
|
||||||
auto edit = editState(); \
|
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.unmark_use(readyLease); \
|
||||||
mStateControl.wait_swap_role(State_Ready, State_Render, [this](const Triple_Buffer_View& view) { \
|
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 ready = reinterpret_cast<ClassName##RenderState*>(stateByIndex(view[State_Ready])); \
|
||||||
auto render = reinterpret_cast<ClassName##RenderState*>(stateByIndex(view[State_Render])); \
|
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; \
|
if(!mRenderStart) mRenderStart = true; \
|
||||||
}
|
}
|
||||||
#define D_Ptr2(ClassName) \
|
#define D_Ptr2(ClassName) \
|
||||||
@@ -515,26 +591,38 @@ private:
|
|||||||
ClassName##RenderState* renderState() override {return reinterpret_cast<ClassName##RenderState*>(state(State_Render));} \
|
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* readyState() override {return reinterpret_cast<ClassName##RenderState*>(state(State_Ready));} \
|
||||||
ClassName##RenderState* editState() override {return reinterpret_cast<ClassName##RenderState*>(state(State_Edit));} \
|
ClassName##RenderState* editState() override {return reinterpret_cast<ClassName##RenderState*>(state(State_Edit));} \
|
||||||
ClassName##TempData* renderTempData() override {return reinterpret_cast<ClassName##TempData*>(mRenderTempData);} \
|
ClassName##InputData* renderInputData() override {return reinterpret_cast<ClassName##InputData*>(inputData(Input_Render));} \
|
||||||
ClassName##TempData* editTempData() override {return reinterpret_cast<ClassName##TempData*>(mEditTempData);} \
|
ClassName##InputData* editInputData() override {return reinterpret_cast<ClassName##InputData*>(inputData(Input_Edit));} \
|
||||||
friend class ClassName; \
|
friend class ClassName; \
|
||||||
void syncStatePipeline() override { \
|
void syncStatePipeline() override { \
|
||||||
Triple_Buffer_Lease readyLease = mStateControl.wait_mark_use_role(State_Ready); \
|
Triple_Buffer_Lease readyLease = mStateControl.wait_mark_use_role(State_Ready); \
|
||||||
auto ready = reinterpret_cast<ClassName##RenderState*>(stateByIndex(readyLease.index)); \
|
auto ready = reinterpret_cast<ClassName##RenderState*>(stateByIndex(readyLease.index)); \
|
||||||
auto edit = editState(); \
|
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.unmark_use(readyLease); \
|
||||||
mStateControl.wait_swap_role(State_Ready, State_Render, [this](const Triple_Buffer_View& view) { \
|
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 ready = reinterpret_cast<ClassName##RenderState*>(stateByIndex(view[State_Ready])); \
|
||||||
auto render = reinterpret_cast<ClassName##RenderState*>(stateByIndex(view[State_Render])); \
|
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; \
|
if(!mRenderStart) mRenderStart = true; \
|
||||||
}
|
}
|
||||||
#define INIT_SET(className) className##Private* pd = d(); \
|
#define INIT_SET(className) className##Private* pd = d(); \
|
||||||
className##RenderState* sc = reinterpret_cast<className##RenderState*>(pd->state(State_Edit));\
|
className##RenderState* sc = reinterpret_cast<className##RenderState*>(pd->state(State_Edit));\
|
||||||
className##TempData* td = reinterpret_cast<className##TempData*>(pd->mEditTempData); \
|
|
||||||
SpinLockGuard _guard(&pd->mBufferLock); \
|
SpinLockGuard _guard(&pd->mBufferLock); \
|
||||||
RenderEditGuard _editGuard(pd);
|
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 {
|
void keyReleaseEvent(QKeyEvent* event) override {
|
||||||
MutiSelectRectRenderState* sc = editState();
|
MutiSelectRectRenderState* sc = editState();
|
||||||
MutiSelectRectTempData* td = editTempData();
|
|
||||||
SpinLockGuard _guard(&mBufferLock);
|
SpinLockGuard _guard(&mBufferLock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,20 +15,18 @@ namespace YSG {
|
|||||||
void Afterglow::set_frequentPointSize(int t) {
|
void Afterglow::set_frequentPointSize(int t) {
|
||||||
AfterglowPrivate* pd = d();
|
AfterglowPrivate* pd = d();
|
||||||
AfterglowRenderState* sc = reinterpret_cast<AfterglowRenderState*>(pd->state(State_Edit));
|
AfterglowRenderState* sc = reinterpret_cast<AfterglowRenderState*>(pd->state(State_Edit));
|
||||||
AfterglowTempData* td = reinterpret_cast<AfterglowTempData*>(pd->mEditTempData);
|
|
||||||
SpinLockGuard _guard(&pd->mBufferLock);
|
SpinLockGuard _guard(&pd->mBufferLock);
|
||||||
RenderEditGuard _editGuard(pd);
|
RenderEditGuard _editGuard(pd);
|
||||||
sc->frequentPointSize = std::move(t);
|
sc->frequentPointSize = std::move(t);
|
||||||
sc->update_PointSize(sc->frequentPointSize, sc->powerPointSize);
|
sc->bufferSize = sc->frequentPointSize * sc->powerPointSize;
|
||||||
}
|
}
|
||||||
void Afterglow::set_powerPointSize(int t) {
|
void Afterglow::set_powerPointSize(int t) {
|
||||||
AfterglowPrivate* pd = d();
|
AfterglowPrivate* pd = d();
|
||||||
AfterglowRenderState* sc = reinterpret_cast<AfterglowRenderState*>(pd->state(State_Edit));
|
AfterglowRenderState* sc = reinterpret_cast<AfterglowRenderState*>(pd->state(State_Edit));
|
||||||
AfterglowTempData* td = reinterpret_cast<AfterglowTempData*>(pd->mEditTempData);
|
|
||||||
SpinLockGuard _guard(&pd->mBufferLock);
|
SpinLockGuard _guard(&pd->mBufferLock);
|
||||||
RenderEditGuard _editGuard(pd);
|
RenderEditGuard _editGuard(pd);
|
||||||
sc->powerPointSize = std::move(t);
|
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) {
|
void Afterglow::giveData(const QVector<double> &powerRangeData) {
|
||||||
if(!ok()) return;
|
if(!ok()) return;
|
||||||
INIT_SET(Afterglow)
|
AfterglowPrivate* pd = d();
|
||||||
sc->pushData(powerRangeData);
|
SpinLockGuard _guard(&pd->mBufferLock);
|
||||||
}
|
AfterglowRenderState* sc = reinterpret_cast<AfterglowRenderState*>(pd->state(State_Edit));
|
||||||
|
if(powerRangeData.size() != sc->frequentPointSize) {
|
||||||
void AfterglowRenderState::pushData(const QVector<double> &powerRangeData) {
|
|
||||||
|
|
||||||
if (powerRangeData.size() != frequentPointSize) {
|
|
||||||
qDebug() << QString("pushData(const QVector<double> &powerRangeData) error 数组大小不匹配 需要%1, 实际为%2")
|
qDebug() << QString("pushData(const QVector<double> &powerRangeData) error 数组大小不匹配 需要%1, 实际为%2")
|
||||||
.arg(frequentPointSize).arg(powerRangeData.size());
|
.arg(sc->frequentPointSize).arg(powerRangeData.size());
|
||||||
return;
|
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;
|
curIndex = 0;
|
||||||
double oldRemain = 1.0 - attenuationRate;
|
double oldRemain = 1.0 - s->attenuationRate;
|
||||||
double cacheRemain = attenuationRate / (double) initStrongValue; //这一次的概率 [0,1]
|
double cacheRemain = s->attenuationRate / (double)s->initStrongValue;
|
||||||
for (int i = 0; i < bufferSize; ++i) {
|
for(int i = 0; i < cacheBufferSize; ++i) {
|
||||||
//std::cout << mCachedPowerData[i] << " " ;
|
|
||||||
mutexPowerData[i] = oldRemain*oldCachePowerData[i] + cacheRemain*cachedPowerData[i];
|
mutexPowerData[i] = oldRemain*oldCachePowerData[i] + cacheRemain*cachedPowerData[i];
|
||||||
cachedPowerData[i] = 0;
|
cachedPowerData[i] = 0;
|
||||||
}
|
}
|
||||||
//std::cout << std::endl;
|
|
||||||
{
|
{
|
||||||
auto d = reinterpret_cast<AfterglowPrivate*>(dPtr);
|
SpinLockGuard g(&dataLock);
|
||||||
SpinLockGuard g(&d->dataLock);
|
std::memmove(oldCachePowerData.data(), mutexPowerData.data(), cacheBufferSize * sizeof(double));
|
||||||
std::memmove(oldCachePowerData.data(), mutexPowerData.data(), bufferSize * sizeof(double));
|
OK.storeRelease(true);
|
||||||
d->OK.storeRelease(true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
QVector<int> indexList(frequentPointSize);
|
QVector<int> indexList(s->frequentPointSize);
|
||||||
double rate = (double)powerPointSize/powerRange.size();
|
double rate = (double)s->powerPointSize/s->powerRange.size();
|
||||||
for (int i = 0; i < frequentPointSize; ++i) {
|
for(int i = 0; i < s->frequentPointSize; ++i) {
|
||||||
int lineIndex = (int) ((powerRangeData[i] - powerRange.lower) * rate);
|
int lineIndex = (int)((powerRangeData[i] - s->powerRange.lower) * rate);
|
||||||
if (lineIndex < 0) lineIndex = 0;
|
if (lineIndex < 0) lineIndex = 0;
|
||||||
if (lineIndex > powerPointSize - 1) lineIndex = powerPointSize - 1;
|
if (lineIndex > s->powerPointSize - 1) lineIndex = s->powerPointSize - 1;
|
||||||
indexList[i] = lineIndex;
|
indexList[i] = lineIndex;
|
||||||
}
|
}
|
||||||
|
if(!s->interpolate) {
|
||||||
if (!interpolate) { //插值 填入没有的概率地方
|
for(int i = 0; i < s->frequentPointSize; ++i) {
|
||||||
for (int i = 0; i < frequentPointSize; ++i) {
|
int index = indexList[i] * s->frequentPointSize + i;
|
||||||
int index = indexList[i] * frequentPointSize + i;
|
|
||||||
cachedPowerData[index]++;
|
cachedPowerData[index]++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int lastLower = -1, lastUpper = -1;
|
int lastLower = -1, lastUpper = -1;
|
||||||
for (int i = 0; i < frequentPointSize; ++i) {
|
for(int i = 0; i < s->frequentPointSize; ++i) {
|
||||||
int y = indexList[i];
|
int y = indexList[i];
|
||||||
cachedPowerData[y * frequentPointSize + i]++;
|
cachedPowerData[y * s->frequentPointSize + i]++;
|
||||||
if (y - lastUpper >= 2) {
|
if (y - lastUpper >= 2) {
|
||||||
for (int curY = lastUpper + 1; curY < y; ++curY) {
|
for (int curY = lastUpper + 1; curY < y; ++curY) {
|
||||||
cachedPowerData[curY * frequentPointSize + i]++;
|
cachedPowerData[curY * s->frequentPointSize + i]++;
|
||||||
}
|
}
|
||||||
lastUpper = y;
|
lastUpper = y;
|
||||||
lastLower = lastLower + 1;
|
lastLower = lastLower + 1;
|
||||||
@@ -101,7 +98,7 @@ namespace YSG {
|
|||||||
}
|
}
|
||||||
if (lastLower - y >= 2) {
|
if (lastLower - y >= 2) {
|
||||||
for (int curY = y + 1; curY < lastLower; ++curY) {
|
for (int curY = y + 1; curY < lastLower; ++curY) {
|
||||||
cachedPowerData[curY * frequentPointSize + i]++;
|
cachedPowerData[curY * s->frequentPointSize + i]++;
|
||||||
}
|
}
|
||||||
lastUpper = lastLower - 1;
|
lastUpper = lastLower - 1;
|
||||||
lastLower = y;
|
lastLower = y;
|
||||||
|
|||||||
@@ -11,34 +11,39 @@ namespace YSG {
|
|||||||
|
|
||||||
|
|
||||||
struct AfterglowRenderState : RenderState, Afterglow_Prop {
|
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 AfterglowInputData : InputData {
|
||||||
|
std::list<QVector<double>> mDataList;
|
||||||
struct AfterglowTempData : TempData {};
|
void clear() override {
|
||||||
|
mDataList.clear();
|
||||||
|
}
|
||||||
|
};
|
||||||
struct AfterglowPrivate : RenderData {
|
struct AfterglowPrivate : RenderData {
|
||||||
D_Ptr(Afterglow)
|
D_Ptr(Afterglow)
|
||||||
QImage image;
|
QImage image;
|
||||||
SpinLock dataLock;
|
SpinLock dataLock;
|
||||||
QAtomicInteger<bool> OK = false;
|
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 {
|
void draw(QPainter* painter) override {
|
||||||
AfterglowRenderState* s = renderState();
|
AfterglowRenderState* s = renderState();
|
||||||
PerformanceShower *shower = q()->mPlot->d->mShower;
|
PerformanceShower *shower = q()->mPlot->d->mShower;
|
||||||
@@ -61,7 +66,7 @@ namespace YSG {
|
|||||||
//double rate = 1.0/s->strengthValue() * 256.0;
|
//double rate = 1.0/s->strengthValue() * 256.0;
|
||||||
for (int row = 0; row < rowCount; ++row) {
|
for (int row = 0; row < rowCount; ++row) {
|
||||||
QRgb* scanLine = reinterpret_cast<QRgb*>(image.scanLine(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) {
|
for (int col = 0; col < colCount; ++col) {
|
||||||
int colorOffset = (int)(list[col] * 255);
|
int colorOffset = (int)(list[col] * 255);
|
||||||
if (colorOffset < 0 || colorOffset > 255) {
|
if (colorOffset < 0 || colorOffset > 255) {
|
||||||
@@ -94,6 +99,15 @@ namespace YSG {
|
|||||||
void prepareData() override {
|
void prepareData() override {
|
||||||
SpinLockGuard guard(&mBufferLock);
|
SpinLockGuard guard(&mBufferLock);
|
||||||
syncStatePipeline();
|
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>
|
template <typename That>
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ namespace YSG {
|
|||||||
void AudioFrequent::giveData(int tick, double data) {
|
void AudioFrequent::giveData(int tick, double data) {
|
||||||
Q_UNUSED(tick)
|
Q_UNUSED(tick)
|
||||||
if(!ok()) return;
|
if(!ok()) return;
|
||||||
INIT_SET(AudioFrequent)
|
INIT_INPUT(AudioFrequent)
|
||||||
td->mDataList.push_front(data);
|
input->mDataList.push_front(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,11 @@
|
|||||||
|
|
||||||
|
|
||||||
namespace YSG {
|
namespace YSG {
|
||||||
struct AudioFrequentTempData : TempData {
|
struct AudioFrequentInputData : InputData {
|
||||||
std::list<double> mDataList;
|
std::list<double> mDataList;
|
||||||
|
void clear() override {
|
||||||
|
mDataList.clear();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
struct AudioFrequentRenderState : RenderState, AudioFrequent_Prop {};
|
struct AudioFrequentRenderState : RenderState, AudioFrequent_Prop {};
|
||||||
|
|
||||||
@@ -22,7 +25,7 @@ namespace YSG {
|
|||||||
SpinLockGuard guard(&mBufferLock);
|
SpinLockGuard guard(&mBufferLock);
|
||||||
syncStatePipeline();
|
syncStatePipeline();
|
||||||
AudioFrequentRenderState *s = renderState();
|
AudioFrequentRenderState *s = renderState();
|
||||||
AudioFrequentTempData *d = renderTempData();
|
AudioFrequentInputData *d = renderInputData();
|
||||||
if(mMutiBuffer.buffers.empty() || mMutiBuffer.n != s->timePointSize) {
|
if(mMutiBuffer.buffers.empty() || mMutiBuffer.n != s->timePointSize) {
|
||||||
mMutiBuffer.resize({sizeof(double)}, s->timePointSize, s->timePointSize * 10);
|
mMutiBuffer.resize({sizeof(double)}, s->timePointSize, s->timePointSize * 10);
|
||||||
PerformanceShower *shower = q()->mPlot->d->mShower;
|
PerformanceShower *shower = q()->mPlot->d->mShower;
|
||||||
@@ -34,7 +37,7 @@ namespace YSG {
|
|||||||
for(double& power : d->mDataList) {
|
for(double& power : d->mDataList) {
|
||||||
mMutiBuffer.pushData({&power});
|
mMutiBuffer.pushData({&power});
|
||||||
}
|
}
|
||||||
d->mDataList.clear();
|
clearRenderInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -46,7 +49,6 @@ namespace YSG {
|
|||||||
.arg(s->timeAxis->timePointSize()));
|
.arg(s->timeAxis->timePointSize()));
|
||||||
}
|
}
|
||||||
painter->save();
|
painter->save();
|
||||||
AudioFrequentTempData *d = renderTempData();
|
|
||||||
QPolygonF polyline;
|
QPolygonF polyline;
|
||||||
int start = (int)s->timeAxis->startCoord();
|
int start = (int)s->timeAxis->startCoord();
|
||||||
QPen newPen = QPen(s->color);
|
QPen newPen = QPen(s->color);
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ namespace YSG {
|
|||||||
void Planisphere::giveData(QPointF pos) {
|
void Planisphere::giveData(QPointF pos) {
|
||||||
if(!ok()) return;
|
if(!ok()) return;
|
||||||
if(!mPlot->isVisible()) return;
|
if(!mPlot->isVisible()) return;
|
||||||
INIT_SET(Planisphere)
|
INIT_INPUT(Planisphere)
|
||||||
td->mDataList.push_back({pos});
|
input->mDataList.push_back({pos});
|
||||||
}
|
}
|
||||||
|
|
||||||
Planisphere::Builder::Builder(Axis* IAxis, Axis* QAxis) {
|
Planisphere::Builder::Builder(Axis* IAxis, Axis* QAxis) {
|
||||||
|
|||||||
@@ -9,8 +9,11 @@ namespace YSG {
|
|||||||
int mRemainTimes{};
|
int mRemainTimes{};
|
||||||
int maxTotalTimes{};
|
int maxTotalTimes{};
|
||||||
};
|
};
|
||||||
struct PlanisphereTempData : TempData {
|
struct PlanisphereInputData : InputData {
|
||||||
std::list<PlanisphereData> mDataList;
|
std::list<PlanisphereData> mDataList;
|
||||||
|
void clear() override {
|
||||||
|
mDataList.clear();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PlanisphereRenderState : RenderState, Planisphere_Prop {
|
struct PlanisphereRenderState : RenderState, Planisphere_Prop {
|
||||||
@@ -66,7 +69,7 @@ namespace YSG {
|
|||||||
void prepareData() override {
|
void prepareData() override {
|
||||||
SpinLockGuard guard(&mBufferLock);
|
SpinLockGuard guard(&mBufferLock);
|
||||||
syncStatePipeline();
|
syncStatePipeline();
|
||||||
PlanisphereTempData *d = renderTempData();
|
PlanisphereInputData *d = renderInputData();
|
||||||
PlanisphereRenderState *s = renderState();
|
PlanisphereRenderState *s = renderState();
|
||||||
int times = qMax(5, (s->continueMillisecond * q()->mPlot->d->mRefreshTimesPreSecond) / 1000);
|
int times = qMax(5, (s->continueMillisecond * q()->mPlot->d->mRefreshTimesPreSecond) / 1000);
|
||||||
for(PlanisphereData& data : d->mDataList) {
|
for(PlanisphereData& data : d->mDataList) {
|
||||||
@@ -74,6 +77,7 @@ namespace YSG {
|
|||||||
data.mRemainTimes = times;
|
data.mRemainTimes = times;
|
||||||
}
|
}
|
||||||
dataList.splice(dataList.end(), d->mDataList);
|
dataList.splice(dataList.end(), d->mDataList);
|
||||||
|
clearRenderInput();
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,13 +29,11 @@ namespace YSG {
|
|||||||
void Spectrum::set_frequentPointSize(int frequentPointSize) {
|
void Spectrum::set_frequentPointSize(int frequentPointSize) {
|
||||||
INIT_SET(Spectrum)
|
INIT_SET(Spectrum)
|
||||||
sc->frequentPointSize = frequentPointSize;
|
sc->frequentPointSize = frequentPointSize;
|
||||||
sc->updateFrequentPointSize(sc->frequentPointSize, sc->frequentRange);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Spectrum::set_frequentRange(Range frequentRange){
|
void Spectrum::set_frequentRange(Range frequentRange){
|
||||||
INIT_SET(Spectrum)
|
INIT_SET(Spectrum)
|
||||||
sc->frequentRange = frequentRange;
|
sc->frequentRange = frequentRange;
|
||||||
sc->updateFrequentPointSize(sc->frequentPointSize, sc->frequentRange);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -72,13 +70,106 @@ namespace YSG {
|
|||||||
PROP_R(QPen, markerPen);
|
PROP_R(QPen, markerPen);
|
||||||
PROP_R(QPen, middleFrequentPen);
|
PROP_R(QPen, middleFrequentPen);
|
||||||
PROP_R(QBrush, sweepRectBrush);
|
PROP_R(QBrush, sweepRectBrush);
|
||||||
sc->updateFrequentPointSize(sc->frequentPointSize, sc->frequentRange);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
Spectrum* SpectrumPrivate::q() {
|
Spectrum* SpectrumPrivate::q() {
|
||||||
return reinterpret_cast<Spectrum*>(qPtr);
|
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) {
|
void SpectrumPrivate::draw(QPainter* painter) {
|
||||||
auto s = renderState();
|
auto s = renderState();
|
||||||
PerformanceShower *shower = q()->mPlot->d->mShower;
|
PerformanceShower *shower = q()->mPlot->d->mShower;
|
||||||
@@ -86,7 +177,7 @@ namespace YSG {
|
|||||||
shower->mInfoMap["mFrequentPointSize"] = PerformanceLine(QString("mFrequentPointSize:%1")
|
shower->mInfoMap["mFrequentPointSize"] = PerformanceLine(QString("mFrequentPointSize:%1")
|
||||||
.arg(s->frequentPointSize));
|
.arg(s->frequentPointSize));
|
||||||
}
|
}
|
||||||
s->draw(painter);
|
drawSpectrum(painter, s);
|
||||||
if(q()->hoverOK(q())) {
|
if(q()->hoverOK(q())) {
|
||||||
q()->drawHover(painter, s->frequentAxis, s->powerAxis);
|
q()->drawHover(painter, s->frequentAxis, s->powerAxis);
|
||||||
}
|
}
|
||||||
@@ -95,8 +186,16 @@ namespace YSG {
|
|||||||
|
|
||||||
void Spectrum::giveData(const QVector<double> &lineData){
|
void Spectrum::giveData(const QVector<double> &lineData){
|
||||||
if(!ok()) return;
|
if(!ok()) return;
|
||||||
INIT_SET(Spectrum)
|
SpectrumPrivate* pd = d();
|
||||||
sc->setFrenquentData(lineData);
|
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){
|
void Spectrum::addCustomMarker(double frequent){
|
||||||
@@ -180,8 +279,8 @@ namespace YSG {
|
|||||||
}
|
}
|
||||||
|
|
||||||
double Spectrum::getPower(double frequent, bool& ok, SRC src) {
|
double Spectrum::getPower(double frequent, bool& ok, SRC src) {
|
||||||
INIT_GET(Spectrum)
|
Q_UNUSED(src)
|
||||||
return renderState->getY(frequent, ok);
|
return d()->getY(frequent, ok);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,18 +21,15 @@ namespace YSG {
|
|||||||
return qFuzzyCompare(frequent, other.frequent) && drawLine == other.drawLine;
|
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 {
|
struct SpectrumRenderState : RenderState, HoverInfoRenderState, Spectrum_PROP {
|
||||||
QVector<Marker> markerList;
|
QVector<Marker> markerList;
|
||||||
int curSelectIndex = -1;
|
int curSelectIndex = -1;
|
||||||
double minMarkerKey{};
|
|
||||||
double minMarkerValue{};
|
|
||||||
double maxMarkerKey{};
|
|
||||||
double maxMarkerValue{};
|
|
||||||
QVector<double> frequents;
|
|
||||||
QVector<double> maxPowers, curPowers, minPowers;
|
|
||||||
|
|
||||||
void unSelect() {
|
void unSelect() {
|
||||||
curSelectIndex = -1;
|
curSelectIndex = -1;
|
||||||
}
|
}
|
||||||
@@ -64,108 +61,6 @@ namespace YSG {
|
|||||||
markerList[index].frequent = frequent;
|
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) {
|
void drawMarker(QPainter *painter, double key, double value, bool isLine = false, bool isSelected = false) {
|
||||||
double x = frequentAxis->coordToPixel(key, SRC::Render);
|
double x = frequentAxis->coordToPixel(key, SRC::Render);
|
||||||
double y = powerAxis->coordToPixel(value, SRC::Render);
|
double y = powerAxis->coordToPixel(value, SRC::Render);
|
||||||
@@ -205,20 +100,39 @@ namespace YSG {
|
|||||||
struct SpectrumPrivate : RenderData {
|
struct SpectrumPrivate : RenderData {
|
||||||
D_Ptr_3(Spectrum)
|
D_Ptr_3(Spectrum)
|
||||||
Spectrum* q();
|
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 draw(QPainter* painter) override;
|
||||||
void prepareData() override {
|
void prepareData() override {
|
||||||
SpinLockGuard guard(&mBufferLock);
|
SpinLockGuard guard(&mBufferLock);
|
||||||
syncStatePipeline();
|
syncStatePipeline();
|
||||||
auto s = renderState();
|
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 {
|
bool selectTest(const QPointF& pos) override {
|
||||||
auto sc = editState();
|
auto sc = editState();
|
||||||
double frequent = sc->frequentAxis->pixelToCoord(pos.x(), SRC::Render);
|
double frequent = sc->frequentAxis->pixelToCoord(pos.x(), SRC::Render);
|
||||||
bool ok;
|
bool ok;
|
||||||
double power = sc->getY(frequent, ok);
|
double power = getY(frequent, ok);
|
||||||
if(!ok) return false;
|
if(!ok) return false;
|
||||||
return qAbs(power - sc->powerAxis->pixelToCoord(pos.y(), SRC::Render)) < 4;
|
return qAbs(power - sc->powerAxis->pixelToCoord(pos.y(), SRC::Render)) < 4;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,12 +16,16 @@ namespace YSG {
|
|||||||
|
|
||||||
void SweepFrequent::giveData(const QVector<double>& data) {
|
void SweepFrequent::giveData(const QVector<double>& data) {
|
||||||
if(!ok()) return;
|
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) {
|
if(data.size() != sc->blockFrequentPointSize) {
|
||||||
qDebug() << "error data size == " << data.size() << " BlockFrquentPointSize" << sc->blockFrequentPointSize;
|
qDebug() << "error data size == " << data.size() << " BlockFrquentPointSize" << sc->blockFrequentPointSize;
|
||||||
return;
|
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 {
|
struct SweepFrequentInputData : YSG::InputData {
|
||||||
std::list<QVector<double>> mData;
|
std::list<QVector<double>> mData;
|
||||||
|
void clear() override {
|
||||||
|
mData.clear();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SweepFrequentPrivate : YSG::RenderData {
|
struct SweepFrequentPrivate : YSG::RenderData {
|
||||||
@@ -46,7 +49,7 @@ namespace YSG {
|
|||||||
SpinLockGuard guard(&mBufferLock);
|
SpinLockGuard guard(&mBufferLock);
|
||||||
syncStatePipeline();
|
syncStatePipeline();
|
||||||
SweepFrequentRenderState *s = renderState();
|
SweepFrequentRenderState *s = renderState();
|
||||||
SweepFrequentTempData *d = renderTempData();
|
SweepFrequentInputData *d = renderInputData();
|
||||||
if(
|
if(
|
||||||
mBlockFrquentPointSize != s->blockFrequentPointSize ||
|
mBlockFrquentPointSize != s->blockFrequentPointSize ||
|
||||||
mBlockNum != s->blockNum ||
|
mBlockNum != s->blockNum ||
|
||||||
@@ -66,7 +69,7 @@ namespace YSG {
|
|||||||
mFristLoop = false;
|
mFristLoop = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
d->mData.clear();
|
clearRenderInput();
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw(QPainter* painter) override {
|
void draw(QPainter* painter) override {
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ namespace YSG {
|
|||||||
|
|
||||||
void WaterFall::giveData(int tick, const QVector<double>& data) {
|
void WaterFall::giveData(int tick, const QVector<double>& data) {
|
||||||
if(!ok()) return;
|
if(!ok()) return;
|
||||||
INIT_SET(WaterFall)
|
INIT_INPUT(WaterFall)
|
||||||
td->mDataList.push_back({tick, data});
|
input->mDataList.push_back({tick, data});
|
||||||
}
|
}
|
||||||
|
|
||||||
WaterFall::Builder::Builder(FrequentAxis* frequentAxis, TimeAxis* timeAxis) {
|
WaterFall::Builder::Builder(FrequentAxis* frequentAxis, TimeAxis* timeAxis) {
|
||||||
|
|||||||
@@ -19,8 +19,11 @@ namespace YSG {
|
|||||||
int mTick;
|
int mTick;
|
||||||
QVector<double> mFrequent;
|
QVector<double> mFrequent;
|
||||||
};
|
};
|
||||||
struct WaterFallTempData : TempData {
|
struct WaterFallInputData : InputData {
|
||||||
std::list<WaterFallData> mDataList;
|
std::list<WaterFallData> mDataList;
|
||||||
|
void clear() override {
|
||||||
|
mDataList.clear();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
struct WaterFallRenderState : RenderState, HoverInfoRenderState, WaterFall_Prop {
|
struct WaterFallRenderState : RenderState, HoverInfoRenderState, WaterFall_Prop {
|
||||||
};
|
};
|
||||||
@@ -88,7 +91,7 @@ namespace YSG {
|
|||||||
void prepareData() override {
|
void prepareData() override {
|
||||||
SpinLockGuard guard(&mBufferLock);
|
SpinLockGuard guard(&mBufferLock);
|
||||||
syncStatePipeline();
|
syncStatePipeline();
|
||||||
WaterFallTempData* data = renderTempData();
|
WaterFallInputData* data = renderInputData();
|
||||||
const WaterFallRenderState* s = renderState();
|
const WaterFallRenderState* s = renderState();
|
||||||
int colCount = s->frequentPointSize, rowCount = s->timeAxis->timePointSize();
|
int colCount = s->frequentPointSize, rowCount = s->timeAxis->timePointSize();
|
||||||
if(!ringBuffer.match(colCount, rowCount)) {
|
if(!ringBuffer.match(colCount, rowCount)) {
|
||||||
@@ -105,7 +108,7 @@ namespace YSG {
|
|||||||
}
|
}
|
||||||
ringBuffer.pushData(frequentData.data(), wd.mTick);
|
ringBuffer.pushData(frequentData.data(), wd.mTick);
|
||||||
}
|
}
|
||||||
data->mDataList.clear();
|
clearRenderInput();
|
||||||
}
|
}
|
||||||
void draw(QPainter* painter) override {
|
void draw(QPainter* painter) override {
|
||||||
WaterFallRenderState* s = renderState();
|
WaterFallRenderState* s = renderState();
|
||||||
@@ -114,7 +117,6 @@ namespace YSG {
|
|||||||
shower->mInfoMap["FrequentRectCount"] = PerformanceLine(QString("FrequentRectCount:%1 timePointSize: %2")
|
shower->mInfoMap["FrequentRectCount"] = PerformanceLine(QString("FrequentRectCount:%1 timePointSize: %2")
|
||||||
.arg(s->frequentPointSize).arg(s->timeAxis->timePointSize()));
|
.arg(s->frequentPointSize).arg(s->timeAxis->timePointSize()));
|
||||||
}
|
}
|
||||||
WaterFallTempData* data = renderTempData();
|
|
||||||
AbsAxis *hAxis = s->frequentAxis;
|
AbsAxis *hAxis = s->frequentAxis;
|
||||||
TimeAxis *vAxis = s->timeAxis;
|
TimeAxis *vAxis = s->timeAxis;
|
||||||
Range hRange = s->frequentRange, vRange = s->timeAxis->coordRange();
|
Range hRange = s->frequentRange, vRange = s->timeAxis->coordRange();
|
||||||
|
|||||||
Reference in New Issue
Block a user