288 lines
11 KiB
C++
288 lines
11 KiB
C++
#include "Spectrum_p.h"
|
|
|
|
|
|
|
|
namespace YSG {
|
|
Q_Ptr_cpp(Spectrum)
|
|
PROP_P(Spectrum, FrequentAxis*, frequentAxis)
|
|
PROP_P(Spectrum, Axis*, powerAxis);
|
|
PROP_G(Spectrum, int, frequentPointSize);
|
|
PROP_G(Spectrum, Range, frequentRange);
|
|
PROP_P(Spectrum, double, middleSweepFrequent);
|
|
PROP_P(Spectrum, Range, sweepFrequentRange);
|
|
PROP_P(Spectrum, bool, useMaxLine);
|
|
PROP_P(Spectrum, bool, useMinLine);
|
|
PROP_P(Spectrum, bool, useMaxMarker);
|
|
PROP_P(Spectrum, bool, useMinMarker);
|
|
PROP_P(Spectrum, bool, useSweepFrequentRect);
|
|
PROP_P(Spectrum, QBrush, maxBrush);
|
|
PROP_P(Spectrum, QBrush, curBrush);
|
|
PROP_P(Spectrum, QBrush, minBrush);
|
|
PROP_P(Spectrum, QPen, maxPen);
|
|
PROP_P(Spectrum, QPen, curPen);
|
|
PROP_P(Spectrum, QPen, minPen);
|
|
PROP_P(Spectrum, QPen, selectMarkerPen);
|
|
PROP_P(Spectrum, QPen, markerPen);
|
|
PROP_P(Spectrum, QPen, middleFrequentPen);
|
|
PROP_P(Spectrum, QBrush, sweepRectBrush);
|
|
|
|
void Spectrum::set_frequentPointSize(int frequentPointSize) {
|
|
INIT_SET(Spectrum)
|
|
sc->frequentPointSize = frequentPointSize;
|
|
}
|
|
|
|
void Spectrum::set_frequentRange(Range frequentRange){
|
|
INIT_SET(Spectrum)
|
|
sc->frequentRange = frequentRange;
|
|
}
|
|
|
|
|
|
Spectrum::Builder::Builder(FrequentAxis* frequentAxis, Axis* powerAxis) {
|
|
ASSERT(frequentAxis->mPlot != nullptr, "Afterglow build error! frequentAxis->mPlot == nullptr");
|
|
ASSERT(frequentAxis->mPlot == powerAxis->mPlot, "Afterglow build error! frequentAxis->mPlot != powerAxis->mPlot");
|
|
plot = frequentAxis->mPlot;
|
|
this->frequentAxis = frequentAxis;
|
|
this->powerAxis = powerAxis;
|
|
}
|
|
Spectrum* Spectrum::Builder::build() {
|
|
auto ret = new Spectrum;
|
|
ret->init(plot, layerName);
|
|
SpectrumPrivate* pd = ret->d();
|
|
SpectrumRenderState* sc = reinterpret_cast<SpectrumRenderState*>(pd->state(State_Edit));
|
|
PROP_R(FrequentAxis*, frequentAxis)
|
|
PROP_R(Axis*, powerAxis);
|
|
PROP_R(int, frequentPointSize);
|
|
PROP_R(Range, frequentRange);
|
|
PROP_R(double, middleSweepFrequent);
|
|
PROP_R(Range, sweepFrequentRange);
|
|
PROP_R(bool, useMaxLine);
|
|
PROP_R(bool, useMinLine);
|
|
PROP_R(bool, useMaxMarker);
|
|
PROP_R(bool, useMinMarker);
|
|
PROP_R(bool, useSweepFrequentRect);
|
|
PROP_R(QBrush, maxBrush);
|
|
PROP_R(QBrush, curBrush);
|
|
PROP_R(QBrush, minBrush);
|
|
PROP_R(QPen, maxPen);
|
|
PROP_R(QPen, curPen);
|
|
PROP_R(QPen, minPen);
|
|
PROP_R(QPen, selectMarkerPen);
|
|
PROP_R(QPen, markerPen);
|
|
PROP_R(QPen, middleFrequentPen);
|
|
PROP_R(QBrush, sweepRectBrush);
|
|
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) {
|
|
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;
|
|
if(shower) {
|
|
shower->setPerformanceLine("mFrequentPointSize", PerformanceLine(QString("mFrequentPointSize:%1").arg(s->frequentPointSize)));
|
|
}
|
|
drawSpectrum(painter, s);
|
|
if(q()->hoverOK(q())) {
|
|
q()->drawHover(painter, s->frequentAxis, s->powerAxis);
|
|
}
|
|
}
|
|
|
|
|
|
void Spectrum::giveData(const QVector<double> &lineData){
|
|
if(!ok()) return;
|
|
SpectrumPrivate* pd = d();
|
|
Triple_Buffer_Lease stateLease = pd->mStateControl.wait_mark_use_role(State_Edit);
|
|
SpectrumRenderState* sc = reinterpret_cast<SpectrumRenderState*>(pd->stateByIndex(stateLease.index));
|
|
int frequentPointSize = sc->frequentPointSize;
|
|
pd->mStateControl.unmark_use(stateLease);
|
|
if(lineData.size() != frequentPointSize) {
|
|
qDebug() << "setFrenquentData 数据大小不对 " << lineData.size() << " mFrequentPointSize == " << frequentPointSize;
|
|
return;
|
|
}
|
|
Triple_Buffer_Lease inputLease = pd->mInputControl.wait_mark_use_role(Input_Edit);
|
|
RenderInputGuard _inputGuard(pd, inputLease);
|
|
auto input = reinterpret_cast<SpectrumInputData*>(pd->inputDataByIndex(inputLease.index));
|
|
input->mDataList.push_back(lineData);
|
|
}
|
|
|
|
void Spectrum::addCustomMarker(double frequent){
|
|
INIT_SET(Spectrum)
|
|
sc->markerList.append(Marker{frequent, false});
|
|
}
|
|
|
|
void Spectrum::addCustomLineMarker(double frequent){
|
|
INIT_SET(Spectrum)
|
|
sc->markerList.append(Marker{frequent, true});
|
|
}
|
|
|
|
void Spectrum::removeCustomMarker(double frequent){
|
|
INIT_SET(Spectrum)
|
|
for (Marker &marker: sc->markerList) {
|
|
if (qFuzzyCompare(marker.frequent, frequent)) {
|
|
sc->markerList.removeOne(marker);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Spectrum::removeCurrentMarker(SRC src) {
|
|
INIT_SET(Spectrum)
|
|
sc->markerList.removeAt(sc->curSelectIndex);
|
|
}
|
|
|
|
void Spectrum::clearAllCustomMarker(SRC src) {
|
|
INIT_SET(Spectrum)
|
|
sc->markerList.clear();
|
|
}
|
|
|
|
double Spectrum::getMarkFrequent(int markIndex, SRC src) {
|
|
INIT_GET(Spectrum)
|
|
if (markIndex < 0 || markIndex >= renderState->markerList.size())
|
|
return -1;
|
|
return renderState->markerList[markIndex].frequent;
|
|
}
|
|
|
|
void Spectrum::setMarkerFrequent(int markerIndex, double frequent) {
|
|
INIT_SET(Spectrum)
|
|
QVector<Marker> &markers = sc->markerList;
|
|
if (markerIndex < 0 || markerIndex >= markers.size())
|
|
return;
|
|
markers[markerIndex].frequent = frequent;
|
|
}
|
|
|
|
void Spectrum::setCurrentMarkerFrequent(double frequent) {
|
|
INIT_SET(Spectrum)
|
|
sc->setCurFrequent(frequent);
|
|
}
|
|
|
|
int Spectrum::selectLineMarkerSize(SRC src) {
|
|
INIT_GET(Spectrum)
|
|
return renderState->markerList.size();
|
|
}
|
|
|
|
int Spectrum::curSelectMarkerIndex(SRC src) {
|
|
INIT_GET(Spectrum)
|
|
return renderState->curSelectIndex;
|
|
}
|
|
|
|
void Spectrum::setSelectedLineMarker(int markerIndex){
|
|
INIT_SET(Spectrum)
|
|
sc->setSelectIndex(markerIndex);
|
|
}
|
|
|
|
void Spectrum::selectNext(SRC src) {
|
|
INIT_SET(Spectrum)
|
|
sc->selectNextMarker();
|
|
}
|
|
|
|
void Spectrum::selectPrevious(SRC src) {
|
|
INIT_SET(Spectrum)
|
|
sc->selectPrevMarker();
|
|
}
|
|
|
|
void Spectrum::unSelectMarker(SRC src) {
|
|
INIT_SET(Spectrum)
|
|
sc->unSelect();
|
|
}
|
|
|
|
double Spectrum::getPower(double frequent, bool& ok, SRC src) {
|
|
Q_UNUSED(src)
|
|
return d()->getY(frequent, ok);
|
|
}
|
|
|
|
}
|