#include "tracepolarchart.h" #include "ui_polarchartdialog.h" #include "preferences.h" #include "unit.h" #include "appwindow.h" #include #include using namespace std; TracePolarChart::TracePolarChart(TraceModel &model, QWidget *parent) : TracePolar(model, parent) { } void TracePolarChart::axisSetupDialog() { auto dialog = new QDialog(); auto ui = new Ui::PolarChartDialog(); ui->setupUi(dialog); if(limitToSpan) { ui->displayModeFreq->setCurrentIndex(1); } else { ui->displayModeFreq->setCurrentIndex(0); } if(limitToEdge) { ui->displayModeRefl->setCurrentIndex(1); } else { ui->displayModeRefl->setCurrentIndex(0); } ui->displayStartFreq->setUnit("Hz"); ui->displayStartFreq->setPrefixes(" kMG"); ui->displayStartFreq->setPrecision(6); ui->displayStartFreq->setValue(fmin); ui->displayStopFreq->setUnit("Hz"); ui->displayStopFreq->setPrefixes(" kMG"); ui->displayStopFreq->setPrecision(6); ui->displayStopFreq->setValue(fmax); connect(ui->displayFreqOverride, &QCheckBox::toggled, [=](bool active){ ui->displayModeFreq->setEnabled(!active); ui->displayStartFreq->setEnabled(active); ui->displayStopFreq->setEnabled(active); }); ui->displayFreqOverride->setChecked(manualFrequencyRange); emit ui->displayFreqOverride->toggled(manualFrequencyRange); ui->zoomFactor->setPrecision(3); ui->offsetXaxis->setPrecision(3); ui->offsetYaxis->setPrecision(3); ui->zoomFactor->setValue(1.0/edgeReflection); ui->offsetXaxis->setValue(offset.x()); ui->offsetYaxis->setValue(offset.y()); connect(ui->buttonBox, &QDialogButtonBox::accepted, [=](){ limitToSpan = ui->displayModeFreq->currentIndex() == 1; limitToEdge = ui->displayModeRefl->currentIndex() == 1; manualFrequencyRange = ui->displayFreqOverride->isChecked(); fmin = ui->displayStartFreq->value(); fmax = ui->displayStopFreq->value(); triggerReplot(); }); connect(ui->zoomFactor, &SIUnitEdit::valueChanged, [=](){ edgeReflection = 1.0 / ui->zoomFactor->value(); }); connect(ui->offsetXaxis, &SIUnitEdit::valueChanged, [=](){ offset = QPointF(ui->offsetXaxis->value(), offset.y()); }); connect(ui->offsetXaxis, &SIUnitEdit::valueChanged, [=](){ offset = QPointF(offset.x(), ui->offsetXaxis->value()); }); if(AppWindow::showGUI()) { dialog->show(); } } void TracePolarChart::draw(QPainter &p) { auto& pref = Preferences::getInstance(); p.setRenderHint(QPainter::Antialiasing); auto w = p.window(); p.save(); p.translate(w.width()/2, w.height()/2); auto scale = qMin(w.height(), w.width()) / (2.0 * polarCoordMax); p.scale(scale, scale); transform = p.transform(); p.restore(); auto drawArc = [&](PolarArc a) { a.constrainToCircle(QPointF(0,0), edgeReflection); auto topleft = dataToPixel(complex(a.center.x() - a.radius, a.center.y() - a.radius)); auto bottomright = dataToPixel(complex(a.center.x() + a.radius, a.center.y() + a.radius)); a.startAngle *= 5760 / (2*M_PI); a.spanAngle *= 5760 / (2*M_PI); p.drawArc(QRect(topleft, bottomright), a.startAngle, a.spanAngle); }; // Outer circle auto pen = QPen(pref.Graphs.Color.axis); pen.setCosmetic(true); p.setPen(pen); drawArc(PolarArc(QPointF(0.0, 0.0), edgeReflection, 0, 2*M_PI)); constexpr int Circles = 6; pen = QPen(pref.Graphs.Color.Ticks.divisions, 0.5, Qt::DashLine); pen.setCosmetic(true); p.setPen(pen); for(int i=1;iisVisible()) { // trace marked invisible continue; } pen = QPen(trace->color(), pref.Graphs.lineWidth); pen.setCosmetic(true); p.setPen(pen); int nPoints = trace->size(); for(int i=1;isample(i-1); auto now = trace->sample(i); if ((trace->getDataType() == Trace::DataType::Frequency) && (last.x < minimumVisibleFrequency() || now.x > maximumVisibleFrequency())) { continue; } if(isnan(now.y.real())) { break; } if(pref.Graphs.SweepIndicator.hide && !isnan(xSweep) && trace->getSource() == Trace::Source::Live && trace->isVisible() && !trace->isPaused()) { // check if this part of the trace is visible double range = maximumVisibleFrequency() - minimumVisibleFrequency(); double afterSweep = now.x - xSweep; if(afterSweep > 0 && afterSweep * 100 / range <= pref.Graphs.SweepIndicator.hidePercent) { // do not display this part of the trace continue; } } last = dataAddOffset(last); now = dataAddOffset(now); // scale to size of smith diagram QPointF p1 = dataToPixel(last); QPointF p2 = dataToPixel(now); if(limitToEdge && (abs(last.y) > edgeReflection || abs(now.y) > edgeReflection)) { // partially outside of visible area, constrain if(!TracePolar::constrainLineToCircle(p1, p2, transform.map(QPointF(0,0)), polarCoordMax * scale)) { // completely out of visible area continue; } } // draw line p.drawLine(p1, p2); } if(trace->size() > 0) { // only draw markers if the trace has at least one point auto markers = t.first->getMarkers(); for(auto m : markers) { if(!m->isVisible()) { continue; } if (m->getPosition() < minimumVisibleFrequency() || m->getPosition() > maximumVisibleFrequency()) { continue; } if(m->getPosition() < trace->minX() || m->getPosition() > trace->maxX()) { // marker not in trace range continue; } auto coords = m->getData(); coords = dataAddOffset(coords); if (limitToEdge && abs(coords) > edgeReflection) { // outside of visible area continue; } auto point = dataToPixel(coords); auto symbol = m->getSymbol(); p.drawPixmap(point.x() - symbol.width()/2, point.y() - symbol.height(), symbol); } } } if(dropPending) { // adjust coords due to shifted restore p.setOpacity(0.5); p.setBrush(Qt::white); p.setPen(Qt::white); p.drawEllipse(-polarCoordMax, -polarCoordMax, 2*polarCoordMax, 2*polarCoordMax); auto font = p.font(); font.setPixelSize(20); p.setFont(font); p.setOpacity(1.0); p.setPen(Qt::white); auto text = "Drop here to add\n" + dropTrace->name() + "\nto polar chart"; p.drawText(p.window(), Qt::AlignCenter, text); } else { } } bool TracePolarChart::dropSupported(Trace *t) { switch(t->outputType()) { case Trace::DataType::Frequency: return true; default: return false; } } bool TracePolarChart::supported(Trace *t) { return dropSupported(t); } QString TracePolarChart::mouseText(QPoint pos) { auto dataDx = pixelToData(pos); if(abs(dataDx) <= edgeReflection) { auto data = complex(dataDx.real()-offset.x(), dataDx.imag()-offset.y()); auto ret = Unit::ToString(abs(data), "", " ", 3); ret += QString("∠"); auto phase = atan(data.imag()/data.real())*180/M_PI; if (data.imag() > 0 && data.real() < 0) { phase += 180; } else if (data.imag() < 0 && data.real() < 0 ) { phase += 180; } else if (data.imag() < 0 && data.real() > 0) { phase += 360; } ret += Unit::ToString(phase, "", " ", 3); return ret; } else { return QString(); } }