2013-06-14 2 views
3

Я нашел около 1000 ответов на этот вопрос, но ни один из них я не могу использовать, потому что я использую 4 контрольных точки с моими кривыми.Попытка найти длину кривой Безье с 4 точками

То есть, я наткнулся на этого парня here:

double BezierArcLength(point2d p1, point2d p2, point2d p3, point2d p4) 
{ 
    point2d k1, k2, k3, k4; 

    k1 = -p1 + 3*(p2 - p3) + p4; 
    k2 = 3*(p1 + p3) - 6*p2; 
    k3 = 3*(p2 - p1); 
    k4 = p1; 

    q1 = 9.0*(sqr(k1.x) + sqr(k1.y)); 
    q2 = 12.0*(k1.x*k2.x + k1.y*k2.y); 
    q3 = 3.0*(k1.x*k3.x + k1.y*k3.y) + 4.0*(sqr(k2.x) + sqr(k2.y)); 
    q4 = 4.0*(k2.x*k3.x + k2.y*k3.y); 
    q5 = sqr(k3.x) + sqr(k3.y); 

    double result = Simpson(balf, 0, 1, 1024, 0.001); 
    return result; 
} 

Похоже, это было бы идеальным решением, но это начальная часть совершенно сбивает с толку меня:

k1 = -p1 + 3*(p2 - p3) + p4; 
k2 = 3*(p1 + p3) - 6*p2; 
k3 = 3*(p2 - p1); 
k4 = p1; 

Как на земле я должен выполнять операции, такие как добавление, вычитание и умножение на двумерные объекты (предположим, point2d - это структура объекта, такая как {x: 0, y: 0})? Я чувствую себя идиоткой, но это единственное, что мешает мне реализовать это чудовище.

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

+2

Вопрос: Как я должен выполнять операции, такие как добавление, вычитание и умножение на двумерные объекты? Ответ: Вы делаете их по одной координате (x или y) за раз. – geowar

ответ

15

Вот как пройти ваш кубический кривой Безье на скорости равномерного

Там ISN одна простая формула для получения четных отрезков длины вдоль кубической кривой безье (что означает даже сегменты длины дуги). В этом заключается вычисление многих точек вдоль кривой, а затем использование интерполяции, чтобы «подтолкнуть» каждую точку к грубо эквидистантному.

Я могу получить вас там почти без вашего получения PH.D по математике.

Начните с использования общей формулы для вычисления x/y точек на кривой от t = 0 до t = 1, где t = 0 представляет собой начальную точку кривой, а t = 1 представляет собой конечную точку кривой. Это общая формула:

// calc the x/y point at t interval 
// t=0 at startPt, t=1 at endPt 
var x=CubicN(t,startPt.x,controlPt1.x,controlPt2.x,endPt.x); 
var y=CubicN(t,startPt.y,controlPt1.y,controlPt2.y,endPt.y); 

// cubic helper formula at t interval 
function CubicN(t, a,b,c,d) { 
    var t2 = t * t; 
    var t3 = t2 * t; 
    return a + (-a * 3 + t * (3 * a - a * t)) * t 
    + (3 * b + t * (-6 * b + b * 3 * t)) * t 
    + (c * 3 - c * 3 * t) * t2 
    + d * t3; 
} 

Если рассчитать достаточное количество интервалов, скажем, 100 интервалов (т + = +0,01 каждый цикл), то вы получите очень хорошее приближение кривой.

Это означает, что если вы соедините 100 точек с линиями, результат будет очень похож на кубическую кривую безье.

Но вы не закончили!

Ряд точек x/y, вычисленных выше, неравномерны по дуге друг от друга.

Некоторые соседние пункты близки друг к другу, а некоторые соседние точки находятся дальше друг от друга.

Для расчета равномерно распределенных точек:

  1. Соедините все точки линиями (создание полилинии).
  2. Рассчитать общее расстояние (T) этой полилинии.
  3. Разделите (T) на количество однородных сегментов, которые вы хотите получить, получить длину единого сегмента (SL)
  4. Наконец, пройдите полилинию от начала до конца, вычислив каждую точку, которая является расстоянием (SL) от предыдущей точки ,

Результат: вы можете использовать эти эквидистантные точки для прохождения вашей кривой.

Дополнительная информация: Это должно привести к визуально плавному движению вдоль пути Безье. Но если вы желаете еще большей гладкости, просто вычислите более 100 баллов - больше очков - более гладкость.

+0

Просто попробуйте попытаться расширить пункт 4 для всех, кто (как и я) борется с ним. В моем случае я взял 10 образцов различных интервалов (представленных в примере выше). Как только я получил «SL», вместо того, чтобы делить каждый образец на 10, я разделил его на результат средней длины интервала. Уравнение представляет собой нечто вроде «одиночного образца из интервала (t)/(длина интервала/средняя длина всех интервалов)». Вам также может потребоваться настроить свою силу в десятки раз, но я не уверен, что это точно или только в моем случае. – atomictom

1

2-мерный объект или Point2D - это просто вектор, а Vector Arithmetic четко определен в математике. Например:

  k*(x,y) = (k*x, k*y) 
      -(x,y) = (-1)*(x,y) 
(x1,y1) + (x2,y2) = (x1+x2, y1+y2) 

Это все формулы, необходимые для расчета k1, k2, k3 и k4

+0

Это не то, что спросил TS. –

+0

Ну, это была часть его вопроса: «Как, на самом деле, я должен делать операции, такие как добавление, вычитание и умножение на двумерные объекты?» – Octopus

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