#pragma once #include #include #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 mFrequent; }; struct WaterFallTempData : TempData { std::list 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& 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(); QVector& 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(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); } } }; }