Commit f703b6d1 authored by Lorenz Meier's avatar Lorenz Meier

Merge pull request #78 from Susurrus/issue_69

Fixed a stack overflow bug when using the regression fitting command
parents 6ba4def6 9c1c1d86
...@@ -560,7 +560,7 @@ void QGCDataPlot2D::loadCsvLog(QString file, QString xAxisName, QString yAxisFil ...@@ -560,7 +560,7 @@ void QGCDataPlot2D::loadCsvLog(QString file, QString xAxisName, QString yAxisFil
bool QGCDataPlot2D::calculateRegression() bool QGCDataPlot2D::calculateRegression()
{ {
// TODO Add support for quadratic / cubic curve fitting // TODO: Add support for quadratic / cubic curve fitting
return calculateRegression(ui->xRegressionComboBox->currentText(), ui->yRegressionComboBox->currentText(), "linear"); return calculateRegression(ui->xRegressionComboBox->currentText(), ui->yRegressionComboBox->currentText(), "linear");
} }
...@@ -579,17 +579,22 @@ bool QGCDataPlot2D::calculateRegression(QString xName, QString yName, QString me ...@@ -579,17 +579,22 @@ bool QGCDataPlot2D::calculateRegression(QString xName, QString yName, QString me
ui->xRegressionComboBox->setCurrentIndex(curveNames.indexOf(xName)); ui->xRegressionComboBox->setCurrentIndex(curveNames.indexOf(xName));
ui->yRegressionComboBox->setCurrentIndex(curveNames.indexOf(yName)); ui->yRegressionComboBox->setCurrentIndex(curveNames.indexOf(yName));
} }
// Create a couple of arrays for us to use to temporarily store some of the data from the plot.
// These arrays are allocated on the heap as they are far too big to go in the stack and will
// cause an overflow.
// TODO: Look into if this would be better done by having a getter return const double pointers instead
// of using memcpy().
const int size = 100000; const int size = 100000;
double x[size]; double *x = new double[size];
double y[size]; double *y = new double[size];
int copied = plot->data(yName, x, y, size); int copied = plot->data(yName, x, y, size);
if (method == "linear") { if (method == "linear") {
double a; // Y-axis crossing double a; // Y-axis crossing
double b; // Slope double b; // Slope
double r; // Regression coefficient double r; // Regression coefficient
int lin = linearRegression(x, y, copied, &a, &b, &r); if (linearRegression(x, y, copied, &a, &b, &r)) {
if(lin == 1) {
function = tr("%1 = %2 * %3 + %4 | R-coefficient: %5").arg(yName, QString::number(b), xName, QString::number(a), QString::number(r)); function = tr("%1 = %2 * %3 + %4 | R-coefficient: %5").arg(yName, QString::number(b), xName, QString::number(a), QString::number(r));
// Plot curve // Plot curve
...@@ -599,19 +604,16 @@ bool QGCDataPlot2D::calculateRegression(QString xName, QString yName, QString me ...@@ -599,19 +604,16 @@ bool QGCDataPlot2D::calculateRegression(QString xName, QString yName, QString me
plot->setStyleText("lines"); plot->setStyleText("lines");
// x-value of the current rightmost x position in the plot // x-value of the current rightmost x position in the plot
plot->appendData(tr("regression %1-%2").arg(xName, yName), plot->invTransform(QwtPlot::xBottom, plot->width() - plot->width()*0.08f), (a + b*plot->invTransform(QwtPlot::xBottom, plot->width() - plot->width() * 0.08f))); plot->appendData(tr("regression %1-%2").arg(xName, yName), plot->invTransform(QwtPlot::xBottom, plot->width() - plot->width()*0.08f), (a + b*plot->invTransform(QwtPlot::xBottom, plot->width() - plot->width() * 0.08f)));
result = true; result = true;
} else { } else {
function = tr("Linear regression failed. (Limit: %1 data points. Try with less)").arg(size); function = tr("Linear regression failed. (Limit: %1 data points. Try with less)").arg(size);
result = false;
} }
} else if (method == "quadratic") {
} else if (method == "cubic") {
} else { } else {
function = tr("Regression method %1 not found").arg(method); function = tr("Regression method %1 not found").arg(method);
result = false;
} }
delete x, y;
} else { } else {
// xName == yName // xName == yName
function = tr("Please select different X and Y dimensions, not %1 = %2").arg(xName, yName); function = tr("Please select different X and Y dimensions, not %1 = %2").arg(xName, yName);
...@@ -635,7 +637,7 @@ bool QGCDataPlot2D::calculateRegression(QString xName, QString yName, QString me ...@@ -635,7 +637,7 @@ bool QGCDataPlot2D::calculateRegression(QString xName, QString yName, QString me
* the match of the regression. * the match of the regression.
* @return 1 on success, 0 on failure (e.g. because of infinite slope) * @return 1 on success, 0 on failure (e.g. because of infinite slope)
*/ */
int QGCDataPlot2D::linearRegression(double* x,double* y,int n,double* a,double* b,double* r) bool QGCDataPlot2D::linearRegression(double *x, double *y, int n, double *a, double *b, double *r)
{ {
int i; int i;
double sumx=0,sumy=0,sumx2=0,sumy2=0,sumxy=0; double sumx=0,sumy=0,sumx2=0,sumy2=0,sumxy=0;
...@@ -645,7 +647,7 @@ int QGCDataPlot2D::linearRegression(double* x,double* y,int n,double* a,double* ...@@ -645,7 +647,7 @@ int QGCDataPlot2D::linearRegression(double* x,double* y,int n,double* a,double*
*b = 0; *b = 0;
*r = 0; *r = 0;
if (n < 2) if (n < 2)
return(FALSE); return true;
/* Conpute some things we need */ /* Conpute some things we need */
for (i=0; i<n; i++) { for (i=0; i<n; i++) {
...@@ -661,7 +663,7 @@ int QGCDataPlot2D::linearRegression(double* x,double* y,int n,double* a,double* ...@@ -661,7 +663,7 @@ int QGCDataPlot2D::linearRegression(double* x,double* y,int n,double* a,double*
/* Infinite slope (b), non existant intercept (a) */ /* Infinite slope (b), non existant intercept (a) */
if (fabs(sxx) == 0) if (fabs(sxx) == 0)
return(FALSE); return false;
/* Calculate the slope (b) and intercept (a) */ /* Calculate the slope (b) and intercept (a) */
*b = sxy / sxx; *b = sxy / sxx;
...@@ -673,7 +675,7 @@ int QGCDataPlot2D::linearRegression(double* x,double* y,int n,double* a,double* ...@@ -673,7 +675,7 @@ int QGCDataPlot2D::linearRegression(double* x,double* y,int n,double* a,double*
else else
*r = sxy / sqrt(sxx * syy); *r = sxy / sqrt(sxx * syy);
return(TRUE); return false;
} }
void QGCDataPlot2D::saveCsvLog() void QGCDataPlot2D::saveCsvLog()
......
...@@ -22,7 +22,7 @@ public: ...@@ -22,7 +22,7 @@ public:
bool calculateRegression(QString xName, QString yName, QString method="linear"); bool calculateRegression(QString xName, QString yName, QString method="linear");
/** @brief Linear regression over data points */ /** @brief Linear regression over data points */
int linearRegression(double* x,double* y,int n,double* a,double* b,double* r); bool linearRegression(double *x, double *y, int n, double *a, double *b, double *r);
public slots: public slots:
/** @brief Load previously selected file */ /** @brief Load previously selected file */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment