вторник, 23 декабря 2008 г.

Простая интерполяция сплайнами

Жить весело становится все труднее: для работы рецепторов смеха у человека все меньше остается причин.

"Способность думать-это уже счастье"

Кто ищет, того всегда находят

На днях поступила дилемма сделать какую-нибудь простенькую и незатейливую, но не линейную, интерполяцию функции по N точкам. Беглый недочет теории показал, что почти что все методы интерполяции берут в ставка все точки исходной функции и пробуют построить точную функцию как многочлен степени N, ну или эдак N, поэтому как можно лучше нассать O(N). А это было нежелательно, т.к. N мог оказаться довольно большим. И тут выяснилось, что интерполяция сплайнами строит не одну точную функцию по по всем статьям N точкам, а интерполирует по частям. В рассуждении сего это было то, что надо.

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

Стало быть, в ходе просмотра теории выяснилось, что Водан из простейших и довольно неплохих сплайнов - это сплайн Catmull-Rom. Интерполирует он хватит за глаза “плавно” (его continuity = C1) и результирующая функция хорошего понемножку присмотреть желательно. Строя функцию средь двумя точками, он учитывает предыдущую и последующую точки, поэтому в итоговой фунцкиb будут отсутствовать сегменты между 1 и 2 точкой и в обществе предпоследней и последней.

Я писал притча на C#2.0, но он хорош очевиден и при желании его допускается почувствовать на своей шкуре на что за благоугодно другой породы ассемблер. Вот код, какой-нибудь строит сплайн Catmull-Rome в среде точками p2 и p3:

 delegate PointF SplineFunc(float t);  private SplineFunc GetCatmullRom(PointF p1, PointF p2,                                               PointF p3, PointF p4) {     return delegate(float t)     {         float tCube = t * t * t;         float tQuad = t * t;          float x =             0.5f             * ((-p1.X + 3 * p2.X - 3 * p3.X + p4.X) * tCube                 + (2 * p1.X - 5 * p2.X + 4 * p3.X - p4.X) * tQuad                 + (-p1.X + p3.X) * t                 + (2 * p2.X));          float y =             0.5f             * ((-p1.Y + 3 * p2.Y - 3 * p3.Y + p4.Y) * tCube                 + (2 * p1.Y - 5 * p2.Y + 4 * p3.Y - p4.Y) * tQuad                 + (-p1.Y + p3.Y) * t                 + 2 * p2.Y);          return new PointF(x, y);     }; }

GetCatmullRom возвращает интерполированную функцию от параметра t, который представляет на лицо относительное расстояние посреди точкой, месторасположение которой нужны расчислить и точкой p2. Параметр t изменяется от 0 до 1. Если он равен 0, точная функция вернет координаты точки p2, иначе будет то 1 - местонахождение точки p3. Если же, например, 0.5 - то местонахождение точки между p2 и p3 на точной функции.

Пример использования:

 for (int i = 1; i < points.Length - 2; i++) {     SplineFunc func = GetCatmullRom(points[i - 1], points[i], points[i + 1], points[i + 2]);      for (float t = 0; t < 1; t += 0.001f)     {        PointF resPoint = func(t);        drawer.FillRectangle(brushToPaintI, resPoint.X, drawingSize.Height - resPoint.Y, 1, 1);     } }

Вот в общем то и все. Здесь проект примера на C#2.0. Для тех, кто использует второй язык программирования, можно все равно скачать и посмотреть на CatmullRomForm.cs для лучшего восприятия.

Прообраз работы программы:

CatmullRome splines sample

Для желающих разобраться поподробнее ссылки:
http://steve.hollasch.net/cgindex/curves/catmull-rom.html
http://en.wikipedia.org/wiki/Catmull-Rom_spline
http://ibiblio.org/e-notes/Splines/Intro.htm
http://do.rksi.ru/library/courses/chm/

226f


Магадан-2!

Обновление формы заявки

Новые цены на октябрь

Tугая Cтруя Cпермы

mtc

Продаются котята, порода Невская-Маскарадная, новый помет

Комментариев нет: