Files
Renderive/YSGraphic_Core/plottable/WaterFall_p.h
T
2026-06-16 13:33:27 +08:00

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);
}
}
};
}