2014-09-08 2 views
2

Возьмем типичную кубическую кривую Безье нарисованный в JavaScript (в этом примере я гугле ...) http://jsfiddle.net/atsanche/K38kM/Могу ли я сделать половину безье от полного безье?

В частности, эти две линии:

context.moveTo(188, 130); 
context.bezierCurveTo(170, 10, 350, 10, 388, 170); 

Мы имеем кубическую Безье, который начинается в 188, 130, концы в 388, 170, и имеет контроль точек: с 170, 10 и б: 350, 10

Мой вопрос в том, будет ли возможность математически корректировать конечная точка и контрольные точки, чтобы сделать другую кривую, которая является только отрезком исходной кривой?

Идеальный результат мог бы в состоянии взять процент кусочек Безье с самого начала, где 0,5 будет рисовать только половину Безье, 0,75 бы привлечь большую часть Безье (и так далее)

Я уже работал над несколькими реализациями Де Кастелау, которые позволяют мне отслеживать контур безье между [0 ... 1], но это не дает возможности математически пересчитать конечные и контрольные точки Безье сделать суб-Безье ...

спасибо заранее

+0

Возможно ли это? Да. С Кастельжау? Да. Но КАК? ... [действуя таким образом] (http://www.helloflash.net/Fichiers/HTML/CATEGORIES/physique/physique1.htm#p12). Только говорить, что Кастельжау необходимо, не является достаточным ответом. Правильный и более сложный ответ: ** как использовать Casteljau ** ... – helloflash

ответ

4

De Casteljau - действительно алгоритм для выхода. Для кубической кривой Безье, определяемой четырьмя контрольными точками P0, P1, P2 и P3, контрольные точки кривой Суб-Безье (0, u) равны P0, Q0, R0 и S0 и контрольные точки кривой Без-Безье (и, 1) S0, R1, Q2 и Р3, где

Q0 = (1-у) * Р0 и * Р1
Q1 = (1-у) * Р1 + и * Р2
Q2 = (1-у) * P2 + и * P3
R0 = (1-у) * Q0 + и * Q1
R1 = (1-у) * Q1 + и * Q2
S0 = (1-у) * R0 + u * R1

Обратите внимание: если вы хотите «извлечь» отрезок (u1, u2) из ​​исходной кривой Безье, вы w больным приходится применять Де Кастеляу дважды. В первый раз будет разбита входная кривая Безье C (t) на C1 (t) и C2 (t) в параметре u1, а во второй раз вам придется разбить кривую C2 (t) на скорректированный параметр u2 * = (u2 -u1)/(1-и1).

+0

Просто реализовано ваше решение. Отлично! Чтобы быть справедливым, это гораздо более точный ответ на мой вопрос. Спасибо, клык! К сожалению, phillipp – 1owk3y

+0

Отлично! Я рад узнать, что мой ответ помогает. – fang

0

Да это! Посмотрите раздел Безье здесь

http://en.m.wikipedia.org/wiki/De_Casteljau «s_algorithm

Это не так уж трудно в целом.

+1

На самом деле я нашел математику в примере, который вы цитировали очень высокоуровневом, и явно не объяснял разделение безье. Однако, используя диаграммы из вашей ссылки, я собрал тот факт, в котором я нуждался: конечная точка следует за кривой точно в [0 ... 1], а контрольные точки приближаются к предыдущим точкам из их исходных положений в коэффициенте [0. ..1]. Я не хочу отмечать это как правильный ответ, так как теперь у меня возникает соблазн опубликовать пример сценария, но в то же время вы помогли мне сделать вывод на мой вопрос, так что спасибо за ваш ответ. – 1owk3y

+0

Ну, геометрическая интерпретация довольно проста, в соответствии с которой математика не существует. Кривые Безье не так просты по своей природе, но в этом случае удача на вашей стороне. N.b .: Я могу рекомендовать paper.js хорошую библиотеку для векторных кривых на холсте ... – philipp

1

Как это сделать. Вы можете получить левую половину или правую половину с помощью этой функции. Эта функция взята из-за отметки отсюда: https://stackoverflow.com/a/23452618/1828637

У меня есть модификация, поэтому она может быть приспособлена к элементарной ячейке, поэтому мы можем использовать ее для cubic-bezier в css-переходах.

function splitCubicBezier(options) { 
    var z = options.z, 
     cz = z-1, 
     z2 = z*z, 
     cz2 = cz*cz, 
     z3 = z2*z, 
     cz3 = cz2*cz, 
     x = options.x, 
     y = options.y; 

    var left = [ 
    x[0], 
    y[0], 
    z*x[1] - cz*x[0], 
    z*y[1] - cz*y[0], 
    z2*x[2] - 2*z*cz*x[1] + cz2*x[0], 
    z2*y[2] - 2*z*cz*y[1] + cz2*y[0], 
    z3*x[3] - 3*z2*cz*x[2] + 3*z*cz2*x[1] - cz3*x[0], 
    z3*y[3] - 3*z2*cz*y[2] + 3*z*cz2*y[1] - cz3*y[0]]; 

    var right = [ 
    z3*x[3] - 3*z2*cz*x[2] + 3*z*cz2*x[1] - cz3*x[0], 
    z3*y[3] - 3*z2*cz*y[2] + 3*z*cz2*y[1] - cz3*y[0], 
        z2*x[3] - 2*z*cz*x[2] + cz2*x[1], 
        z2*y[3] - 2*z*cz*y[2] + cz2*y[1], 
            z*x[3] - cz*x[2], 
            z*y[3] - cz*y[2], 
               x[3], 
               y[3]]; 

    if (options.fitUnitSquare) { 
    return { 
     left: left.map(function(el, i) { 
     if (i % 2 == 0) { 
      //return el * (1/left[6]) 
      var Xmin = left[0]; 
      var Xmax = left[6]; //should be 1 
      var Sx = 1/(Xmax - Xmin); 
      return (el - Xmin) * Sx; 
     } else { 
      //return el * (1/left[7]) 
      var Ymin = left[1]; 
      var Ymax = left[7]; //should be 1 
      var Sy = 1/(Ymax - Ymin); 
      return (el - Ymin) * Sy; 
     } 
     }), 
     right: right.map(function(el, i) { 
     if (i % 2 == 0) { 
      //xval 
      var Xmin = right[0]; //should be 0 
      var Xmax = right[6]; 
      var Sx = 1/(Xmax - Xmin); 
      return (el - Xmin) * Sx; 
     } else { 
      //yval 
      var Ymin = right[1]; //should be 0 
      var Ymax = right[7]; 
      var Sy = 1/(Ymax - Ymin); 
      return (el - Ymin) * Sy; 
     } 
     }) 
    } 
    } else { 
    return { left: left, right: right}; 
    } 
} 

Это функция и теперь использовать ее с вашими параметрами.

var myBezier = { 
    xs: [188, 170, 350, 388], 
    ys: [130, 10, 10, 170] 
}; 

var splitRes = splitCubicBezier({ 
    z: .5, //percent 
    x: myBezier.xs, 
    y: myBezier.ys, 
    fitUnitSquare: false 
}); 

Это дает

({ 
    left: [188, 130, 179, 70, 219.5, 40, 267, 45], 
    right: [267, 45, 314.5, 50, 369, 90, 388, 170] 
}) 

скрипку доказывающий свою половину, я выложил его на оригинал:

http://jsfiddle.net/K38kM/8/

+0

Отличный ответ, и идеальная реализация действительно. Правильно ли изменить мой выбранный ответ сейчас в третий раз? Это похоже на эксплуатацию какого-то рода. Фактически, я также сделал аналогичную реализацию самостоятельно на основе ранее выбранного ответа, который я имел в виду для публикации. Спасибо, тем не менее, за вашу помощь! – 1owk3y

+0

Не беспокойтесь о том, чтобы принять его, им просто поделиться, чтобы помочь другим, если они будут искать это. :) Если вы можете поделиться своим методом, а это будет потрясающе :) – Noitidart

Смежные вопросы