keep original trace data when de-embedding, toggle de-embedding view for individual traces
This commit is contained in:
parent
b67275831b
commit
89c9f20d16
@ -91,11 +91,11 @@ public:
|
||||
};
|
||||
static TypeInfo getInfo(Type type);
|
||||
|
||||
Data getSample(unsigned int index);
|
||||
Data getInterpolatedSample(double x);
|
||||
virtual Data getSample(unsigned int index);
|
||||
virtual Data getInterpolatedSample(double x);
|
||||
double getStepResponse(unsigned int index);
|
||||
double getInterpolatedStepResponse(double x);
|
||||
unsigned int numSamples();
|
||||
virtual unsigned int numSamples();
|
||||
|
||||
static QString dataTypeToString(DataType type);
|
||||
static DataType dataTypeFromString(QString s);
|
||||
|
@ -74,6 +74,7 @@ void Trace::clear(bool force) {
|
||||
return;
|
||||
}
|
||||
data.clear();
|
||||
clearDeembedding();
|
||||
settings.valid = false;
|
||||
warning("No data");
|
||||
emit cleared(this);
|
||||
@ -149,6 +150,39 @@ void Trace::addData(const Trace::Data &d, const VirtualDevice::SASettings &s, in
|
||||
addData(d, domain, 50.0, index);
|
||||
}
|
||||
|
||||
void Trace::addDeembeddingData(const Trace::Data &d, int index)
|
||||
{
|
||||
if(index >= 0) {
|
||||
// index position specified
|
||||
if(deembeddingData.size() <= (unsigned int) index) {
|
||||
deembeddingData.resize(index + 1);
|
||||
}
|
||||
deembeddingData[index] = d;
|
||||
} else {
|
||||
// no index given, determine position by X-coordinate
|
||||
|
||||
// add or replace data in vector while keeping it sorted with increasing frequency
|
||||
auto lower = lower_bound(deembeddingData.begin(), deembeddingData.end(), d, [](const Data &lhs, const Data &rhs) -> bool {
|
||||
return lhs.x < rhs.x;
|
||||
});
|
||||
// calculate index now because inserting a sample into data might lead to reallocation -> arithmetic on lower not valid anymore
|
||||
index = lower - deembeddingData.begin();
|
||||
if(lower == deembeddingData.end()) {
|
||||
// highest frequency yet, add to vector
|
||||
deembeddingData.push_back(d);
|
||||
} else if(lower->x == d.x) {
|
||||
*lower = d;
|
||||
} else {
|
||||
// insert at this position
|
||||
deembeddingData.insert(lower, d);
|
||||
}
|
||||
}
|
||||
if(deembeddingActive) {
|
||||
emit outputSamplesChanged(index, index + 1);
|
||||
}
|
||||
emit deembeddingChanged();
|
||||
}
|
||||
|
||||
void Trace::setName(QString name) {
|
||||
_name = name;
|
||||
emit nameChanged();
|
||||
@ -265,11 +299,15 @@ QString Trace::fillFromCSV(CSV &csv, unsigned int parameter)
|
||||
return lastTraceName;
|
||||
}
|
||||
|
||||
void Trace::fillFromDatapoints(std::map<QString, Trace *> traceSet, const std::vector<VirtualDevice::VNAMeasurement> &data)
|
||||
void Trace::fillFromDatapoints(std::map<QString, Trace *> traceSet, const std::vector<VirtualDevice::VNAMeasurement> &data, bool deembedded)
|
||||
{
|
||||
// remove all previous points
|
||||
for(auto m : traceSet) {
|
||||
m.second->clear();
|
||||
if(!deembedded) {
|
||||
m.second->clear();
|
||||
} else {
|
||||
m.second->clearDeembedding();
|
||||
}
|
||||
}
|
||||
// add new points to traces
|
||||
for(auto d : data) {
|
||||
@ -279,7 +317,11 @@ void Trace::fillFromDatapoints(std::map<QString, Trace *> traceSet, const std::v
|
||||
td.y = m.second;
|
||||
QString measurement = m.first;
|
||||
if(traceSet.count(measurement)) {
|
||||
traceSet[measurement]->addData(td, DataType::Frequency);
|
||||
if(!deembedded) {
|
||||
traceSet[measurement]->addData(td, DataType::Frequency);
|
||||
} else {
|
||||
traceSet[measurement]->addDeembeddingData(td);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -743,6 +785,17 @@ nlohmann::json Trace::toJSON()
|
||||
j["data"] = jdata;
|
||||
}
|
||||
|
||||
j["deembeddingActive"] = deembeddingActive;
|
||||
nlohmann::json jdedata;
|
||||
for(const auto &d : deembeddingData) {
|
||||
nlohmann::json jpoint;
|
||||
jpoint["x"] = d.x;
|
||||
jpoint["real"] = d.y.real();
|
||||
jpoint["imag"] = d.y.imag();
|
||||
jdedata.push_back(jpoint);
|
||||
}
|
||||
j["deembeddingData"] = jdedata;
|
||||
|
||||
nlohmann::json mathList;
|
||||
for(auto m : mathOps) {
|
||||
if(m.math->getType() == Type::Last) {
|
||||
@ -759,6 +812,7 @@ nlohmann::json Trace::toJSON()
|
||||
j["math"] = mathList;
|
||||
j["math_enabled"] = mathEnabled();
|
||||
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
@ -785,6 +839,18 @@ void Trace::fromJSON(nlohmann::json j)
|
||||
data.push_back(d);
|
||||
}
|
||||
}
|
||||
if(j.contains("deembeddingData")) {
|
||||
// Deembedded data is contained in the json, load now
|
||||
clearDeembedding();
|
||||
for(auto jpoint : j["deembeddingData"]) {
|
||||
Data d;
|
||||
d.x = jpoint.value("x", 0.0);
|
||||
d.y = complex<double>(jpoint.value("real", 0.0), jpoint.value("imag", 0.0));
|
||||
deembeddingData.push_back(d);
|
||||
}
|
||||
}
|
||||
deembeddingActive = j.value("deembeddingActive", false);
|
||||
|
||||
if(type == "Live") {
|
||||
if(j.contains("parameter")) {
|
||||
if(j["parameter"].type() == nlohmann::json::value_t::string) {
|
||||
@ -1226,6 +1292,36 @@ unsigned int Trace::size() const
|
||||
return lastMath->numSamples();
|
||||
}
|
||||
|
||||
bool Trace::isDeembeddingActive()
|
||||
{
|
||||
return deembeddingActive;
|
||||
}
|
||||
|
||||
bool Trace::deembeddingAvailable()
|
||||
{
|
||||
return deembeddingData.size() > 0;
|
||||
}
|
||||
|
||||
void Trace::setDeembeddingActive(bool active)
|
||||
{
|
||||
deembeddingActive = active;
|
||||
if(deembeddingAvailable()) {
|
||||
if(active) {
|
||||
emit outputSamplesChanged(0, deembeddingData.size());
|
||||
} else {
|
||||
emit outputSamplesChanged(0, data.size());
|
||||
}
|
||||
}
|
||||
emit deembeddingChanged();
|
||||
}
|
||||
|
||||
void Trace::clearDeembedding()
|
||||
{
|
||||
setDeembeddingActive(false);
|
||||
deembeddingData.clear();
|
||||
deembeddingChanged();
|
||||
}
|
||||
|
||||
double Trace::minX()
|
||||
{
|
||||
if(lastMath->numSamples() > 0) {
|
||||
@ -1331,6 +1427,60 @@ Trace::Data Trace::sample(unsigned int index, bool getStepResponse) const
|
||||
return data;
|
||||
}
|
||||
|
||||
Trace::Data Trace::getSample(unsigned int index)
|
||||
{
|
||||
if(deembeddingActive && deembeddingAvailable()) {
|
||||
if(index < deembeddingData.size()) {
|
||||
return deembeddingData[index];
|
||||
} else {
|
||||
TraceMath::Data d;
|
||||
d.x = 0;
|
||||
d.y = 0;
|
||||
return d;
|
||||
}
|
||||
} else {
|
||||
return TraceMath::getSample(index);
|
||||
}
|
||||
}
|
||||
|
||||
Trace::Data Trace::getInterpolatedSample(double x)
|
||||
{
|
||||
if(deembeddingActive && deembeddingAvailable()) {
|
||||
Data ret;
|
||||
if(deembeddingData.size() == 0 || x < deembeddingData.front().x || x > deembeddingData.back().x) {
|
||||
ret.y = std::numeric_limits<std::complex<double>>::quiet_NaN();
|
||||
ret.x = std::numeric_limits<double>::quiet_NaN();
|
||||
} else {
|
||||
auto it = lower_bound(deembeddingData.begin(), deembeddingData.end(), x, [](const Data &lhs, const double x) -> bool {
|
||||
return lhs.x < x;
|
||||
});
|
||||
if(it->x == x) {
|
||||
ret = *it;
|
||||
} else {
|
||||
// no exact match, needs to interpolate
|
||||
auto high = *it;
|
||||
it--;
|
||||
auto low = *it;
|
||||
double alpha = (x - low.x) / (high.x - low.x);
|
||||
ret.y = low.y * (1 - alpha) + high.y * alpha;
|
||||
ret.x = x;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
} else {
|
||||
return TraceMath::getInterpolatedSample(x);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int Trace::numSamples()
|
||||
{
|
||||
if(deembeddingActive && deembeddingAvailable()) {
|
||||
return deembeddingData.size();
|
||||
} else {
|
||||
return TraceMath::numSamples();
|
||||
}
|
||||
}
|
||||
|
||||
double Trace::getUnwrappedPhase(unsigned int index)
|
||||
{
|
||||
if(index >= size()) {
|
||||
|
@ -45,11 +45,12 @@ public:
|
||||
void clear(bool force = false);
|
||||
void addData(const Data& d, DataType domain, double reference_impedance = 50.0, int index = -1);
|
||||
void addData(const Data& d, const VirtualDevice::SASettings &s, int index = -1);
|
||||
void addDeembeddingData(const Data& d, int index = -1);
|
||||
void setName(QString name);
|
||||
void setVelocityFactor(double v);
|
||||
void fillFromTouchstone(Touchstone &t, unsigned int parameter);
|
||||
QString fillFromCSV(CSV &csv, unsigned int parameter); // returns the suggested trace name (not yet set in member data)
|
||||
static void fillFromDatapoints(std::map<QString, Trace*> traceSet, const std::vector<VirtualDevice::VNAMeasurement> &data);
|
||||
static void fillFromDatapoints(std::map<QString, Trace*> traceSet, const std::vector<VirtualDevice::VNAMeasurement> &data, bool deembedded = false);
|
||||
void fromLivedata(LivedataType type, QString param);
|
||||
void fromMath();
|
||||
QString name() { return _name; }
|
||||
@ -65,6 +66,12 @@ public:
|
||||
LivedataType liveType() { return _liveType; }
|
||||
TraceMath::DataType outputType() const { return lastMath->getDataType(); }
|
||||
unsigned int size() const;
|
||||
|
||||
bool isDeembeddingActive();
|
||||
bool deembeddingAvailable();
|
||||
void setDeembeddingActive(bool active);
|
||||
void clearDeembedding();
|
||||
|
||||
double minX();
|
||||
double maxX();
|
||||
double findExtremum(bool max, double xmin = std::numeric_limits<double>::lowest(), double xmax = std::numeric_limits<double>::max());
|
||||
@ -82,6 +89,11 @@ public:
|
||||
};
|
||||
|
||||
Data sample(unsigned int index, bool getStepResponse = false) const;
|
||||
|
||||
virtual Data getSample(unsigned int index) override;
|
||||
virtual Data getInterpolatedSample(double x) override;
|
||||
virtual unsigned int numSamples() override;
|
||||
|
||||
double getUnwrappedPhase(unsigned int index);
|
||||
// returns a (possibly interpolated sample) at a specified frequency/time/power
|
||||
Data interpolatedSample(double x);
|
||||
@ -190,6 +202,7 @@ signals:
|
||||
void dataChanged(unsigned int begin, unsigned int end);
|
||||
void nameChanged();
|
||||
void pauseChanged();
|
||||
void deembeddingChanged();
|
||||
void colorChanged(Trace *t);
|
||||
void markerAdded(Marker *m);
|
||||
void markerRemoved(Marker *m);
|
||||
@ -266,6 +279,10 @@ private:
|
||||
bool valid;
|
||||
} settings;
|
||||
|
||||
// de-embedding variables
|
||||
std::vector<Data> deembeddingData;
|
||||
bool deembeddingActive;
|
||||
|
||||
std::vector<MathInfo> mathOps;
|
||||
TraceMath *lastMath;
|
||||
std::vector<double> unwrappedPhase;
|
||||
|
@ -32,6 +32,9 @@ void TraceModel::addTrace(Trace *t)
|
||||
connect(t, &Trace::pauseChanged, [=](){
|
||||
emit dataChanged(createIndex(0, 0), createIndex(traces.size() - 1, ColIndexLast - 1));
|
||||
});
|
||||
connect(t, &Trace::deembeddingChanged, [=](){
|
||||
emit dataChanged(createIndex(0, 0), createIndex(traces.size() - 1, ColIndexLast - 1));
|
||||
});
|
||||
traces.push_back(t);
|
||||
endInsertRows();
|
||||
t->setModel(this);
|
||||
@ -106,6 +109,18 @@ void TraceModel::toggleMath(unsigned int index)
|
||||
}
|
||||
}
|
||||
|
||||
void TraceModel::toggleDeembedding(unsigned int index)
|
||||
{
|
||||
if (index >= traces.size()) {
|
||||
return;
|
||||
}
|
||||
auto trace = traces[index];
|
||||
if(trace->deembeddingAvailable()) {
|
||||
trace->setDeembeddingActive(!trace->isDeembeddingActive());
|
||||
emit dataChanged(createIndex(index, ColIndexDeembedding), createIndex(index, ColIndexDeembedding));
|
||||
}
|
||||
}
|
||||
|
||||
int TraceModel::rowCount(const QModelIndex &) const
|
||||
{
|
||||
return traces.size();
|
||||
@ -133,6 +148,8 @@ QVariant TraceModel::data(const QModelIndex &index, int role) const
|
||||
} else {
|
||||
return QIcon(":/icons/invisible.svg");
|
||||
}
|
||||
} else if(role == Qt::ToolTipRole){
|
||||
return "Toggle Visibility";
|
||||
} else {
|
||||
return QVariant();
|
||||
}
|
||||
@ -144,6 +161,21 @@ QVariant TraceModel::data(const QModelIndex &index, int role) const
|
||||
} else {
|
||||
return QIcon(":/icons/play.svg");
|
||||
}
|
||||
} else if(role == Qt::ToolTipRole && trace->canBePaused()){
|
||||
return "Toggle Play/Pause";
|
||||
} else {
|
||||
return QVariant();
|
||||
}
|
||||
break;
|
||||
case ColIndexDeembedding:
|
||||
if (role == Qt::DecorationRole && trace->deembeddingAvailable()) {
|
||||
if(trace->isDeembeddingActive()) {
|
||||
return QIcon(":icons/deembedding_enabled.svg");
|
||||
} else {
|
||||
return QIcon(":icons/deembedding_disabled.svg");
|
||||
}
|
||||
} else if(role == Qt::ToolTipRole && trace->deembeddingAvailable()){
|
||||
return "Toggle De-embedding";
|
||||
} else {
|
||||
return QVariant();
|
||||
}
|
||||
@ -155,6 +187,10 @@ QVariant TraceModel::data(const QModelIndex &index, int role) const
|
||||
} else {
|
||||
return QIcon(":icons/math_disabled");
|
||||
}
|
||||
} else if(role == Qt::ToolTipRole && trace->hasMathOperations()){
|
||||
return "Toggle Math Operations";
|
||||
} else {
|
||||
return QVariant();
|
||||
}
|
||||
break;
|
||||
case ColIndexName:
|
||||
@ -175,6 +211,17 @@ std::vector<Trace *> TraceModel::getTraces() const
|
||||
return traces;
|
||||
}
|
||||
|
||||
std::vector<Trace *> TraceModel::getLiveTraces() const
|
||||
{
|
||||
std::vector<Trace*> ret;
|
||||
for(auto t : traces) {
|
||||
if(t->getSource() == Trace::Source::Live) {
|
||||
ret.push_back(t);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool TraceModel::PortExcitationRequired(int port)
|
||||
{
|
||||
port++;
|
||||
@ -233,7 +280,7 @@ void TraceModel::clearLiveData()
|
||||
}
|
||||
}
|
||||
|
||||
void TraceModel::addVNAData(const VirtualDevice::VNAMeasurement& d, TraceMath::DataType datatype)
|
||||
void TraceModel::addVNAData(const VirtualDevice::VNAMeasurement& d, TraceMath::DataType datatype, bool deembedded)
|
||||
{
|
||||
source = DataSource::VNA;
|
||||
lastReceivedData = QDateTime::currentDateTimeUtc();
|
||||
@ -263,7 +310,11 @@ void TraceModel::addVNAData(const VirtualDevice::VNAMeasurement& d, TraceMath::D
|
||||
// parameter not included in data, skip
|
||||
continue;
|
||||
}
|
||||
t->addData(td, datatype, d.Z0, index);
|
||||
if(!deembedded) {
|
||||
t->addData(td, datatype, d.Z0, index);
|
||||
} else {
|
||||
t->addDeembeddingData(td, index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,8 +20,9 @@ public:
|
||||
enum {
|
||||
ColIndexVisible = 0,
|
||||
ColIndexPlayPause = 1,
|
||||
ColIndexMath = 2,
|
||||
ColIndexName = 3,
|
||||
ColIndexDeembedding = 2,
|
||||
ColIndexMath = 3,
|
||||
ColIndexName = 4,
|
||||
ColIndexLast,
|
||||
};
|
||||
|
||||
@ -39,12 +40,14 @@ public:
|
||||
void toggleVisibility(unsigned int index);
|
||||
void togglePause(unsigned int index);
|
||||
void toggleMath(unsigned int index);
|
||||
void toggleDeembedding(unsigned int index);
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
|
||||
std::vector<Trace*> getTraces() const;
|
||||
std::vector<Trace*> getLiveTraces() const;
|
||||
|
||||
bool PortExcitationRequired(int port);
|
||||
|
||||
@ -68,7 +71,7 @@ signals:
|
||||
|
||||
public slots:
|
||||
void clearLiveData();
|
||||
void addVNAData(const VirtualDevice::VNAMeasurement& d, TraceMath::DataType datatype);
|
||||
void addVNAData(const VirtualDevice::VNAMeasurement& d, TraceMath::DataType datatype, bool deembedded);
|
||||
void addSAData(const VirtualDevice::SAMeasurement &d, const VirtualDevice::SASettings &settings);
|
||||
|
||||
private:
|
||||
|
@ -140,6 +140,8 @@ void TraceWidget::on_view_clicked(const QModelIndex &index)
|
||||
case TraceModel::ColIndexPlayPause:
|
||||
model.togglePause(index.row());
|
||||
break;
|
||||
case TraceModel::ColIndexDeembedding:
|
||||
model.toggleDeembedding(index.row());
|
||||
case TraceModel::ColIndexMath:
|
||||
model.toggleMath(index.row());
|
||||
break;
|
||||
|
@ -124,7 +124,10 @@ void Deembedding::Deembed(std::map<QString, Trace *> traceSet)
|
||||
for(auto &p : points) {
|
||||
Deembed(p);
|
||||
}
|
||||
Trace::fillFromDatapoints(traceSet, points);
|
||||
Trace::fillFromDatapoints(traceSet, points, true);
|
||||
for(auto t : traceSet) {
|
||||
t.second->setDeembeddingActive(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include "ui_manualdeembeddingdialog.h"
|
||||
#include "Traces/sparamtraceselector.h"
|
||||
#include "CustomWidgets/informationbox.h"
|
||||
|
||||
ManualDeembeddingDialog::ManualDeembeddingDialog(const TraceModel &model, Deembedding *deemb) :
|
||||
ui(new Ui::ManualDeembeddingDialog)
|
||||
@ -12,6 +13,22 @@ ManualDeembeddingDialog::ManualDeembeddingDialog(const TraceModel &model, Deembe
|
||||
ui->buttonBox->setEnabled(false);
|
||||
connect(traceSelector, &SparamTraceSelector::selectionValid, ui->buttonBox, &QDialogButtonBox::setEnabled);
|
||||
connect(ui->buttonBox, &QDialogButtonBox::accepted, [=]() {
|
||||
auto traces = traceSelector->getTraces();
|
||||
bool clearDeembedding = false;
|
||||
for(auto t : traces) {
|
||||
if(t.second->deembeddingAvailable()) {
|
||||
clearDeembedding = InformationBox::AskQuestion("Clear previous de-embedding data?", "At least one of the selected traces "
|
||||
"has already been de-embedded. Do you want to clear the old de-embedding data before applying the new de-embedding?", true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(clearDeembedding) {
|
||||
for(auto t : traces) {
|
||||
if(t.second->deembeddingAvailable()) {
|
||||
t.second->clearDeembedding();
|
||||
}
|
||||
}
|
||||
}
|
||||
deemb->Deembed(traceSelector->getTraces());
|
||||
accept();
|
||||
});
|
||||
|
@ -850,10 +850,6 @@ void VNA::NewDatapoint(VirtualDevice::VNAMeasurement m)
|
||||
|
||||
cal.correctMeasurement(m_avg);
|
||||
|
||||
if(deembedding_active) {
|
||||
deembedding.Deembed(m_avg);
|
||||
}
|
||||
|
||||
TraceMath::DataType type;
|
||||
if(settings.zerospan) {
|
||||
type = TraceMath::DataType::TimeZeroSpan;
|
||||
@ -877,7 +873,11 @@ void VNA::NewDatapoint(VirtualDevice::VNAMeasurement m)
|
||||
}
|
||||
}
|
||||
|
||||
traceModel.addVNAData(m_avg, type);
|
||||
traceModel.addVNAData(m_avg, type, false);
|
||||
if(deembedding_active) {
|
||||
deembedding.Deembed(m_avg);
|
||||
traceModel.addVNAData(m_avg, type, true);
|
||||
}
|
||||
emit dataChanged();
|
||||
if(m_avg.pointNum == settings.npoints - 1) {
|
||||
UpdateAverageCount();
|
||||
@ -1579,6 +1579,14 @@ void VNA::EnableDeembedding(bool enable)
|
||||
enableDeembeddingAction->blockSignals(true);
|
||||
enableDeembeddingAction->setChecked(enable);
|
||||
enableDeembeddingAction->blockSignals(false);
|
||||
for(auto t : traceModel.getLiveTraces()) {
|
||||
if(enable) {
|
||||
t->setDeembeddingActive(true);
|
||||
} else {
|
||||
t->clearDeembedding();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void VNA::setAveragingMode(Averaging::Mode mode)
|
||||
|
@ -71,5 +71,7 @@
|
||||
<file>icons/definedShunt.svg</file>
|
||||
<file>icons/definedThrough.png</file>
|
||||
<file>icons/definedThrough.svg</file>
|
||||
<file>icons/deembedding_disabled.svg</file>
|
||||
<file>icons/deembedding_enabled.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
@ -0,0 +1,97 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="20mm"
|
||||
height="20mm"
|
||||
viewBox="0 0 20 20"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01, custom)"
|
||||
sodipodi:docname="deembedding_disabled.svg"
|
||||
inkscape:export-filename="deembedding_disabled.svg"
|
||||
inkscape:export-xdpi="17.1"
|
||||
inkscape:export-ydpi="17.1"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="8"
|
||||
inkscape:cx="32.625"
|
||||
inkscape:cy="38.0625"
|
||||
inkscape:window-width="1848"
|
||||
inkscape:window-height="1016"
|
||||
inkscape:window-x="1992"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs2">
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
id="TriangleStart"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
inkscape:stockid="TriangleStart"
|
||||
markerWidth="3"
|
||||
markerHeight="5.99999999"
|
||||
viewBox="0 0 5.3244081 6.15538509"
|
||||
inkscape:isstock="true"
|
||||
inkscape:collect="always"
|
||||
preserveAspectRatio="none">
|
||||
<path
|
||||
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:0.5pt"
|
||||
d="M 2.885,0 -1.44,2.5 v -5 z"
|
||||
id="path135" />
|
||||
</marker>
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<rect
|
||||
style="fill:#000000;stroke-width:0.396875"
|
||||
id="rect234"
|
||||
width="15"
|
||||
height="1"
|
||||
x="2.5"
|
||||
y="16.5" />
|
||||
<path
|
||||
style="fill:#000000;stroke-width:0.396875"
|
||||
d="M 9.7834433,13.650246 V 3.2217677"
|
||||
id="path453" />
|
||||
<path
|
||||
style="display:none;fill:none;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#TriangleStart)"
|
||||
d="M 10.015208,14.285628 10,6"
|
||||
id="path1395"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.8;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 11.015525,14.28403 V 7.997396 h 4.994451 L 9.99278,1.9801998 3.9615043,8.0114755 H 8.995516 v 6.2752715 z"
|
||||
id="path13540" />
|
||||
<path
|
||||
style="display:inline;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke"
|
||||
d="M 1.8217445,18.24796 18.5743,1.8171144"
|
||||
id="path819-2"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="display:inline;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#000000;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:fill markers stroke"
|
||||
d="M 1.8322416,18.193877 18.562413,1.8336946"
|
||||
id="path819-2-6"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cc" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.4 KiB |
@ -0,0 +1,85 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="20mm"
|
||||
height="20mm"
|
||||
viewBox="0 0 20 20"
|
||||
version="1.1"
|
||||
id="svg5"
|
||||
inkscape:version="1.2.2 (b0a8486541, 2022-12-01, custom)"
|
||||
sodipodi:docname="deembedding_enabled.svg"
|
||||
inkscape:export-filename="deembedding_disabled.svg"
|
||||
inkscape:export-xdpi="17.1"
|
||||
inkscape:export-ydpi="17.1"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview7"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#000000"
|
||||
borderopacity="0.25"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:document-units="mm"
|
||||
showgrid="false"
|
||||
inkscape:zoom="8"
|
||||
inkscape:cx="32.625"
|
||||
inkscape:cy="38.0625"
|
||||
inkscape:window-width="1848"
|
||||
inkscape:window-height="1016"
|
||||
inkscape:window-x="1992"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1" />
|
||||
<defs
|
||||
id="defs2">
|
||||
<marker
|
||||
style="overflow:visible"
|
||||
id="TriangleStart"
|
||||
refX="0"
|
||||
refY="0"
|
||||
orient="auto"
|
||||
inkscape:stockid="TriangleStart"
|
||||
markerWidth="3"
|
||||
markerHeight="5.99999999"
|
||||
viewBox="0 0 5.3244081 6.15538509"
|
||||
inkscape:isstock="true"
|
||||
inkscape:collect="always"
|
||||
preserveAspectRatio="none">
|
||||
<path
|
||||
style="fill:context-stroke;fill-rule:evenodd;stroke:context-stroke;stroke-width:0.5pt"
|
||||
d="M 2.885,0 -1.44,2.5 v -5 z"
|
||||
id="path135" />
|
||||
</marker>
|
||||
</defs>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<rect
|
||||
style="fill:#000000;stroke-width:0.396875"
|
||||
id="rect234"
|
||||
width="15"
|
||||
height="1"
|
||||
x="2.5"
|
||||
y="16.5" />
|
||||
<path
|
||||
style="fill:#000000;stroke-width:0.396875"
|
||||
d="M 9.7834433,13.650246 V 3.2217677"
|
||||
id="path453" />
|
||||
<path
|
||||
style="display:none;fill:none;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#TriangleStart)"
|
||||
d="M 10.015208,14.285628 10,6"
|
||||
id="path1395"
|
||||
sodipodi:nodetypes="cc" />
|
||||
<path
|
||||
style="display:inline;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1.8;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 11.015525,14.28403 V 7.997396 h 4.994451 L 9.99278,1.9801998 3.9615043,8.0114755 H 8.995516 v 6.2752715 z"
|
||||
id="path13540" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.7 KiB |
Loading…
Reference in New Issue
Block a user