Реализация кривых Безье

Я пытаюсь реализовать кривые Безье для задания. Я пытаюсь переместить мяч (используя кривые Безье), предоставив моей функции массив ключевых кадров. Функция должна дать мне все кадры между ключевыми кадрами... или контрольными точками... но хотя я использую формулу, найденную на wikipedia... на самом деле это не работает :s

ее мой код:

  private void interpolate(){
      float x,y,b, t = 0;
      frames = new Frame[keyFrames.length];
      for(int i =0;i<keyFrames.length;++i){   
         t+=0.001;
         b = Bint(i,keyFrames.length,t);   
         x = b*keyFrames[i].x;
         y = b*keyFrames[i].y;
         frames[i] = new Frame(x,y);     
      }
  }

private float Bint(int i, int n, float t){
  float Cni = fact(n)/(fact(i) * fact(n-i));
  return Cni * pow(1-t,n-i) * pow(t,i);
}

Также я заметил, что массив frameworks[] должен быть намного больше, но я не могу найти другой текст, более удобный для программиста.

Заранее спасибо.


person Jonny    schedule 30.03.2011    source источник
comment
[Processing]processing.org основан на Java, однако классы Frame и KeyFrame созданы мной. (на самом деле это не что иное, как позиция x, y и поле времени, которые я не использую в этом коде   -  person Jonny    schedule 30.03.2011


Ответы (2)


Тут много чего не так выглядит.

  1. Таким образом, ваша интерполяция пройдет точно через первую и последнюю контрольные точки, но не через остальные. Это то, что вы хотите?

  2. Если у вас много ключевых кадров, вы используете полином очень высокой степени для интерполяции. Общеизвестно, что полиномы высокой степени плохо себя ведут, ваша позиция может сильно колебаться между позициями ключевого кадра. (Это одна из причин, по которой ответ на вопрос 1, вероятно, должен быть отрицательным.)

  3. Предполагая ради аргумента, что вы действительно делаете это, ваше значение t должно меняться от 0 в начале до 1 в конце. У вас случайно нет ровно 1001 таких ключевых кадров? Если нет, вы будете делать неправильные вещи.

  4. Вычисление этих полиномов с большим количеством вызовов fact и pow, вероятно, будет неэффективным, особенно если n велико.

Я не хочу вдаваться в подробности о том, что вы должны делать, не зная больше о масштабах вашего задания — Stack Overflow не принесет пользы никому, если сделает вашу домашнюю работу за вас! Что вам уже говорили о кривых Безье? Что конкретно требует от вас выполнение вашего задания?

ОТРЕДАКТИРОВАНО, чтобы добавить:

Вероятно, это самый простой способ интерполяции с использованием кривых Безье. Имейте одну (кубическую) кривую Безье между каждой парой ключевых точек. Этими ключевыми точками являются конечные точки (первая и последняя контрольные точки) каждой кривой Безье. Вам нужны еще две контрольные точки. Чтобы движение было плавным при перемещении через заданную ключевую точку, вам нужно (ключевая точка минус предыдущая контрольная точка) = (следующая контрольная точка минус ключевая точка). Таким образом, вы выбираете один вектор в каждой ключевой точке, который определяет, куда идут предыдущая и последующая контрольные точки. Когда вы проходите через каждую ключевую точку, вы будете двигаться в направлении этого вектора, и чем длиннее вектор, тем быстрее вы будете двигаться. (Если вектор равен нулю, то ваш кубический Безье вырождается в простой прямолинейный путь.)

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

person Gareth McCaughan    schedule 30.03.2011
comment
И я не хочу, чтобы ты делал мою домашнюю работу за меня. По сути, у нас есть тема под названием «Анимация», где мы очень кратко рассказали о линейной интерполяции, кубических сплайнах, ромбах Cutmul и кривых Безье, а затем нас попросили реализовать их, хех, это вся информация, которая у меня есть. Однако я больше склоняюсь к программированию, а не к математике, и хотя формула, найденная в Википедии, довольно проста, я не совсем понял, что такое t? - person Jonny; 30.03.2011
comment
Даже, может быть, какое-нибудь учебное пособие для программиста или что-то еще, и это все, о чем я прошу. Я обычно горжусь своими программами и люблю принимать новые вызовы, но я думаю, что ударился головой или что-то в этом роде. - person Jonny; 30.03.2011
comment
Вы можете думать о t как о значении времени, параметризирующем движение по кривой. В t=0 вы находитесь на первой контрольной точке. В t=1 вы находитесь на последней контрольной точке. В промежутках вы двигаетесь в соответствии с другими контрольными точками, но не обязательно (или даже обычно) проходите через какую-либо из них. - person Gareth McCaughan; 30.03.2011
comment
Если у вас есть произвольная последовательность позиций, и вы хотите сделать что-то, что плавно интерполирует между ними, то вы смотрите на какую-то разновидность сплайновой интерполяции. Вы можете сделать это с кривыми Безье, но есть дополнительная (нетривиальная) работа, связанная с выбором контрольных точек: это выходит за рамки простой реализации кривых Безье. (Не зная точно, что вам сказали делать, я не знаю, указывает ли это на то, что ваш инструктор хочет, чтобы вы делали больше!) - person Gareth McCaughan; 30.03.2011
comment
Выполните промежуточный анализ с использованием различных методов (линейная интерполяция, сплайны Кэтмулла-Рома и кривые Безье) и оцените результаты. Это один из вопросов в задании (остальные затем комментируют реализация и производительность и т.д...) - person Jonny; 30.03.2011
comment
Хм, достаточно честно. Что ж, если в материалах вашего курса есть что-то, рассказывающее вам, как использовать кривые Безье для промежуточного положения, когда все, что у вас есть, — это набор позиций ключевого кадра, то вам следует использовать это. В противном случае сделайте что-нибудь простое, как то, что я описал в отредактированной версии моего ответа. Думали ли вы спросить своего инструктора, должны ли вы делать что-то очень сложное при выборе кривых Безье для интерполяции? - person Gareth McCaughan; 30.03.2011

Наконец-то получил То, что мне было нужно! Вот что я сделал:

private void interpolate() {    
  float t = 0;
  float x,y,b;
  for(int f =0;f<frames.length;f++) {      
    x=0;
    y=0;
    for(int i = 0; i<keyFrames.length; i++) {       
      b = Bint(i,keyFrames.length-1,map(t,0,time,0,1));   
      x += b*keyFrames[i].x;
      y += b*keyFrames[i].y;
    }    
  frames[f] = new Frame(x,y); 
  t+=partialTime;     
}

}

private void createInterpolationData() {
     time = keyFrames[keyFrames.length-1].time -
     keyFrames[0].time;
     noOfFrames = 60*time;
     partialTime = time/noOfFrames;
     frames = new Frame[ceil(noOfFrames)];  
}
person Jonny    schedule 30.03.2011
comment
Это в основном то же самое, что и код в исходном вопросе, и имеет все те же недостатки, о которых я упоминал в своем ответе, за исключением № 3 (который он исправляет). Но если это соответствует вашим потребностям, достаточно справедливо. - person Gareth McCaughan; 08.06.2012