Как сделать инструменты пера, чтобы кривая шла плавно, используя функцию бейзера

У меня проблема с написанием функции beizer. Я написал простой код на С#:

public static PointF[] BeizerFunction (int interval, PointF point0, PointF point1, PointF point2) {
        //x = (1 - t) * (1 - t) * p[0].x + 2 * (1 - t) * t * p[1].x + t * t * p[2].x;
        //y = (1 - t) * (1 - t) * p[0].y + 2 * (1 - t) * t * p[1].y + t * t * p[2].y;
        var Points = new PointF[interval];
        var time = 1.0f / (float) interval;

        for (var i=0; i<Points.Length; i++) {
            var point = Points [i];

            point = new PointF ();
            point.X = (1 - time) * (1 - time) * point0.X
                + 2 * (1 - time) * time * point1.X
                + time * time * point2.X;
            point.Y = (1 - time) * (1 - time) * point0.Y
                + 2 * (1 - time) * time * point1.Y
                + time * time * point2.Y;

            Points [i] = point;
            time ++;
        }

        return Points;
    }

Приложение прослушивает движение мыши, поэтому я предполагаю, что указатель мыши будет контрольными точками для этой функции. Приведенный выше код, если он правильный, должен дать мне кривую Бейзера по трем точкам.

На самом деле кривых несколько, поэтому точек будет больше 3. Чтобы соединить кривую бейза вместе, я делаю что-то вроде этого.

Bezier(p0.5, p1, p1.5);
Bezier(p1.5, p2, p2.5);
Bezier(p2.5, p3, p3.5); 

Код С# для рисования всего 3 точки таков:

var p0 = new PointF (50, 50);
        var p1 = new PointF (100, 100);
        var p2 = new PointF (150, 50);

        var points = QuadraticBezierFunction.BeizerFunction (100, p0, p1, p2);

        for (var i=0; points != null && i<points.Length-1; i=i+1)
            canvas.DrawLine (points[i].X, points[i].Y, points[i+1].X, points[i+1].Y, new Android.Graphics.Paint ());

Когда я пытаюсь нарисовать кривую, она не выглядит кривой.


person LittleFunny    schedule 21.05.2016    source источник
comment
На что вы ориентируетесь: Winforms, WPF, ASP..? Всегда правильно отмечайте свой вопрос! - Кроме того: я надеюсь, что вы не используете все те многие многие точки, которые вы получаете от mousemove, чтобы построить кривую Безье, так как весь смысл (или один основной) заключается в том, что вам нужно только очень несколько для создания красивых кривых.   -  person TaW    schedule 21.05.2016
comment
используйте не квадратичный БЕЗЬЕ, а кубический (4 контрольные точки). Квадратичный БЕЗЬЕ (3 контрольные точки) действительно трудно соединить с приятными результатами (вам потребуется подгонка). С кубиками вам ничего из этого не нужно, просто используйте точки в правильном порядке. См. stackoverflow.com/a/30438865/2521214, также я думаю, что это ваша цель stackoverflow.com/a/30750626/2521214   -  person Spektre    schedule 21.05.2016
comment
Спасибо Спектру. Вы имеете в виду, что с Cubics мне нужно применить только что-то вроде этого: Cubic (p0, p1, p2, p3), затем Cubic (p3, p4, p5, p6). Извините, мои познания в математике весьма ограничены.   -  person LittleFunny    schedule 21.05.2016
comment
TaW - я не нацелен на какую-либо конкретную платформу... Раньше я использовал java quadTo для выполнения этой работы, но мне нужно применить ее к одной из библиотек, но у них нет такой же функции, поэтому я должен создать свой собственный алгоритм Безье. Спасибо за совет. Сначала я попробую версию со многими точками, а затем попробую точку в более поздней версии.   -  person LittleFunny    schedule 21.05.2016
comment
Время++; заявление в ваших кодах не кажется правильным.   -  person fang    schedule 22.05.2016
comment
@Simon да, почти вызывающая последовательность (p0,p0,p0,p1),(p0,p0,p1,p2),(p0,p1,p2,p3),(p1,p2,p3,p4),(p2,p3,p4,p5)... для получения дополнительной информации см. Связанный QA ... Вы также можете использовать для этого любой тип куба (мой любимый для этого - интерполяционный куб также в этом связанном контенте) . PS чтобы отметить пользователя комментарием, вам нужно добавить @ перед nick и сайт сделает это за вас. (например, @Spektre)   -  person Spektre    schedule 22.05.2016


Ответы (1)


Согласно наблюдению @fang, не используйте time ++;, потому что вы не хотите переходить от 0.xyz к 1.xyz, вы хотите увеличивать его небольшими частями. Функции Безье «работают» (то есть предназначены для обычных графических целей) только для параметра времени от 0 до 1 (включительно), поэтому вы хотите начать с time=0;, повторить несколько раз с небольшим time += step; и остановитесь один раз time>=1+step.

(и затем, если вам не повезет, вам, вероятно, придется вручную добавить конечную точку для time=1, чтобы вам гарантированно была правильная конечная точка)

person Mike 'Pomax' Kamermans    schedule 24.05.2016