Построение кривой Безье по N контрольным точкам

 
 
 
Сообщения:19
Всем доброго времени суток.
Подскажите пж-та алгоритм вычисления точек для кривой Безье с N контрольными точками.
Нашел готовые формулы для 4 контрольных точек
метод расчета выглядит так :
private Point calculateBezierFunction(double t)
    {
        Point p1,p2,p3,p4;
        p1=controlPoints[0].getPosition();
        p2=controlPoints[1].getPosition();
        p3=controlPoints[2].getPosition();
        p4=controlPoints[3].getPosition();
        double x,y;
        x = p1.x*(Math.pow(-t,3)+3*Math.pow(t,2)-3*t+1)
                +3*p2.x*t*(Math.pow(t,2)-2*t+1)
                +3*p3.x*Math.pow(t,2)*(1-t)+p4.x*Math.pow(t,3);
        y = p1.y*(Math.pow(-t,3)+3*Math.pow(t,2)-3*t+1)
                +3*p2.y*t*(Math.pow(t,2)-2*t+1)
                +3*p3.y*Math.pow(t,2)*(1-t)+p4.y*Math.pow(t,3);
        return new Point((int)Math.round(x),(int)Math.round(y));
    }

Этот код правильный и верно расчитывает точки.
А при попытки сделать общее решение т.е. построение по N точкам ошибка,
попробовал реализовать подсчет полинома Берштейна(для 4 точек данные почему то не совпадают), кто сталвивался подскажите пж- та в чем ошибка:
private Point calculateBershteinPoint(double t)
    {
        int x = 0;
        int y = 0;
        int N = controlPoints.length;
        for (int i = 0; i < N ; i++)
        {
            Point controlPoint = controlPoints[i].getPosition();
            int NFact = factorials.get(N);
            int iFact = factorials.get(i);
            int NsubstIFact = factorials.get(N - i);
            double Bi = (NFact / (iFact * NsubstIFact)) * Math.pow(t, i) * Math.pow((1 - t), (N - i));
            x +=controlPoint.x * Bi;
            x +=controlPoint.y * Bi;
        }
        return new Point(x, y);
    }

Сдесь factorials - мапа которая хранит занчения первых 9 значений факториала, что бы не пересчитывать каждый раз для каждой точки.
 
 
Сообщения:5
Мое решение для произвольного набора точек:
    private void bezierGoGo(ArrayList<Point> sourcePoints, Graphics painter){
        // ф-ия расчитывает финальный набор точек, по которым будет строится кривуля, а затем рисует ее
        ArrayList<Point> finalPoints = new ArrayList<>();

        for (double t=0; t<=1; t += 0.01)
            finalPoints.add(calculateBezierFunction(t, sourcePoints));
        drawCurve(finalPoints, painter);
    }

    private Point calculateBezierFunction(double t, ArrayList<Point> srcPoints)
    {   // ф-ия расчитывает очередную точку на кривой исходя из входного набора управляющих точек
        double x = 0;
        double y = 0;

        int n = srcPoints.size() - 1;
        for (int i=0; i <= n; i++)
        {
            x += fact(n)/(fact(i)*fact(n-i)) * srcPoints.get(i).getX() * Math.pow(t, i) * Math.pow(1-t, n-i);
            y += fact(n)/(fact(i)*fact(n-i)) * srcPoints.get(i).getY() * Math.pow(t, i) * Math.pow(1-t, n-i);
        }
        return new Point((int)x, (int)y);
    }

    private double fact(double arg){
        if (arg < 0) throw new RuntimeException("negative argument.");
        if (arg == 0) return 1;

        double rezult = 1;
        for (int i=1; i<=arg; i++)
            rezult *= i;
        return rezult;
    }

    private void drawCurve(ArrayList<Point> points, Graphics painter){
        for (int i = 1; i < points.size(); i++)
        {
            int x1 = (int)(points.get(i-1).getX());
            int y1 = (int)(points.get(i-1).getY());
            int x2 = (int)(points.get(i).getX());
            int y2 = (int)(points.get(i).getY());
            painter.drawLine(x1, y1, x2, y2);
        }
    }

Весьма годный пример: Пример 5-7 Кривая Безье
 
 
Сообщения:7990
Нормально так через 3 года решил тему обновить :)

www.codeabbey.com - programming problems for novice coders (+ certificates)
 
 
Сообщения:1
Kliokli:
Мое решение для произвольного набора точек:
    private void bezierGoGo(ArrayList<Point> sourcePoints, Graphics painter){
        // ф-ия расчитывает финальный набор точек, по которым будет строится кривуля, а затем рисует ее
        ArrayList<Point> finalPoints = new ArrayList<>();

        for (double t=0; t<=1; t += 0.01)
            finalPoints.add(calculateBezierFunction(t, sourcePoints));
        drawCurve(finalPoints, painter);
    }

    private Point calculateBezierFunction(double t, ArrayList<Point> srcPoints)
    {   // ф-ия расчитывает очередную точку на кривой исходя из входного набора управляющих точек
        double x = 0;
        double y = 0;

        int n = srcPoints.size() - 1;
        for (int i=0; i <= n; i++)
        {
            x += fact(n)/(fact(i)*fact(n-i)) * srcPoints.get(i).getX() * Math.pow(t, i) * Math.pow(1-t, n-i);
            y += fact(n)/(fact(i)*fact(n-i)) * srcPoints.get(i).getY() * Math.pow(t, i) * Math.pow(1-t, n-i);
        }
        return new Point((int)x, (int)y);
    }

    private double fact(double arg){
        if (arg < 0) throw new RuntimeException("negative argument.");
        if (arg == 0) return 1;

        double rezult = 1;
        for (int i=1; i<=arg; i++)
            rezult *= i;
        return rezult;
    }

    private void drawCurve(ArrayList<Point> points, Graphics painter){
        for (int i = 1; i < points.size(); i++)
        {
            int x1 = (int)(points.get(i-1).getX());
            int y1 = (int)(points.get(i-1).getY());
            int x2 = (int)(points.get(i).getX());
            int y2 = (int)(points.get(i).getY());
            painter.drawLine(x1, y1, x2, y2);
        }
    }

Весьма годный пример: Пример 5-7 Кривая Безье


Вы не могли бы подсказать? В случае, если список всех точек у меня задан не заранее, а пополняется динамически в редакторе, можно ли как то решить проблему с отображением кривой? Двойная буферизация присутствует, но проблему не решает, почему то чертятся вовсе не те линии, что надо, а код вроде бы совпадает с вашим...

 
Модераторы:Нет
Сейчас эту тему просматривают:Нет