mirror of
https://github.com/jankae/LibreVNA.git
synced 2026-01-09 10:10:00 +01:00
Merge branch 'master' into SCPI_improvement
This commit is contained in:
commit
792f678b99
|
|
@ -41,6 +41,14 @@ static double createAutomaticTicks(vector<double>& ticks, double start, double s
|
|||
}
|
||||
|
||||
static void createLogarithmicTicks(vector<double>& ticks, double start, double stop, int minDivisions) {
|
||||
double mult = 1.0;
|
||||
if(start < 0.0 && stop < 0.0) {
|
||||
mult = -1.0;
|
||||
auto buf = -stop;
|
||||
stop = -start;
|
||||
start = buf;
|
||||
}
|
||||
|
||||
// enforce usable log settings
|
||||
if(start <= 0) {
|
||||
start = 1.0;
|
||||
|
|
@ -55,7 +63,9 @@ static void createLogarithmicTicks(vector<double>& ticks, double start, double s
|
|||
int zeros = floor(log10(max_div_decade));
|
||||
double decimals_shift = pow(10, zeros);
|
||||
max_div_decade /= decimals_shift;
|
||||
if(max_div_decade < 2) {
|
||||
if(max_div_decade <= 1) {
|
||||
max_div_decade = 1;
|
||||
} else if(max_div_decade < 2) {
|
||||
max_div_decade = 2;
|
||||
} else if(max_div_decade < 5) {
|
||||
max_div_decade = 5;
|
||||
|
|
@ -70,15 +80,17 @@ static void createLogarithmicTicks(vector<double>& ticks, double start, double s
|
|||
step *= 10;
|
||||
}
|
||||
do {
|
||||
ticks.push_back(div);
|
||||
if(ticks.size() > 1 && div != step && floor(log10(div)) != floor(log10(div - step))) {
|
||||
ticks.push_back(div * mult);
|
||||
if(ticks.size() > 1 && div != step && floor(log10(div)+std::numeric_limits<double>::epsilon()) != floor(log10(div - step)+std::numeric_limits<double>::epsilon())) {
|
||||
// reached a new decade with this switch
|
||||
step *= 10;
|
||||
div = step;
|
||||
} else {
|
||||
div += step;
|
||||
}
|
||||
div += step;
|
||||
} while(div <= stop);
|
||||
|
||||
if(mult == -1.0) {
|
||||
std::reverse(ticks.begin(), ticks.end());
|
||||
}
|
||||
}
|
||||
|
||||
YAxis::YAxis()
|
||||
|
|
@ -108,6 +120,8 @@ double YAxis::sampleToCoordinate(Trace::Data data, Trace *t, unsigned int sample
|
|||
return data.y.real();
|
||||
case YAxis::Type::Imaginary:
|
||||
return data.y.imag();
|
||||
case YAxis::Type::AbsImpedance:
|
||||
return abs(Util::SparamToImpedance(data.y, t->getReferenceImpedance()));
|
||||
case YAxis::Type::SeriesR:
|
||||
return Util::SparamToResistance(data.y, t->getReferenceImpedance());
|
||||
case YAxis::Type::Reactance:
|
||||
|
|
@ -201,6 +215,7 @@ QString YAxis::TypeToName(Type type)
|
|||
case Type::VSWR: return "VSWR";
|
||||
case Type::Real: return "Real";
|
||||
case Type::Imaginary: return "Imaginary";
|
||||
case Type::AbsImpedance: return "Impedance (absolute)";
|
||||
case Type::SeriesR: return "Resistance";
|
||||
case Type::Reactance: return "Reactance";
|
||||
case Type::Capacitance: return "Capacitance";
|
||||
|
|
@ -247,6 +262,7 @@ QString YAxis::Unit(Type type, TraceModel::DataSource source)
|
|||
case Type::Imaginary:
|
||||
case Type::QualityFactor:
|
||||
return "";
|
||||
case Type::AbsImpedance: return "Ω";
|
||||
case Type::SeriesR: return "Ω";
|
||||
case Type::Reactance: return "Ω";
|
||||
case Type::Capacitance: return "F";
|
||||
|
|
@ -281,6 +297,7 @@ QString YAxis::Prefixes(Type type, TraceModel::DataSource source)
|
|||
case Type::Real: return "pnum ";
|
||||
case Type::Imaginary: return "pnum ";
|
||||
case Type::QualityFactor: return " ";
|
||||
case Type::AbsImpedance: return "m k";
|
||||
case Type::SeriesR: return "m kM";
|
||||
case Type::Reactance: return "m kM";
|
||||
case Type::Capacitance: return "pnum ";
|
||||
|
|
@ -337,6 +354,7 @@ std::set<YAxis::Type> YAxis::getSupported(XAxis::Type type, TraceModel::DataSour
|
|||
ret.insert(YAxis::Type::VSWR);
|
||||
ret.insert(YAxis::Type::Real);
|
||||
ret.insert(YAxis::Type::Imaginary);
|
||||
ret.insert(YAxis::Type::AbsImpedance);
|
||||
ret.insert(YAxis::Type::SeriesR);
|
||||
ret.insert(YAxis::Type::Reactance);
|
||||
ret.insert(YAxis::Type::Capacitance);
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ public:
|
|||
Real,
|
||||
Imaginary,
|
||||
// derived parameter options
|
||||
AbsImpedance,
|
||||
SeriesR,
|
||||
Reactance,
|
||||
Capacitance,
|
||||
|
|
|
|||
|
|
@ -478,7 +478,11 @@ void TraceXYPlot::draw(QPainter &p)
|
|||
step = max / 1000;
|
||||
}
|
||||
int significantDigits = floor(log10(max)) - floor(log10(step)) + 1;
|
||||
if(yAxis[i].getLog() && yAxis[i].getRangeMax()/yAxis[i].getRangeMin() >= 100) {
|
||||
significantDigits = floor(log10(max)) + 1;
|
||||
}
|
||||
|
||||
int lastTickLabelEnd = std::numeric_limits<int>::max();
|
||||
for(unsigned int j = 0; j < yAxis[i].getTicks().size(); j++) {
|
||||
auto yCoord = yAxis[i].transform(yAxis[i].getTicks()[j], w.height() - xAxisSpace, plotAreaTop);
|
||||
p.setPen(QPen(pref.Graphs.Color.axis, 1));
|
||||
|
|
@ -486,17 +490,23 @@ void TraceXYPlot::draw(QPainter &p)
|
|||
auto tickStart = i == 0 ? plotAreaLeft : plotAreaLeft + plotAreaWidth;
|
||||
auto tickLen = i == 0 ? -2 : 2;
|
||||
p.drawLine(tickStart, yCoord, tickStart + tickLen, yCoord);
|
||||
QString unit = "";
|
||||
QString prefix = " ";
|
||||
if(pref.Graphs.showUnits) {
|
||||
unit = yAxis[i].Unit();
|
||||
prefix = yAxis[i].Prefixes();
|
||||
}
|
||||
auto tickValue = Unit::ToString(yAxis[i].getTicks()[j], unit, prefix, significantDigits);
|
||||
if(i == 0) {
|
||||
p.drawText(QRectF(0, yCoord - pref.Graphs.fontSizeAxis/2 - 2, tickStart + 2 * tickLen, pref.Graphs.fontSizeAxis*1.5), Qt::AlignRight, tickValue);
|
||||
if(yCoord + pref.Graphs.fontSizeAxis >= lastTickLabelEnd) {
|
||||
// would overlap previous tick label, skip
|
||||
} else {
|
||||
p.drawText(QRectF(tickStart + 2 * tickLen + 2, yCoord - pref.Graphs.fontSizeAxis/2 - 2, yAxisSpace, pref.Graphs.fontSizeAxis*1.5), Qt::AlignLeft, tickValue);
|
||||
QString unit = "";
|
||||
QString prefix = " ";
|
||||
if(pref.Graphs.showUnits) {
|
||||
unit = yAxis[i].Unit();
|
||||
prefix = yAxis[i].Prefixes();
|
||||
}
|
||||
auto tickValue = Unit::ToString(yAxis[i].getTicks()[j], unit, prefix, significantDigits);
|
||||
QRect bounding;
|
||||
if(i == 0) {
|
||||
p.drawText(QRect(0, yCoord - pref.Graphs.fontSizeAxis/2 - 2, tickStart + 2 * tickLen, pref.Graphs.fontSizeAxis*1.5), Qt::AlignRight, tickValue, &bounding);
|
||||
} else {
|
||||
p.drawText(QRect(tickStart + 2 * tickLen + 2, yCoord - pref.Graphs.fontSizeAxis/2 - 2, yAxisSpace, pref.Graphs.fontSizeAxis*1.5), Qt::AlignLeft, tickValue, &bounding);
|
||||
}
|
||||
lastTickLabelEnd = bounding.y();
|
||||
}
|
||||
|
||||
// tick lines
|
||||
|
|
@ -509,8 +519,8 @@ void TraceXYPlot::draw(QPainter &p)
|
|||
if (pref.Graphs.Color.Ticks.Background.enabled) {
|
||||
if (j%2)
|
||||
{
|
||||
int yCoordTop = yAxis[i].transform(yAxis[i].getTicks()[j], plotAreaTop, w.height() - xAxisSpace);
|
||||
int yCoordBot = yAxis[i].transform(yAxis[i].getTicks()[j-1], plotAreaTop, w.height() - xAxisSpace);
|
||||
int yCoordTop = yCoord;
|
||||
int yCoordBot = yAxis[i].transform(yAxis[i].getTicks()[j-1], w.height() - xAxisSpace, plotAreaTop);
|
||||
if(yCoordTop > yCoordBot) {
|
||||
auto buf = yCoordBot;
|
||||
yCoordBot = yCoordTop;
|
||||
|
|
@ -925,26 +935,51 @@ void TraceXYPlot::updateAxisTicks()
|
|||
}
|
||||
if(max >= min) {
|
||||
auto range = max - min;
|
||||
if(range == 0.0) {
|
||||
// this could happen if all values in a trace are identical (e.g. imported ideal touchstone files)
|
||||
if(max == 0.0) {
|
||||
// simply use +/-1 range
|
||||
max = 1.0;
|
||||
min = -1.0;
|
||||
} else {
|
||||
// +/-5% around value
|
||||
max += abs(max * 0.05);
|
||||
min -= abs(max * 0.05);
|
||||
if(yAxis[i].getLog()){
|
||||
// log axis
|
||||
|
||||
double maxLog10 = log10(abs(max));
|
||||
// prevent zero-crossing
|
||||
if(min <= 0.0 && max > 0) {
|
||||
min = pow(10, maxLog10 - 3); // just show 3 decades by default
|
||||
} else if(min >= 0.0 && max < 0) {
|
||||
// same thing if negative
|
||||
min = -pow(10, maxLog10 - 3);
|
||||
}
|
||||
// add 5% visible range
|
||||
double ratio = log10(max/min);
|
||||
max *= pow(10, ratio * 0.05);
|
||||
min /= pow(10, ratio * 0.05);
|
||||
} else {
|
||||
// add 5% of range at both ends
|
||||
min -= range * 0.05;
|
||||
max += range * 0.05;
|
||||
// linear axis
|
||||
if(range == 0.0) {
|
||||
// this could happen if all values in a trace are identical (e.g. imported ideal touchstone files)
|
||||
if(max == 0.0) {
|
||||
// simply use +/-1 range
|
||||
max = 1.0;
|
||||
min = -1.0;
|
||||
} else {
|
||||
// +/-5% around value
|
||||
max += abs(max * 0.05);
|
||||
min -= abs(max * 0.05);
|
||||
}
|
||||
} else {
|
||||
// add 5% of range at both ends
|
||||
min -= range * 0.05;
|
||||
max += range * 0.05;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// max/min still at default values, no valid samples are available for this axis, use default range
|
||||
max = 1.0;
|
||||
min = -1.0;
|
||||
if(!yAxis[i].getLog()) {
|
||||
// linear axis
|
||||
max = 1.0;
|
||||
min = -1.0;
|
||||
} else {
|
||||
// log axis
|
||||
max = 100.0;
|
||||
min = 0.1;
|
||||
}
|
||||
}
|
||||
yAxis[i].set(yAxis[i].getType(), yAxis[i].getLog(), true, min, max, 0);
|
||||
}
|
||||
|
|
@ -1035,6 +1070,7 @@ bool TraceXYPlot::supported(Trace *t, YAxis::Type type)
|
|||
case YAxis::Type::Capacitance:
|
||||
case YAxis::Type::Inductance:
|
||||
case YAxis::Type::QualityFactor:
|
||||
case YAxis::Type::AbsImpedance:
|
||||
if(!t->isReflection()) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1171,9 +1207,9 @@ void TraceXYPlot::traceDropped(Trace *t, QPoint position)
|
|||
{
|
||||
Q_UNUSED(position)
|
||||
if(!supported(t)) {
|
||||
// needs to switch to a different domain for the graph
|
||||
if(!InformationBox::AskQuestion("X Axis Domain Change", "You dropped a trace that is not supported with the currently selected X axis domain."
|
||||
" Do you want to remove all traces and change the graph to the correct domain?", true, "DomainChangeRequest")) {
|
||||
// needs to switch to a different setting for the graph
|
||||
if(!InformationBox::AskQuestion("Graph Configuration Change", "You dropped a trace that is not supported with the currently configured axes."
|
||||
" Do you want to remove all traces and change the graph to the correct configuration?", true, "DomainChangeRequest")) {
|
||||
// user declined to change domain, to not add trace
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ XYplotAxisDialog::XYplotAxisDialog(TraceXYPlot *plot) :
|
|||
|
||||
// Setup GUI connections
|
||||
connect(ui->Y1type, qOverload<int>(&QComboBox::currentIndexChanged), [=](int index) {
|
||||
//ui->Y1log->setEnabled(index != 0);
|
||||
ui->Y1log->setEnabled(index != 0);
|
||||
ui->Y1linear->setEnabled(index != 0);
|
||||
ui->Y1auto->setEnabled(index != 0);
|
||||
bool autoRange = ui->Y1auto->isChecked();
|
||||
|
|
@ -70,11 +70,14 @@ XYplotAxisDialog::XYplotAxisDialog(TraceXYPlot *plot) :
|
|||
connect(ui->Y1auto, &QCheckBox::toggled, [this](bool checked) {
|
||||
ui->Y1min->setEnabled(!checked);
|
||||
ui->Y1max->setEnabled(!checked);
|
||||
ui->Y1divs->setEnabled(!checked);
|
||||
ui->Y1divs->setEnabled(!checked && !ui->Y1log->isChecked());
|
||||
});
|
||||
connect(ui->Y1log, &QCheckBox::toggled, [this](bool checked) {
|
||||
ui->Y1divs->setEnabled(!checked && !ui->Y1auto->isChecked());
|
||||
});
|
||||
|
||||
connect(ui->Y2type, qOverload<int>(&QComboBox::currentIndexChanged), [=](int index) {
|
||||
//ui->Y2log->setEnabled(index != 0);
|
||||
ui->Y2log->setEnabled(index != 0);
|
||||
ui->Y2linear->setEnabled(index != 0);
|
||||
ui->Y2auto->setEnabled(index != 0);
|
||||
bool autoRange = ui->Y2auto->isChecked();
|
||||
|
|
@ -95,7 +98,10 @@ XYplotAxisDialog::XYplotAxisDialog(TraceXYPlot *plot) :
|
|||
connect(ui->Y2auto, &QCheckBox::toggled, [this](bool checked) {
|
||||
ui->Y2min->setEnabled(!checked);
|
||||
ui->Y2max->setEnabled(!checked);
|
||||
ui->Y2divs->setEnabled(!checked);
|
||||
ui->Y2divs->setEnabled(!checked && !ui->Y1log->isChecked());
|
||||
});
|
||||
connect(ui->Y2log, &QCheckBox::toggled, [this](bool checked) {
|
||||
ui->Y2divs->setEnabled(!checked && !ui->Y2auto->isChecked());
|
||||
});
|
||||
|
||||
connect(ui->Xauto, &QCheckBox::toggled, [this](bool checked) {
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@
|
|||
<item>
|
||||
<widget class="QRadioButton" name="Y1log">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Log</string>
|
||||
|
|
@ -204,7 +204,7 @@
|
|||
<item>
|
||||
<widget class="QRadioButton" name="Y2log">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Log</string>
|
||||
|
|
@ -592,8 +592,8 @@
|
|||
</connection>
|
||||
</connections>
|
||||
<buttongroups>
|
||||
<buttongroup name="Xgroup"/>
|
||||
<buttongroup name="Y1group"/>
|
||||
<buttongroup name="Xgroup"/>
|
||||
<buttongroup name="Y2group"/>
|
||||
</buttongroups>
|
||||
</ui>
|
||||
|
|
|
|||
Loading…
Reference in a new issue