スプライン補間法とか
自分用メモ。
ラグランジュの補間法だと、たまに極端な山とかができてしまうので、スプラインにしてみる。
参考にしたのはここ。
補間法(スプライン)
ソースはこんな感じ。今度は線の描画付き。
[php]<?php
$list = array();
for ($i=0;$i<=10;$i++) {
$list = rand(1,9);
}
$xx = $yy = array();
for ($i=0;$i<count($list);$i++) { $xx = $i * 20; $yy = $list[$i] * 10; }
$q = $r = $s = array(); spline_init(); for ($i=$xx[0];$i<=$xx[count($xx) - 1];$i++) { $xx2 = $i; $yy2[] = spline($i); }
$w = 200; $h = 100;
$im = imagecreatetruecolor($w, $h); $white = imagecolorallocate($im, 255, 255, 255); $black = imagecolorallocate($im, 0, 0, 0); $blue = imagecolorallocate($im, 0,0,255); imagefill($im, 0, 0, $white);
$x1 = $y1 = $x2 = $y2 = 0; for ($i=0;$i<count($xx2);$i++) {
$x1 = $x2; $y1 = $y2;
$x2 = $xx2[$i]; $y2 = $yy2[$i];
if ($i == 0) { continue; } imageline($im, $x1, $y1, $x2, $y2, $black);
}
for ($i=0;$i<count($xx);$i++) {
$x1 = $x2; $y1 = $y2;
$x2 = $xx[$i]; $y2 = $yy[$i];
if ($i == 0) { continue; } imageline($im, $x1, $y1, $x2, $y2, $blue); }
header('Content-Type: image/gif'); imagegif($im);
imagedestroy($im);
exit();
function spline_init() {
global $xx, $yy, $q, $r, $s;
$n = count($xx) - 1;
$h = $b = $d = $g = array();
for ($i=0;$i<$n;$i++) { $h[$i] = $xx[$i+1] - $xx[$i]; } for ($i=1;$i<$n;$i++) { $b[$i] = (double) 2.0 * ($h[$i] + $h[$i-1]); $d[$i] = (double) 3.0 * *1; return $res; }[/php]
*1:$yy[$i+1] - $yy[$i]) / $h[$i] - ($yy[$i] - $yy[$i-1]) / $h[$i-1]); }
$g[1] = $h[1] / $b[1]; for ($i=2;$i<$n - 1;$i++) { $g[$i] = $h[$i] / ($b[$i] - $h[$i-1] * $g[$i-1]); } $u[1] = $d[1] / $b[1]; for ($i=2;$i<$n;$i++) { $u[$i] = ($d[$i]- $h[$i-1] * $u[$i-1]) / ($b[$i] - $h[$i-1] * $g[$i-1]); }
$r[0] = $r[$n] = (double) 0.0; $r[$n-1] = $u[$n-1]; for ($i=$n - 2;$i >= 1; $i--) { $r[$i] = $u[$i] - $g[$i] * $r[$i+1]; }
for ($i=0;$i<$n;$i++) { $q[$i] = (double) ($yy[$i+1] - $yy[$i]) / $h[$i] - $h[$i] * ($r[$i+1] + 2.0 * $r[$i]) / 3.0; $s[$i] = (double) ($r[$i+1] - $r[$i]) / (3.0 * $h[$i]); }
return; }
function spline($x) { global $xx, $yy, $q, $r, $s; $n = count($xx) - 1; $m = -1; for ($i=1;$i<$n && $m < 0;$i++) { if ($x < $xx[$i]) { $m = $i - 1; } } if ($m < 0) { $m = $n - 1; }
$x2 = $x - $xx[$m]; $res = $yy[$m] + $x2 * ($q[$m] + $x2 * ($r[$m] + $s[$m] * $x2