интерполяция кубическим сплайном
От: D.S.Khan  
Дата: 04.03.08 08:43
Оценка:
Имеем постоянно обновляющиеся значения, которые необходимо быстро интерполировать.
К примеру по последним 4-м точкам. Т.е. постоянно первые значения удаляются и добавляются новые.
Для обычного сплайна по фиксированным точкам составил следующее, нужно дописать функцию добавления и удаления точек в массив с пересчетом сплайна:
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include "math.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
сlass Spline2D
{
public:
//нулевой коэффициет не используем
static const int num = 100;
float mx[num], my[num]; // 1..10 -контрольные точки сплайна
float a[num],b[num],c[num],d[num]; // 1..10
float alpha[num],beta[num]; // 1..10

static const int n=num-1; // 1..10

float t; //--------то что мы выводим
//---------------------------------------------------------------------------
float delt(int i)
{
return (my[i+1]-my[i]);
}
//---------------------------------------------------------------------------
float delt2(int i)
{
return (my[i+2]-2*my[i+1]+my[i]);
}
//---------------------------------------------------------------------------
void progonka(void)
{
beta[1]=-0.25;
alpha[1]=(3*delt2(1))/4;//(3*delt2(1))/(4*h*h);

for(int k=3;k<=n;k++) // 3..10
{
beta[k-1] =(-1)/(4+beta[k-2]); //beta[10]=0 ???
alpha[k-1]=( ((3*delt2(k-2))/pow((mx[k-1]-mx[k-2]),2)-alpha[k-2]) )/(4+beta[k-2]);
}
}
//---------------------------------------------------------------------------
void calc(void)
{
progonka();
c[n]=0; //10
for(int k=n; k>=2 ;k--) //10..2
{
c[k-1]=beta[k-1]*c[k]+alpha[k-1]; //9..1
}
c[0]=0;
for(int k=2;k<=n;k++) //1..10
{
b[k]=delt(k-1)/(mx[k]-mx[k-1])+((mx[k]-mx[k-1])*(2*c[k]+c[k-1]))/3;
d[k]=(c[k]-c[k-1])/(3*(mx[k]-mx[k-1]));
}
for(int k=0;k<=n; k++)
a[k]=my[k];
}
//---------------------------------------------------------------------------
};

