LINUX.ORG.RU

Кривые Безье по точкам

 ,


0

2

Добрый день, пытаюсь понять аппроксимацию набора точек на плоскости кривыми Безье. Нашёл вот такую тему - Кривые Безье - математический ликбез., где человек предлагает использовать первые производные для нахождения прямых, на которых лежат задающие точки P2 и P3 кубической кривой, т.к. геометрический смысл первых производных - касательные к кривой в точках P1 и P4. Дальше он спрашивает как найти найти расстояние, на котором лежат точки P1 и P2. Ему говорят про вторые производные и он понимает, а я нет. Вот отрывок -

B(t) = (1-t)^3 P1 + 3t(1-t)^2 P2 + 3t^2(1-t) P3 + t^3 P4.

B'(0) = -3 P1 + 3 P2 — это производная на одном конце, то же на другом конце. Остаются два свободных параметра.

Можешь их подогнать так чтобы например вторые производные на концах тоже совпадали с твоим гребаным графиком:

B"(0) = 6 P1 - 12 P2 + 6 P3 B"(1) = 6 P4 - 12 P3 + 6 P2

эти два вектора значит должны быть параллельны (1, f"(x) и (1, f"(x[i+1])) соответственно.

Помогите понять что имел в виду анонимус в том сообщении, используя вторые производные?

★★★

Последнее исправление: pseudo-cat (всего исправлений: 3)

может ты сначала поможешь понять зачем ты пытаешься использовать кривые безье не по назначению?

anonymous
()
Ответ на: комментарий от pseudo-cat

Как бы помягче... Аппроксимировать и провести через - не одно и то же. Как минимум.

Elyas ★★★★★
()

Ему говорят про вторые производные и он понимает, а я нет.

Хм. Я тоже не понял.

При нормальной параметризации кривой, вторая производная всегда перпендикулярна первой, а её величина суть кривизна кривой. Поэтому зачем может быть нужно обращать внимание на направление вектора (1, f"(x)) — для меня загадка.

Ну а что скажет Absurd?

Manhunt ★★★★★
()
Ответ на: комментарий от pseudo-cat

почему не по назначению, у меня есть набор точек, которые можно аппроксимировать кривой Безье.

А чем плоха кусочно-линейная аппроксимация?

Manhunt ★★★★★
()
Ответ на: комментарий от pseudo-cat

просто надо

Без ясного понимания тех свойств, которые тебе нужны от аппроксимации, ничего хорошего получится. Безьятина, мало того, что не слишком удобна при анализе, так ещё и всяких лишних петель/перегибов может наплодить, если бездумно её фигачить. Ради чего это?

Manhunt ★★★★★
()
Ответ на: комментарий от Manhunt

Для рисования красивой svg графики из битмапов. Это часть задачи. Вторая часть сравнение с шаблонами svg-графики. И у меня уже есть функция сравнения двух кривых Безье, которая хорошо работает и всех устраивает, поэтому всё что надо - аппроксимировать кривой Безье набор точек. Сейчас у меня там работает линейная аппроксимация МНК, хочется что-то подобное для Безье.

pseudo-cat ★★★
() автор топика

кому нибудь может пригодиться -

    member x.svgParseBezier (yx : (int * int) list) = 
        let yxFloat = 
            yx |> List.map (fun (a,b) -> float a, float b)
           
        let mb = Matrix<float>.Build
        let M = 
            mb.Dense(4, 4, 
                    [|  -1.0; 3.0; -3.0; 1.0; 
                        3.0; -6.0; 3.0; 0.0;
                        -3.0; 3.0; 0.0; 0.0;
                        1.0; 0.0; 0.0; 0.0 
                    |])
        let d =
            yxFloat 
            |> List.fold 
                (fun (acc, y1, x1) (y2, x2) -> 
                    match acc with
                    | [] -> [0.0], y2, x2
                    | d1 :: _ -> 
                        let d2 = d1 + (Geometry.Segment.length y2 x2 y1 x1)
                        (d2 :: acc), y2, x2)
                ([], 0.0, 0.0)
            |> (fun (acc, _, _) -> acc |> List.rev)
        let dsum = 
            match d with
            | h :: t -> 
                t |> List.fold (fun (acc, d1) d2 -> acc + abs(d2 - d1), d2) (0.0, h) |> (fun (a,_) -> a)
        let t = 
            d 
            |> List.fold 
                (fun (acc, d1) d2 -> abs(d2 - d1) / dsum :: acc, d1)
                ([], 0.0)
            |> (fun (acc,_) -> acc |> List.rev)
        let T = 
            t 
            |> List.map (fun t -> [Math.Pow(t, 3.0); Math.Pow(t, 2.0); t; 1.0] |> Array.ofList)
            |> mb.DenseOfRowArrays 

        let Y, X = 
            yxFloat 
            |> List.fold (fun (ys, xs) (y, x) -> y::ys, x::xs) ([],[]) 
            |> (fun (ys, xs) -> Array.ofList(List.rev ys), Array.ofList(List.rev xs))
            |> (fun (ys, xs) -> Vector.Build.DenseOfArray ys, Vector.Build.DenseOfArray xs)
        let Cadd = M.Inverse() * (T.Transpose() * T).Inverse() * T.Transpose()
        let Cy = Cadd * Y
        let Cx = Cadd * X
        match Cx |> Vector.toList |> List.map2 (fun cx cy -> cy, cx) (Cy |> Vector.toList) with
        | p1 :: p2 :: p3 :: p4 :: _ -> Helper.SVG.BezierCurve(p1, p2, p3, p4) 

pseudo-cat ★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.