[an error occurred while processing this directive]
Вот пример и несколько слов.
(«Телесистемы»: Конференция «Микроконтроллеры и их применение»)

миниатюрный аудио-видеорекордер mAVR

Отправлено cout 11 января 2005 г. 13:46
В ответ на: Киньте плиз, программку на С как по нескольким точкам построить плвную кривую отправлено IgorA 11 января 2005 г. 11:01

Для нахождения значений функции в промежутках между узлами (точками измерений) удобно применять сплайн-интерполяцию, одним из достоинств которой является то, что ВЫЧИСЛЕННЫЕ по ней значения функции в узлах (точках измерения) гарантированно совпадут с ИЗМЕРЕННЫМИ значениями, что не всегда достижимо при "обычной" интерполяции полиномами (Ньютона,Лагранжа,Эверетта, где для повышения точности
применяются полиномы высокой степени, что само по себе дает погрешность, да и время вычисления увеличивается. В случае сплайна достаточно полинома 3-ей степени).
Ниже приведена Си-функция для вычисления по сплайн-методу значения Y в промежутках между известными узлами (точками измерений).
Работать с ней очень просто (покажу на примере 6 узловых точек):
Пусть в известные Вам 6 точек времени Вы намеряли 6 значений и хотите построить на экране плавненький график.
1. Сохраните измеренные значения (вольты, омы, градусы, литры...) во float-виде в глобальном массиве Yy[1]...Yy[6].
(Обратите внимание, что здесь индекс массива идет не с нуля, а с 1. Это рудимент Бейсика, т.к. первоначально программа была написана на нем, и работала на Синклере и БК).
2. ВременА измерений сохраните во float-виде в глобальном массиве Xx[1]...Xx[6](Конечно, каждое время Xx[i] должно ответствовать "своему" измерению Yy[i] ).
Пусть для определенности временА измерений 1, 2, 3, 4, 5, 6 мс. Промежутки между измерениями, вообще-то, могут быть неодинаковыми. Сплайну пох.
3. Ну, и запускайте функцию задавая ей в качестве аргумента интересующее Вас время.
"Просканируйте" таким образом Ваш временной диапазон - и выводите
график на экран прибора.
4. С чувством выполненного долга займите очередь в кассу предприятия за премией.
Примеры вызова:
Value1 = Spline( 1.5 ); // вычислит значение функции для 1.5 мс
........................
Value2 = Spline( 4.0 ); // даст то же значение, что Вы намеряли в узловой точке 4 мс
........................
Исходный код на Си:
////////////////////////////////////////////
#define MAXIMAL 6
/* Для изменения количества узлов изменять только значение MAXIMAL, но не трогая
констант 6.0 внутри функции */
/*******************************************/
float power3(float zx )
{
return (zx*zx*zx);
}/*power3*/
/*******************************************/
float Spline( float TimePoint )
{
unsigned char ii, jj, kk;
float dd, ee, hh, ff, pp, xxx, rrr, yyy;
float Ll[MAXIMAL+2], Rr[MAXIMAL+2], Ss[MAXIMAL+2], Mm[MAXIMAL+2];

dd = Xx[2] - Xx[1];

ee = ( Yy[ 2 ] - Yy[ 1 ] ) / dd;

for( kk=2; kk <= MAXIMAL-1; kk++ )
{
hh = dd;
dd = Xx[kk+1] - Xx[kk];
ff = ee;
ee = ( Yy[kk+1] - Yy[kk] ) / dd;
Ll[kk] = dd / ( dd + hh);
Rr[kk] = 1.0 - Ll[kk];
Ss[kk] = ( 6.0 * (ee - ff) ) / ( hh + dd );
}/*for*/

for( kk = 2; kk <= MAXIMAL-1; kk++ )
{
pp = 1.0 / ( Rr[kk] * Ll[kk-1] + 2 );
Ll[kk] = (-Ll[kk]) * pp;
Ss[kk] = ( Ss[kk] - Rr[kk] * Ss[kk-1] ) * pp;
}/*for*/

Mm[ MAXIMAL ] = 0.0;
Ll[ MAXIMAL-1 ] = Ss[ MAXIMAL-1 ];
Mm[ MAXIMAL-1 ] = Ll[ MAXIMAL-1 ];

for( kk = MAXIMAL-2; kk >= 1; kk-- )
{
Ll[kk] = Ll[kk] * Ll[kk+1] + Ss[kk];
Mm[kk] = Ll[kk];
}/*for*/

xxx = TimePoint;

ii = 0;

if( xxx > Xx[ MAXIMAL ] )
{
// экстраполяция вправо по оси времени
dd = Xx[MAXIMAL] - Xx[MAXIMAL-1];
yyy = dd * Mm[ MAXIMAL-1 ] / 6.0 + ( Yy[MAXIMAL] - Yy[MAXIMAL-1] ) / dd;
yyy = yyy * ( xxx - Xx[MAXIMAL] ) + Yy[MAXIMAL];
}/*if*/

else if( xxx <= Xx[ 1 ] )
{
// экстраполяция влево по оси времени
dd = ( Xx[2] - Xx[1] );
yyy = (((-dd) * Mm[2]) / 6.0) + (( Yy[2] - Yy[1] ) / dd);
yyy = (yyy * ( xxx - Xx[1] ) ) + Yy[1];
}/*else if*/

else
{
// интерполяция
do{ ii++; }while( xxx > Xx[ ii ] );
jj = ( ii - 1 );
dd = ( Xx[ii] - Xx[jj] );
hh = ( xxx - Xx[jj] );
rrr = ( Xx[ii] - xxx );
pp = dd * dd / 6.0;
yyy = ( ( Mm[jj]*(power3(rrr)) + Mm[ii]*(power3(hh)) ) / 6.0 ) / dd;
yyy = yyy+((( Yy[jj]-(Mm[jj]*pp))*rrr) + ((Yy[ii]-(Mm[ii]*pp))*hh) ) / dd;
}/*else*/

return (yyy);

}/*Spline*/
/*********************************/

Легко заметить, что задавать значения времени можно и за пределами периода
измерений, т.е. можно проводить экстраполяцию. Но не ждите от такой
экстраполяции чудес, здесь это будет всего лишь прямая линия. Это линейная
экстраполяция или т.н. Задание Асимптотического Поведения.
Про экстраполяцию тоже немножко могу написать, если, конечно, кому-то это нужно.

Составить ответ  |||  Конференция  |||  Архив

Ответы


Отправка ответа

Имя (обязательно): 
Пароль: 
E-mail: 

Тема (обязательно):
Сообщение:

Ссылка на URL: 
Название ссылки: 

URL изображения: 


Перейти к списку ответов  |||  Конференция  |||  Архив  |||  Главная страница  |||  Содержание  |||  Без кадра

E-mail: info@telesys.ru