Spline2D spl;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
// инициализация графика
graph.CreateChart(Form1,10,10,2);
graph.ChangeLeftAxis(-200,200);
graph.SetSeriesColor(0,clGreen);
graph.SetSeriesColor(1,clRed);
graph.LinePoints(true);
graph.SlideAll(false);
graph.AllInScreen(true);
// заполнение массивов
spl.mx[0]=0;
spl.my[0]=0;
for(int k=0;k<spl.num;k++) // 0..9
{
spl.mx[k+1]=k+k; //массив аргументов
spl.my[k+1]=random(90); //массив значений
graph.AddXYPoint(0,spl.mx[k+1],spl.my[k+1]); //добавление точек на график
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
graph.ClearAllGraphs(); // очистка графика
// генерация новых точек сплайна
spl.mx[0]=0;
spl.my[0]=0;
for(int k=0;k<spl.num;k++) // 0..9
{
spl.mx[k+1]=k;
spl.my[k+1]=random(160);
graph.AddXYPoint(0,spl.mx[k+1],spl.my[k+1]);// добавление точек на график
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
spl.calc(); // расчет коэффициентов сплайна
float step=0.1f; // с каким шагом интерполируем
for(int k=2;k<spl.num;k++)
{
for(spl.t=spl.mx[k-1];spl.t<(spl.mx[k]);spl.t+=step)
{
// добавление необходимых точек на график
graph.AddXYPoint(1,spl.t,(spl.a[k]
+ spl.b[k]*(spl.t-spl.mx[k])
+ spl.c[k]*pow((spl.t-spl.mx[k]),2)
+ spl.d[k] * pow((spl.t-spl.mx[k]),3)));
}
}
}
//---------------------------------------------------------------------------
Re: интерполяция кубическим сплайном
От: MBo  
Дата: 04.03.08 11:43
Оценка:
Здравствуйте, D.S.Khan, Вы писали:

DSK>Имеем постоянно обновляющиеся значения, которые необходимо быстро интерполировать.

DSK>К примеру по последним 4-м точкам. Т.е. постоянно первые значения удаляются и добавляются новые.
DSK>Для обычного сплайна по фиксированным точкам составил следующее, нужно дописать функцию добавления и удаления точек в массив с пересчетом сплайна:

Обязательно ли использовать глобальный интерпол. кубический сплайн с гладкостью второго порядка?
Если устроит гладкость первого порядка, то можно быстро считать локальный сплайн, например, Кэтмулл-Рома по четырем точкам.
Re: всё уже написано до нас
От: shvonder Россия  
Дата: 04.03.08 12:36
Оценка:
Например здесь.
Re[2]: всё уже написано до нас
От: shvonder Россия  
Дата: 04.03.08 12:45
Оценка:
Вот лучше.
Re[2]: интерполяция кубическим сплайном
От: D.S.Khan  
Дата: 05.03.08 16:02
Оценка:
Здравствуйте, MBo, Вы писали:

MBo>Обязательно ли использовать глобальный интерпол. кубический сплайн с гладкостью второго порядка?

MBo>Если устроит гладкость первого порядка, то можно быстро считать локальный сплайн, например, Кэтмулл-Рома по четырем точкам.

Желательно использовать гладкость второго порядка, т.к. функция будет дважды интегрироваться, хочется как можно точнее получать данные.
Но подойдет для начала и первого порядка. Но мне нужно что-то именно в виде класса с функцией добавления точки, при этом которая сама будет следить:
если количество точек 4 то рисует сплайн между двумя первыми,
при добавлении следующей точки удаляет первую точку и рисует снова между двумя первыми и т.д.

Проблема в том что мой сплайн меня во всем устраивает, но не выходит именно добавлять и дорисовывать график.
Теряется связь между старыми точками и второй сплайн не дорисовывает предыдущий.
Re[2]: всё уже написано до нас
От: D.S.Khan  
Дата: 05.03.08 16:07
Оценка:
Здравствуйте, shvonder, Вы писали:

S>Например здесь.



Спасибо за ссылки, но проблема не в получении сплайна по существующим точкам, этого я добился.
Проблема в постоянном добавлении и удалении точек и этот процесс должен быть очень быстрым.
Т.е. пришли 4 точки, интерполировал первые две, жду следующую точку.
Далее пришла еще точка, удалил первую добавил следующую пересчитал снова интерполировал первые две.
При этом если смотреть на график он должен быть непрерывным и гладким. Шаг поступления точек переменный.
Re[3]: всё уже написано до нас
От: shvonder Россия  
Дата: 07.03.08 09:28
Оценка:
Здравствуйте, D.S.Khan, Вы писали:
DSK>Спасибо за ссылки, но проблема не в получении сплайна по существующим точкам, этого я добился.
DSK>Проблема в постоянном добавлении и удалении точек и этот процесс должен быть очень быстрым.
DSK>Т.е. пришли 4 точки, интерполировал первые две, жду следующую точку.
DSK>Далее пришла еще точка, удалил первую добавил следующую пересчитал снова интерполировал первые две.
DSK>При этом если смотреть на график он должен быть непрерывным и гладким. Шаг поступления точек переменный.

Ну, вообще говоря, сплайн хорошо интерполирует внутри набора точек, и очень плохо экстраполирует вне его. Т.е. если вы продолжите сплайн за краевые точки, то увидите безобразную картину. И потом, кубический сплайн требует задания значений на краевых точках (первая, вторая производные, их комбинации). Это дело произвольное, в крайнем случае вы оцените их по первым 3 точкам. Так что продолжить единый глобальный сплайн через всё новые и новые поступающие точки, мне кажеться, не удасться. Но, во-первых, на сплайнах клином свет не сошёлся. Во-вторых, проблема явно не новая, да книжек по сплайнам горы (нет под рукой ссылки). В-третьих, вы не в том форуме спрашиваете, см. на этом же сайте "Общие вопр. программирования->Алгоритмы".
Re[4]: всё уже написано до нас
От: Аноним  
Дата: 07.03.08 21:16
Оценка:
Здравствуйте, shvonder, Вы писали:

Спасибо за советы и замечания, буду думать. Я вроде зашел в модерирование и попробовал перенести ветку в алгоритмы — у меня не вышло, наверно делаю что-то не так. Если будет возможность (может что-то, где-то встретится) скиньте ссылку или отпишите в каком направлении копать.

S>Ну, вообще говоря, сплайн хорошо интерполирует внутри набора точек, и очень плохо экстраполирует вне его. Т.е. если вы продолжите сплайн за краевые точки, то увидите безобразную картину. И потом, кубический сплайн требует задания значений на краевых точках (первая, вторая производные, их комбинации). Это дело произвольное, в крайнем случае вы оцените их по первым 3 точкам. Так что продолжить единый глобальный сплайн через всё новые и новые поступающие точки, мне кажеться, не удасться. Но, во-первых, на сплайнах клином свет не сошёлся. Во-вторых, проблема явно не новая, да книжек по сплайнам горы (нет под рукой ссылки). В-третьих, вы не в том форуме спрашиваете, см. на этом же сайте "Общие вопр. программирования->Алгоритмы".
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.