From 89ca64e301776fe73e4032657909d2ef59e63611 Mon Sep 17 00:00:00 2001 From: Collin Kidder Date: Wed, 16 Sep 2015 22:35:32 -0400 Subject: [PATCH 1/5] Initial simple implemention of an idea to turn graphs into spreadsheets that are nicely formatted. --- graphingwindow.cpp | 55 ++++++++++++++++++++++++++++++++++++++++++++++ graphingwindow.h | 1 + 2 files changed, 56 insertions(+) diff --git a/graphingwindow.cpp b/graphingwindow.cpp index f790375..5a343ef 100644 --- a/graphingwindow.cpp +++ b/graphingwindow.cpp @@ -382,6 +382,7 @@ void GraphingWindow::contextMenuRequest(QPoint pos) menu->addAction(tr("Save graph image to file"), this, SLOT(saveGraphs())); menu->addAction(tr("Save graph definitions to file"), this, SLOT(saveDefinitions())); menu->addAction(tr("Load graph definitions from file"), this, SLOT(loadDefinitions())); + menu->addAction(tr("Save spreadsheet of data"), this, SLOT(saveSpreadsheet())); menu->addAction(tr("Add new graph"), this, SLOT(addNewGraph())); if (ui->graphingView->selectedGraphs().size() > 0) { @@ -432,6 +433,60 @@ void GraphingWindow::saveGraphs() } } +void GraphingWindow::saveSpreadsheet() +{ + QString filename; + QFileDialog dialog(this); + + QStringList filters; + filters.append(QString(tr("Spreadsheet (*.csv)"))); + + dialog.setFileMode(QFileDialog::AnyFile); + dialog.setNameFilters(filters); + dialog.setViewMode(QFileDialog::Detail); + dialog.setAcceptMode(QFileDialog::AcceptSave); + + if (dialog.exec() == QDialog::Accepted) + { + filename = dialog.selectedFiles()[0]; + if (!filename.contains('.')) filename += ".csv"; + + QFile *outFile = new QFile(filename); + + if (!outFile->open(QIODevice::WriteOnly | QIODevice::Text)) + return; + + /* + * save some data + * The problem here is that we've got X number of graphs that all have different + * timestamps but a spreadsheet would be best if each graph were taken at the same slice + * such that you have a list of slices with the value of each graph at that slice. + * + * But, for now export each graph in turn with the proper timestamp for each piece of data + * and a reference for which graph it came from. This is better than nothing. + */ + + QList::iterator iter; + int graphNum = 0; + for (iter = graphParams.begin(); iter != graphParams.end(); ++iter) + { + for (int j = 0; j < iter->x.count(); j++) + { + outFile->write(QString::number(iter->x[j]).toUtf8()); + outFile->putChar(','); + outFile->write(QString::number(graphNum).toUtf8()); + outFile->putChar(','); + outFile->write(QString::number(iter->y[j]).toUtf8()); + outFile->write("\n"); + } + graphNum++; + } + + outFile->close(); + } + +} + void GraphingWindow::saveDefinitions() { QString filename; diff --git a/graphingwindow.h b/graphingwindow.h index f59c31e..cdd97e5 100644 --- a/graphingwindow.h +++ b/graphingwindow.h @@ -51,6 +51,7 @@ private slots: void contextMenuRequest(QPoint pos); void moveLegend(); void saveGraphs(); + void saveSpreadsheet(); void saveDefinitions(); void loadDefinitions(); void addNewGraph(); From 705a7802d781a07820ca7abea7b64a855b167306 Mon Sep 17 00:00:00 2001 From: Collin Kidder Date: Thu, 17 Sep 2015 19:27:38 -0400 Subject: [PATCH 2/5] More implementation of the spreadsheet output. --- graphingwindow.cpp | 71 ++++++++++++++++++++++++++++++++++++++++------ utility.h | 6 ++++ 2 files changed, 69 insertions(+), 8 deletions(-) diff --git a/graphingwindow.cpp b/graphingwindow.cpp index 5a343ef..51dc811 100644 --- a/graphingwindow.cpp +++ b/graphingwindow.cpp @@ -467,19 +467,74 @@ void GraphingWindow::saveSpreadsheet() */ QList::iterator iter; - int graphNum = 0; + double xMin = 1000000000, xMax=-1000000000; + int maxCount = 0; + int numGraphs = 0; for (iter = graphParams.begin(); iter != graphParams.end(); ++iter) { - for (int j = 0; j < iter->x.count(); j++) + if (iter->x[0] < xMin) xMin = iter->x[0]; + if (iter->x[iter->x.count() - 1] > xMax) xMax = iter->x[iter->x.count() - 1]; + if (maxCount < iter->x.count()) maxCount = iter->x.count(); + numGraphs++; + } + qDebug() << "xMin: " << xMin; + qDebug() << "xMax: " << xMax; + qDebug() << "MaxCount: " << maxCount; + //The idea now is to iterate from xMin to xMax slicing all graphs up into MaxCount slices. + //But, actually, don't visit actual xMin or xMax, inset from there by one slice. Then, if + //a given graph doesn't exist there use the value from the nearest place that does exist. + double xSize = xMax - xMin; + double sliceSize = xSize / ((double)maxCount); + double equivValue = sliceSize / 100.0; + double currentX; + double value; + QList indices; + indices.reserve(numGraphs); + for (int zero = 0; zero < numGraphs; zero++) indices[zero] = 0; + + for (int j = 1; j < (maxCount - 1); j++) + { + currentX = xMin + (j * sliceSize); + outFile->write(QString::number(currentX).toUtf8()); + for (int k = 0; k < graphParams.count(); k++) { - outFile->write(QString::number(iter->x[j]).toUtf8()); + value = 0.0; + //five possibilities. + //1: we're at the beginning for this graph but the slice is before this graph even starts + if (indices[k] == 0 && graphParams[k].x[indices[k]] > currentX) + { + value = graphParams[k].y[indices[k]]; + } + //2: The opposite, we're at the end of this graph but the slices keep going + else if (indices[k] == (graphParams[k].x.count() - 1) && graphParams[k].x[indices[k]] < currentX) + { + value = graphParams[k].y[indices[k]]; + } + //3: the slice is right near the current value we're at for this graph + else if (fabs(graphParams[k].x[indices[k]] - currentX) < equivValue) + { + value = graphParams[k].y[indices[k]]; + } + //4: the slice is right next to the next value for this graph + else if (fabs(graphParams[k].x[indices[k] + 1] - currentX) < equivValue) + { + value = graphParams[k].y[indices[k] + 1]; + } + //5: it's somewhere in between two values for this graph + //the two values will be indices[k] and indices[k] + 1 + else + { + double span = graphParams[k].x[indices[k] + 1] - graphParams[k].x[indices[k]]; + double progress = (currentX - graphParams[k].x[indices[k]]) / span; + value = Utility::Lerp(graphParams[k].y[indices[k]], graphParams[k].y[indices[k] + 1], progress); + } + + if (currentX >= graphParams[k].x[indices[k] + 1]) indices[k]++; + outFile->putChar(','); - outFile->write(QString::number(graphNum).toUtf8()); - outFile->putChar(','); - outFile->write(QString::number(iter->y[j]).toUtf8()); - outFile->write("\n"); + outFile->write(QString::number(value).toUtf8()); } - graphNum++; + outFile->write("\n"); } outFile->close(); diff --git a/utility.h b/utility.h index 0197899..c4de0b8 100644 --- a/utility.h +++ b/utility.h @@ -104,6 +104,12 @@ public: } return builder; } + + //simple linear interpolation between value1 and value2. sample point is 0.0 to 1.0 + static double Lerp(double value1, double value2, double samplePoint) + { + return (value1 * (1.0 - samplePoint)) + (value2 * samplePoint); + } }; #endif // UTILITY_H From c9816595907d1a13cc74872f621eaf79183f92b7 Mon Sep 17 00:00:00 2001 From: Collin Kidder Date: Thu, 17 Sep 2015 20:14:03 -0400 Subject: [PATCH 3/5] Fixed errors in spreadsheet calcs and added a header --- graphingwindow.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/graphingwindow.cpp b/graphingwindow.cpp index 51dc811..9a457de 100644 --- a/graphingwindow.cpp +++ b/graphingwindow.cpp @@ -490,7 +490,15 @@ void GraphingWindow::saveSpreadsheet() double value; QList indices; indices.reserve(numGraphs); - for (int zero = 0; zero < numGraphs; zero++) indices[zero] = 0; + + outFile->write("TimeStamp,"); + for (int zero = 0; zero < numGraphs; zero++) + { + indices.append(0); + outFile->putChar(','); + outFile->write(graphParams[zero].graphName.toUtf8()); + } + outFile->write("\n"); for (int j = 1; j < (maxCount - 1); j++) { From 183a70310c02ec523595d01c6cc444ebf64fd309 Mon Sep 17 00:00:00 2001 From: Collin Kidder Date: Thu, 17 Sep 2015 20:35:05 -0400 Subject: [PATCH 4/5] Fix extra comma in spreadsheet output --- graphingwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graphingwindow.cpp b/graphingwindow.cpp index 9a457de..33ba21c 100644 --- a/graphingwindow.cpp +++ b/graphingwindow.cpp @@ -491,7 +491,7 @@ void GraphingWindow::saveSpreadsheet() QList indices; indices.reserve(numGraphs); - outFile->write("TimeStamp,"); + outFile->write("TimeStamp"); for (int zero = 0; zero < numGraphs; zero++) { indices.append(0); From 239aad1febdbc73f030817b5793f957b233ad9f5 Mon Sep 17 00:00:00 2001 From: Collin Kidder Date: Wed, 23 Sep 2015 21:31:02 -0400 Subject: [PATCH 5/5] Fix a bug where a faulty DBC file could crash the DBC editor --- dbcsignaleditor.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dbcsignaleditor.cpp b/dbcsignaleditor.cpp index 40d4d09..6f439f7 100644 --- a/dbcsignaleditor.cpp +++ b/dbcsignaleditor.cpp @@ -373,8 +373,9 @@ void DBCSignalEditor::fillSignalForm(DBC_SIGNAL *sig) int byt = startBit / 8; bitpattern[byt] |= 1 << (startBit % 8); size--; - if ((startBit % 8) == 0) startBit += 15; + if ((startBit % 8) == 0) startBit += 15; else startBit--; + if (startBit > 63) startBit = 63; } }