157 lines
6.6 KiB
C++
157 lines
6.6 KiB
C++
#pragma once
|
|
#include <iomanip>
|
|
#include <sstream>
|
|
|
|
#include "../Axis/FrequentAxis_p.h"
|
|
#include "../Axis/TimeAxis_p.h"
|
|
#include "../RenderAble.h"
|
|
#include "../base/Global.h"
|
|
#include "../base/PerformanceShower_p.h"
|
|
#include "../base/Plot.h"
|
|
#include "../base/Plot_p.h"
|
|
#include "WaterFall.h"
|
|
|
|
|
|
namespace YSG {
|
|
|
|
|
|
|
|
struct WaterFallData {
|
|
int mTick;
|
|
QVector<double> mFrequent;
|
|
};
|
|
|
|
struct WaterFallTempData : TempData {
|
|
std::list<WaterFallData> mDataList;
|
|
};
|
|
|
|
struct WaterFallRenderState : RenderState, HoverInfoRenderState, WaterFall_Prop {
|
|
|
|
};
|
|
|
|
struct WaterFallPrivate : RenderData {
|
|
D_Ptr(WaterFall)
|
|
YSG::MutiRingBuffer mutiBuffer;
|
|
QImage image;
|
|
int listByteSize{};
|
|
bool selectTest(const QPointF& pos) override {return true;}
|
|
void mouseMoveEvent(QMouseEvent* event) override {
|
|
WaterFallRenderState* sc = renderStateCache();
|
|
{
|
|
SpinLockGuard guard(&mBufferLock);
|
|
|
|
}
|
|
}
|
|
|
|
void prepareData() override {
|
|
SpinLockGuard guard(&mBufferLock);
|
|
loadCache();
|
|
WaterFallTempData* data = tempData();
|
|
const WaterFallRenderState* s = renderState();
|
|
int colCount = s->frequentPointSize, rowCount = s->timeAxis->timePointSize();
|
|
listByteSize = colCount * (int)sizeof(double);
|
|
if(mutiBuffer.n != rowCount || mutiBuffer.buffers.empty() || mutiBuffer.buffers[0].l != listByteSize) {
|
|
mutiBuffer.resize({listByteSize, sizeof(int)}, rowCount, rowCount * 10);
|
|
}
|
|
for(WaterFallData& wd : data->mDataList) {
|
|
QVector<double>& frequentData = wd.mFrequent;
|
|
if(frequentData.size() != colCount) {
|
|
qDebug() << "WaterFall 舍弃数据 colCount == " << colCount <<
|
|
" dataSize == " << frequentData.size() <<
|
|
"s FrequentRectCount==" << s->frequentPointSize <<
|
|
"sc FrequentRectCount==" << renderStateCache()->frequentPointSize;
|
|
break;
|
|
}
|
|
mutiBuffer.pushData({frequentData.data(), &wd.mTick});
|
|
}
|
|
data->mDataList.clear();
|
|
}
|
|
|
|
|
|
|
|
void draw(QPainter* painter) override {
|
|
WaterFallRenderState* s = renderState();
|
|
PerformanceShower *shower = q()->mPlot->d->mShower;
|
|
if(shower) {
|
|
shower->mInfoMap["FrequentRectCount"] = PerformanceLine(QString("FrequentRectCount:%1 timePointSize: %2")
|
|
.arg(s->frequentPointSize).arg(s->timeAxis->timePointSize()));
|
|
}
|
|
WaterFallTempData* data = tempData();
|
|
AbsAxis *hAxis = s->frequentAxis;
|
|
TimeAxis *vAxis = s->timeAxis;
|
|
Range hRange = s->frequentRange, vRange = s->timeAxis->coordRange();
|
|
|
|
TimeTicker& maker = s->timeAxis->d()->mTimeTicker;
|
|
if(!maker.mStartCoordToEndCoord){
|
|
std::swap(vRange.lower, vRange.upper);
|
|
}
|
|
int colCount = s->frequentPointSize, rowCount = s->timeAxis->timePointSize();
|
|
if(image.width() != colCount || image.height() != rowCount) {
|
|
image = QImage(colCount, rowCount, QImage::Format_ARGB32_Premultiplied);
|
|
image.fill(q()->mPlot->backgroundColor());
|
|
PerformanceShower *shower = q()->mPlot->d->mShower;
|
|
if(shower) {
|
|
shower->mInfoMap["colCount, rowCount"] = PerformanceLine(QString("colCount:%1, rowCount:%2")
|
|
.arg(colCount).arg(rowCount));
|
|
}
|
|
}
|
|
double valueStartCoord = s->powerRange.lower;
|
|
double rate = 256.0 / s->powerRange.size();
|
|
|
|
|
|
auto data2 = mutiBuffer.buffers[0].list();
|
|
auto l2 = mutiBuffer.buffers[1].list<int>();
|
|
QVector<QRgb>& mColorMap = Global::instance()->mColorMap;
|
|
{
|
|
Cacl c("waterfull setTime:%1", q()->mPlot->d->mShower);
|
|
int startTick = (int)s->timeAxis->startCoord();
|
|
// 不用 mMutiBuffer.buffers[0].f 的话,可能会出现一种情况那就是
|
|
// 意外的通过了 tickOffset < 0 || tickOffset >= rowCount 导致显示0值时的颜色
|
|
// 这种意外的原因时0值的位置 默认tick值0 在当前坐标轴显示的tick范围内
|
|
for(int row = 0; row < mutiBuffer.buffers[0].f; ++row) {
|
|
auto list = (double*)(data2+row*listByteSize);
|
|
int tick = *(l2 + row);
|
|
int tickOffset = tick - startTick;
|
|
// 瀑布图数据对应的 tick 可能不是 timeTick轴能显示的
|
|
if(tickOffset < 0 || tickOffset >= rowCount) continue;
|
|
QRgb* scanLine = reinterpret_cast<QRgb*>(image.scanLine(tickOffset));
|
|
|
|
|
|
//std::string color_offset_line = "row: " + std::to_string(row)
|
|
// + " tick: " + std::to_string(tick)
|
|
// + " tick off: " + std::to_string(tickOffset) + " ";
|
|
for (int col = 0; col < colCount; ++col) {
|
|
int colorOffset = int((list[col] - valueStartCoord) * rate);
|
|
if (colorOffset < 0 || colorOffset > 255) {
|
|
qDebug() << "colorOffset:" << colorOffset << " value: " << list[col] << s->frequentRange;
|
|
}
|
|
//color_offset_line += std::to_string(colorOffset) + ",";
|
|
scanLine[col] = mColorMap.at(clamp(colorOffset, 0, 255));
|
|
}
|
|
|
|
//std::cout << color_offset_line<< std::endl;
|
|
}
|
|
}
|
|
|
|
|
|
double x = hAxis->coordToPixel(hRange.lower, SRC::Render);
|
|
double y = vAxis->coordToPixel(vRange.lower, SRC::Render);
|
|
double w = hAxis->coordToPixel(hRange.upper, SRC::Render) - x;
|
|
double h = vAxis->coordToPixel(vRange.upper, SRC::Render) - y;
|
|
Range &&hAxisRange = hAxis->coordRange(), &&vAxisRange = vAxis->coordRange();
|
|
double hr = ((hAxisRange.lower < hAxisRange.upper) ^ (hRange.lower < hRange.upper)) ? -1 : 1;
|
|
double vr = ((vAxisRange.lower < vAxisRange.upper) ^ (vRange.lower < vRange.upper)) ? -1 : 1;
|
|
|
|
painter->save();
|
|
painter->scale(hr, vr);
|
|
painter->drawImage(QRectF(hr * x, vr * y, hr * w, vr * h), image);
|
|
painter->restore();
|
|
|
|
if(q()->hoverOK(q())) {
|
|
q()->drawHover(painter, s->frequentAxis, s->timeAxis);
|
|
}
|
|
}
|
|
};
|
|
|
|
}
|