简体   繁体   中英

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) ?

在此处输入图片说明

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 .

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM