diff --git a/Software/PC_Application/Traces/Marker/marker.cpp b/Software/PC_Application/Traces/Marker/marker.cpp index 122c13b..ecaec13 100644 --- a/Software/PC_Application/Traces/Marker/marker.cpp +++ b/Software/PC_Application/Traces/Marker/marker.cpp @@ -85,8 +85,8 @@ void Marker::assignTrace(Trace *t) // Marker was just created and this is the first assignment to a trace. // Use display format on graph from preferences auto p = Preferences::getInstance(); - if(p.Graphs.markerBehavior.showDataOnGraphs) { - if(p.Graphs.markerBehavior.showAllData) { + if(p.Marker.defaultBehavior.showDataOnGraphs) { + if(p.Marker.defaultBehavior.showAllData) { for(auto f : applicableFormats()) { formatGraph.insert(f); } @@ -598,7 +598,7 @@ void Marker::traceDataChanged() newdata = numeric_limits>::quiet_NaN(); } else { // some data of the parent trace changed, check if marker data also changed - newdata = parentTrace->sample(parentTrace->index(position)).y; + newdata = parentTrace->interpolatedSample(position).y; } } if (newdata != data) { @@ -839,8 +839,10 @@ void Marker::constrainPosition() } else if(position < parentTrace->minX()) { position = parentTrace->minX(); } - // set position to closest trace index - position = parentTrace->sample(parentTrace->index(position)).x; + if(!Preferences::getInstance().Marker.interpolatePoints) { + // marker interpolation disabled, set position to closest trace index + position = parentTrace->sample(parentTrace->index(position)).x; + } } traceDataChanged(); } diff --git a/Software/PC_Application/Traces/tracesmithchart.cpp b/Software/PC_Application/Traces/tracesmithchart.cpp index 7a3117c..c16b989 100644 --- a/Software/PC_Application/Traces/tracesmithchart.cpp +++ b/Software/PC_Application/Traces/tracesmithchart.cpp @@ -5,6 +5,7 @@ #include "ui_smithchartdialog.h" #include "unit.h" #include "QFileDialog" +#include "Util/util.h" #include #include @@ -141,6 +142,7 @@ double TraceSmithChart::nearestTracePoint(Trace *t, QPoint pixel, double *distan { double closestDistance = numeric_limits::max(); double closestXpos = 0; + unsigned int closestIndex = 0; auto samples = t->size(); for(unsigned int i=0;isample(i); @@ -154,6 +156,28 @@ double TraceSmithChart::nearestTracePoint(Trace *t, QPoint pixel, double *distan if(distance < closestDistance) { closestDistance = distance; closestXpos = t->sample(i).x; + closestIndex = i; + } + } + closestDistance = sqrt(closestDistance); + if(closestIndex > 0) { + auto l1 = dataToPixel(t->sample(closestIndex-1)); + auto l2 = dataToPixel(t->sample(closestIndex)); + double ratio; + auto distance = Util::distanceToLine(pixel, l1, l2, nullptr, &ratio); + if(distance < closestDistance) { + closestDistance = distance; + closestXpos = t->sample(closestIndex-1).x + (t->sample(closestIndex).x - t->sample(closestIndex-1).x) * ratio; + } + } + if(closestIndex < t->size() - 1) { + auto l1 = dataToPixel(t->sample(closestIndex)); + auto l2 = dataToPixel(t->sample(closestIndex+1)); + double ratio; + auto distance = Util::distanceToLine(pixel, l1, l2, nullptr, &ratio); + if(distance < closestDistance) { + closestDistance = distance; + closestXpos = t->sample(closestIndex).x + (t->sample(closestIndex+1).x - t->sample(closestIndex).x) * ratio; } } if(distance) { diff --git a/Software/PC_Application/Traces/tracexyplot.cpp b/Software/PC_Application/Traces/tracexyplot.cpp index 7d75e06..84f6e3d 100644 --- a/Software/PC_Application/Traces/tracexyplot.cpp +++ b/Software/PC_Application/Traces/tracexyplot.cpp @@ -491,7 +491,17 @@ void TraceXYPlot::draw(QPainter &p) continue; } auto t = m->getTrace(); - QPointF markerPoint = traceToCoordinate(t, t->index(xPosition), YAxis[i].type); + auto index = t->index(xPosition); + QPointF markerPoint; + if(xPosition < t->sample(index).x && index > 0) { + // marker is not located exactly at this point, interpolate display location + QPointF l0 = traceToCoordinate(t, index - 1, YAxis[i].type); + QPointF l1 = traceToCoordinate(t, index, YAxis[i].type); + auto t0 = (xPosition - t->sample(index - 1).x) / (t->sample(index).x - t->sample(index - 1).x); + markerPoint = l0 + (l1 - l0) * t0; + } else { + markerPoint = traceToCoordinate(t, t->index(xPosition), YAxis[i].type); + } auto point = plotValueToPixel(markerPoint, i); if(!plotRect.contains(point)) { // out of screen @@ -1096,6 +1106,7 @@ double TraceXYPlot::nearestTracePoint(Trace *t, QPoint pixel, double *distance) } double closestDistance = numeric_limits::max(); double closestXpos = 0; + unsigned int closestIndex = 0; auto samples = t->size(); for(unsigned int i=0;i 0) { + auto l1 = plotValueToPixel(traceToCoordinate(t, closestIndex - 1, YAxis[0].type), 0); + auto l2 = plotValueToPixel(traceToCoordinate(t, closestIndex, YAxis[0].type), 0); + double ratio; + auto distance = Util::distanceToLine(pixel, l1, l2, nullptr, &ratio); + if(distance < closestDistance) { + closestDistance = distance; + closestXpos = t->sample(closestIndex-1).x + (t->sample(closestIndex).x - t->sample(closestIndex-1).x) * ratio; + } + } + if(closestIndex < t->size() - 1) { + auto l1 = plotValueToPixel(traceToCoordinate(t, closestIndex, YAxis[0].type), 0); + auto l2 = plotValueToPixel(traceToCoordinate(t, closestIndex + 1, YAxis[0].type), 0); + double ratio; + auto distance = Util::distanceToLine(pixel, l1, l2, nullptr, &ratio); + if(distance < closestDistance) { + closestDistance = distance; + closestXpos = t->sample(closestIndex).x + (t->sample(closestIndex+1).x - t->sample(closestIndex).x) * ratio; } } if(XAxis.type == XAxisType::Distance) { diff --git a/Software/PC_Application/Util/util.cpp b/Software/PC_Application/Util/util.cpp index 90baaef..fe2e2ab 100644 --- a/Software/PC_Application/Util/util.cpp +++ b/Software/PC_Application/Util/util.cpp @@ -1,5 +1,7 @@ #include "util.h" +#include + void Util::unwrapPhase(std::vector &phase) { for (unsigned int i = 1; i < phase.size(); i++) { @@ -24,3 +26,31 @@ void Util::linearRegression(const std::vector &input, double &B_0, doubl B_1 = ss_xy / ss_xx; B_0 = y_mean - B_1 * x_mean; } + +double Util::distanceToLine(QPointF point, QPointF l1, QPointF l2, QPointF *closestLinePoint, double *pointRatio) +{ + auto M = l2 - l1; + auto t0 = QPointF::dotProduct(M, point - l1) / QPointF::dotProduct(M, M); + QPointF closestPoint; + QVector2D orthVect; + if (t0 <= 0) { + orthVect = QVector2D(point - l1); + closestPoint = l1; + t0 = 0; + } else if(t0 >= 1) { + orthVect = QVector2D(point - l2); + closestPoint = l2; + t0 = 1; + } else { + auto intersect = l1 + t0 * M; + orthVect = QVector2D(point - intersect); + closestPoint = intersect; + } + if(closestLinePoint) { + *closestLinePoint = closestPoint; + } + if(pointRatio) { + *pointRatio = t0; + } + return orthVect.length(); +} diff --git a/Software/PC_Application/Util/util.h b/Software/PC_Application/Util/util.h index 806262e..30a61e6 100644 --- a/Software/PC_Application/Util/util.h +++ b/Software/PC_Application/Util/util.h @@ -7,6 +7,7 @@ #include #include +#include namespace Util { template T Scale(T value, T from_low, T from_high, T to_low, T to_high, bool log_from = false, bool log_to = false) { @@ -69,6 +70,8 @@ namespace Util { // input values are Y coordinates, assumes evenly spaced linear X values from 0 to input.size() - 1 void linearRegression(const std::vector &input, double &B_0, double &B_1); + + double distanceToLine(QPointF point, QPointF l1, QPointF l2, QPointF *closestLinePoint = nullptr, double *pointRatio = nullptr); } #endif // UTILH_H diff --git a/Software/PC_Application/preferences.cpp b/Software/PC_Application/preferences.cpp index 4a3e6a2..8b2dcb6 100644 --- a/Software/PC_Application/preferences.cpp +++ b/Software/PC_Application/preferences.cpp @@ -80,8 +80,8 @@ PreferencesDialog::PreferencesDialog(Preferences *pref, QWidget *parent) : ui->SCPIServerEnabled->setEnabled(false); } - connect(ui->GraphsShowMarkerData, &QCheckBox::toggled, [=](bool enabled) { - ui->GraphsShowAllMarkerData->setEnabled(enabled); + connect(ui->MarkerShowMarkerData, &QCheckBox::toggled, [=](bool enabled) { + ui->MarkerShowAllMarkerData->setEnabled(enabled); }); // Page selection @@ -128,6 +128,7 @@ PreferencesDialog::PreferencesDialog(Preferences *pref, QWidget *parent) : p->Startup.SA.window = ui->StartupSAWindow->currentIndex(); p->Startup.SA.detector = ui->StartupSADetector->currentIndex(); p->Startup.SA.signalID = ui->StartupSASignalID->isChecked(); + p->Acquisition.alwaysExciteBothPorts = ui->AcquisitionAlwaysExciteBoth->isChecked(); p->Acquisition.suppressPeaks = ui->AcquisitionSuppressPeaks->isChecked(); p->Acquisition.adjustPowerLevel = ui->AcquisitionAdjustPowerLevel->isChecked(); @@ -135,6 +136,7 @@ PreferencesDialog::PreferencesDialog(Preferences *pref, QWidget *parent) : p->Acquisition.useDFTinSAmode = ui->AcquisitionUseDFT->isChecked(); p->Acquisition.RBWLimitForDFT = ui->AcquisitionDFTlimitRBW->value(); p->Acquisition.useMedianAveraging = ui->AcquisitionAveragingMode->currentIndex() == 1; + p->Graphs.showUnits = ui->GraphsShowUnit->isChecked(); p->Graphs.Color.background = ui->GraphsColorBackground->getColor(); p->Graphs.Color.axis = ui->GraphsColorAxis->getColor(); @@ -142,9 +144,12 @@ PreferencesDialog::PreferencesDialog(Preferences *pref, QWidget *parent) : p->Graphs.Color.Ticks.Background.background = ui->GraphsColorTicksBackground->getColor(); p->Graphs.Color.Ticks.divisions = ui->GraphsColorTicksDivisions->getColor(); p->Graphs.domainChangeBehavior = (GraphDomainChangeBehavior) ui->GraphsDomainChangeBehavior->currentIndex(); - p->Graphs.markerBehavior.showDataOnGraphs = ui->GraphsShowMarkerData->isChecked(); - p->Graphs.markerBehavior.showAllData = ui->GraphsShowAllMarkerData->isChecked(); p->Graphs.lineWidth = ui->GraphsLineWidth->value(); + + p->Marker.defaultBehavior.showDataOnGraphs = ui->MarkerShowMarkerData->isChecked(); + p->Marker.defaultBehavior.showAllData = ui->MarkerShowAllMarkerData->isChecked(); + p->Marker.interpolatePoints = ui->MarkerInterpolate->currentIndex() == 1; + p->SCPIServer.enabled = ui->SCPIServerEnabled->isChecked(); p->SCPIServer.port = ui->SCPIServerPort->value(); accept(); @@ -211,10 +216,12 @@ void PreferencesDialog::setInitialGUIState() ui->GraphsColorTicksBackgroundEnabled->setChecked(p->Graphs.Color.Ticks.Background.enabled); ui->GraphsColorTicksBackground->setColor(p->Graphs.Color.Ticks.Background.background); ui->GraphsDomainChangeBehavior->setCurrentIndex((int) p->Graphs.domainChangeBehavior); - ui->GraphsShowMarkerData->setChecked(p->Graphs.markerBehavior.showDataOnGraphs); - ui->GraphsShowAllMarkerData->setChecked(p->Graphs.markerBehavior.showAllData); ui->GraphsLineWidth->setValue(p->Graphs.lineWidth); + ui->MarkerShowMarkerData->setChecked(p->Marker.defaultBehavior.showDataOnGraphs); + ui->MarkerShowAllMarkerData->setChecked(p->Marker.defaultBehavior.showAllData); + ui->MarkerInterpolate->setCurrentIndex(p->Marker.interpolatePoints ? 1 : 0); + ui->SCPIServerEnabled->setChecked(p->SCPIServer.enabled); ui->SCPIServerPort->setValue(p->SCPIServer.port); diff --git a/Software/PC_Application/preferences.h b/Software/PC_Application/preferences.h index d3f3c83..475a1a2 100644 --- a/Software/PC_Application/preferences.h +++ b/Software/PC_Application/preferences.h @@ -83,12 +83,16 @@ public: } Ticks; } Color; GraphDomainChangeBehavior domainChangeBehavior; + + double lineWidth; + } Graphs; + struct { struct { bool showDataOnGraphs; bool showAllData; - } markerBehavior; - double lineWidth; - } Graphs; + } defaultBehavior; + bool interpolatePoints; + } Marker; struct { bool enabled; int port; @@ -104,7 +108,7 @@ private: QString name; QVariant def; }; - const std::array descr = {{ + const std::array descr = {{ {&Startup.ConnectToFirstDevice, "Startup.ConnectToFirstDevice", true}, {&Startup.RememberSweepSettings, "Startup.RememberSweepSettings", false}, {&Startup.DefaultSweep.type, "Startup.DefaultSweep.type", "Frequency"}, @@ -141,9 +145,10 @@ private: {&Graphs.Color.Ticks.Background.background, "Graphs.Color.Ticks.Background.background", QColor(20, 20, 20)}, {&Graphs.Color.Ticks.divisions, "Graphs.Color.Ticks.divisions", QColor(Qt::gray)}, {&Graphs.domainChangeBehavior, "Graphs.domainChangeBehavior", GraphDomainChangeBehavior::AdjustGraphs}, - {&Graphs.markerBehavior.showDataOnGraphs, "Graphs.markerBehavior.ShowDataOnGraphs", true}, - {&Graphs.markerBehavior.showAllData, "Graphs.markerBehavior.ShowAllData", false}, {&Graphs.lineWidth, "Graphs.lineWidth", 1.0}, + {&Marker.defaultBehavior.showDataOnGraphs, "Marker.defaultBehavior.ShowDataOnGraphs", true}, + {&Marker.defaultBehavior.showAllData, "Marker.defaultBehavior.ShowAllData", false}, + {&Marker.interpolatePoints, "Marker.interpolatePoints", false}, {&SCPIServer.enabled, "SCPIServer.enabled", true}, {&SCPIServer.port, "SCPIServer.port", 19542}, }}; diff --git a/Software/PC_Application/preferencesdialog.ui b/Software/PC_Application/preferencesdialog.ui index 9411c97..52a0b65 100644 --- a/Software/PC_Application/preferencesdialog.ui +++ b/Software/PC_Application/preferencesdialog.ui @@ -56,6 +56,11 @@ Graphs + + + Marker + + SCPI Server @@ -78,7 +83,7 @@ - 2 + 3 @@ -831,29 +836,6 @@ - - - - Marker Default Behavior - - - - - - Show data on graphs - - - - - - - Show data in all available formats - - - - - - @@ -884,6 +866,88 @@ + + + + + + + + Default Behavior + + + + + + Show data on graphs + + + + + + + Show data in all available formats + + + + + + + + + + + + Positioning: + + + + + + + + Snap to measurement points + + + + + Interpolate between points + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + Qt::Horizontal + + + + 368 + 20 + + + + + +