kookoo121
kookoo121

Reputation: 1136

How to fit a parabola to set of points?

I have a set of points as seen in the following picture. All points position are known. How can I fit a parabola to this set of points and get the new position on parabolic equation (x, y)?

enter image description here

Upvotes: 3

Views: 4502

Answers (2)

Ziezi
Ziezi

Reputation: 6467

To implement a Quadratic Curve Fitting is not a simple task (check the second link at the end). As a start you could use simple linear regression, once you've understood the principles (check first link at the end) you can apply it for your case.

The code below is a simple implementation that will fit your data (x, y) to: y = m*x + b:

linear_regression.h:

#ifndef LINEAR_REGRESSION_H
#define LINEAR_REGRESSION_H
// data structure used as returning type of the function finding m and b
struct Coefficients {
    // constructor
    Coefficients (double mm, double bb)
        : m(mm), b(bb) { }

    // data members 
    double m;
    double b;
};

// This function fits: y = mx + b, to your (x,y) data.
Coefficients linear_regression(const std::vector<double>& x,const std::vector<double>& y){
    // variables needed for the calculations
    double sum_x = 0.0;     double sum_y = 0.0;
    double sum_x2 = 0.0;    double sum_y2 = 0.0;
    double sum_xy = 0.0;

    double m = 0.0;         double b = 0.0;

    if (x.size() != y.size()) std::cerr << "Mismatched number of points!\n";
    double number_of_points = x.size();

    // calculate the sums
    for (size_t i = 0; i < number_of_points; ++i) {
        sum_x  += x[i];
        sum_y  += y[i];          
        sum_x2 += std::sqrt(x[i]); 
        sum_y2 += std::sqrt(y[i]);       
        sum_xy += x[i] * y[i];   
    }
    double denominator = number_of_points * sum_x2 - std::sqrt(sum_x);

    // no solution, return: m = 0, b = 0  
    if (denominator == 0) return Coefficients(m, b);

    // calculate the slope: m and the intercept: b
    m = (number_of_points * sum_xy - sum_x * sum_y) / denominator;
    b = (sum_y * sum_x2 - sum_x * sum_xy) / denominator;

    return Coefficients (m, b);
}
#endif

main.cpp:

#include <iostream>
#include <vector>
#include "linear_regression.h"


int main () {
    // vectors holding the set of points
    std::vector<double> x_points;
    std::vector<double> y_points;

    Coefficients coeff = linear_regression (x_points, y_points);

    // where: y = m * x + b
    double m = coeff.m;
    double b = coeff.b;
}

Here, for more information on the method of Linear Regression and Least Squares Regression for Quadratic Curve Fitting.

Upvotes: 1

Paul R.
Paul R.

Reputation: 738

You could express the curve in polar coordinates (see Wikipedia: “Polar coordinate system”). Just choose an arbitrary point ‘inside’ the parabola as your origin and transform the (x,y) coordinates to (r,phi) coordinates. Now you can express the points in the form r = f(phi), with r being the distance to the origin and phi being the angle in your polar coordinates. A point that would always do the job as an origin is the average of all points, since it is always located inside the parabola.

In the next step you need to transform the equation of the parabola in your new polar coordinates. It needs one extra parameter compared to the simple parabola equation for the rotation. This equation can be used to fit your data, for example using an implementation of the methods described in the Wikipedia article “Non-linear least squares”.

I don’t know if this is the easiest way to solve this problem, but I hope it a least gives you an idea on how you could proceed.

Upvotes: 0

Related Questions