"Способность думать-это уже счастье"
Кто ищет, того всегда находят
На днях поступила дилемма сделать какую-нибудь простенькую и незатейливую, но не линейную, интерполяцию функции по 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 для лучшего восприятия.
Прообраз работы программы:
Для желающих разобраться поподробнее ссылки:
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/
Магадан-2!
Обновление формы заявки
Новые цены на октябрь
Tугая Cтруя Cпермы
mtc
Продаются котята, порода Невская-Маскарадная, новый помет
Комментариев нет:
Отправить комментарий