Как найти линию, которая лучше всего описывает группу точек? - PullRequest
0 голосов
/ 27 мая 2019

Итак, у меня была проблема (не домашняя работа, не волнуйтесь), когда мне нужно было найти линию, которая лучше всего описывает набор точек, если это имеет смысл.Я придумал алгоритм, который:

  1. Вычисляет наклон между каждой парой точек и получает среднее значение

  2. Используя среднее значениенайденный на шаге 1, он находит средний перехват с осью y, проходя по всем точкам (y = mx + b, находит b)

  3. Мы проверяем все значения m, b, которые находятся в диапазоне + -5 от среднего значения, найденного ранее, и затем получаем пару, у которой линия имеет наименьшую сумму расстояний до точек

  4. Мы повторяем сколько угоднораз нам нравится, беря результат шага 3, а затем проверяя радиус + -0,5, а затем + -0,05 и т. д.

У меня есть два основных вопроса / проблемы для васесли вы можете помочь:

  • Есть ли способ сделать этот алгоритм более эффективным / точным в некотором смысле?И если да, то как?

  • Поскольку я довольно плохо знаком с OOP / C ++, не могли бы вы быстро разобраться и посмотреть, не сделал ли я какие-либо ошибки / неправильные вызовы в своем коде?

Большое спасибо за потраченное время!

#include <iostream>
#include <string>
using namespace std;
class Point {
private:
    double x;
    double y;
public:
    Point() //default
    {
        x = 0;
        y = 0;
    }
    Point(double xAxis, double yAxis)
    {
        x = xAxis;
        y = yAxis;
    }
    double getX()
    {
        return x;
    }
    double getY()
    {
        return y;
    }
    void setX(double tx)
    {
        x = tx;
    }
    void setY(double ty)
    {
        y = ty;
    }
    double calcSlope(Point p2)
    {
        return (p2.getY() - y) / (p2.getX() - x);
    }
};
class Line {
private:
    double m;
    double b;
public:
    Line()
    {
        m = b = 0;
    }
    Line(double slope, double remain)
    {
        m = slope;
        b = remain;
    }
    Line(Point p1, Point p2)
    {
        m = (p1.getY() - p2.getY()) / (p1.getX() - p2.getX());
        b = p1.getY() - p1.getX() * m;
    }
    double getSlope()
    {
        return m;
    }
    double getB()
    {
        return b;
    }
    void setSlope(double slope)
    {
        m = slope;
    }
    void setB(double bb)
    {
        b = bb;
    }
    double dist(Point p)
    {
        double d = (double)abs(m*p.getX() - p.getY() + b) / sqrt(1 + m * m);
        return d;
    }
    void avgLine(Point pArr[], int size)
    {
        double sum = 0;
        for (int i = 0; i < size; i++)
        {
            for (int j = i+1; j < size; j++)
            {
                sum += pArr[i].calcSlope(pArr[j]);
            }
        }
        sum /= ((size)*(size - 1) / 2);
        double sumB = 0;
        for (int i = 0; i < size; i++)
        {
            sumB += pArr[i].getY() - sum * pArr[i].getX();
        }
        sumB /= size;
        m = sum;
        b = sumB;
    }
    double sumDist(Point pArr[], int size)
    {
        double sum = 0;
        for (int i = 0; i < size; i++)
        {
            sum += this->dist(pArr[i]);
        }
        return sum;
    }
};
int main()
{
    int accuracy, size;
    double x, y, min, tmp;
    cout << "Please choose number of points:" << endl;
    cin >> size;
    Point *pArr;
    pArr = new Point[size];
    cout << "Please choose accuracy 0 < d < 5, accuracy is 10^(-d)" << endl;
    cin >> accuracy;
    for (int i = 0; i < size; i++)
    {
        cout << "X value:" << endl;
        cin >> x;
        cout << "Y value:" << endl;
        cin >> y;
        pArr[i].setX(x);
        pArr[i].setY(y);
    }
    Line avgL;
    avgL.avgLine(pArr, size);
    Line minL = avgL, tmpLine;
    min = minL.sumDist(pArr, size);
    for (int i = 1; i >= pow(10, -accuracy); i /= 10)
    {
        for (double startM = avgL.getSlope() - 5 * i; startM <= avgL.getSlope() + 5 * i; startM += i)
        {
            for (double startB = avgL.getB() - 5 * i; startB <= avgL.getB() + 5 * i; startB += i)
            {
                tmpLine.setSlope(startM);
                tmpLine.setB(startB);
                tmp = tmpLine.sumDist(pArr, size);
                if (tmp < min)
                {
                    tmp = min;
                    minL = tmpLine;
                }
            }
        }
        avgL = minL;
    }
    cout << "The line is: y = " << minL.getSlope() << "x + " << minL.getB() << endl;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...