diff --git a/Software/PC_Application/LibreVNA-GUI/Traces/polarchartdialog.ui b/Software/PC_Application/LibreVNA-GUI/Traces/polarchartdialog.ui index 97fcf2c..5331957 100644 --- a/Software/PC_Application/LibreVNA-GUI/Traces/polarchartdialog.ui +++ b/Software/PC_Application/LibreVNA-GUI/Traces/polarchartdialog.ui @@ -124,24 +124,24 @@ - + - <html><head/><body><p>|Γ| at edge:</p></body></html> + Offset X axis: - + - + - Offset real axis: + Offset Y axis: - + diff --git a/Software/PC_Application/LibreVNA-GUI/Traces/smithchartdialog.ui b/Software/PC_Application/LibreVNA-GUI/Traces/smithchartdialog.ui index 88c5a31..57926c7 100644 --- a/Software/PC_Application/LibreVNA-GUI/Traces/smithchartdialog.ui +++ b/Software/PC_Application/LibreVNA-GUI/Traces/smithchartdialog.ui @@ -6,8 +6,8 @@ 0 0 - 976 - 460 + 974 + 491 @@ -155,13 +155,23 @@ - Offset real axis + Offset real axis: + + + + Offset imag axis: + + + + + + diff --git a/Software/PC_Application/LibreVNA-GUI/Traces/tracepolar.cpp b/Software/PC_Application/LibreVNA-GUI/Traces/tracepolar.cpp index 7de48ea..05a49b7 100644 --- a/Software/PC_Application/LibreVNA-GUI/Traces/tracepolar.cpp +++ b/Software/PC_Application/LibreVNA-GUI/Traces/tracepolar.cpp @@ -16,7 +16,7 @@ TracePolar::TracePolar(TraceModel &model, QWidget *parent) fmin = 0; fmax = 6000000000; edgeReflection = 1.0; - dx = 0; + offset = QPointF(0.0, 0.0); initializeTraceInfo(); } @@ -26,7 +26,8 @@ nlohmann::json TracePolar::toJSON() j["limit_to_span"] = limitToSpan; j["limit_to_edge"] = limitToEdge; j["edge_reflection"] = edgeReflection; - j["offset_axis_x"] = dx; + j["offset_axis_x"] = offset.x(); + j["offset_axis_y"] = offset.y(); j["frequency_override"] = manualFrequencyRange; j["override_min"] = fmin; j["override_max"] = fmax; @@ -48,7 +49,7 @@ void TracePolar::fromJSON(nlohmann::json j) manualFrequencyRange = j.value("frequency_override", false); fmin = j.value("override_min", 0.0); fmax = j.value("override_max", 6000000000.0); - dx = j.value("offset_axis_x", 0.0); + offset = QPointF(j.value("offset_axis_x", 0.0), j.value("offset_axis_y", 0.0)); for(unsigned int hash : j["traces"]) { // attempt to find the traces with this hash bool found = false; @@ -65,21 +66,59 @@ void TracePolar::fromJSON(nlohmann::json j) } } -void TracePolar::wheelEvent(QWheelEvent *event) +void TracePolar::move(const QPoint &vect) { - // most mousewheel have 15 degree increments, the reported delta is in 1/8th degree -> 120 - auto increment = event->angleDelta().y() / 120.0; - // round toward bigger step in case of special higher resolution mousewheel - int steps = increment > 0 ? ceil(increment) : floor(increment); + Trace::Data center; + center.y = 0.0; + center.x = 0.0; + auto shift = pixelToData(dataToPixel(center) + vect); + offset.rx() += shift.real(); + offset.ry() += shift.imag(); + replot(); +} - constexpr double zoomfactor = 1.1; - auto zoom = pow(zoomfactor, steps); - edgeReflection /= zoom; +void TracePolar::zoom(const QPoint ¢er, double factor, bool horizontally, bool vertically) +{ + Q_UNUSED(horizontally); + Q_UNUSED(vertically); + auto pos = pixelToData(center); + auto shift = QPointF(pos.real(), pos.imag()); + offset -= shift; + edgeReflection *= factor; + offset += shift * factor; + replot(); +} - auto incrementX = event->angleDelta().x() / 120.0; - dx += incrementX/10; +void TracePolar::setAuto(bool horizontally, bool vertically) +{ + Q_UNUSED(horizontally); + Q_UNUSED(vertically); + edgeReflection = 1.0; + offset = QPointF(0.0, 0.0); + replot(); +} - triggerReplot(); +//void TracePolar::wheelEvent(QWheelEvent *event) +//{ +// // most mousewheel have 15 degree increments, the reported delta is in 1/8th degree -> 120 +// auto increment = event->angleDelta().y() / 120.0; +// // round toward bigger step in case of special higher resolution mousewheel +// int steps = increment > 0 ? ceil(increment) : floor(increment); + +// constexpr double zoomfactor = 1.1; +// auto zoom = pow(zoomfactor, steps); +// edgeReflection /= zoom; + +// auto incrementX = event->angleDelta().x() / 120.0; +//// dx += incrementX/10; + +// triggerReplot(); +//} + +bool TracePolar::positionWithinGraphArea(const QPoint &p) +{ + // TODO + return true; } QPoint TracePolar::dataToPixel(std::complex d) @@ -92,19 +131,24 @@ QPoint TracePolar:: dataToPixel(Trace::Data d) return dataToPixel(d.y); } -std::complex TracePolar::dataAddDx(std::complex d) +std::complex TracePolar::dataAddOffset(std::complex d) { - auto dataShift = complex(dx, 0); + auto dataShift = complex(offset.x(), offset.y()); d = d + dataShift; return d; } -Trace::Data TracePolar::dataAddDx(Trace::Data d) +Trace::Data TracePolar::dataAddOffset(Trace::Data d) { - d.y = dataAddDx(d.y); + d.y = dataAddOffset(d.y); return d; } +QPoint TracePolar::dataToPixel(QPointF d) +{ + return dataToPixel(complex(d.x(), d.y())); +} + std::complex TracePolar::pixelToData(QPoint p) { auto data = transform.inverted().map(QPointF(p)); @@ -117,7 +161,7 @@ QPoint TracePolar::markerToPixel(Marker *m) // if(!m->isTimeDomain()) { if(m->getPosition() >= sweep_fmin && m->getPosition() <= sweep_fmax) { auto d = m->getData(); - d = dataAddDx(d); + d = dataAddOffset(d); ret = dataToPixel(d); } // } @@ -132,7 +176,7 @@ double TracePolar::nearestTracePoint(Trace *t, QPoint pixel, double *distance) auto samples = t->size(); for(unsigned int i=0;isample(i); - data = dataAddDx(data); + data = dataAddOffset(data); auto plotPoint = dataToPixel(data); if (plotPoint.isNull()) { // destination point outside of currently displayed range @@ -149,8 +193,8 @@ double TracePolar::nearestTracePoint(Trace *t, QPoint pixel, double *distance) closestDistance = sqrt(closestDistance); if(closestIndex > 0) { - auto l1 = dataToPixel(dataAddDx(t->sample(closestIndex-1))); - auto l2 = dataToPixel(dataAddDx(t->sample(closestIndex))); + auto l1 = dataToPixel(dataAddOffset(t->sample(closestIndex-1))); + auto l2 = dataToPixel(dataAddOffset(t->sample(closestIndex))); double ratio; auto distance = Util::distanceToLine(pixel, l1, l2, nullptr, &ratio); if(distance < closestDistance) { @@ -159,8 +203,8 @@ double TracePolar::nearestTracePoint(Trace *t, QPoint pixel, double *distance) } } if(closestIndex < t->size() - 1) { - auto l1 = dataToPixel(dataAddDx(t->sample(closestIndex))); - auto l2 = dataToPixel(dataAddDx(t->sample(closestIndex+1))); + auto l1 = dataToPixel(dataAddOffset(t->sample(closestIndex))); + auto l2 = dataToPixel(dataAddOffset(t->sample(closestIndex+1))); double ratio; auto distance = Util::distanceToLine(pixel, l1, l2, nullptr, &ratio); if(distance < closestDistance) { diff --git a/Software/PC_Application/LibreVNA-GUI/Traces/tracepolar.h b/Software/PC_Application/LibreVNA-GUI/Traces/tracepolar.h index 563bf2d..c17630d 100644 --- a/Software/PC_Application/LibreVNA-GUI/Traces/tracepolar.h +++ b/Software/PC_Application/LibreVNA-GUI/Traces/tracepolar.h @@ -21,7 +21,11 @@ public: virtual nlohmann::json toJSON() override; // derived classes must call TracePolar::joJSON before doing anything virtual void fromJSON(nlohmann::json j) override; // derived classes must call TracePolar::joJSON before doing anything - void wheelEvent(QWheelEvent *event) override; + virtual void move(const QPoint &vect) override; + virtual void zoom(const QPoint ¢er, double factor, bool horizontally, bool vertically) override; + virtual void setAuto(bool horizontally, bool vertically) override; + +// void wheelEvent(QWheelEvent *event) override; public slots: virtual void axisSetupDialog() {} @@ -29,9 +33,11 @@ public slots: protected: static constexpr double polarCoordMax = 4096; - virtual std::complex dataAddDx(std::complex d); - virtual Trace::Data dataAddDx(Trace::Data d); + virtual bool positionWithinGraphArea(const QPoint &p) override; + virtual std::complex dataAddOffset(std::complex d); + virtual Trace::Data dataAddOffset(Trace::Data d); + QPoint dataToPixel(QPointF d); QPoint dataToPixel(std::complex d); QPoint dataToPixel(Trace::Data d); std::complex pixelToData(QPoint p); @@ -54,7 +60,7 @@ protected: double fmin, fmax; // frequency range when manual range is selected double edgeReflection; // magnitude of reflection coefficient at the edge of the polar chart (zoom factor) - double dx; + QPointF offset; QTransform transform; }; diff --git a/Software/PC_Application/LibreVNA-GUI/Traces/tracepolarchart.cpp b/Software/PC_Application/LibreVNA-GUI/Traces/tracepolarchart.cpp index a0cb9aa..bbc32bb 100644 --- a/Software/PC_Application/LibreVNA-GUI/Traces/tracepolarchart.cpp +++ b/Software/PC_Application/LibreVNA-GUI/Traces/tracepolarchart.cpp @@ -48,12 +48,12 @@ void TracePolarChart::axisSetupDialog() ui->displayFreqOverride->setChecked(manualFrequencyRange); emit ui->displayFreqOverride->toggled(manualFrequencyRange); - ui->zoomReflection->setPrecision(3); ui->zoomFactor->setPrecision(3); - ui->offsetRealAxis->setPrecision(3); - ui->zoomReflection->setValue(edgeReflection); + ui->offsetXaxis->setPrecision(3); + ui->offsetYaxis->setPrecision(3); ui->zoomFactor->setValue(1.0/edgeReflection); - ui->offsetRealAxis->setValue(dx); + ui->offsetXaxis->setValue(offset.x()); + ui->offsetYaxis->setValue(offset.y()); connect(ui->buttonBox, &QDialogButtonBox::accepted, [=](){ limitToSpan = ui->displayModeFreq->currentIndex() == 1; @@ -65,14 +65,12 @@ void TracePolarChart::axisSetupDialog() }); connect(ui->zoomFactor, &SIUnitEdit::valueChanged, [=](){ edgeReflection = 1.0 / ui->zoomFactor->value(); - ui->zoomReflection->setValueQuiet(edgeReflection); }); - connect(ui->zoomReflection, &SIUnitEdit::valueChanged, [=](){ - edgeReflection = ui->zoomReflection->value(); - ui->zoomFactor->setValueQuiet(1.0 / edgeReflection); + connect(ui->offsetXaxis, &SIUnitEdit::valueChanged, [=](){ + offset = QPointF(ui->offsetXaxis->value(), offset.y()); }); - connect(ui->offsetRealAxis, &SIUnitEdit::valueChanged, [=](){ - dx = ui->offsetRealAxis->value(); + connect(ui->offsetXaxis, &SIUnitEdit::valueChanged, [=](){ + offset = QPointF(offset.x(), ui->offsetXaxis->value()); }); if(AppWindow::showGUI()) { dialog->show(); @@ -123,20 +121,20 @@ void TracePolarChart::draw(QPainter &p) { p.setPen(pen); for(int i=1;i(dx, cir.center.y() + cir.radius*sin(angle)); - auto p2 = complex(dx, cir.center.y() - cir.radius*sin(angle)); + if ( (cir.spanAngle == 90 )&& (offset == QPointF(0.0, 0.0))) { + auto angle = acos(offset.x() / cir.radius); + auto p1 = complex(offset.x(), cir.center.y() + cir.radius*sin(angle)); + auto p2 = complex(offset.x(), cir.center.y() - cir.radius*sin(angle)); p.drawLine(dataToPixel(p1),dataToPixel(p2)); } else { auto slope = tan(cir.spanAngle*2*M_PI/360); auto y0 = cir.center.y(); - auto f = dx; + auto f = offset.x(); auto a = 1 + (slope*slope); auto b = (-2*cir.center.x())-(2*f*slope*slope)+(2*slope*y0)-(2*cir.center.y()*slope); auto c = (cir.center.x()*cir.center.x()) +(cir.center.y()*cir.center.y()) - (cir.radius*cir.radius) + (y0*y0) \ @@ -157,8 +155,15 @@ void TracePolarChart::draw(QPainter &p) { constexpr int Lines = 6; for(int i=0;igetData(); - coords = dataAddDx(coords); + coords = dataAddOffset(coords); if (limitToEdge && abs(coords) > edgeReflection) { // outside of visible area @@ -278,7 +283,7 @@ QString TracePolarChart::mouseText(QPoint pos) { auto dataDx = pixelToData(pos); if(abs(dataDx) <= edgeReflection) { - auto data = complex(dataDx.real()-dx, dataDx.imag()); + 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; diff --git a/Software/PC_Application/LibreVNA-GUI/Traces/tracesmithchart.cpp b/Software/PC_Application/LibreVNA-GUI/Traces/tracesmithchart.cpp index 53f6908..592f9d2 100644 --- a/Software/PC_Application/LibreVNA-GUI/Traces/tracesmithchart.cpp +++ b/Software/PC_Application/LibreVNA-GUI/Traces/tracesmithchart.cpp @@ -84,7 +84,10 @@ void TraceSmithChart::axisSetupDialog() ui->zoomFactor->setPrecision(3); ui->zoomReflection->setValue(edgeReflection); ui->zoomFactor->setValue(1.0/edgeReflection); - ui->offsetRealAxis->setValue(dx); + ui->offsetRealAxis->setPrecision(4); + ui->offsetRealAxis->setValue(offset.x()); + ui->offsetImagAxis->setPrecision(4); + ui->offsetImagAxis->setValue(offset.y()); ui->impedance->setUnit("Ω"); ui->impedance->setPrecision(3); @@ -113,7 +116,10 @@ void TraceSmithChart::axisSetupDialog() ui->zoomFactor->setValueQuiet(1.0 / edgeReflection); }); connect(ui->offsetRealAxis, &SIUnitEdit::valueChanged, [=](){ - dx = ui->offsetRealAxis->value(); + offset = QPointF(ui->offsetRealAxis->value(), offset.y()); + }); + connect(ui->offsetImagAxis, &SIUnitEdit::valueChanged, [=](){ + offset = QPointF(offset.x(), ui->offsetRealAxis->value()); }); connect(ui->impedance, &SIUnitEdit::valueChanged, [=](){ Z0 = ui->impedance->value(); @@ -232,17 +238,22 @@ void TraceSmithChart::draw(QPainter &p) { p.setPen(pen); for(int i=1;i(edgeReflection,0)),dataToPixel(complex(-edgeReflection,0))); + QPointF p1 = QPointF(-100, offset.y()); + QPointF p2 = QPointF(100, offset.y()); + if(TracePolar::constrainLineToCircle(p1, p2, QPointF(0,0), edgeReflection)) { + // center line visible + p.drawLine(dataToPixel(p1),dataToPixel(p2)); + } constexpr std::array impedanceLines = {10, 25, 50, 100, 250}; for(auto z : impedanceLines) { z /= Z0; auto radius = 1.0/z; - drawArc(SmithChartArc(QPointF(1.0+dx, radius), radius, 0, 2*M_PI)); - drawArc(SmithChartArc(QPointF(1.0+dx, -radius), radius, 0, 2*M_PI)); + drawArc(SmithChartArc(QPointF(1.0+offset.x(), radius+offset.y()), radius, 0, 2*M_PI)); + drawArc(SmithChartArc(QPointF(1.0+offset.x(), -radius+offset.y()), radius, 0, 2*M_PI)); } // draw custom constant parameter lines @@ -251,6 +262,7 @@ void TraceSmithChart::draw(QPainter &p) { pen.setCosmetic(true); p.setPen(pen); for(auto arc : line.getArcs(Z0)) { + arc.center += offset; drawArc(arc); } } @@ -289,8 +301,8 @@ void TraceSmithChart::draw(QPainter &p) { } } - last = dataAddDx(last); - now = dataAddDx(now); + last = dataAddOffset(last); + now = dataAddOffset(now); // scale to size of smith diagram QPointF p1 = dataToPixel(last); @@ -325,7 +337,7 @@ void TraceSmithChart::draw(QPainter &p) { continue; } auto coords = m->getData(); - coords = dataAddDx(coords); + coords = dataAddOffset(coords); if (limitToEdge && abs(coords) > edgeReflection) { // outside of visible area @@ -388,7 +400,7 @@ QString TraceSmithChart::mouseText(QPoint pos) { auto dataDx = pixelToData(pos); if(abs(dataDx) <= edgeReflection) { - auto data = complex(dataDx.real()-dx, dataDx.imag()); + auto data = complex(dataDx.real()-offset.x(), dataDx.imag()-offset.y()); data = Z0 * (1.0 + data) / (1.0 - data); auto ret = Unit::ToString(data.real(), "", " ", 3); if(data.imag() >= 0) { diff --git a/Software/PC_Application/LibreVNA-GUI/Traces/tracewaterfall.cpp b/Software/PC_Application/LibreVNA-GUI/Traces/tracewaterfall.cpp index b8e94c8..3738402 100644 --- a/Software/PC_Application/LibreVNA-GUI/Traces/tracewaterfall.cpp +++ b/Software/PC_Application/LibreVNA-GUI/Traces/tracewaterfall.cpp @@ -61,6 +61,38 @@ void TraceWaterfall::replot() TracePlot::replot(); } +//void TraceWaterfall::move(const QPoint &vect) +//{ +// if(!xAxis.getLog()) { +// // can only move axis in linear mode +// // calculate amount of movement +// double distance = xAxis.inverseTransform(vect.x(), 0, plotAreaWidth) - xAxis.getRangeMin(); +// xAxis.set(xAxis.getType(), false, false, xAxis.getRangeMin() - distance, xAxis.getRangeMax() - distance, xAxis.getRangeDiv()); +// } +// replot(); +//} + +//void TraceWaterfall::zoom(const QPoint ¢er, double factor, bool horizontally, bool vertically) +//{ +// if(horizontally && !xAxis.getLog()) { +// // can only zoom axis in linear mode +// // calculate center point +// double cp = xAxis.inverseTransform(center.x(), plotAreaLeft, plotAreaLeft + plotAreaWidth); +// double min = ((xAxis.getRangeMin() - cp) * factor) + cp; +// double max = ((xAxis.getRangeMax() - cp) * factor) + cp; +// xAxis.set(xAxis.getType(), false, false, min, max, xAxis.getRangeDiv() * factor); +// } +// replot(); +//} + +//void TraceWaterfall::setAuto(bool horizontally, bool vertically) +//{ +// if(horizontally) { +// xAxis.set(xAxis.getType(), xAxis.getLog(), true, xAxis.getRangeMin(), xAxis.getRangeMax(), xAxis.getRangeDiv()); +// } +// replot(); +//} + void TraceWaterfall::fromJSON(nlohmann::json j) { resetWaterfall(); diff --git a/Software/PC_Application/LibreVNA-GUI/Traces/tracewaterfall.h b/Software/PC_Application/LibreVNA-GUI/Traces/tracewaterfall.h index fd750f1..62bd7a5 100644 --- a/Software/PC_Application/LibreVNA-GUI/Traces/tracewaterfall.h +++ b/Software/PC_Application/LibreVNA-GUI/Traces/tracewaterfall.h @@ -17,6 +17,11 @@ public: virtual void enableTrace(Trace *t, bool enabled) override; void replot() override; + +// virtual void move(const QPoint &vect) override; +// virtual void zoom(const QPoint ¢er, double factor, bool horizontally, bool vertically) override; +// virtual void setAuto(bool horizontally, bool vertically) override; + virtual Type getType() override { return Type::Waterfall;} void fromJSON(nlohmann::json j) override; diff --git a/Software/PC_Application/LibreVNA-GUI/preferencesdialog.ui b/Software/PC_Application/LibreVNA-GUI/preferencesdialog.ui index 1881808..0bd9807 100644 --- a/Software/PC_Application/LibreVNA-GUI/preferencesdialog.ui +++ b/Software/PC_Application/LibreVNA-GUI/preferencesdialog.ui @@ -1223,7 +1223,11 @@ - + + + 1 + +