timon_timonich (timon_timonich) wrote,
timon_timonich
timon_timonich

Categories:
  • Mood:
  • Music:

PHP. Линейная интерполяция или если по-русски красивое сглаживание графиков

Закончил почти 9 часовое сражение с невообразомой херней, так как херня была крайне не стандартная, то решил поделиться с миром.

Вообще, вначале хотел пост обозвать  "Линейная интерполяция или Интерполяционный многочлен Лагранжа", но я сам толком не понимаю что это значит.

Работаю в данный момент над одним крупным проектом аналитической системы, как и в любой системе, здесь дофига графиков. Ниже пример.  



Ну график как график, куча значений и все такое, но вот прибило заказчику, хочу говорит, сглаженный график как в Экселе и все тут. И подкинул он мне мило ссылочку на википедию Интерполяционный_многочлен_Лагранжа Как бы я тоже слегка прибалдел, когда прочитал что от меня хотят. Ну думаю, ладно, фик с вами в интернете явно что-то есть готовое... Я искал долго, очень долго и самое забавное нифига не нашел, было пара решений на Си, но там использовались встроенные библиотеки. Долго думал что делать, потом подсказали, что на странице википедии, как бы есть код на Си, который можно легко переписать на PHP. Код мелкий, 24 строки всего, быстренько переделал и получилось вот что...



Обрадовался, показываю заказчику, на что мне выдается ответ, а чего по бокам прыжки огромные? Ну думаю жопа. Все вроде бы по формуле, что делать не особо понятно. Ладно, будем копать дальше. Вначале был найден эксельный файл, который тоже умеет это делать, но как оттуда выцепить алгоритм непонятно, да и вообще мне кажется, что в экселе это какие-то встроенные функции. Дальше наткнулся на очень прикольный проект на яваскрипте JSXGraph Надо будеть взять на заметку и попользовать его функционал в будущем. Тут я тоже нашел рабоющий пример интерполяции и решил переписать метод отсюда, в результате кстати получилось почти тоже самое что и на графике выше. Совсем я погрустнел, и пересмотрел множество запасных решений, нашел пару модулей для Perl, пытался найти консольную утилиту через которую можно было бы тоже данные подцепить, но ничего не получилось.. После долгих экспериментов выяснилось что если клонировать первичное и конечное значение в массиве координат, то крайние пики очень сильно сглаживаются. На выходе у меня получился вот такой вот график.  



Как видите пиков нет, все плавненько. Степень скругления можно задавать в параметре функции.. Код прилагаю снизу, в принципе все понятно. Пишу на случай, вдруг кому пригодится, чтобы не мучился как я..
/* значит так, входящие параметры это координаты Y и X для которого получаем Y
* массив координат x строится автоматом так как он у меня всегда массив [0 - кол-во значений Y]
* smooth - степень скругления, иначе на концах графика у нас огромные скачки...
*/
function lagrange_polynomial($y, $argx, $smooth = 10 ) { $num = 0; $denom = 0;     $x = range( -1*$smooth, count($y) + $smooth + 1 ); $last = $y[count($y)-1];   for( $i=1;$i<=$smooth;$i++) { $y[] = $y[0]; array_unshift( $y, $last); }   $len = count($y);   for ($i=0;$i<$len;$i++) { $w[$i] = 1.0; $xi = $x[$i]; for ($k=0;$k<$len;$k++) if ($k!=$i) { $w[$i] *= ($xi-$x[$k]); } $w[$i] = 1/$w[$i]; }   for ($i=0;$i<$len;$i++) { $xi = $x[$i]; if ( $argx==$xi ) { return $y[$i]; } else { $s = $w[$i]/( $argx-$xi ); $denom += $s; $num += $s*$y[$i]; } }   return $num/$denom; }
з.ы. Сервис для подсветки PHP код я искал дольше чем писал эту заметку, но все таки нашел http://highlight.hohli.com/ всем советую, отличный сервис!
Tags: разное
Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 0 comments